From 199e7e5f3b3c89d76d8df7fd83c03dcdbb4bc489 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 15:18:48 -0500 Subject: [PATCH 1/6] Trace pipeline creation before it actually happens --- wgpu-core/src/device/mod.rs | 60 ++++++++++++++----------------------- wgpu-core/src/hub.rs | 50 +++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index f7d032f92e..e79a76ee27 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -4018,40 +4018,32 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.render_pipelines.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(device_id) { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - let (pipeline, derived_bind_group_count, layout_id) = match device + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateRenderPipeline(fid.id(), desc.clone())); + } + + let (pipeline, derived_bind_group_count, _layout_id) = match device .create_render_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token) { Ok(pair) => pair, Err(e) => break e, }; - let id = hub - .render_pipelines - .register_identity(id_in, pipeline, &mut token); - - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace.lock().add(trace::Action::CreateRenderPipeline( - id.0, - pipeline::RenderPipelineDescriptor { - layout: Some(layout_id), - ..desc.clone() - }, - )); - } - let _ = layout_id; + let id = fid.assign(pipeline, &mut token); return (id.0, derived_bind_group_count, None); }; - let id = - hub.render_pipelines - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, 0, Some(error)) } @@ -4149,40 +4141,32 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.compute_pipelines.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(device_id) { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - let (pipeline, derived_bind_group_count, layout_id) = match device + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateComputePipeline(fid.id(), desc.clone())); + } + + let (pipeline, derived_bind_group_count, _layout_id) = match device .create_compute_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token) { Ok(pair) => pair, Err(e) => break e, }; - let id = hub - .compute_pipelines - .register_identity(id_in, pipeline, &mut token); - - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace.lock().add(trace::Action::CreateComputePipeline( - id.0, - pipeline::ComputePipelineDescriptor { - layout: Some(layout_id), - ..desc.clone() - }, - )); - } - let _ = layout_id; + let id = fid.assign(pipeline, &mut token); return (id.0, derived_bind_group_count, None); }; - let id = - hub.compute_pipelines - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, 0, Some(error)) } diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index a25f7f7889..0760c6640f 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -439,10 +439,37 @@ impl> Registry { } } +#[must_use] +pub(crate) struct FutureId<'a, I: TypedId, T> { + id: I, + data: &'a RwLock>, +} + +impl FutureId<'_, I, T> { + pub fn id(&self) -> I { + self.id + } + + pub fn assign<'a, A: Access>(self, value: T, _: &'a mut Token) -> Valid { + self.data.write().insert(self.id, value); + Valid(self.id) + } + + pub fn assign_error<'a, A: Access>(self, label: &str, _: &'a mut Token) -> I { + self.data.write().insert_error(self.id, label); + self.id + } +} + impl> Registry { - pub fn register>(&self, id: I, value: T, _token: &mut Token) { - debug_assert_eq!(id.unzip().2, self.backend); - self.data.write().insert(id, value); + pub(crate) fn prepare( + &self, + id_in: >::Input, + ) -> FutureId { + FutureId { + id: self.identity.process(id_in, self.backend), + data: &self.data, + } } pub fn read<'a, A: Access>( @@ -459,15 +486,14 @@ impl> Registry>( &self, id_in: >::Input, value: T, token: &mut Token, ) -> Valid { - let id = self.identity.process(id_in, self.backend); - self.register(id, value, token); - Valid(id) + self.prepare(id_in).assign(value, token) } pub(crate) fn register_identity_locked( @@ -481,16 +507,14 @@ impl> Registry>( &self, id_in: >::Input, label: &str, - _token: &mut Token, + token: &mut Token, ) -> I { - let id = self.identity.process(id_in, self.backend); - debug_assert_eq!(id.unzip().2, self.backend); - self.data.write().insert_error(id, label); - id + self.prepare(id_in).assign_error(label, token) } pub fn unregister_locked(&self, id: I, guard: &mut Storage) -> Option { @@ -513,10 +537,6 @@ impl> Registry>::Input) -> I { - self.identity.process(id_in, self.backend) - } - pub fn free_id(&self, id: I) { self.identity.free(id) } From f7e1304c38b1af49afec63c3035e2a8335bd7722 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 15:43:55 -0500 Subject: [PATCH 2/6] Expose CA surface creation --- wgpu-core/src/hub.rs | 11 ++++++----- wgpu-core/src/instance.rs | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 0760c6640f..bdd461a7d0 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -302,7 +302,7 @@ thread_local! { /// /// Note: there can only be one non-borrowed `Token` alive on a thread /// at a time, which is enforced by `ACTIVE_TOKEN`. -pub struct Token<'a, T: 'a> { +pub(crate) struct Token<'a, T: 'a> { level: PhantomData<&'a T>, } @@ -446,6 +446,7 @@ pub(crate) struct FutureId<'a, I: TypedId, T> { } impl FutureId<'_, I, T> { + #[cfg(feature = "trace")] pub fn id(&self) -> I { self.id } @@ -472,14 +473,14 @@ impl> Registry>( + pub(crate) fn read<'a, A: Access>( &'a self, _token: &'a mut Token, ) -> (RwLockReadGuard<'a, Storage>, Token<'a, T>) { (self.data.read(), Token::new()) } - pub fn write<'a, A: Access>( + pub(crate) fn write<'a, A: Access>( &'a self, _token: &'a mut Token, ) -> (RwLockWriteGuard<'a, Storage>, Token<'a, T>) { @@ -508,7 +509,7 @@ impl> Registry>( + pub(crate) fn register_error>( &self, id_in: >::Input, label: &str, @@ -525,7 +526,7 @@ impl> Registry>( + pub(crate) fn unregister<'a, A: Access>( &self, id: I, _token: &'a mut Token, diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 229eb5bdb4..4379525ef5 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -631,6 +631,28 @@ impl Global { id.0 } + #[cfg(metal)] + pub fn instance_create_surface_metal( + &self, + layer: *mut std::ffi::c_void, + id_in: Input, + ) -> SurfaceId { + span!(_guard, INFO, "Instance::instance_create_surface_metal"); + + let surface = + Surface { + #[cfg(feature = "vulkan-portability")] + vulkan: None, //TODO: create_surface_from_layer ? + metal: self.instance.metal.as_ref().map(|inst| { + inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) }) + }), + }; + + let mut token = Token::root(); + let id = self.surfaces.register_identity(id_in, surface, &mut token); + id.0 + } + pub fn surface_drop(&self, id: SurfaceId) { span!(_guard, INFO, "Surface::drop"); let mut token = Token::root(); From 7c1db12cdcccd4819ec690572c0dff6c9a2f7ff3 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 16:48:23 -0500 Subject: [PATCH 3/6] Refactor implicit BGLs to support early tracing --- Cargo.lock | 1 - player/src/lib.rs | 30 ++- player/tests/data/bind-group.ron | 17 +- player/tests/data/buffer-zero-init.ron | 337 +++++++++++++------------ player/tests/data/quad.ron | 45 ++-- wgpu-core/Cargo.toml | 4 +- wgpu-core/src/device/mod.rs | 136 +++++----- wgpu-core/src/device/trace.rs | 20 +- wgpu-core/src/hub.rs | 15 +- 9 files changed, 310 insertions(+), 295 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44585a39cf..cd794e9d38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -956,7 +956,6 @@ dependencies = [ "log", "num-traits", "petgraph", - "serde", "spirv_headers", "thiserror", ] diff --git a/player/src/lib.rs b/player/src/lib.rs index 9d416993c7..dfb956b39a 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -254,10 +254,21 @@ impl GlobalPlay for wgc::hub::Global { A::DestroyShaderModule(id) => { self.shader_module_drop::(id); } - A::CreateComputePipeline(id, desc) => { + A::CreateComputePipeline { + id, + desc, + implicit_context, + } => { self.device_maintain_ids::(device).unwrap(); + let implicit_ids = + implicit_context + .as_ref() + .map(|ic| wgc::device::ImplicitPipelineIds { + root_id: ic.root_id, + group_ids: &ic.group_ids, + }); let (_, _, error) = - self.device_create_compute_pipeline::(device, &desc, id, None); + self.device_create_compute_pipeline::(device, &desc, id, implicit_ids); if let Some(e) = error { panic!("{:?}", e); } @@ -265,10 +276,21 @@ impl GlobalPlay for wgc::hub::Global { A::DestroyComputePipeline(id) => { self.compute_pipeline_drop::(id); } - A::CreateRenderPipeline(id, desc) => { + A::CreateRenderPipeline { + id, + desc, + implicit_context, + } => { self.device_maintain_ids::(device).unwrap(); + let implicit_ids = + implicit_context + .as_ref() + .map(|ic| wgc::device::ImplicitPipelineIds { + root_id: ic.root_id, + group_ids: &ic.group_ids, + }); let (_, _, error) = - self.device_create_render_pipeline::(device, &desc, id, None); + self.device_create_render_pipeline::(device, &desc, id, implicit_ids); if let Some(e) = error { panic!("{:?}", e); } diff --git a/player/tests/data/bind-group.ron b/player/tests/data/bind-group.ron index 06a95aec75..f47b75d477 100644 --- a/player/tests/data/bind-group.ron +++ b/player/tests/data/bind-group.ron @@ -15,14 +15,17 @@ ), data: "empty.wgsl", ), - CreateComputePipeline(Id(0, 1, Empty), ( - label: None, - layout: Some(Id(0, 1, Empty)), - stage: ( - module: Id(0, 1, Empty), - entry_point: "main", + CreateComputePipeline( + id: Id(0, 1, Empty), + desc: ( + label: None, + layout: Some(Id(0, 1, Empty)), + stage: ( + module: Id(0, 1, Empty), + entry_point: "main", + ), ), - )), + ), CreateBuffer(Id(0, 1, Empty), ( label: None, size: 16, diff --git a/player/tests/data/buffer-zero-init.ron b/player/tests/data/buffer-zero-init.ron index 1be2f294ff..b415a81c9a 100644 --- a/player/tests/data/buffer-zero-init.ron +++ b/player/tests/data/buffer-zero-init.ron @@ -1,167 +1,170 @@ -( - features: (bits: 0x0), - expectations: [ - // Ensuring that mapping zero-inits buffers. - ( - name: "mapped_at_creation: false, with MAP_WRITE", - buffer: (index: 0, epoch: 1), - offset: 0, - data: Raw([0x00, 0x00, 0x00, 0x00]), - ), - ( - name: "mapped_at_creation: false, without MAP_WRITE", - buffer: (index: 1, epoch: 1), - offset: 0, - data: Raw([0x00, 0x00, 0x00, 0x00]), - ), - ( - name: "partially written buffer", - buffer: (index: 2, epoch: 1), - offset: 0, - data: Raw([0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xBF, - 0x00, 0x00, 0x80, 0xBF, - 0x00, 0x00, 0x80, 0x3F, - 0x00, 0x00, 0x80, 0x3F, - 0x00, 0x00, 0x00, 0x00]), - ), - // Ensuring that binding zero-inits buffers - // (by observing correct side effects of compute shader reading & writing values) - ( - name: "buffer has correct values", - buffer: (index: 3, epoch: 1), - offset: 0, - data: Raw([0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00]), - ) - ], - actions: [ - CreateBuffer( - Id(0, 1, Empty), - ( - label: Some("mapped_at_creation: false, with MAP_WRITE"), - size: 16, - usage: ( - bits: 131, // STORAGE + MAP_READ + MAP_WRITE - ), - mapped_at_creation: false, - ), - ), - CreateBuffer( - Id(1, 1, Empty), - ( - label: Some("mapped_at_creation: false, without MAP_WRITE"), - size: 16, - usage: ( - bits: 129, // STORAGE + MAP_READ - ), - mapped_at_creation: false, - ), - ), - CreateBuffer( - Id(2, 1, Empty), - ( - label: Some("partially written"), - size: 24, - usage: ( - bits: 9, // MAP_READ + COPY_DST - ), - mapped_at_creation: false, - ), - ), - WriteBuffer( - id: Id(2, 1, Empty), - data: "data1.bin", - range: ( - start: 4, - end: 20, - ), - queued: true, - ), - CreateShaderModule( - id: Id(0, 1, Empty), - desc: ( - label: None, - flags: (bits: 3), - ), - data: "buffer-zero-init-for-binding.wgsl", - ), - CreateBuffer(Id(3, 1, Empty), ( - label: Some("used in binding"), - size: 16, - usage: ( - bits: 129, // STORAGE + MAP_READ - ), - mapped_at_creation: false, - )), - CreateBindGroupLayout(Id(0, 1, Empty), ( - label: None, - entries: [ - ( - binding: 0, - visibility: ( - bits: 4, - ), - ty: Buffer( - ty: Storage( - read_only: false, - ), - has_dynamic_offset: false, - min_binding_size: Some(16), - ), - count: None, - ), - ], - )), - CreateBindGroup(Id(0, 1, Empty), ( - label: None, - layout: Id(0, 1, Empty), - entries: [ - ( - binding: 0, - resource: Buffer(( - buffer_id: Id(3, 1, Empty), - offset: 0, - size: Some(16), - )), - ), - ], - )), - CreatePipelineLayout(Id(0, 1, Empty), ( - label: None, - bind_group_layouts: [ - Id(0, 1, Empty), - ], - push_constant_ranges: [], - )), - CreateComputePipeline(Id(0, 1, Empty), ( - label: None, - layout: Some(Id(0, 1, Empty)), - stage: ( - module: Id(0, 1, Empty), - entry_point: "main", - ), - )), - Submit(1, [ - RunComputePass( - base: ( - label: None, - commands: [ - SetPipeline(Id(0, 1, Empty)), - SetBindGroup( - index: 0, - num_dynamic_offsets: 0, - bind_group_id: Id(0, 1, Empty), - ), - Dispatch((4, 1, 1)), - ], - dynamic_offsets: [], - string_data: [], - push_constant_data: [], - ), - ) - ]), - ] -) +( + features: (bits: 0x0), + expectations: [ + // Ensuring that mapping zero-inits buffers. + ( + name: "mapped_at_creation: false, with MAP_WRITE", + buffer: (index: 0, epoch: 1), + offset: 0, + data: Raw([0x00, 0x00, 0x00, 0x00]), + ), + ( + name: "mapped_at_creation: false, without MAP_WRITE", + buffer: (index: 1, epoch: 1), + offset: 0, + data: Raw([0x00, 0x00, 0x00, 0x00]), + ), + ( + name: "partially written buffer", + buffer: (index: 2, epoch: 1), + offset: 0, + data: Raw([0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xBF, + 0x00, 0x00, 0x80, 0xBF, + 0x00, 0x00, 0x80, 0x3F, + 0x00, 0x00, 0x80, 0x3F, + 0x00, 0x00, 0x00, 0x00]), + ), + // Ensuring that binding zero-inits buffers + // (by observing correct side effects of compute shader reading & writing values) + ( + name: "buffer has correct values", + buffer: (index: 3, epoch: 1), + offset: 0, + data: Raw([0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00]), + ) + ], + actions: [ + CreateBuffer( + Id(0, 1, Empty), + ( + label: Some("mapped_at_creation: false, with MAP_WRITE"), + size: 16, + usage: ( + bits: 131, // STORAGE + MAP_READ + MAP_WRITE + ), + mapped_at_creation: false, + ), + ), + CreateBuffer( + Id(1, 1, Empty), + ( + label: Some("mapped_at_creation: false, without MAP_WRITE"), + size: 16, + usage: ( + bits: 129, // STORAGE + MAP_READ + ), + mapped_at_creation: false, + ), + ), + CreateBuffer( + Id(2, 1, Empty), + ( + label: Some("partially written"), + size: 24, + usage: ( + bits: 9, // MAP_READ + COPY_DST + ), + mapped_at_creation: false, + ), + ), + WriteBuffer( + id: Id(2, 1, Empty), + data: "data1.bin", + range: ( + start: 4, + end: 20, + ), + queued: true, + ), + CreateShaderModule( + id: Id(0, 1, Empty), + desc: ( + label: None, + flags: (bits: 3), + ), + data: "buffer-zero-init-for-binding.wgsl", + ), + CreateBuffer(Id(3, 1, Empty), ( + label: Some("used in binding"), + size: 16, + usage: ( + bits: 129, // STORAGE + MAP_READ + ), + mapped_at_creation: false, + )), + CreateBindGroupLayout(Id(0, 1, Empty), ( + label: None, + entries: [ + ( + binding: 0, + visibility: ( + bits: 4, + ), + ty: Buffer( + ty: Storage( + read_only: false, + ), + has_dynamic_offset: false, + min_binding_size: Some(16), + ), + count: None, + ), + ], + )), + CreateBindGroup(Id(0, 1, Empty), ( + label: None, + layout: Id(0, 1, Empty), + entries: [ + ( + binding: 0, + resource: Buffer(( + buffer_id: Id(3, 1, Empty), + offset: 0, + size: Some(16), + )), + ), + ], + )), + CreatePipelineLayout(Id(0, 1, Empty), ( + label: None, + bind_group_layouts: [ + Id(0, 1, Empty), + ], + push_constant_ranges: [], + )), + CreateComputePipeline( + id: Id(0, 1, Empty), + desc: ( + label: None, + layout: Some(Id(0, 1, Empty)), + stage: ( + module: Id(0, 1, Empty), + entry_point: "main", + ), + ), + ), + Submit(1, [ + RunComputePass( + base: ( + label: None, + commands: [ + SetPipeline(Id(0, 1, Empty)), + SetBindGroup( + index: 0, + num_dynamic_offsets: 0, + bind_group_id: Id(0, 1, Empty), + ), + Dispatch((4, 1, 1)), + ], + dynamic_offsets: [], + string_data: [], + push_constant_data: [], + ), + ) + ]), + ] +) diff --git a/player/tests/data/quad.ron b/player/tests/data/quad.ron index e004d52e72..c6f690a8cc 100644 --- a/player/tests/data/quad.ron +++ b/player/tests/data/quad.ron @@ -53,28 +53,31 @@ bind_group_layouts: [], push_constant_ranges: [], )), - CreateRenderPipeline(Id(0, 1, Empty), ( - label: None, - layout: Some(Id(0, 1, Empty)), - vertex: ( - stage: ( - module: Id(0, 1, Empty), - entry_point: "vs_main", - ), - buffers: [], - ), - fragment: Some(( - stage: ( - module: Id(0, 1, Empty), - entry_point: "fs_main", - ), - targets: [ - ( - format: Rgba8Unorm, + CreateRenderPipeline( + id: Id(0, 1, Empty), + desc: ( + label: None, + layout: Some(Id(0, 1, Empty)), + vertex: ( + stage: ( + module: Id(0, 1, Empty), + entry_point: "vs_main", ), - ], - )), - )), + buffers: [], + ), + fragment: Some(( + stage: ( + module: Id(0, 1, Empty), + entry_point: "fs_main", + ), + targets: [ + ( + format: Rgba8Unorm, + ), + ], + )), + ), + ), Submit(1, [ RunRenderPass( base: ( diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 30317ddf3a..ccb178092c 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -16,9 +16,9 @@ default = [] # Enable SPIRV-Cross cross = ["gfx-backend-metal/cross", "gfx-backend-gl/cross"] # Enable API tracing -trace = ["ron", "serde", "wgt/trace", "naga/serialize"] +trace = ["ron", "serde", "wgt/trace", "arrayvec/serde"] # Enable API replaying -replay = ["serde", "wgt/replay", "naga/deserialize"] +replay = ["serde", "wgt/replay", "arrayvec/serde"] # Enable serializable compute/render passes, and bundle encoders. serial-pass = ["serde", "wgt/serde", "arrayvec/serde"] diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index e79a76ee27..44f57d4cff 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -49,8 +49,6 @@ pub mod queue; pub mod trace; use smallvec::SmallVec; -#[cfg(feature = "trace")] -use trace::{Action, Trace}; pub const MAX_COLOR_TARGETS: usize = 4; pub const MAX_MIP_LEVELS: u32 = 16; @@ -290,7 +288,7 @@ pub struct Device { // to borrow Device immutably, such as `write_buffer`, `write_texture`, and `buffer_unmap`. pending_writes: queue::PendingWrites, #[cfg(feature = "trace")] - pub(crate) trace: Option>, + pub(crate) trace: Option>, } #[derive(Clone, Debug, Error)] @@ -359,9 +357,9 @@ impl Device { life_tracker: Mutex::new(life::LifetimeTracker::new()), temp_suspected: life::SuspectedResources::default(), #[cfg(feature = "trace")] - trace: trace_path.and_then(|path| match Trace::new(path) { + trace: trace_path.and_then(|path| match trace::Trace::new(path) { Ok(mut trace) => { - trace.add(Action::Init { + trace.add(trace::Action::Init { desc: desc.clone(), backend: B::VARIANT, }); @@ -1787,14 +1785,13 @@ impl Device { //TODO: refactor this. It's the only method of `Device` that registers new objects // (the pipeline layout). - fn derive_pipeline_layout( + fn derive_pipeline_layout( &self, self_id: id::DeviceId, - implicit_pipeline_ids: Option>, + implicit_context: Option, mut derived_group_layouts: ArrayVec<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>, bgl_guard: &mut Storage, id::BindGroupLayoutId>, pipeline_layout_guard: &mut Storage, id::PipelineLayoutId>, - hub: &Hub, ) -> Result< (id::PipelineLayoutId, pipeline::ImplicitBindGroupCount), pipeline::ImplicitLayoutError, @@ -1808,10 +1805,9 @@ impl Device { { derived_group_layouts.pop(); } - let ids = implicit_pipeline_ids - .as_ref() - .ok_or(pipeline::ImplicitLayoutError::MissingIds(0))?; - if ids.group_ids.len() < derived_group_layouts.len() { + let mut ids = implicit_context.ok_or(pipeline::ImplicitLayoutError::MissingIds(0))?; + let group_count = derived_group_layouts.len(); + if ids.group_ids.len() < group_count { tracing::error!( "Not enough bind group IDs ({}) specified for the implicit layout ({})", ids.group_ids.len(), @@ -1822,66 +1818,33 @@ impl Device { )); } - let mut derived_group_layout_ids = - ArrayVec::<[id::BindGroupLayoutId; MAX_BIND_GROUPS]>::new(); - for (bgl_id, map) in ids.group_ids.iter().zip(derived_group_layouts) { - let processed_id = match Device::deduplicate_bind_group_layout(self_id, &map, bgl_guard) - { - Some(dedup_id) => dedup_id, + for (bgl_id, map) in ids.group_ids.iter_mut().zip(derived_group_layouts) { + match Device::deduplicate_bind_group_layout(self_id, &map, bgl_guard) { + Some(dedup_id) => { + *bgl_id = dedup_id; + } None => { - #[cfg(feature = "trace")] - let bgl_desc = binding_model::BindGroupLayoutDescriptor { - label: None, - entries: if self.trace.is_some() { - Cow::Owned(map.values().cloned().collect()) - } else { - Cow::Borrowed(&[]) - }, - }; let bgl = self.create_bind_group_layout(self_id, None, map)?; - let out_id = hub.bind_group_layouts.register_identity_locked( - bgl_id.clone(), - bgl, - bgl_guard, - ); - #[cfg(feature = "trace")] - if let Some(ref trace) = self.trace { - trace - .lock() - .add(trace::Action::CreateBindGroupLayout(out_id.0, bgl_desc)); - } - out_id.0 + bgl_guard.insert(*bgl_id, bgl); } }; - derived_group_layout_ids.push(processed_id); } let layout_desc = binding_model::PipelineLayoutDescriptor { label: None, - bind_group_layouts: Cow::Borrowed(&derived_group_layout_ids), + bind_group_layouts: Cow::Borrowed(&ids.group_ids[..group_count]), push_constant_ranges: Cow::Borrowed(&[]), //TODO? }; let layout = self.create_pipeline_layout(self_id, &layout_desc, bgl_guard)?; - let layout_id = hub.pipeline_layouts.register_identity_locked( - ids.root_id.clone(), - layout, - pipeline_layout_guard, - ); - #[cfg(feature = "trace")] - if let Some(ref trace) = self.trace { - trace.lock().add(trace::Action::CreatePipelineLayout( - layout_id.0, - layout_desc, - )); - } - Ok((layout_id.0, derived_bind_group_count)) + pipeline_layout_guard.insert(ids.root_id, layout); + Ok((ids.root_id, derived_bind_group_count)) } fn create_compute_pipeline( &self, self_id: id::DeviceId, desc: &pipeline::ComputePipelineDescriptor, - implicit_pipeline_ids: Option>, + implicit_context: Option, hub: &Hub, token: &mut Token, ) -> Result< @@ -1951,11 +1914,10 @@ impl Device { Some(id) => (id, 0), None => self.derive_pipeline_layout( self_id, - implicit_pipeline_ids, + implicit_context, derived_group_layouts, &mut *bgl_guard, &mut *pipeline_layout_guard, - &hub, )?, }; let layout = pipeline_layout_guard @@ -1999,7 +1961,7 @@ impl Device { &self, self_id: id::DeviceId, desc: &pipeline::RenderPipelineDescriptor, - implicit_pipeline_ids: Option>, + implicit_context: Option, hub: &Hub, token: &mut Token, ) -> Result< @@ -2367,11 +2329,10 @@ impl Device { Some(id) => (id, 0), None => self.derive_pipeline_layout( self_id, - implicit_pipeline_ids, + implicit_context, derived_group_layouts, &mut *bgl_guard, &mut *pipeline_layout_guard, - &hub, )?, }; let layout = pipeline_layout_guard @@ -2582,11 +2543,32 @@ impl DeviceError { } } +#[derive(Clone, Debug)] +#[cfg_attr(feature = "trace", derive(serde::Serialize))] +#[cfg_attr(feature = "replay", derive(serde::Deserialize))] +pub struct ImplicitPipelineContext { + pub root_id: id::PipelineLayoutId, + pub group_ids: ArrayVec<[id::BindGroupLayoutId; MAX_BIND_GROUPS]>, +} + pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> { pub root_id: Input, pub group_ids: &'a [Input], } +impl ImplicitPipelineIds<'_, G> { + fn prepare(self, hub: &Hub) -> ImplicitPipelineContext { + ImplicitPipelineContext { + root_id: hub.pipeline_layouts.prepare(self.root_id).into_id(), + group_ids: self + .group_ids + .iter() + .map(|id_in| hub.bind_group_layouts.prepare(id_in.clone()).into_id()) + .collect(), + } + } +} + impl Global { pub fn adapter_get_swap_chain_preferred_format( &self, @@ -3621,11 +3603,9 @@ impl Global { pipeline::ShaderModuleSource::Wgsl(ref code) => { trace.make_binary("wgsl", code.as_bytes()) } - pipeline::ShaderModuleSource::Naga(ref module) => { - let config = ron::ser::PrettyConfig::new(); - let mut ron = Vec::new(); - ron::ser::to_writer_pretty(&mut ron, &module, config).unwrap(); - trace.make_binary("ron", &ron) + pipeline::ShaderModuleSource::Naga(_) => { + // we don't want to enable Naga serialization just for this alone + trace.make_binary("ron", &[]) } } } @@ -4019,6 +3999,8 @@ impl Global { let mut token = Token::root(); let fid = hub.render_pipelines.prepare(id_in); + let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(&hub)); + let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(device_id) { @@ -4027,13 +4009,15 @@ impl Global { }; #[cfg(feature = "trace")] if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateRenderPipeline(fid.id(), desc.clone())); + trace.lock().add(trace::Action::CreateRenderPipeline { + id: fid.id(), + desc: desc.clone(), + implicit_context: implicit_context.clone(), + }); } let (pipeline, derived_bind_group_count, _layout_id) = match device - .create_render_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token) + .create_render_pipeline(device_id, desc, implicit_context, &hub, &mut token) { Ok(pair) => pair, Err(e) => break e, @@ -4142,6 +4126,8 @@ impl Global { let mut token = Token::root(); let fid = hub.compute_pipelines.prepare(id_in); + let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(&hub)); + let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(device_id) { @@ -4150,13 +4136,15 @@ impl Global { }; #[cfg(feature = "trace")] if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateComputePipeline(fid.id(), desc.clone())); + trace.lock().add(trace::Action::CreateComputePipeline { + id: fid.id(), + desc: desc.clone(), + implicit_context: implicit_context.clone(), + }); } let (pipeline, derived_bind_group_count, _layout_id) = match device - .create_compute_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token) + .create_compute_pipeline(device_id, desc, implicit_context, &hub, &mut token) { Ok(pair) => pair, Err(e) => break e, @@ -4353,7 +4341,7 @@ impl Global { if let Some(ref trace) = device.trace { trace .lock() - .add(Action::CreateSwapChain(sc_id, desc.clone())); + .add(trace::Action::CreateSwapChain(sc_id, desc.clone())); } let swap_chain = swap_chain::SwapChain { diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index 48207aa307..007baba7f7 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -75,15 +75,19 @@ pub enum Action<'a> { data: FileName, }, DestroyShaderModule(id::ShaderModuleId), - CreateComputePipeline( - id::ComputePipelineId, - crate::pipeline::ComputePipelineDescriptor<'a>, - ), + CreateComputePipeline { + id: id::ComputePipelineId, + desc: crate::pipeline::ComputePipelineDescriptor<'a>, + #[cfg_attr(feature = "replay", serde(default))] + implicit_context: Option, + }, DestroyComputePipeline(id::ComputePipelineId), - CreateRenderPipeline( - id::RenderPipelineId, - crate::pipeline::RenderPipelineDescriptor<'a>, - ), + CreateRenderPipeline { + id: id::RenderPipelineId, + desc: crate::pipeline::RenderPipelineDescriptor<'a>, + #[cfg_attr(feature = "replay", serde(default))] + implicit_context: Option, + }, DestroyRenderPipeline(id::RenderPipelineId), CreateRenderBundle { id: id::RenderBundleId, diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index bdd461a7d0..3849aa6649 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -451,6 +451,10 @@ impl FutureId<'_, I, T> { self.id } + pub fn into_id(self) -> I { + self.id + } + pub fn assign<'a, A: Access>(self, value: T, _: &'a mut Token) -> Valid { self.data.write().insert(self.id, value); Valid(self.id) @@ -497,17 +501,6 @@ impl> Registry>::Input, - value: T, - guard: &mut Storage, - ) -> Valid { - let id = self.identity.process(id_in, self.backend); - guard.insert(id, value); - Valid(id) - } - //TODO: consider remove this once everything uses `prepare` pub(crate) fn register_error>( &self, From 20bcb44c855e20ca2e939046d51e1ce760b021ab Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 16:54:38 -0500 Subject: [PATCH 4/6] Early tracing of buffer, texture, and view creation --- wgpu-core/src/device/mod.rs | 74 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 44f57d4cff..d8fb016f87 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -2630,8 +2630,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); - - tracing::info!("Create buffer {:?} with ID {:?}", desc, id_in); + let fid = hub.buffers.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { @@ -2639,6 +2638,18 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + let mut desc = desc.clone(); + let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false); + if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) { + desc.usage |= wgt::BufferUsage::COPY_DST; + } + trace + .lock() + .add(trace::Action::CreateBuffer(fid.id(), desc)); + } + let mut buffer = match device.create_buffer(device_id, desc, false) { Ok(buffer) => buffer, Err(e) => break e, @@ -2723,17 +2734,8 @@ impl Global { resource::BufferUse::COPY_DST }; - let id = hub.buffers.register_identity(id_in, buffer, &mut token); + let id = fid.assign(buffer, &mut token); tracing::info!("Created buffer {:?} with {:?}", id, desc); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - let mut desc = desc.clone(); - let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false); - if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) { - desc.usage |= wgt::BufferUsage::COPY_DST; - } - trace.lock().add(trace::Action::CreateBuffer(id.0, desc)); - } device .trackers @@ -2744,9 +2746,7 @@ impl Global { return (id.0, None); }; - let id = hub - .buffers - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -2952,6 +2952,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.textures.prepare(id_in); let (adapter_guard, mut token) = hub.adapters.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token); @@ -2960,6 +2961,13 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateTexture(fid.id(), desc.clone())); + } + let adapter = &adapter_guard[device.adapter_id.value]; let texture = match device.create_texture(device_id, adapter, desc) { Ok(texture) => texture, @@ -2969,14 +2977,8 @@ impl Global { let num_layers = texture.full_range.layers.end; let ref_count = texture.life_guard.add_ref(); - let id = hub.textures.register_identity(id_in, texture, &mut token); + let id = fid.assign(texture, &mut token); tracing::info!("Created texture {:?} with {:?}", id, desc); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateTexture(id.0, desc.clone())); - } device .trackers @@ -2987,9 +2989,7 @@ impl Global { return (id.0, None); }; - let id = hub - .textures - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3102,6 +3102,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.texture_views.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let (texture_guard, mut token) = hub.textures.read(&mut token); @@ -3111,22 +3112,21 @@ impl Global { Err(_) => break resource::CreateTextureViewError::InvalidTexture, }; let device = &device_guard[texture.device_id.value]; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace.lock().add(trace::Action::CreateTextureView { + id: fid.id(), + parent_id: texture_id, + desc: desc.clone(), + }); + } let view = match device.create_texture_view(texture, texture_id, desc) { Ok(view) => view, Err(e) => break e, }; let ref_count = view.life_guard.add_ref(); - - let id = hub.texture_views.register_identity(id_in, view, &mut token); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace.lock().add(trace::Action::CreateTextureView { - id: id.0, - parent_id: texture_id, - desc: desc.clone(), - }); - } + let id = fid.assign(view, &mut token); device .trackers @@ -3137,9 +3137,7 @@ impl Global { return (id.0, None); }; - let id = - hub.texture_views - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } From fb1b98ebb12cbaef086499019783a4d5b040821b Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 17:24:09 -0500 Subject: [PATCH 5/6] Early tracing of the other device things --- wgpu-core/src/command/bundle.rs | 10 +- wgpu-core/src/device/mod.rs | 245 +++++++++++++------------------- wgpu-core/src/device/trace.rs | 4 +- 3 files changed, 107 insertions(+), 152 deletions(-) diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index f67fb61cb1..272413d158 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -128,6 +128,11 @@ impl RenderBundleEncoder { } } + #[cfg(feature = "trace")] + pub(crate) fn to_base_pass(&self) -> BasePass { + BasePass::from_ref(self.base.as_ref()) + } + pub fn parent(&self) -> id::DeviceId { self.parent_id } @@ -552,11 +557,6 @@ unsafe impl Send for RenderBundle {} unsafe impl Sync for RenderBundle {} impl RenderBundle { - #[cfg(feature = "trace")] - pub(crate) fn to_base_pass(&self) -> BasePass { - BasePass::from_ref(self.base.as_ref()) - } - /// Actually encode the contents into a native command buffer. /// /// This is partially duplicating the logic of `command_encoder_run_render_pass`. diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index d8fb016f87..95e3311a7c 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -3213,27 +3213,27 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); - let (device_guard, mut token) = hub.devices.read(&mut token); + let fid = hub.samplers.prepare(id_in); + let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(device_id) { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateSampler(fid.id(), desc.clone())); + } let sampler = match device.create_sampler(device_id, desc) { Ok(sampler) => sampler, Err(e) => break e, }; let ref_count = sampler.life_guard.add_ref(); - - let id = hub.samplers.register_identity(id_in, sampler, &mut token); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateSampler(id.0, desc.clone())); - } + let id = fid.assign(sampler, &mut token); device .trackers @@ -3244,9 +3244,7 @@ impl Global { return (id.0, None); }; - let id = hub - .samplers - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3296,8 +3294,21 @@ impl Global { let mut token = Token::root(); let hub = B::hub(self); + let fid = hub.bind_group_layouts.prepare(id_in); let error = 'outer: loop { + let (device_guard, mut token) = hub.devices.read(&mut token); + let device = match device_guard.get(device_id) { + Ok(device) => device, + Err(_) => break DeviceError::Invalid.into(), + }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateBindGroupLayout(fid.id(), desc.clone())); + } + let mut entry_map = FastHashMap::default(); for entry in desc.entries.iter() { if entry_map.insert(entry.binding, entry.clone()).is_some() { @@ -3307,12 +3318,6 @@ impl Global { } } - let (device_guard, mut token) = hub.devices.read(&mut token); - let device = match device_guard.get(device_id) { - Ok(device) => device, - Err(_) => break DeviceError::Invalid.into(), - }; - // If there is an equivalent BGL, just bump the refcount and return it. // This is only applicable for identity filters that are generating new IDs, // so their inputs are `PhantomData` of size 0. @@ -3334,23 +3339,11 @@ impl Global { Err(e) => break e, }; - let id = hub - .bind_group_layouts - .register_identity(id_in, layout, &mut token); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateBindGroupLayout(id.0, desc.clone())); - } + let id = fid.assign(layout, &mut token); return (id.0, None); }; - let id = hub.bind_group_layouts.register_error( - id_in, - desc.label.borrow_or_default(), - &mut token, - ); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3399,6 +3392,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.pipeline_layouts.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { @@ -3406,6 +3400,12 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreatePipelineLayout(fid.id(), desc.clone())); + } let layout = { let (bgl_guard, _) = hub.bind_group_layouts.read(&mut token); @@ -3415,21 +3415,11 @@ impl Global { } }; - let id = hub - .pipeline_layouts - .register_identity(id_in, layout, &mut token); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreatePipelineLayout(id.0, desc.clone())); - } + let id = fid.assign(layout, &mut token); return (id.0, None); }; - let id = - hub.pipeline_layouts - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3478,6 +3468,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.bind_groups.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let (bind_group_layout_guard, mut token) = hub.bind_group_layouts.read(&mut token); @@ -3487,11 +3478,17 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace + .lock() + .add(trace::Action::CreateBindGroup(fid.id(), desc.clone())); + } + let bind_group_layout = match bind_group_layout_guard.get(desc.layout) { Ok(layout) => layout, Err(_) => break binding_model::CreateBindGroupError::InvalidLayout, }; - let bind_group = match device.create_bind_group( device_id, bind_group_layout, @@ -3504,20 +3501,12 @@ impl Global { }; let ref_count = bind_group.life_guard.add_ref(); - let id = hub - .bind_groups - .register_identity(id_in, bind_group, &mut token); + let id = fid.assign(bind_group, &mut token); tracing::debug!( "Bind group {:?} {:#?}", id, hub.bind_groups.read(&mut token).0[id].used ); - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace - .lock() - .add(trace::Action::CreateBindGroup(id.0, desc.clone())); - } device .trackers @@ -3528,9 +3517,7 @@ impl Global { return (id.0, None); }; - let id = hub - .bind_groups - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3581,6 +3568,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.shader_modules.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { @@ -3589,51 +3577,38 @@ impl Global { Err(_) => break DeviceError::Invalid.into(), }; #[cfg(feature = "trace")] - let data = match device.trace { - Some(ref trace) => { - let mut trace = trace.lock(); - match source { - pipeline::ShaderModuleSource::SpirV(ref spv) => { - trace.make_binary("spv", unsafe { - std::slice::from_raw_parts(spv.as_ptr() as *const u8, spv.len() * 4) - }) - } - pipeline::ShaderModuleSource::Wgsl(ref code) => { - trace.make_binary("wgsl", code.as_bytes()) - } - pipeline::ShaderModuleSource::Naga(_) => { - // we don't want to enable Naga serialization just for this alone - trace.make_binary("ron", &[]) - } + if let Some(ref trace) = device.trace { + let mut trace = trace.lock(); + let data = match source { + pipeline::ShaderModuleSource::SpirV(ref spv) => { + trace.make_binary("spv", unsafe { + std::slice::from_raw_parts(spv.as_ptr() as *const u8, spv.len() * 4) + }) } - } - None => String::new(), + pipeline::ShaderModuleSource::Wgsl(ref code) => { + trace.make_binary("wgsl", code.as_bytes()) + } + pipeline::ShaderModuleSource::Naga(_) => { + // we don't want to enable Naga serialization just for this alone + trace.make_binary("ron", &[]) + } + }; + trace.add(trace::Action::CreateShaderModule { + id: fid.id(), + desc: desc.clone(), + data, + }); }; let shader = match device.create_shader_module(device_id, desc, source) { Ok(shader) => shader, Err(e) => break e, }; - let id = hub - .shader_modules - .register_identity(id_in, shader, &mut token); - - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - let mut trace = trace.lock(); - trace.add(trace::Action::CreateShaderModule { - id: id.0, - desc: desc.clone(), - data, - }); - } - + let id = fid.assign(shader, &mut token); return (id.0, None); }; - let id = - hub.shader_modules - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3672,6 +3647,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.command_buffers.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { @@ -3706,18 +3682,11 @@ impl Global { raw.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT); } - let id = hub - .command_buffers - .register_identity(id_in, command_buffer, &mut token); - + let id = fid.assign(command_buffer, &mut token); return (id.0, None); }; - let id = B::hub(self).command_buffers.register_error( - id_in, - desc.label.borrow_or_default(), - &mut token, - ); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3773,37 +3742,34 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); - let (device_guard, mut token) = hub.devices.read(&mut token); + let fid = hub.render_bundles.prepare(id_in); + let (device_guard, mut token) = hub.devices.read(&mut token); let error = loop { let device = match device_guard.get(bundle_encoder.parent()) { Ok(device) => device, Err(_) => break command::RenderBundleError::INVALID_DEVICE, }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace.lock().add(trace::Action::CreateRenderBundle { + id: fid.id(), + desc: trace::new_render_bundle_encoder_descriptor( + desc.label.clone(), + &bundle_encoder.context, + ), + base: bundle_encoder.to_base_pass(), + }); + } let render_bundle = match bundle_encoder.finish(desc, device, &hub, &mut token) { Ok(bundle) => bundle, Err(e) => break e, }; - tracing::debug!("Render bundle {:?} = {:#?}", id_in, render_bundle.used); - + tracing::debug!("Render bundle {:#?}", render_bundle.used); let ref_count = render_bundle.life_guard.add_ref(); - let id = hub - .render_bundles - .register_identity(id_in, render_bundle, &mut token); - - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - let (bundle_guard, _) = hub.render_bundles.read(&mut token); - let bundle = &bundle_guard[id]; - let label = desc.label.as_ref().map(|l| l.as_ref()); - trace.lock().add(trace::Action::CreateRenderBundle { - id: id.0, - desc: trace::new_render_bundle_encoder_descriptor(label, &bundle.context), - base: bundle.to_base_pass(), - }); - } + let id = fid.assign(render_bundle, &mut token); device .trackers @@ -3814,11 +3780,7 @@ impl Global { return (id.0, None); }; - let id = B::hub(self).render_bundles.register_error( - id_in, - desc.label.borrow_or_default(), - &mut token, - ); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } @@ -3864,14 +3826,21 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.query_sets.prepare(id_in); let (device_guard, mut token) = hub.devices.read(&mut token); - let error = loop { let device = match device_guard.get(device_id) { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace.lock().add(trace::Action::CreateQuerySet { + id: fid.id(), + desc: desc.clone(), + }); + } match desc.ty { wgt::QueryType::Timestamp => { @@ -3920,18 +3889,7 @@ impl Global { }; let ref_count = query_set.life_guard.add_ref(); - - let id = hub - .query_sets - .register_identity(id_in, query_set, &mut token); - #[cfg(feature = "trace")] - match device.trace { - Some(ref trace) => trace.lock().add(trace::Action::CreateQuerySet { - id: id.0, - desc: desc.clone(), - }), - None => (), - }; + let id = fid.assign(query_set, &mut token); device .trackers @@ -3943,9 +3901,7 @@ impl Global { return (id.0, None); }; - let id = B::hub(self) - .query_sets - .register_error(id_in, "", &mut token); + let id = fid.assign_error("", &mut token); (id, Some(error)) } @@ -3966,12 +3922,11 @@ impl Global { let device = &device_guard[device_id]; #[cfg(feature = "trace")] - match device.trace { - Some(ref trace) => trace + if let Some(ref trace) = device.trace { + trace .lock() - .add(trace::Action::DestroyQuerySet(query_set_id)), - None => (), - }; + .add(trace::Action::DestroyQuerySet(query_set_id)); + } device .lock_life(&mut token) diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index 007baba7f7..c67e64da0b 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -15,11 +15,11 @@ pub const FILE_NAME: &str = "trace.ron"; #[cfg(feature = "trace")] pub(crate) fn new_render_bundle_encoder_descriptor<'a>( - label: Option<&'a str>, + label: crate::Label<'a>, context: &'a super::RenderPassContext, ) -> crate::command::RenderBundleEncoderDescriptor<'a> { crate::command::RenderBundleEncoderDescriptor { - label: label.map(Cow::Borrowed), + label, color_formats: Cow::Borrowed(&context.attachments.colors), depth_stencil_format: context.attachments.depth_stencil, sample_count: context.sample_count as u32, From 10245cece90055685f383eda07a0ebb5ddcb05e1 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Mar 2021 19:59:29 -0500 Subject: [PATCH 6/6] Early tracing of swapchain-related things, clean up the hub API --- player/src/lib.rs | 12 ++++------ wgpu-core/src/device/mod.rs | 6 +++-- wgpu-core/src/device/trace.rs | 2 +- wgpu-core/src/hub.rs | 24 ------------------- wgpu-core/src/instance.rs | 44 ++++++++++++++--------------------- wgpu-core/src/swap_chain.rs | 23 +++++++++--------- 6 files changed, 39 insertions(+), 72 deletions(-) diff --git a/player/src/lib.rs b/player/src/lib.rs index dfb956b39a..fe2573e2c4 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -196,13 +196,11 @@ impl GlobalPlay for wgc::hub::Global { self.sampler_drop::(id); } A::GetSwapChainTexture { id, parent_id } => { - if let Some(id) = id { - self.device_maintain_ids::(device).unwrap(); - self.swap_chain_get_current_texture_view::(parent_id, id) - .unwrap() - .view_id - .unwrap(); - } + self.device_maintain_ids::(device).unwrap(); + self.swap_chain_get_current_texture_view::(parent_id, id) + .unwrap() + .view_id + .unwrap(); } A::CreateBindGroupLayout(id, desc) => { let (_, error) = self.device_create_bind_group_layout::(device, &desc, id); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 95e3311a7c..60777f04a9 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -4022,7 +4022,8 @@ impl Global { let id = hub .bind_group_layouts - .register_error(id_in, "", &mut token); + .prepare(id_in) + .assign_error("", &mut token); (id, Some(error)) } @@ -4149,7 +4150,8 @@ impl Global { let id = hub .bind_group_layouts - .register_error(id_in, "", &mut token); + .prepare(id_in) + .assign_error("", &mut token); (id, Some(error)) } diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index c67e64da0b..80ce1c69c8 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -50,7 +50,7 @@ pub enum Action<'a> { DestroySampler(id::SamplerId), CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor), GetSwapChainTexture { - id: Option, + id: id::TextureViewId, parent_id: id::SwapChainId, }, PresentSwapChain(id::SwapChainId), diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 3849aa6649..fb784d5079 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -491,26 +491,6 @@ impl> Registry>( - &self, - id_in: >::Input, - value: T, - token: &mut Token, - ) -> Valid { - self.prepare(id_in).assign(value, token) - } - - //TODO: consider remove this once everything uses `prepare` - pub(crate) fn register_error>( - &self, - id_in: >::Input, - label: &str, - token: &mut Token, - ) -> I { - self.prepare(id_in).assign_error(label, token) - } - pub fn unregister_locked(&self, id: I, guard: &mut Storage) -> Option { let value = guard.remove(id); //Note: careful about the order here! @@ -531,10 +511,6 @@ impl> Registry String { let guard = self.data.read(); diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 4379525ef5..a9168d8426 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -627,7 +627,7 @@ impl Global { }; let mut token = Token::root(); - let id = self.surfaces.register_identity(id_in, surface, &mut token); + let id = self.surfaces.prepare(id_in).assign(surface, &mut token); id.0 } @@ -649,7 +649,7 @@ impl Global { }; let mut token = Token::root(); - let id = self.surfaces.register_identity(id_in, surface, &mut token); + let id = self.surfaces.prepare(id_in).assign(surface, &mut token); id.0 } @@ -675,11 +675,9 @@ impl Global { for raw in inst.enumerate_adapters() { let adapter = Adapter::new(raw); tracing::info!("Adapter {} {:?}", backend_info, adapter.raw.info); - let id = hub.adapters.register_identity( - id_backend.clone(), - adapter, - &mut token, - ); + let id = hub.adapters + .prepare(id_backend.clone()) + .assign(adapter, &mut token); adapters.push(id.0); } } @@ -825,11 +823,9 @@ impl Global { if selected < adapters_backend.len() { let adapter = Adapter::new(adapters_backend.swap_remove(selected)); tracing::info!("Adapter {} {:?}", info_adapter, adapter.raw.info); - let id = backend_hub(self).adapters.register_identity( - id_backend.take().unwrap(), - adapter, - &mut token, - ); + let id = backend_hub(self).adapters + .prepare(id_backend.take().unwrap()) + .assign(adapter, &mut token); return Ok(id.0); } selected -= adapters_backend.len(); @@ -927,16 +923,13 @@ impl Global { let mut token = Token::root(); let (mut adapter_guard, _) = hub.adapters.write(&mut token); - match adapter_guard.get_mut(adapter_id) { - Ok(adapter) => { - if adapter.life_guard.ref_count.take().unwrap().load() == 1 { - hub.adapters - .unregister_locked(adapter_id, &mut *adapter_guard); - } - } - Err(_) => { - hub.adapters.free_id(adapter_id); - } + let free = match adapter_guard.get_mut(adapter_id) { + Ok(adapter) => adapter.life_guard.ref_count.take().unwrap().load() == 1, + Err(_) => true, + }; + if free { + hub.adapters + .unregister_locked(adapter_id, &mut *adapter_guard); } } } @@ -953,6 +946,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.devices.prepare(id_in); let error = loop { let (adapter_guard, mut token) = hub.adapters.read(&mut token); @@ -964,13 +958,11 @@ impl Global { Ok(device) => device, Err(e) => break e, }; - let id = hub.devices.register_identity(id_in, device, &mut token); + let id = fid.assign(device, &mut token); return (id.0, None); }; - let id = hub - .devices - .register_error(id_in, desc.label.borrow_or_default(), &mut token); + let id = fid.assign_error(desc.label.borrow_or_default(), &mut token); (id, Some(error)) } } diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index 65fa57149b..db493f1839 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -143,6 +143,7 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); + let fid = hub.texture_views.prepare(view_id_in); let (mut surface_guard, mut token) = self.surfaces.write(&mut token); let surface = surface_guard @@ -153,8 +154,16 @@ impl Global { let sc = swap_chain_guard .get_mut(swap_chain_id) .map_err(|_| SwapChainError::Invalid)?; - #[cfg_attr(not(feature = "trace"), allow(unused_variables))] + + #[allow(unused_variables)] let device = &device_guard[sc.device_id.value]; + #[cfg(feature = "trace")] + if let Some(ref trace) = device.trace { + trace.lock().add(Action::GetSwapChainTexture { + id: fid.id(), + parent_id: swap_chain_id, + }); + } let suf = B::get_surface_mut(surface); let (image, status) = match unsafe { suf.acquire_image(FRAME_TIMEOUT_MS * 1_000_000) } { @@ -206,9 +215,7 @@ impl Global { }; let ref_count = view.life_guard.add_ref(); - let id = hub - .texture_views - .register_identity(view_id_in, view, &mut token); + let id = fid.assign(view, &mut token); if sc.acquired_view_id.is_some() { return Err(SwapChainError::AlreadyAcquired); @@ -224,14 +231,6 @@ impl Global { None => None, }; - #[cfg(feature = "trace")] - if let Some(ref trace) = device.trace { - trace.lock().add(Action::GetSwapChainTexture { - id: view_id, - parent_id: swap_chain_id, - }); - } - Ok(SwapChainOutput { status, view_id }) }