mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-04-28 02:57:24 +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> {
|
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> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match (self.sa.peek(), self.sb.peek()) {
|
match (self.sa.peek(), self.sb.peek()) {
|
||||||
// we have both streams
|
// 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
|
let (range, usage) = if ra.start < self.base { // in the middle of the left stream
|
||||||
if self.base == rb.start { // right stream is starting
|
if self.base == rb.start { // right stream is starting
|
||||||
debug_assert!(self.base < ra.end);
|
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
|
} else { // right hasn't started yet
|
||||||
debug_assert!(self.base < rb.start);
|
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
|
} else if rb.start < self.base { // in the middle of the right stream
|
||||||
if self.base == ra.start { // left stream is starting
|
if self.base == ra.start { // left stream is starting
|
||||||
debug_assert!(self.base < rb.end);
|
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
|
} else { // left hasn't started yet
|
||||||
debug_assert!(self.base < ra.start);
|
debug_assert!(self.base < ra.start);
|
||||||
(self.base .. ra.start, *vb .. *vb)
|
(self.base .. ra.start, None .. Some(*vb))
|
||||||
}
|
}
|
||||||
} else { // no active streams
|
} else { // no active streams
|
||||||
match ra.start.cmp(&rb.start) {
|
match ra.start.cmp(&rb.start) {
|
||||||
// both are starting
|
// 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
|
// 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
|
// 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;
|
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;
|
let range = self.base.max(rb.start) .. rb.end;
|
||||||
self.base = rb.end;
|
self.base = rb.end;
|
||||||
let _ = self.sb.next();
|
let _ = self.sb.next();
|
||||||
Some((range, *vb .. *vb))
|
Some((range, None .. Some(*vb)))
|
||||||
}
|
}
|
||||||
// only left stream
|
// only left stream
|
||||||
(Some(&(ref ra, va)), None) => {
|
(Some(&(ref ra, va)), None) => {
|
||||||
let range = self.base.max(ra.start) .. ra.end;
|
let range = self.base.max(ra.start) .. ra.end;
|
||||||
self.base = ra.end;
|
self.base = ra.end;
|
||||||
let _ = self.sa.next();
|
let _ = self.sa.next();
|
||||||
Some((range, *va .. *va))
|
Some((range, Some(*va) .. None))
|
||||||
}
|
}
|
||||||
// done
|
// done
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
@ -247,7 +247,7 @@ mod test {
|
|||||||
|
|
||||||
fn easy_merge<T: PartialEq + Copy + Debug>(
|
fn easy_merge<T: PartialEq + Copy + Debug>(
|
||||||
ra: Vec<(Range<usize>, T)>, rb: Vec<(Range<usize>, T)>
|
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()
|
RangedStates { ranges: ra }.merge(&RangedStates { ranges: rb }, 0).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +337,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..4, 0..2),
|
(1..4, Some(0)..Some(2)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -353,7 +353,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..2, 0..0),
|
(1..2, Some(0)..None),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -365,7 +365,7 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(3..4, 1..1),
|
(3..4, None..Some(1)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -383,9 +383,9 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..2, 0..0),
|
(1..2, Some(0)..None),
|
||||||
(2..4, 2..2),
|
(2..4, None..Some(2)),
|
||||||
(5..6, 1..1),
|
(5..6, Some(1)..None),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -402,9 +402,9 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..2, 0..0),
|
(1..2, Some(0)..None),
|
||||||
(2..4, 0..2),
|
(2..4, Some(0)..Some(2)),
|
||||||
(4..6, 0..0),
|
(4..6, Some(0)..None),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -417,8 +417,8 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..2, 2..2),
|
(1..2, None..Some(2)),
|
||||||
(2..4, 0..2),
|
(2..4, Some(0)..Some(2)),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -437,13 +437,13 @@ mod test {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
(1..2, 0..0),
|
(1..2, Some(0)..None),
|
||||||
(2..4, 0..2),
|
(2..4, Some(0)..Some(2)),
|
||||||
(4..5, 2..2),
|
(4..5, None..Some(2)),
|
||||||
(5..6, 1..2),
|
(5..6, Some(1)..Some(2)),
|
||||||
(6..7, 1..1),
|
(6..7, Some(1)..None),
|
||||||
(7..8, 1..3),
|
(7..8, Some(1)..Some(3)),
|
||||||
(8..9, 3..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) {
|
if selector.aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
|
||||||
for level in selector.levels.clone() {
|
for level in selector.levels.clone() {
|
||||||
|
//TODO: improve this, it's currently not tested enough and not sound
|
||||||
let ds_state = DepthStencilState {
|
let ds_state = DepthStencilState {
|
||||||
depth: Unit::new(usage),
|
depth: Unit::new(
|
||||||
stencil: Unit::new(usage),
|
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)
|
.isolate(&selector.layers, ds_state)
|
||||||
{
|
{
|
||||||
//TODO: check if anything needs to be done when only one of the depth/stencil
|
//TODO: check if anything needs to be done when only one of the depth/stencil
|
||||||
// is selected?
|
// 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 {
|
let pending = PendingTransition {
|
||||||
id,
|
id,
|
||||||
selector: hal::image::SubresourceRange {
|
selector: hal::image::SubresourceRange {
|
||||||
@ -152,11 +157,11 @@ impl ResourceState for TextureStates {
|
|||||||
levels: level .. level + 1,
|
levels: level .. level + 1,
|
||||||
layers: range.clone(),
|
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 {
|
let pending = PendingTransition {
|
||||||
id,
|
id,
|
||||||
selector: hal::image::SubresourceRange {
|
selector: hal::image::SubresourceRange {
|
||||||
@ -164,9 +169,9 @@ impl ResourceState for TextureStates {
|
|||||||
levels: level .. level + 1,
|
levels: level .. level + 1,
|
||||||
layers: range.clone(),
|
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));
|
temp_color.extend(mip_self.merge(mip_other, 0));
|
||||||
mip_self.clear();
|
mip_self.clear();
|
||||||
for (layers, states) in temp_color.drain(..) {
|
for (layers, states) in temp_color.drain(..) {
|
||||||
let mut color_usage = states.start.last .. states.end.select(stitch);
|
let unit = match states {
|
||||||
if color_usage.start != color_usage.end {
|
Range { start: None, end: None } => unreachable!(),
|
||||||
let level = mip_id as hal::image::Level;
|
Range { start: Some(start), end: None } => start,
|
||||||
let pending = PendingTransition {
|
Range { start: None, end: Some(end) } => Unit::new(end.select(stitch)),
|
||||||
id,
|
Range { start: Some(start), end: Some(end) } => {
|
||||||
selector: hal::image::SubresourceRange {
|
let mut final_usage = end.select(stitch);
|
||||||
aspects: hal::format::Aspects::COLOR,
|
if start.last != final_usage {
|
||||||
levels: level .. level + 1,
|
let level = mip_id as hal::image::Level;
|
||||||
layers: layers.clone(),
|
let pending = PendingTransition {
|
||||||
},
|
id,
|
||||||
usage: color_usage.clone(),
|
selector: hal::image::SubresourceRange {
|
||||||
};
|
aspects: hal::format::Aspects::COLOR,
|
||||||
color_usage.end = pending.record(output.as_mut())?;
|
levels: level .. level + 1,
|
||||||
}
|
layers: layers.clone(),
|
||||||
mip_self.append(layers, Unit {
|
},
|
||||||
init: states.start.init,
|
usage: start.last .. final_usage,
|
||||||
last: color_usage.end,
|
};
|
||||||
});
|
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));
|
temp_ds.extend(self.depth_stencil.merge(&other.depth_stencil, 0));
|
||||||
self.depth_stencil.clear();
|
self.depth_stencil.clear();
|
||||||
for (layers, states) in temp_ds.drain(..) {
|
for (layers, states) in temp_ds.drain(..) {
|
||||||
let mut usage_depth = states.start.depth.last .. states.end.depth.select(stitch);
|
let ds = match states {
|
||||||
let mut usage_stencil = states.start.stencil.last .. states.end.stencil.select(stitch);
|
Range { start: None, end: None } => unreachable!(),
|
||||||
if usage_depth.start != usage_depth.end {
|
Range { start: Some(start), end: None } => start,
|
||||||
let pending = PendingTransition {
|
Range { start: None, end: Some(end) } => DepthStencilState {
|
||||||
id,
|
depth: Unit::new(end.depth.select(stitch)),
|
||||||
selector: hal::image::SubresourceRange {
|
stencil: Unit::new(end.stencil.select(stitch)),
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
stencil: Unit {
|
Range { start: Some(start), end: Some(end) } => {
|
||||||
init: states.start.stencil.init,
|
let mut final_depth = end.depth.select(stitch);
|
||||||
last: usage_stencil.end,
|
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(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user