mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Improve texture state merging with proper error handling
This commit is contained in:
@@ -10,6 +10,7 @@ use std::ops::Range;
|
||||
pub type BufferState = Unit<BufferUsage>;
|
||||
|
||||
impl PendingTransition<BufferState> {
|
||||
/// Produce the gfx-hal buffer states corresponding to the transition.
|
||||
pub fn to_states(&self) -> Range<hal::buffer::State> {
|
||||
conv::map_buffer_state(self.usage.start) ..
|
||||
conv::map_buffer_state(self.usage.end)
|
||||
|
||||
@@ -181,7 +181,6 @@ 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>);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
println!("Peek {:?} {:?} base = {:?}", self.sa.peek(), self.sb.peek(), self.base);
|
||||
match (self.sa.peek(), self.sb.peek()) {
|
||||
// we have both streams
|
||||
(Some(&(ref ra, va)), Some(&(ref rb, vb))) => {
|
||||
|
||||
@@ -27,10 +27,32 @@ pub struct TextureStates {
|
||||
}
|
||||
|
||||
impl PendingTransition<TextureStates> {
|
||||
/// Produce the gfx-hal image states corresponding to the transition.
|
||||
pub fn to_states(&self) -> Range<hal::image::State> {
|
||||
conv::map_texture_state(self.usage.start, self.selector.aspects) ..
|
||||
conv::map_texture_state(self.usage.end, self.selector.aspects)
|
||||
}
|
||||
|
||||
/// Check for the validity of `self` with regards to the presense of `output`.
|
||||
///
|
||||
/// Return the end usage if the `output` is provided and pushes self to it.
|
||||
/// Otherwise, return the extended usage, or an error if extension is impossible.
|
||||
fn record(self, output: Option<&mut &mut Vec<Self>>) -> Result<TextureUsage, Self> {
|
||||
let u = self.usage.clone();
|
||||
match output {
|
||||
Some(out) => {
|
||||
out.push(self);
|
||||
Ok(u.end)
|
||||
}
|
||||
None => {
|
||||
if !u.start.is_empty() && TextureUsage::WRITE_ALL.intersects(u.start | u.end) {
|
||||
Err(self)
|
||||
} else {
|
||||
Ok(u.start | u.end)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceState for TextureStates {
|
||||
@@ -95,8 +117,7 @@ impl ResourceState for TextureStates {
|
||||
.color_mips[level as usize]
|
||||
.isolate(&selector.layers, Unit::new(usage));
|
||||
for &mut (ref range, ref mut unit) in layers {
|
||||
let old = unit.last;
|
||||
if old == usage {
|
||||
if unit.last == usage {
|
||||
continue
|
||||
}
|
||||
let pending = PendingTransition {
|
||||
@@ -106,20 +127,9 @@ impl ResourceState for TextureStates {
|
||||
levels: level .. level + 1,
|
||||
layers: range.clone(),
|
||||
},
|
||||
usage: old .. usage,
|
||||
};
|
||||
unit.last = match output.as_mut() {
|
||||
Some(out) => {
|
||||
out.push(pending);
|
||||
usage
|
||||
}
|
||||
None => {
|
||||
if !old.is_empty() && TextureUsage::WRITE_ALL.intersects(old | usage) {
|
||||
return Err(pending);
|
||||
}
|
||||
old | usage
|
||||
}
|
||||
usage: unit.last .. usage,
|
||||
};
|
||||
unit.last = pending.record(output.as_mut())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +145,6 @@ impl ResourceState for TextureStates {
|
||||
//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) {
|
||||
let old = unit.depth.last;
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
@@ -143,23 +152,11 @@ impl ResourceState for TextureStates {
|
||||
levels: level .. level + 1,
|
||||
layers: range.clone(),
|
||||
},
|
||||
usage: old .. usage,
|
||||
};
|
||||
unit.depth.last = match output.as_mut() {
|
||||
Some(out) => {
|
||||
out.push(pending);
|
||||
usage
|
||||
}
|
||||
None => {
|
||||
if !old.is_empty() && TextureUsage::WRITE_ALL.intersects(old | usage) {
|
||||
return Err(pending);
|
||||
}
|
||||
old | usage
|
||||
}
|
||||
usage: unit.depth.last .. usage,
|
||||
};
|
||||
unit.depth.last = pending.record(output.as_mut())?;
|
||||
}
|
||||
if unit.stencil.last != usage && selector.aspects.contains(hal::format::Aspects::STENCIL) {
|
||||
let old = unit.stencil.last;
|
||||
let pending = PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
@@ -167,20 +164,9 @@ impl ResourceState for TextureStates {
|
||||
levels: level .. level + 1,
|
||||
layers: range.clone(),
|
||||
},
|
||||
usage: old .. usage,
|
||||
};
|
||||
unit.stencil.last = match output.as_mut() {
|
||||
Some(out) => {
|
||||
out.push(pending);
|
||||
usage
|
||||
}
|
||||
None => {
|
||||
if !old.is_empty() && TextureUsage::WRITE_ALL.intersects(old | usage) {
|
||||
return Err(pending);
|
||||
}
|
||||
old | usage
|
||||
}
|
||||
usage: unit.stencil.last .. usage,
|
||||
};
|
||||
unit.stencil.last = pending.record(output.as_mut())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +181,6 @@ impl ResourceState for TextureStates {
|
||||
stitch: Stitch,
|
||||
mut output: Option<&mut Vec<PendingTransition<Self>>>,
|
||||
) -> Result<(), PendingTransition<Self>> {
|
||||
//TODO: extend the logic to error out properly
|
||||
let mut temp_color = Vec::new();
|
||||
while self.color_mips.len() < other.color_mips.len() {
|
||||
self.color_mips.push(PlaneStates::default());
|
||||
@@ -208,20 +193,19 @@ impl ResourceState for TextureStates {
|
||||
temp_color.extend(mip_self.merge(mip_other, 0));
|
||||
mip_self.clear();
|
||||
for (layers, states) in temp_color.drain(..) {
|
||||
let color_usage = states.start.last .. states.end.select(stitch);
|
||||
if let Some(out) = output.as_mut() {
|
||||
if color_usage.start != color_usage.end {
|
||||
let level = mip_id as hal::image::Level;
|
||||
out.push(PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::COLOR,
|
||||
levels: level .. level + 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: color_usage.clone(),
|
||||
});
|
||||
}
|
||||
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,
|
||||
@@ -234,31 +218,31 @@ 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 usage_depth = states.start.depth.last .. states.end.depth.select(stitch);
|
||||
let usage_stencil = states.start.stencil.last .. states.end.stencil.select(stitch);
|
||||
if let Some(out) = output.as_mut() {
|
||||
if usage_depth.start != usage_depth.end {
|
||||
out.push(PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::DEPTH,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: usage_depth.clone(),
|
||||
});
|
||||
}
|
||||
if usage_stencil.start != usage_stencil.end {
|
||||
out.push(PendingTransition {
|
||||
id,
|
||||
selector: hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::STENCIL,
|
||||
levels: 0 .. 1,
|
||||
layers: layers.clone(),
|
||||
},
|
||||
usage: usage_stencil.clone(),
|
||||
});
|
||||
}
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user