From 64c80998c62c1b0b04b1d8ca1a7f27f61ccb8cf8 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 13 Apr 2020 22:46:31 +0000 Subject: [PATCH] Bug 1629605 - wgpu tracking fixes r=jgilbert Differential Revision: https://phabricator.services.mozilla.com/D70707 --HG-- extra : moz-landing-system : lando --- gfx/wgpu/CHANGELOG.md | 30 ++++ gfx/wgpu/Cargo.lock | 16 +- gfx/wgpu/ffi/wgpu.h | 4 +- gfx/wgpu/wgpu-core/Cargo.toml | 4 +- gfx/wgpu/wgpu-core/src/command/render.rs | 54 ++++--- gfx/wgpu/wgpu-core/src/device/mod.rs | 9 +- gfx/wgpu/wgpu-core/src/id.rs | 8 +- gfx/wgpu/wgpu-core/src/track/buffer.rs | 113 +++++++++++--- gfx/wgpu/wgpu-core/src/track/mod.rs | 2 +- gfx/wgpu/wgpu-core/src/track/range.rs | 2 +- gfx/wgpu/wgpu-core/src/track/texture.rs | 188 +++++++++++++++++++++-- gfx/wgpu/wgpu-native/Cargo.toml | 6 +- gfx/wgpu/wgpu-remote/Cargo.toml | 5 +- gfx/wgpu/wgpu-types/Cargo.toml | 2 +- 14 files changed, 353 insertions(+), 90 deletions(-) diff --git a/gfx/wgpu/CHANGELOG.md b/gfx/wgpu/CHANGELOG.md index 3c06a8aaefa1..b6871a07dee0 100644 --- a/gfx/wgpu/CHANGELOG.md +++ b/gfx/wgpu/CHANGELOG.md @@ -1,5 +1,35 @@ # Change Log +## v0.5 (06-04-2020) + - Crates: + - `wgpu-types`: common types between native and web targets + - `wgpu-core`: internal API for the native and remote wrappers + - Features: + - based on gfx-hal-0.5 + - moved from Rendy to the new `gfx-memory` and `gfx-descriptor` crates + - passes are now recorded on the client side. The user is also responsible to keep all resources referenced in the pass up until it ends recording. + - revised GPU lifetime tracking of all resources + - revised usage tracking logic + - all IDs are now non-zero + - Mailbox present mode + - Validation: + - active pipeline + - Fixes: + - lots of small API changes to closely match upstream WebGPU + - true read-only storage bindings + - unmapping dropped buffers + - better error messages on misused swapchain frames + +## v0.4.3 (20-01-2020) + - improved swap chain error handling + +## v0.4.2 (15-12-2019) + - fixed render pass transitions + +## v0.4.1 (28-11-2019) + - fixed depth/stencil transitions + - fixed dynamic offset iteration + ## v0.4 (03-11-2019) - Platforms: removed OpenGL/WebGL support temporarily - Features: diff --git a/gfx/wgpu/Cargo.lock b/gfx/wgpu/Cargo.lock index 7b61ff46a9c1..13bf452a3243 100644 --- a/gfx/wgpu/Cargo.lock +++ b/gfx/wgpu/Cargo.lock @@ -653,7 +653,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wgpu-core" -version = "0.1.0" +version = "0.5.0" dependencies = [ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "battery 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -674,12 +674,12 @@ dependencies = [ "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wgpu-types 0.1.0", + "wgpu-types 0.5.0", ] [[package]] name = "wgpu-native" -version = "0.4.0" +version = "0.5.0" dependencies = [ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -687,8 +687,8 @@ dependencies = [ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "raw-window-handle 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wgpu-core 0.1.0", - "wgpu-types 0.1.0", + "wgpu-core 0.5.0", + "wgpu-types 0.5.0", ] [[package]] @@ -697,13 +697,13 @@ version = "0.1.0" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wgpu-core 0.1.0", - "wgpu-types 0.1.0", + "wgpu-core 0.5.0", + "wgpu-types 0.5.0", ] [[package]] name = "wgpu-types" -version = "0.1.0" +version = "0.5.0" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/gfx/wgpu/ffi/wgpu.h b/gfx/wgpu/ffi/wgpu.h index 7d7e7bfe5271..7d4e0b4b425f 100644 --- a/gfx/wgpu/ffi/wgpu.h +++ b/gfx/wgpu/ffi/wgpu.h @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* Generated with cbindgen:0.14.0 */ +/* Generated with cbindgen:0.14.1 */ /* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. * To generate this file: @@ -37,7 +37,7 @@ typedef unsigned long long WGPUOption_TextureViewId; #define WGPUMAX_MIP_LEVELS 16 -#define WGPUMAX_VERTEX_BUFFERS 8 +#define WGPUMAX_VERTEX_BUFFERS 16 typedef enum { WGPUAddressMode_ClampToEdge = 0, diff --git a/gfx/wgpu/wgpu-core/Cargo.toml b/gfx/wgpu/wgpu-core/Cargo.toml index c26fb55da61e..0b1185bbd52d 100644 --- a/gfx/wgpu/wgpu-core/Cargo.toml +++ b/gfx/wgpu/wgpu-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-core" -version = "0.1.0" +version = "0.5.0" authors = [ "Dzmitry Malyshau ", "Joshua Groves ", @@ -45,7 +45,7 @@ optional = true [dependencies.wgt] path = "../wgpu-types" package = "wgpu-types" -version = "0.1" +version = "0.5" features = ["peek-poke"] [target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies] diff --git a/gfx/wgpu/wgpu-core/src/command/render.rs b/gfx/wgpu/wgpu-core/src/command/render.rs index 41e82c78090f..421e35163685 100644 --- a/gfx/wgpu/wgpu-core/src/command/render.rs +++ b/gfx/wgpu/wgpu-core/src/command/render.rs @@ -23,15 +23,14 @@ use crate::{ use arrayvec::ArrayVec; use hal::command::CommandBuffer as _; use peek_poke::{Peek, PeekPoke, Poke}; +use smallvec::SmallVec; use wgt::{ BufferAddress, BufferUsage, Color, DynamicOffset, IndexFormat, InputStepMode, LoadOp, RenderPassColorAttachmentDescriptorBase, RenderPassDepthStencilAttachmentDescriptorBase, TextureUsage, BIND_BUFFER_ALIGNMENT, }; -use std::{ - borrow::Borrow, collections::hash_map::Entry, iter, marker::PhantomData, mem, ops::Range, slice, -}; +use std::{borrow::Borrow, collections::hash_map::Entry, iter, mem, ops::Range, slice}; pub type RenderPassColorAttachmentDescriptor = RenderPassColorAttachmentDescriptorBase; @@ -227,7 +226,7 @@ impl VertexBufferState { #[derive(Debug)] pub struct VertexState { - inputs: [VertexBufferState; MAX_VERTEX_BUFFERS], + inputs: SmallVec<[VertexBufferState; MAX_VERTEX_BUFFERS]>, vertex_limit: u32, instance_limit: u32, } @@ -438,7 +437,10 @@ impl Global { let mut resolves = ArrayVec::new(); for at in &color_attachments { - let view = &view_guard[at.attachment]; + let view = trackers + .views + .use_extend(&*view_guard, at.attachment, (), ()) + .unwrap(); if let Some(ex) = extent { assert_eq!(ex, view.extent); } else { @@ -448,10 +450,6 @@ impl Global { view.samples, sample_count, "All attachments must have the same sample_count" ); - let first_use = trackers - .views - .init(at.attachment, view.life_guard.add_ref(), PhantomData) - .is_ok(); let layouts = match view.inner { TextureViewInner::Native { ref source_id, .. } => { @@ -477,10 +475,9 @@ impl Global { } let end = hal::image::Layout::Present; - let start = if first_use { - hal::image::Layout::Undefined - } else { - end + let start = match base_trackers.views.query(at.attachment, ()) { + Some(_) => end, + None => hal::image::Layout::Undefined, }; start..end } @@ -496,16 +493,15 @@ impl Global { } for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) { - let view = &view_guard[resolve_target]; + let view = trackers + .views + .use_extend(&*view_guard, resolve_target, (), ()) + .unwrap(); assert_eq!(extent, Some(view.extent)); assert_eq!( view.samples, 1, "All resolve_targets must have a sample_count of 1" ); - let first_use = trackers - .views - .init(resolve_target, view.life_guard.add_ref(), PhantomData) - .is_ok(); let layouts = match view.inner { TextureViewInner::Native { ref source_id, .. } => { @@ -531,10 +527,9 @@ impl Global { } let end = hal::image::Layout::Present; - let start = if first_use { - hal::image::Layout::Undefined - } else { - end + let start = match base_trackers.views.query(resolve_target, ()) { + Some(_) => end, + None => hal::image::Layout::Undefined, }; start..end } @@ -798,7 +793,7 @@ impl Global { limit: 0, }, vertex: VertexState { - inputs: [VertexBufferState::EMPTY; MAX_VERTEX_BUFFERS], + inputs: SmallVec::new(), vertex_limit: 0, instance_limit: 0, }, @@ -968,7 +963,8 @@ impl Global { vbs.stride = stride; vbs.rate = rate; } - for vbs in state.vertex.inputs[pipeline.vertex_strides.len()..].iter_mut() { + let vertex_strides_len = pipeline.vertex_strides.len(); + for vbs in state.vertex.inputs.iter_mut().skip(vertex_strides_len) { vbs.stride = 0; vbs.rate = InputStepMode::Vertex; } @@ -1017,6 +1013,11 @@ impl Global { .use_extend(&*buffer_guard, buffer_id, (), BufferUsage::VERTEX) .unwrap(); assert!(buffer.usage.contains(BufferUsage::VERTEX)); + let empty_slots = (1 + slot as usize).saturating_sub(state.vertex.inputs.len()); + state + .vertex + .inputs + .extend(iter::repeat(VertexBufferState::EMPTY).take(empty_slots)); state.vertex.inputs[slot as usize].total_size = if size != 0 { size } else { @@ -1158,6 +1159,10 @@ impl Global { } } + log::trace!("Merging {:?} with the render pass", encoder_id); + unsafe { + raw.end_render_pass(); + } super::CommandBuffer::insert_barriers( cmb.raw.last_mut().unwrap(), &mut cmb.trackers, @@ -1167,7 +1172,6 @@ impl Global { ); unsafe { cmb.raw.last_mut().unwrap().finish(); - raw.end_render_pass(); } cmb.raw.push(raw); } diff --git a/gfx/wgpu/wgpu-core/src/device/mod.rs b/gfx/wgpu/wgpu-core/src/device/mod.rs index 2091b521b4f2..e04c8395b4f6 100644 --- a/gfx/wgpu/wgpu-core/src/device/mod.rs +++ b/gfx/wgpu/wgpu-core/src/device/mod.rs @@ -34,7 +34,7 @@ mod life; pub const MAX_COLOR_TARGETS: usize = 4; pub const MAX_MIP_LEVELS: usize = 16; -pub const MAX_VERTEX_BUFFERS: usize = 8; +pub const MAX_VERTEX_BUFFERS: usize = 16; pub fn all_buffer_stages() -> hal::pso::PipelineStage { use hal::pso::PipelineStage as Ps; @@ -1044,7 +1044,7 @@ impl Global { let (bind_group_layout_guard, mut token) = hub.bind_group_layouts.read(&mut token); let bind_group_layout = &bind_group_layout_guard[desc.layout]; let entries = unsafe { slice::from_raw_parts(desc.entries, desc.entries_length) }; - assert_eq!(entries.len(), bind_group_layout.entries.len()); + assert_eq!(entries.len(), bind_group_layout.entries.len(), "Bind group has {} entries and bind group layout has {} entries, they should be the same.", entries.len(), bind_group_layout.entries.len()); let desc_set = unsafe { let mut desc_sets = ArrayVec::<[_; 1]>::new(); @@ -1503,6 +1503,8 @@ impl Global { // execute resource transitions let mut transit = device.com_allocator.extend(comb); unsafe { + // the last buffer was open, closing now + comb.raw.last_mut().unwrap().finish(); transit.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT); } log::trace!("Stitching command buffer {:?} before submission", cmb_id); @@ -1517,9 +1519,6 @@ impl Global { transit.finish(); } comb.raw.insert(0, transit); - unsafe { - comb.raw.last_mut().unwrap().finish(); - } } log::debug!("Device after submission {}: {:#?}", submit_index, trackers); diff --git a/gfx/wgpu/wgpu-core/src/id.rs b/gfx/wgpu/wgpu-core/src/id.rs index 897829e56da9..f50477cbebf2 100644 --- a/gfx/wgpu/wgpu-core/src/id.rs +++ b/gfx/wgpu/wgpu-core/src/id.rs @@ -23,7 +23,13 @@ pub struct Id(NonZeroU64, PhantomData); // required for PeekPoke impl Default for Id { fn default() -> Self { - Id(unsafe { NonZeroU64::new_unchecked(!0) }, PhantomData) + Id( + // Create an ID that doesn't make sense: + // the high `BACKEND_BITS` are to be set to 0, which matches `Backend::Empty`, + // the other bits are all 1s + unsafe { NonZeroU64::new_unchecked(!0 >> BACKEND_BITS) }, + PhantomData, + ) } } diff --git a/gfx/wgpu/wgpu-core/src/track/buffer.rs b/gfx/wgpu/wgpu-core/src/track/buffer.rs index fb882c3c6836..fbeb3d640e48 100644 --- a/gfx/wgpu/wgpu-core/src/track/buffer.rs +++ b/gfx/wgpu/wgpu-core/src/track/buffer.rs @@ -55,22 +55,28 @@ impl ResourceState for BufferState { output: Option<&mut Vec>>, ) -> Result<(), PendingTransition> { let old = self.last; - if usage != old || !BufferUsage::ORDERED.contains(usage) { + if old != usage || !BufferUsage::ORDERED.contains(usage) { let pending = PendingTransition { id, selector: (), usage: old..usage, }; - self.last = match output { - None => pending.collapse()?, + *self = match output { + None => { + assert_eq!( + self.first, None, + "extending a state that is already a transition" + ); + Unit::new(pending.collapse()?) + } Some(transitions) => { transitions.push(pending); - if self.first.is_none() { - self.first = Some(old); + Unit { + first: self.first.or(Some(old)), + last: usage, } - usage } - } + }; } Ok(()) } @@ -83,28 +89,33 @@ impl ResourceState for BufferState { ) -> Result<(), PendingTransition> { let old = self.last; let new = other.port(); - self.last = if old == new && BufferUsage::ORDERED.contains(new) { - if self.first.is_none() { + if old == new && BufferUsage::ORDERED.contains(new) { + if output.is_some() && self.first.is_none() { self.first = Some(old); } - other.last } else { let pending = PendingTransition { id, selector: (), usage: old..new, }; - match output { - None => pending.collapse()?, + *self = match output { + None => { + assert_eq!( + self.first, None, + "extending a state that is already a transition" + ); + Unit::new(pending.collapse()?) + } Some(transitions) => { transitions.push(pending); - if self.first.is_none() { - self.first = Some(old); + Unit { + first: self.first.or(Some(old)), + last: other.last, } - other.last } - } - }; + }; + } Ok(()) } @@ -114,19 +125,71 @@ impl ResourceState for BufferState { #[cfg(test)] mod test { use super::*; - use crate::id::TypedId; + use crate::id::Id; #[test] - fn change() { + fn change_extend() { let mut bs = Unit { - first: Some(BufferUsage::INDEX), + first: None, + last: BufferUsage::INDEX, + }; + let id = Id::default(); + assert_eq!( + bs.change(id, (), BufferUsage::STORAGE, None), + Err(PendingTransition { + id, + selector: (), + usage: BufferUsage::INDEX..BufferUsage::STORAGE, + }), + ); + bs.change(id, (), BufferUsage::VERTEX, None).unwrap(); + bs.change(id, (), BufferUsage::INDEX, None).unwrap(); + assert_eq!(bs, Unit::new(BufferUsage::VERTEX | BufferUsage::INDEX)); + } + + #[test] + fn change_replace() { + let mut bs = Unit { + first: None, last: BufferUsage::STORAGE, }; - let id = TypedId::zip(1, 0, wgt::Backend::Empty); - assert!(bs.change(id, (), BufferUsage::VERTEX, None).is_err()); - bs.change(id, (), BufferUsage::VERTEX, Some(&mut Vec::new())) + let id = Id::default(); + let mut list = Vec::new(); + bs.change(id, (), BufferUsage::VERTEX, Some(&mut list)) .unwrap(); - bs.change(id, (), BufferUsage::INDEX, None).unwrap(); - assert_eq!(bs.last, BufferUsage::VERTEX | BufferUsage::INDEX); + assert_eq!( + &list, + &[PendingTransition { + id, + selector: (), + usage: BufferUsage::STORAGE..BufferUsage::VERTEX, + }], + ); + assert_eq!( + bs, + Unit { + first: Some(BufferUsage::STORAGE), + last: BufferUsage::VERTEX, + } + ); + + list.clear(); + bs.change(id, (), BufferUsage::STORAGE, Some(&mut list)) + .unwrap(); + assert_eq!( + &list, + &[PendingTransition { + id, + selector: (), + usage: BufferUsage::VERTEX..BufferUsage::STORAGE, + }], + ); + assert_eq!( + bs, + Unit { + first: Some(BufferUsage::STORAGE), + last: BufferUsage::STORAGE, + } + ); } } diff --git a/gfx/wgpu/wgpu-core/src/track/mod.rs b/gfx/wgpu/wgpu-core/src/track/mod.rs index 1faefeb4c797..576a3d1f1201 100644 --- a/gfx/wgpu/wgpu-core/src/track/mod.rs +++ b/gfx/wgpu/wgpu-core/src/track/mod.rs @@ -111,7 +111,7 @@ struct Resource { /// A structure containing all the information about a particular resource /// transition. User code should be able to generate a pipeline barrier /// based on the contents. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct PendingTransition { pub id: S::Id, pub selector: S::Selector, diff --git a/gfx/wgpu/wgpu-core/src/track/range.rs b/gfx/wgpu/wgpu-core/src/track/range.rs index 0aa9a3602ac1..13376d97b005 100644 --- a/gfx/wgpu/wgpu-core/src/track/range.rs +++ b/gfx/wgpu/wgpu-core/src/track/range.rs @@ -9,7 +9,7 @@ use std::{cmp::Ordering, fmt::Debug, iter, ops::Range, slice::Iter}; /// Structure that keeps track of a I -> T mapping, /// optimized for a case where keys of the same values /// are often grouped together linearly. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct RangedStates { /// List of ranges, each associated with a singe value. /// Ranges of keys have to be non-intersecting and ordered. diff --git a/gfx/wgpu/wgpu-core/src/track/texture.rs b/gfx/wgpu/wgpu-core/src/track/texture.rs index d5010a82913c..d37ac6bb59d2 100644 --- a/gfx/wgpu/wgpu-core/src/track/texture.rs +++ b/gfx/wgpu/wgpu-core/src/track/texture.rs @@ -13,7 +13,7 @@ use std::{iter, ops::Range}; //TODO: store `hal::image::State` here to avoid extra conversions type PlaneStates = RangedStates>; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct TextureState { mips: ArrayVec<[PlaneStates; MAX_MIP_LEVELS]>, /// True if we have the information about all the subresources here @@ -116,14 +116,20 @@ impl ResourceState for TextureState { usage: unit.last..usage, }; - unit.last = match output { - None => pending.collapse()?, + *unit = match output { + None => { + assert_eq!( + unit.first, None, + "extending a state that is already a transition" + ); + Unit::new(pending.collapse()?) + } Some(ref mut out) => { out.push(pending); - if unit.first.is_none() { - unit.first = Some(unit.last); + Unit { + first: unit.first.or(Some(unit.last)), + last: usage, } - usage } }; } @@ -172,7 +178,10 @@ impl ResourceState for TextureState { let to_usage = end.port(); if start.last == to_usage && TextureUsage::ORDERED.contains(to_usage) { Unit { - first: start.first, + first: match output { + None => start.first, + Some(_) => start.first.or(Some(start.last)), + }, last: end.last, } } else { @@ -191,14 +200,18 @@ impl ResourceState for TextureState { }; match output { - None => Unit { - first: start.first, - last: pending.collapse()?, - }, + None => { + assert_eq!( + start.first, None, + "extending a state that is already a transition" + ); + Unit::new(pending.collapse()?) + } Some(ref mut out) => { out.push(pending); Unit { - first: Some(start.last), + // this has to leave a valid `first` state + first: start.first.or(Some(start.last)), last: end.last, } } @@ -222,9 +235,9 @@ impl ResourceState for TextureState { #[cfg(test)] mod test { - //TODO: change() and merge() tests - //use crate::TypedId; + //TODO: change() tests use super::*; + use crate::id::Id; use hal::{format::Aspects, image::SubresourceRange}; #[test] @@ -274,4 +287,151 @@ mod test { None, ); } + + #[test] + fn merge() { + let id = Id::default(); + let mut ts1 = TextureState::default(); + ts1.mips.push(PlaneStates::from_slice(&[( + 1..3, + Unit::new(TextureUsage::SAMPLED), + )])); + let mut ts2 = TextureState::default(); + assert_eq!( + ts1.merge(id, &ts2, None), + Ok(()), + "failed to merge with an empty" + ); + + ts2.mips.push(PlaneStates::from_slice(&[( + 1..2, + Unit::new(TextureUsage::COPY_SRC), + )])); + assert_eq!( + ts1.merge(Id::default(), &ts2, None), + Ok(()), + "failed to extend a compatible state" + ); + assert_eq!( + ts1.mips[0].query(&(1..2), |&v| v), + Some(Ok(Unit { + first: None, + last: TextureUsage::SAMPLED | TextureUsage::COPY_SRC, + })), + "wrong extension result" + ); + + ts2.mips[0] = PlaneStates::from_slice(&[(1..2, Unit::new(TextureUsage::COPY_DST))]); + assert_eq!( + ts1.clone().merge(Id::default(), &ts2, None), + Err(PendingTransition { + id, + selector: SubresourceRange { + aspects: Aspects::empty(), + levels: 0..1, + layers: 1..2, + }, + usage: TextureUsage::SAMPLED | TextureUsage::COPY_SRC..TextureUsage::COPY_DST, + }), + "wrong error on extending with incompatible state" + ); + + let mut list = Vec::new(); + ts2.mips[0] = PlaneStates::from_slice(&[ + (1..2, Unit::new(TextureUsage::COPY_DST)), + ( + 2..3, + Unit { + first: Some(TextureUsage::COPY_SRC), + last: TextureUsage::OUTPUT_ATTACHMENT, + }, + ), + ]); + ts1.merge(Id::default(), &ts2, Some(&mut list)).unwrap(); + assert_eq!( + &list, + &[ + PendingTransition { + id, + selector: SubresourceRange { + aspects: Aspects::empty(), + levels: 0..1, + layers: 1..2, + }, + usage: TextureUsage::SAMPLED | TextureUsage::COPY_SRC..TextureUsage::COPY_DST, + }, + PendingTransition { + id, + selector: SubresourceRange { + aspects: Aspects::empty(), + levels: 0..1, + layers: 2..3, + }, + // the transition links the end of the base rage (..SAMPLED) + // with the start of the next range (COPY_SRC..) + usage: TextureUsage::SAMPLED..TextureUsage::COPY_SRC, + }, + ], + "replacing produced wrong transitions" + ); + assert_eq!( + ts1.mips[0].query(&(1..2), |&v| v), + Some(Ok(Unit { + first: Some(TextureUsage::SAMPLED | TextureUsage::COPY_SRC), + last: TextureUsage::COPY_DST, + })), + "wrong final layer 1 state" + ); + assert_eq!( + ts1.mips[0].query(&(2..3), |&v| v), + Some(Ok(Unit { + first: Some(TextureUsage::SAMPLED), + last: TextureUsage::OUTPUT_ATTACHMENT, + })), + "wrong final layer 2 state" + ); + + list.clear(); + ts2.mips[0] = PlaneStates::from_slice(&[( + 2..3, + Unit { + first: Some(TextureUsage::OUTPUT_ATTACHMENT), + last: TextureUsage::COPY_SRC, + }, + )]); + ts1.merge(Id::default(), &ts2, Some(&mut list)).unwrap(); + assert_eq!(&list, &[], "unexpected replacing transition"); + + list.clear(); + ts2.mips[0] = PlaneStates::from_slice(&[( + 2..3, + Unit { + first: Some(TextureUsage::COPY_DST), + last: TextureUsage::COPY_DST, + }, + )]); + ts1.merge(Id::default(), &ts2, Some(&mut list)).unwrap(); + assert_eq!( + &list, + &[PendingTransition { + id, + selector: SubresourceRange { + aspects: Aspects::empty(), + levels: 0..1, + layers: 2..3, + }, + usage: TextureUsage::COPY_SRC..TextureUsage::COPY_DST, + },], + "invalid replacing transition" + ); + assert_eq!( + ts1.mips[0].query(&(2..3), |&v| v), + Some(Ok(Unit { + // the initial state here is never expected to change + first: Some(TextureUsage::SAMPLED), + last: TextureUsage::COPY_DST, + })), + "wrong final layer 2 state" + ); + } } diff --git a/gfx/wgpu/wgpu-native/Cargo.toml b/gfx/wgpu/wgpu-native/Cargo.toml index 28a216755797..273999a6d7b7 100644 --- a/gfx/wgpu/wgpu-native/Cargo.toml +++ b/gfx/wgpu/wgpu-native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-native" -version = "0.4.0" +version = "0.5.0" authors = [ "Dzmitry Malyshau ", "Joshua Groves ", @@ -23,12 +23,12 @@ vulkan-portability = ["core/gfx-backend-vulkan"] [dependencies.core] path = "../wgpu-core" package = "wgpu-core" -version = "0.1" +version = "0.5" [dependencies.wgt] path = "../wgpu-types" package = "wgpu-types" -version = "0.1" +version = "0.5" [dependencies] arrayvec = "0.5" diff --git a/gfx/wgpu/wgpu-remote/Cargo.toml b/gfx/wgpu/wgpu-remote/Cargo.toml index 891a06834e28..87cabad1c081 100644 --- a/gfx/wgpu/wgpu-remote/Cargo.toml +++ b/gfx/wgpu/wgpu-remote/Cargo.toml @@ -7,6 +7,7 @@ authors = [ ] edition = "2018" license = "MPL-2.0" +publish = false [lib] # Enabling these targets makes our CI bots try to build them and fail atm @@ -18,13 +19,13 @@ default = [] [dependencies.core] path = "../wgpu-core" package = "wgpu-core" -version = "0.1" +version = "0.5" features = ["serde"] [dependencies.wgt] path = "../wgpu-types" package = "wgpu-types" -version = "0.1" +version = "0.5" features = ["serde"] [dependencies] diff --git a/gfx/wgpu/wgpu-types/Cargo.toml b/gfx/wgpu/wgpu-types/Cargo.toml index 2c485c7f5add..616e7e5e036d 100644 --- a/gfx/wgpu/wgpu-types/Cargo.toml +++ b/gfx/wgpu/wgpu-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-types" -version = "0.1.0" +version = "0.5.0" authors = [ "Dzmitry Malyshau ", "Joshua Groves ",