mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-10-30 22:11:50 +00:00
Improve texture state merging
This commit is contained in:
parent
ef1c373887
commit
7c647a7d3c
@ -179,7 +179,7 @@ pub struct Merge<'a, I, T> {
|
||||
}
|
||||
|
||||
impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
||||
type Item = (Range<I>, Range<T>);
|
||||
type Item = (Range<I>, Range<Option<T>>);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match (self.sa.peek(), self.sb.peek()) {
|
||||
// we have both streams
|
||||
@ -187,27 +187,27 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
||||
let (range, usage) = if ra.start < self.base { // in the middle of the left stream
|
||||
if self.base == rb.start { // right stream is starting
|
||||
debug_assert!(self.base < ra.end);
|
||||
(self.base .. ra.end.min(rb.end), *va .. *vb)
|
||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
||||
} else { // right hasn't started yet
|
||||
debug_assert!(self.base < rb.start);
|
||||
(self.base .. rb.start, *va .. *va)
|
||||
(self.base .. rb.start, Some(*va) .. None)
|
||||
}
|
||||
} else if rb.start < self.base { // in the middle of the right stream
|
||||
if self.base == ra.start { // left stream is starting
|
||||
debug_assert!(self.base < rb.end);
|
||||
(self.base .. ra.end.min(rb.end), *va .. *vb)
|
||||
(self.base .. ra.end.min(rb.end), Some(*va) .. Some(*vb))
|
||||
} else { // left hasn't started yet
|
||||
debug_assert!(self.base < ra.start);
|
||||
(self.base .. ra.start, *vb .. *vb)
|
||||
(self.base .. ra.start, None .. Some(*vb))
|
||||
}
|
||||
} else { // no active streams
|
||||
match ra.start.cmp(&rb.start) {
|
||||
// both are starting
|
||||
Ordering::Equal => (ra.start .. ra.end.min(rb.end), *va .. *vb),
|
||||
Ordering::Equal => (ra.start .. ra.end.min(rb.end), Some(*va) .. Some(*vb)),
|
||||
// only left is starting
|
||||
Ordering::Less => (ra.start .. rb.start.min(ra.end), *va .. *va),
|
||||
Ordering::Less => (ra.start .. rb.start.min(ra.end), Some(*va) .. None),
|
||||
// only right is starting
|
||||
Ordering::Greater => (rb.start .. ra.start.min(rb.end), *vb .. *vb),
|
||||
Ordering::Greater => (rb.start .. ra.start.min(rb.end), None .. Some(*vb)),
|
||||
}
|
||||
};
|
||||
self.base = range.end;
|
||||
@ -224,14 +224,14 @@ impl<'a, I: Copy + Debug + Ord, T: Copy + Debug> Iterator for Merge<'a, I, T> {
|
||||
let range = self.base.max(rb.start) .. rb.end;
|
||||
self.base = rb.end;
|
||||
let _ = self.sb.next();
|
||||
Some((range, *vb .. *vb))
|
||||
Some((range, None .. Some(*vb)))
|
||||
}
|
||||
// only left stream
|
||||
(Some(&(ref ra, va)), None) => {
|
||||
let range = self.base.max(ra.start) .. ra.end;
|
||||
self.base = ra.end;
|
||||
let _ = self.sa.next();
|
||||
Some((range, *va .. *va))
|
||||
Some((range, Some(*va) .. None))
|
||||
}
|
||||
// done
|
||||
(None, None) => None,
|
||||
@ -247,7 +247,7 @@ mod test {
|
||||
|
||||
fn easy_merge<T: PartialEq + Copy + Debug>(
|
||||
ra: Vec<(Range<usize>, T)>, rb: Vec<(Range<usize>, T)>
|
||||
) -> Vec<(Range<usize>, Range<T>)> {
|
||||
) -> Vec<(Range<usize>, Range<Option<T>>)> {
|
||||
RangedStates { ranges: ra }.merge(&RangedStates { ranges: rb }, 0).collect()
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..4, 0..2),
|
||||
(1..4, Some(0)..Some(2)),
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -353,7 +353,7 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, 0..0),
|
||||
(1..2, Some(0)..None),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@ -365,7 +365,7 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(3..4, 1..1),
|
||||
(3..4, None..Some(1)),
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -383,9 +383,9 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, 0..0),
|
||||
(2..4, 2..2),
|
||||
(5..6, 1..1),
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, None..Some(2)),
|
||||
(5..6, Some(1)..None),
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -402,9 +402,9 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, 0..0),
|
||||
(2..4, 0..2),
|
||||
(4..6, 0..0),
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
(4..6, Some(0)..None),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@ -417,8 +417,8 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, 2..2),
|
||||
(2..4, 0..2),
|
||||
(1..2, None..Some(2)),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -437,13 +437,13 @@ mod test {
|
||||
],
|
||||
),
|
||||
vec![
|
||||
(1..2, 0..0),
|
||||
(2..4, 0..2),
|
||||
(4..5, 2..2),
|
||||
(5..6, 1..2),
|
||||
(6..7, 1..1),
|
||||
(7..8, 1..3),
|
||||
(8..9, 3..3),
|
||||
(1..2, Some(0)..None),
|
||||
(2..4, Some(0)..Some(2)),
|
||||
(4..5, None..Some(2)),
|
||||
(5..6, Some(1)..Some(2)),
|
||||
(6..7, Some(1)..None),
|
||||
(7..8, Some(1)..Some(3)),
|
||||
(8..9, None..Some(3)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -135,16 +135,21 @@ impl ResourceState for TextureStates {
|
||||
}
|
||||
if selector.aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
|
||||
for level in selector.levels.clone() {
|
||||
//TODO: improve this, it's currently not tested enough and not sound
|
||||
let ds_state = DepthStencilState {
|
||||
depth: Unit::new(usage),
|
||||
stencil: Unit::new(usage),
|
||||
depth: Unit::new(
|
||||
if selector.aspects.contains(hal::format::Aspects::DEPTH) { usage } else { TextureUsage::empty() }
|
||||
),
|
||||
stencil: Unit::new(
|
||||
if selector.aspects.contains(hal::format::Aspects::STENCIL) { usage } else { TextureUsage::empty() }
|
||||
),
|
||||
};
|
||||
for &mut (ref range, ref mut unit) in self.depth_stencil
|
||||
for &mut (ref range, ref mut ds) in self.depth_stencil
|
||||
.isolate(&selector.layers, ds_state)
|
||||
{
|
||||
//TODO: check if anything needs to be done when only one of the depth/stencil
|
||||
// is selected?
|
||||
if unit.depth.last != usage && selector.aspects.contains(hal::format::Aspects::DEPTH) {
|
||||
if ds.depth.last != usage && selector.aspects.contains(hal::format::Aspects::DEPTH) {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
@ -152,11 +157,11 @@ impl ResourceState for TextureStates {
|
||||
levels: level .. level + 1,
|
||||
layers: range.clone(),
|
||||
},
|
||||
usage: unit.depth.last .. usage,
|
||||
usage: ds.depth.last .. usage,
|
||||
};
|
||||
unit.depth.last = pending.record(output.as_mut())?;
|
||||
ds.depth.last = pending.record(output.as_mut())?;
|
||||
}
|
||||
if unit.stencil.last != usage && selector.aspects.contains(hal::format::Aspects::STENCIL) {
|
||||
if ds.stencil.last != usage && selector.aspects.contains(hal::format::Aspects::STENCIL) {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
@ -164,9 +169,9 @@ impl ResourceState for TextureStates {
|
||||
levels: level .. level + 1,
|
||||
layers: range.clone(),
|
||||
},
|
||||
usage: unit.stencil.last .. usage,
|
||||
usage: ds.stencil.last .. usage,
|
||||
};
|
||||
unit.stencil.last = pending.record(output.as_mut())?;
|
||||
ds.stencil.last = pending.record(output.as_mut())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,24 +198,32 @@ impl ResourceState for TextureStates {
|
||||
temp_color.extend(mip_self.merge(mip_other, 0));
|
||||
mip_self.clear();
|
||||
for (layers, states) in temp_color.drain(..) {
|
||||
let mut color_usage = states.start.last .. states.end.select(stitch);
|
||||
if color_usage.start != color_usage.end {
|
||||
let level = mip_id as hal::image::Level;
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::COLOR,
|
||||
levels: level .. level + 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: color_usage.clone(),
|
||||
};
|
||||
color_usage.end = pending.record(output.as_mut())?;
|
||||
}
|
||||
mip_self.append(layers, Unit {
|
||||
init: states.start.init,
|
||||
last: color_usage.end,
|
||||
});
|
||||
let unit = match states {
|
||||
Range { start: None, end: None } => unreachable!(),
|
||||
Range { start: Some(start), end: None } => start,
|
||||
Range { start: None, end: Some(end) } => Unit::new(end.select(stitch)),
|
||||
Range { start: Some(start), end: Some(end) } => {
|
||||
let mut final_usage = end.select(stitch);
|
||||
if start.last != final_usage {
|
||||
let level = mip_id as hal::image::Level;
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::COLOR,
|
||||
levels: level .. level + 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: start.last .. final_usage,
|
||||
};
|
||||
final_usage = pending.record(output.as_mut())?;
|
||||
}
|
||||
Unit {
|
||||
init: start.init,
|
||||
last: final_usage,
|
||||
}
|
||||
}
|
||||
};
|
||||
mip_self.append(layers, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,42 +231,53 @@ impl ResourceState for TextureStates {
|
||||
temp_ds.extend(self.depth_stencil.merge(&other.depth_stencil, 0));
|
||||
self.depth_stencil.clear();
|
||||
for (layers, states) in temp_ds.drain(..) {
|
||||
let mut usage_depth = states.start.depth.last .. states.end.depth.select(stitch);
|
||||
let mut usage_stencil = states.start.stencil.last .. states.end.stencil.select(stitch);
|
||||
if usage_depth.start != usage_depth.end {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::DEPTH,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: usage_depth.clone(),
|
||||
};
|
||||
usage_depth.end = pending.record(output.as_mut())?;
|
||||
}
|
||||
if usage_stencil.start != usage_stencil.end {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::STENCIL,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: usage_stencil.clone(),
|
||||
};
|
||||
usage_stencil.end = pending.record(output.as_mut())?;
|
||||
}
|
||||
self.depth_stencil.append(layers, DepthStencilState {
|
||||
depth: Unit {
|
||||
init: states.start.depth.init,
|
||||
last: usage_depth.end,
|
||||
let ds = match states {
|
||||
Range { start: None, end: None } => unreachable!(),
|
||||
Range { start: Some(start), end: None } => start,
|
||||
Range { start: None, end: Some(end) } => DepthStencilState {
|
||||
depth: Unit::new(end.depth.select(stitch)),
|
||||
stencil: Unit::new(end.stencil.select(stitch)),
|
||||
},
|
||||
stencil: Unit {
|
||||
init: states.start.stencil.init,
|
||||
last: usage_stencil.end,
|
||||
},
|
||||
});
|
||||
Range { start: Some(start), end: Some(end) } => {
|
||||
let mut final_depth = end.depth.select(stitch);
|
||||
let mut final_stencil = end.stencil.select(stitch);
|
||||
if start.depth.last != final_depth {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::DEPTH,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: start.depth.last .. final_depth,
|
||||
};
|
||||
final_depth = pending.record(output.as_mut())?;
|
||||
}
|
||||
if start.stencil.last != final_stencil {
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::STENCIL,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: start.stencil.last .. final_stencil,
|
||||
};
|
||||
final_stencil = pending.record(output.as_mut())?;
|
||||
}
|
||||
DepthStencilState {
|
||||
depth: Unit {
|
||||
init: start.depth.init,
|
||||
last: final_depth,
|
||||
},
|
||||
stencil: Unit {
|
||||
init: start.stencil.init,
|
||||
last: final_stencil,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
self.depth_stencil.append(layers, ds);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user