diff --git a/deno_webgpu/queue.rs b/deno_webgpu/queue.rs index 1f6258935..61b56c758 100644 --- a/deno_webgpu/queue.rs +++ b/deno_webgpu/queue.rs @@ -32,7 +32,7 @@ pub fn op_webgpu_queue_submit( }) .collect::, AnyError>>()?; - let maybe_err = gfx_select!(queue => instance.queue_submit(queue, &ids)).err(); + let maybe_err = gfx_select!(queue => instance.queue_submit(queue.transmute(), &ids)).err(); for rid in command_buffers { let resource = state.resource_table.take::(rid)?; @@ -84,7 +84,7 @@ pub fn op_webgpu_write_buffer( None => &buf[data_offset..], }; let maybe_err = gfx_select!(queue => instance.queue_write_buffer( - queue, + queue.transmute(), buffer, buffer_offset, data @@ -120,7 +120,7 @@ pub fn op_webgpu_write_texture( let data_layout = data_layout.into(); gfx_ok!(queue => instance.queue_write_texture( - queue, + queue.transmute(), &destination, buf, &data_layout, diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index f91b1b661..5e87232d8 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -61,7 +61,7 @@ fn main() { global.instance_create_surface( window.display_handle().unwrap().into(), window.window_handle().unwrap().into(), - wgc::id::TypedId::zip(0, 1, wgt::Backend::Empty), + wgc::id::Id::zip(0, 1, wgt::Backend::Empty), ) } .unwrap(); @@ -79,22 +79,21 @@ fn main() { #[cfg(not(feature = "winit"))] compatible_surface: None, }, - wgc::instance::AdapterInputs::IdSet( - &[wgc::id::TypedId::zip(0, 0, backend)], - |id| id.backend(), - ), + wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| { + id.backend() + }), ) .expect("Unable to find an adapter for selected backend"); let info = gfx_select!(adapter => global.adapter_get_info(adapter)).unwrap(); log::info!("Picked '{}'", info.name); - let id = wgc::id::TypedId::zip(1, 0, backend); + let id = wgc::id::Id::zip(1, 0, backend); let (_, _, error) = gfx_select!(adapter => global.adapter_request_device( adapter, &desc, None, id, - id + id.transmute() )); if let Some(e) = error { panic!("{:?}", e); diff --git a/player/src/lib.rs b/player/src/lib.rs index ec8b91371..3062d6a85 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -14,10 +14,10 @@ use std::{borrow::Cow, fs, path::Path}; pub struct IdentityPassThroughFactory; -impl wgc::identity::IdentityHandlerFactory for IdentityPassThroughFactory { - type Input = I; +impl wgc::identity::IdentityHandlerFactory for IdentityPassThroughFactory { + type Input = wgc::id::Id; - fn input_to_id(id_in: Self::Input) -> I { + fn input_to_id(id_in: Self::Input) -> wgc::id::Id { id_in } @@ -38,7 +38,7 @@ pub trait GlobalPlay { device: wgc::id::DeviceId, action: trace::Action, dir: &Path, - comb_manager: &mut wgc::identity::IdentityManager, + comb_manager: &mut wgc::identity::IdentityManager, ); } @@ -153,7 +153,7 @@ impl GlobalPlay for wgc::global::Global { device: wgc::id::DeviceId, action: trace::Action, dir: &Path, - comb_manager: &mut wgc::identity::IdentityManager, + comb_manager: &mut wgc::identity::IdentityManager, ) { use wgc::device::trace::Action; log::debug!("action {:?}", action); @@ -350,7 +350,7 @@ impl GlobalPlay for wgc::global::Global { let bin = std::fs::read(dir.join(data)).unwrap(); let size = (range.end - range.start) as usize; if queued { - self.queue_write_buffer::(device, id, range.start, &bin) + self.queue_write_buffer::(device.transmute(), id, range.start, &bin) .unwrap(); } else { self.device_wait_for_buffer::(device, id).unwrap(); @@ -365,23 +365,24 @@ impl GlobalPlay for wgc::global::Global { size, } => { let bin = std::fs::read(dir.join(data)).unwrap(); - self.queue_write_texture::(device, &to, &bin, &layout, &size) + self.queue_write_texture::(device.transmute(), &to, &bin, &layout, &size) .unwrap(); } Action::Submit(_index, ref commands) if commands.is_empty() => { - self.queue_submit::(device, &[]).unwrap(); + self.queue_submit::(device.transmute(), &[]).unwrap(); } Action::Submit(_index, commands) => { let (encoder, error) = self.device_create_command_encoder::( device, &wgt::CommandEncoderDescriptor { label: None }, - comb_manager.process(device.backend()), + comb_manager.process(device.backend()).transmute(), ); if let Some(e) = error { panic!("{e}"); } let cmdbuf = self.encode_commands::(encoder, commands); - self.queue_submit::(device, &[cmdbuf]).unwrap(); + self.queue_submit::(device.transmute(), &[cmdbuf]) + .unwrap(); } } } diff --git a/player/tests/test.rs b/player/tests/test.rs index cb09aeceb..bf6e0b315 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -105,7 +105,7 @@ impl Test<'_> { test_num: u32, ) { let backend = adapter.backend(); - let device_id = wgc::id::TypedId::zip(test_num, 0, backend); + let device_id = wgc::id::Id::zip(test_num, 0, backend); let (_, _, error) = wgc::gfx_select!(adapter => global.adapter_request_device( adapter, &wgt::DeviceDescriptor { @@ -115,7 +115,7 @@ impl Test<'_> { }, None, device_id, - device_id + device_id.transmute() )); if let Some(e) = error { panic!("{:?}", e); @@ -128,7 +128,7 @@ impl Test<'_> { } println!("\t\t\tMapping..."); for expect in &self.expectations { - let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend); + let buffer = wgc::id::Id::zip(expect.buffer.index, expect.buffer.epoch, backend); wgc::gfx_select!(device_id => global.buffer_map_async( buffer, expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress, @@ -148,7 +148,7 @@ impl Test<'_> { for expect in self.expectations { println!("\t\t\tChecking {}", expect.name); - let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend); + let buffer = wgc::id::Id::zip(expect.buffer.index, expect.buffer.epoch, backend); let (ptr, size) = wgc::gfx_select!(device_id => global.buffer_get_mapped_range(buffer, expect.offset, Some(expect.data.len() as wgt::BufferAddress))) .unwrap(); @@ -221,10 +221,9 @@ impl Corpus { force_fallback_adapter: false, compatible_surface: None, }, - wgc::instance::AdapterInputs::IdSet( - &[wgc::id::TypedId::zip(0, 0, backend)], - |id| id.backend(), - ), + wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| { + id.backend() + }), ) { Ok(adapter) => adapter, Err(_) => continue, diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index fe4f977d0..9520c50cd 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -6,10 +6,7 @@ use crate::{ }, error::{ErrorFormatter, PrettyError}, hal_api::HalApi, - id::{ - BindGroupId, BindGroupLayoutId, BufferId, PipelineLayoutId, SamplerId, TextureId, - TextureViewId, - }, + id::{BindGroupLayoutId, BufferId, SamplerId, TextureId, TextureViewId}, init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, resource::{Resource, ResourceInfo, ResourceType}, resource_log, @@ -441,7 +438,7 @@ pub struct BindGroupLayoutDescriptor<'a> { pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>, } -pub type BindGroupLayouts = crate::storage::Storage, BindGroupLayoutId>; +pub type BindGroupLayouts = crate::storage::Storage>; /// Bind group layout. #[derive(Debug)] @@ -458,7 +455,7 @@ pub struct BindGroupLayout { pub(crate) origin: bgl::Origin, #[allow(unused)] pub(crate) binding_count_validator: BindingTypeMaxCountValidator, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) label: String, } @@ -482,14 +479,16 @@ impl Drop for BindGroupLayout { } } -impl Resource for BindGroupLayout { +impl Resource for BindGroupLayout { const TYPE: ResourceType = "BindGroupLayout"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::BindGroupLayout; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } @@ -602,7 +601,7 @@ pub struct PipelineLayoutDescriptor<'a> { pub struct PipelineLayout { pub(crate) raw: Option, pub(crate) device: Arc>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) bind_group_layouts: ArrayVec>, { hal::MAX_BIND_GROUPS }>, pub(crate) push_constant_ranges: ArrayVec, } @@ -716,14 +715,16 @@ impl PipelineLayout { } } -impl Resource for PipelineLayout { +impl Resource for PipelineLayout { const TYPE: ResourceType = "PipelineLayout"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::PipelineLayout; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -830,7 +831,7 @@ pub struct BindGroup { pub(crate) raw: Snatchable, pub(crate) device: Arc>, pub(crate) layout: Arc>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) used: BindGroupStates, pub(crate) used_buffer_ranges: Vec>, pub(crate) used_texture_ranges: Vec>, @@ -919,14 +920,16 @@ impl BindGroup { } } -impl Resource for BindGroup { +impl Resource for BindGroup { const TYPE: ResourceType = "BindGroup"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::BindGroup; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 49def22d4..9d80c62f8 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -94,7 +94,7 @@ use crate::{ error::{ErrorFormatter, PrettyError}, hal_api::HalApi, hub::Hub, - id::{self, RenderBundleId}, + id, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, pipeline::{PipelineFlags, RenderPipeline, VertexStep}, resource::{Resource, ResourceInfo, ResourceType}, @@ -832,7 +832,7 @@ pub struct RenderBundle { pub(super) buffer_memory_init_actions: Vec>, pub(super) texture_memory_init_actions: Vec>, pub(super) context: RenderPassContext, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, discard_hal_labels: bool, } @@ -1067,14 +1067,16 @@ impl RenderBundle { } } -impl Resource for RenderBundle { +impl Resource for RenderBundle { const TYPE: ResourceType = "RenderBundle"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::RenderBundle; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index cd7949b3d..afd9c5204 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -305,7 +305,7 @@ impl State { &mut self, raw_encoder: &mut A::CommandEncoder, base_trackers: &mut Tracker, - bind_group_guard: &Storage, id::BindGroupId>, + bind_group_guard: &Storage>, indirect_buffer: Option, snatch_guard: &SnatchGuard, ) -> Result<(), UsageConflict> { diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 40ac0628f..1201e30f0 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -140,7 +140,7 @@ pub struct CommandBuffer { pub(crate) device: Arc>, limits: wgt::Limits, support_clear_texture: bool, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) data: Mutex>>, } @@ -255,7 +255,7 @@ impl CommandBuffer { id: id::CommandEncoderId, ) -> Result, CommandEncoderError> { let storage = hub.command_buffers.read(); - match storage.get(id) { + match storage.get(id.transmute()) { Ok(cmd_buf) => match cmd_buf.data.lock().as_ref().unwrap().status { CommandEncoderStatus::Recording => Ok(cmd_buf.clone()), CommandEncoderStatus::Finished => Err(CommandEncoderError::NotRecording), @@ -296,14 +296,16 @@ impl CommandBuffer { } } -impl Resource for CommandBuffer { +impl Resource for CommandBuffer { const TYPE: ResourceType = "CommandBuffer"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::CommandBuffer; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } @@ -418,7 +420,7 @@ impl Global { let hub = A::hub(self); - let error = match hub.command_buffers.get(encoder_id) { + let error = match hub.command_buffers.get(encoder_id.transmute()) { Ok(cmd_buf) => { let mut cmd_buf_data = cmd_buf.data.lock(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); @@ -444,7 +446,7 @@ impl Global { Err(_) => Some(CommandEncoderError::Invalid), }; - (encoder_id, error) + (encoder_id.transmute(), error) } pub fn command_encoder_push_debug_group( @@ -700,7 +702,7 @@ impl PrettyError for PassErrorScope { // This error is not in the error chain, only notes are needed match *self { Self::Pass(id) => { - fmt.command_buffer_label(&id); + fmt.command_buffer_label(&id.transmute()); } Self::SetBindGroup(id) => { fmt.bind_group_label(&id); diff --git a/wgpu-core/src/command/query.rs b/wgpu-core/src/command/query.rs index 8c1f4b8f1..ab97cfc37 100644 --- a/wgpu-core/src/command/query.rs +++ b/wgpu-core/src/command/query.rs @@ -7,7 +7,7 @@ use crate::{ device::DeviceError, global::Global, hal_api::HalApi, - id::{self, Id, TypedId}, + id::{self, Id}, identity::GlobalIdentityHandlerFactory, init_tracker::MemoryInitKind, resource::QuerySet, @@ -49,7 +49,7 @@ impl QueryResetMap { pub fn reset_queries( &mut self, raw_encoder: &mut A::CommandEncoder, - query_set_storage: &Storage, id::QuerySetId>, + query_set_storage: &Storage>, backend: wgt::Backend, ) -> Result<(), id::QuerySetId> { for (query_set_id, (state, epoch)) in self.map.drain() { @@ -314,7 +314,7 @@ impl QuerySet { pub(super) fn end_occlusion_query( raw_encoder: &mut A::CommandEncoder, - storage: &Storage, id::QuerySetId>, + storage: &Storage>, active_query: &mut Option<(id::QuerySetId, u32)>, ) -> Result<(), QueryUseError> { if let Some((query_set_id, query_index)) = active_query.take() { @@ -331,7 +331,7 @@ pub(super) fn end_occlusion_query( pub(super) fn end_pipeline_statistics_query( raw_encoder: &mut A::CommandEncoder, - storage: &Storage, id::QuerySetId>, + storage: &Storage>, active_query: &mut Option<(id::QuerySetId, u32)>, ) -> Result<(), QueryUseError> { if let Some((query_set_id, query_index)) = active_query.take() { diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index fedc6f7c8..933e00824 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -784,10 +784,10 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { trackers: &mut Tracker, texture_memory_actions: &mut CommandBufferTextureMemoryActions, pending_query_resets: &mut QueryResetMap, - view_guard: &'a Storage, id::TextureViewId>, - buffer_guard: &'a Storage, id::BufferId>, - texture_guard: &'a Storage, id::TextureId>, - query_set_guard: &'a Storage, id::QuerySetId>, + view_guard: &'a Storage>, + buffer_guard: &'a Storage>, + texture_guard: &'a Storage>, + query_set_guard: &'a Storage>, snatch_guard: &SnatchGuard<'a>, ) -> Result { profiling::scope!("RenderPassInfo::start"); @@ -2391,7 +2391,7 @@ impl Global { (trackers, pending_discard_init_fixups) }; - let cmd_buf = hub.command_buffers.get(encoder_id).unwrap(); + let cmd_buf = hub.command_buffers.get(encoder_id.transmute()).unwrap(); let mut cmd_buf_data = cmd_buf.data.lock(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 1872159fc..8db2db913 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -8,6 +8,7 @@ use crate::{ }, global::Global, hal_api::HalApi, + id::markers, id::{self, AdapterId, DeviceId, QueueId, SurfaceId}, identity::{GlobalIdentityHandlerFactory, Input}, init_tracker::TextureInitTracker, @@ -146,12 +147,12 @@ impl Global { &self, device_id: DeviceId, desc: &resource::BufferDescriptor, - id_in: Input, + id_in: Input, ) -> (id::BufferId, Option) { profiling::scope!("Device::create_buffer"); let hub = A::hub(self); - let fid = hub.buffers.prepare::(id_in); + let fid = hub.buffers.prepare::(id_in); let mut to_destroy: ArrayVec, 2> = ArrayVec::new(); let error = loop { @@ -309,20 +310,20 @@ impl Global { /// [`device_create_buffer`]: Global::device_create_buffer /// [`usage`]: https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-usage /// [`wgpu_types::BufferUsages`]: wgt::BufferUsages - pub fn create_buffer_error(&self, id_in: Input, label: Label) { + pub fn create_buffer_error(&self, id_in: Input, label: Label) { let hub = A::hub(self); - let fid = hub.buffers.prepare::(id_in); + let fid = hub.buffers.prepare::(id_in); fid.assign_error(label.borrow_or_default()); } pub fn create_render_bundle_error( &self, - id_in: Input, + id_in: Input, label: Label, ) { let hub = A::hub(self); - let fid = hub.render_bundles.prepare::(id_in); + let fid = hub.render_bundles.prepare::(id_in); fid.assign_error(label.borrow_or_default()); } @@ -330,9 +331,9 @@ impl Global { /// Assign `id_in` an error with the given `label`. /// /// See `create_buffer_error` for more context and explaination. - pub fn create_texture_error(&self, id_in: Input, label: Label) { + pub fn create_texture_error(&self, id_in: Input, label: Label) { let hub = A::hub(self); - let fid = hub.textures.prepare::(id_in); + let fid = hub.textures.prepare::(id_in); fid.assign_error(label.borrow_or_default()); } @@ -545,13 +546,13 @@ impl Global { &self, device_id: DeviceId, desc: &resource::TextureDescriptor, - id_in: Input, + id_in: Input, ) -> (id::TextureId, Option) { profiling::scope!("Device::create_texture"); let hub = A::hub(self); - let fid = hub.textures.prepare::(id_in); + let fid = hub.textures.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -599,13 +600,13 @@ impl Global { hal_texture: A::Texture, device_id: DeviceId, desc: &resource::TextureDescriptor, - id_in: Input, + id_in: Input, ) -> (id::TextureId, Option) { profiling::scope!("Device::create_texture_from_hal"); let hub = A::hub(self); - let fid = hub.textures.prepare::(id_in); + let fid = hub.textures.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -673,12 +674,12 @@ impl Global { hal_buffer: A::Buffer, device_id: DeviceId, desc: &resource::BufferDescriptor, - id_in: Input, + id_in: Input, ) -> (id::BufferId, Option) { profiling::scope!("Device::create_buffer"); let hub = A::hub(self); - let fid = hub.buffers.prepare::(id_in); + let fid = hub.buffers.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -783,13 +784,13 @@ impl Global { &self, texture_id: id::TextureId, desc: &resource::TextureViewDescriptor, - id_in: Input, + id_in: Input, ) -> (id::TextureViewId, Option) { profiling::scope!("Texture::create_view"); let hub = A::hub(self); - let fid = hub.texture_views.prepare::(id_in); + let fid = hub.texture_views.prepare::(id_in); let error = loop { let texture = match hub.textures.get(texture_id) { @@ -873,12 +874,12 @@ impl Global { &self, device_id: DeviceId, desc: &resource::SamplerDescriptor, - id_in: Input, + id_in: Input, ) -> (id::SamplerId, Option) { profiling::scope!("Device::create_sampler"); let hub = A::hub(self); - let fid = hub.samplers.prepare::(id_in); + let fid = hub.samplers.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -934,7 +935,7 @@ impl Global { &self, device_id: DeviceId, desc: &binding_model::BindGroupLayoutDescriptor, - id_in: Input, + id_in: Input, ) -> ( id::BindGroupLayoutId, Option, @@ -942,7 +943,7 @@ impl Global { profiling::scope!("Device::create_bind_group_layout"); let hub = A::hub(self); - let fid = hub.bind_group_layouts.prepare::(id_in); + let fid = hub.bind_group_layouts.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1004,7 +1005,7 @@ impl Global { return (id.unwrap(), None); }; - let fid = hub.bind_group_layouts.prepare::(id_in); + let fid = hub.bind_group_layouts.prepare::(id_in); let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -1033,7 +1034,7 @@ impl Global { &self, device_id: DeviceId, desc: &binding_model::PipelineLayoutDescriptor, - id_in: Input, + id_in: Input, ) -> ( id::PipelineLayoutId, Option, @@ -1041,7 +1042,7 @@ impl Global { profiling::scope!("Device::create_pipeline_layout"); let hub = A::hub(self); - let fid = hub.pipeline_layouts.prepare::(id_in); + let fid = hub.pipeline_layouts.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1094,12 +1095,12 @@ impl Global { &self, device_id: DeviceId, desc: &binding_model::BindGroupDescriptor, - id_in: Input, + id_in: Input, ) -> (id::BindGroupId, Option) { profiling::scope!("Device::create_bind_group"); let hub = A::hub(self); - let fid = hub.bind_groups.prepare::(id_in); + let fid = hub.bind_groups.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1178,7 +1179,7 @@ impl Global { device_id: DeviceId, desc: &pipeline::ShaderModuleDescriptor, source: pipeline::ShaderModuleSource, - id_in: Input, + id_in: Input, ) -> ( id::ShaderModuleId, Option, @@ -1186,7 +1187,7 @@ impl Global { profiling::scope!("Device::create_shader_module"); let hub = A::hub(self); - let fid = hub.shader_modules.prepare::(id_in); + let fid = hub.shader_modules.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1256,7 +1257,7 @@ impl Global { device_id: DeviceId, desc: &pipeline::ShaderModuleDescriptor, source: Cow<[u32]>, - id_in: Input, + id_in: Input, ) -> ( id::ShaderModuleId, Option, @@ -1264,7 +1265,7 @@ impl Global { profiling::scope!("Device::create_shader_module"); let hub = A::hub(self); - let fid = hub.shader_modules.prepare::(id_in); + let fid = hub.shader_modules.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1318,12 +1319,14 @@ impl Global { &self, device_id: DeviceId, desc: &wgt::CommandEncoderDescriptor(command_buffer_id) + self.command_encoder_drop::(command_buffer_id.transmute()) } pub fn device_create_render_bundle_encoder( @@ -1394,7 +1400,7 @@ impl Global { device_id: DeviceId, desc: &command::RenderBundleEncoderDescriptor, ) -> ( - id::RenderBundleEncoderId, + *mut command::RenderBundleEncoder, Option, ) { profiling::scope!("Device::create_render_bundle_encoder"); @@ -1410,13 +1416,13 @@ impl Global { &self, bundle_encoder: command::RenderBundleEncoder, desc: &command::RenderBundleDescriptor, - id_in: Input, + id_in: Input, ) -> (id::RenderBundleId, Option) { profiling::scope!("RenderBundleEncoder::finish"); let hub = A::hub(self); - let fid = hub.render_bundles.prepare::(id_in); + let fid = hub.render_bundles.prepare::(id_in); let error = loop { let device = match hub.devices.get(bundle_encoder.parent()) { @@ -1480,12 +1486,12 @@ impl Global { &self, device_id: DeviceId, desc: &resource::QuerySetDescriptor, - id_in: Input, + id_in: Input, ) -> (id::QuerySetId, Option) { profiling::scope!("Device::create_query_set"); let hub = A::hub(self); - let fid = hub.query_sets.prepare::(id_in); + let fid = hub.query_sets.prepare::(id_in); let error = loop { let device = match hub.devices.get(device_id) { @@ -1554,7 +1560,7 @@ impl Global { &self, device_id: DeviceId, desc: &pipeline::RenderPipelineDescriptor, - id_in: Input, + id_in: Input, implicit_pipeline_ids: Option>, ) -> ( id::RenderPipelineId, @@ -1564,7 +1570,7 @@ impl Global { let hub = A::hub(self); - let fid = hub.render_pipelines.prepare::(id_in); + let fid = hub.render_pipelines.prepare::(id_in); let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub)); let implicit_error_context = implicit_context.clone(); @@ -1633,7 +1639,7 @@ impl Global { &self, pipeline_id: id::RenderPipelineId, index: u32, - id_in: Input, + id_in: Input, ) -> ( id::BindGroupLayoutId, Option, @@ -1648,7 +1654,7 @@ impl Global { let id = match pipeline.layout.bind_group_layouts.get(index as usize) { Some(bg) => hub .bind_group_layouts - .prepare::(id_in) + .prepare::(id_in) .assign_existing(bg), None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index), }; @@ -1657,7 +1663,7 @@ impl Global { let id = hub .bind_group_layouts - .prepare::(id_in) + .prepare::(id_in) .assign_error(""); (id, Some(error)) } @@ -1692,7 +1698,7 @@ impl Global { &self, device_id: DeviceId, desc: &pipeline::ComputePipelineDescriptor, - id_in: Input, + id_in: Input, implicit_pipeline_ids: Option>, ) -> ( id::ComputePipelineId, @@ -1702,7 +1708,7 @@ impl Global { let hub = A::hub(self); - let fid = hub.compute_pipelines.prepare::(id_in); + let fid = hub.compute_pipelines.prepare::(id_in); let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub)); let implicit_error_context = implicit_context.clone(); @@ -1766,7 +1772,7 @@ impl Global { &self, pipeline_id: id::ComputePipelineId, index: u32, - id_in: Input, + id_in: Input, ) -> ( id::BindGroupLayoutId, Option, @@ -1782,7 +1788,7 @@ impl Global { let id = match pipeline.layout.bind_group_layouts.get(index as usize) { Some(bg) => hub .bind_group_layouts - .prepare::(id_in) + .prepare::(id_in) .assign_existing(bg), None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index), }; @@ -1792,7 +1798,7 @@ impl Global { let id = hub .bind_group_layouts - .prepare::(id_in) + .prepare::(id_in) .assign_error(""); (id, Some(error)) } @@ -2118,7 +2124,7 @@ impl Global { let (closures, queue_empty) = { if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain { - if submission_index.queue_id != device_id { + if submission_index.queue_id != device_id.transmute() { return Err(WaitIdleError::WrongSubmissionIndex( submission_index.queue_id, device_id, diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index eeae61774..ced987725 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -7,7 +7,7 @@ use crate::{ }, hal_api::HalApi, id::{ - self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, PipelineLayoutId, + self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, Id, PipelineLayoutId, QuerySetId, RenderBundleId, RenderPipelineId, SamplerId, StagingBufferId, TextureId, TextureViewId, }, @@ -419,15 +419,14 @@ impl LifetimeTracker { } impl LifetimeTracker { - fn triage_resources( - resources_map: &mut FastHashMap>, + fn triage_resources( + resources_map: &mut FastHashMap, Arc>, active: &mut [ActiveSubmission], - trackers: &mut impl ResourceTracker, - get_resource_map: impl Fn(&mut ResourceMaps) -> &mut FastHashMap>, + trackers: &mut impl ResourceTracker, + get_resource_map: impl Fn(&mut ResourceMaps) -> &mut FastHashMap, Arc>, ) -> Vec> where - Id: id::TypedId, - R: Resource, + R: Resource, { let mut removed_resources = Vec::new(); resources_map.retain(|&id, resource| { diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 2d5302616..703b21ae9 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -2,7 +2,8 @@ use crate::{ binding_model, hal_api::HalApi, hub::Hub, - id::{self}, + id, + id::markers, identity::{GlobalIdentityHandlerFactory, Input}, resource::{Buffer, BufferAccessResult}, resource::{BufferAccessError, BufferMapOperation}, @@ -463,18 +464,18 @@ pub struct ImplicitPipelineContext { } pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> { - pub root_id: Input, - pub group_ids: &'a [Input], + 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(), + 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).into_id()) + .map(|id_in| hub.bind_group_layouts.prepare::(*id_in).into_id()) .collect(), } } diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 4e56350d8..4bd004622 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -12,6 +12,7 @@ use crate::{ global::Global, hal_api::HalApi, hal_label, + id::markers, id::{self, QueueId}, identity::{GlobalIdentityHandlerFactory, Input}, init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange}, @@ -37,17 +38,19 @@ use super::Device; pub struct Queue { pub device: Option>>, pub raw: Option, - pub info: ResourceInfo, + pub info: ResourceInfo>, } -impl Resource for Queue { +impl Resource for Queue { const TYPE: ResourceType = "Queue"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Queue; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -436,7 +439,7 @@ impl Global { &self, queue_id: QueueId, buffer_size: wgt::BufferSize, - id_in: Input, + id_in: Input, ) -> Result<(id::StagingBufferId, *mut u8), QueueWriteError> { profiling::scope!("Queue::create_staging_buffer"); let hub = A::hub(self); @@ -451,7 +454,7 @@ impl Global { let (staging_buffer, staging_buffer_ptr) = prepare_staging_buffer(device, buffer_size.get(), device.instance_flags)?; - let fid = hub.staging_buffers.prepare::(id_in); + let fid = hub.staging_buffers.prepare::(id_in); let (id, _) = fid.assign(staging_buffer); resource_log!("Queue::create_staging_buffer {id:?}"); @@ -669,7 +672,7 @@ impl Global { .get(destination.texture) .map_err(|_| TransferError::InvalidTexture(destination.texture))?; - if dst.device.as_info().id() != queue_id { + if dst.device.as_info().id() != queue_id.transmute() { return Err(DeviceError::WrongDevice.into()); } @@ -1150,7 +1153,7 @@ impl Global { Err(_) => continue, }; - if cmdbuf.device.as_info().id() != queue_id { + if cmdbuf.device.as_info().id() != queue_id.transmute() { return Err(DeviceError::WrongDevice.into()); } diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index b46bfde69..b9b942449 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -12,7 +12,7 @@ use crate::{ hal_api::HalApi, hal_label, hub::Hub, - id::{self, DeviceId, QueueId}, + id::QueueId, init_tracker::{ BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange, TextureInitTracker, TextureInitTrackerAction, @@ -90,7 +90,7 @@ pub struct Device { pub(crate) queue_id: RwLock>, queue_to_drop: RwLock>, pub(crate) zero_buffer: Option, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) command_allocator: Mutex>>, //Note: The submission index here corresponds to the last submission that is done. @@ -1785,7 +1785,7 @@ impl Device { dynamic_binding_info: &mut Vec, late_buffer_binding_sizes: &mut FastHashMap, used: &mut BindGroupStates, - storage: &'a Storage, id::BufferId>, + storage: &'a Storage>, limits: &wgt::Limits, snatch_guard: &'a SnatchGuard<'a>, ) -> Result, binding_model::CreateBindGroupError> { @@ -2386,7 +2386,7 @@ impl Device { pub(crate) fn create_pipeline_layout( self: &Arc, desc: &binding_model::PipelineLayoutDescriptor, - bgl_registry: &Registry>, + bgl_registry: &Registry>, ) -> Result, binding_model::CreatePipelineLayoutError> { use crate::binding_model::CreatePipelineLayoutError as Error; @@ -2499,8 +2499,8 @@ impl Device { self: &Arc, implicit_context: Option, mut derived_group_layouts: ArrayVec, - bgl_registry: &Registry>, - pipeline_layout_registry: &Registry>, + bgl_registry: &Registry>, + pipeline_layout_registry: &Registry>, ) -> Result>, pipeline::ImplicitLayoutError> { while derived_group_layouts .last() @@ -3440,14 +3440,16 @@ impl Device { } } -impl Resource for Device { +impl Resource for Device { const TYPE: ResourceType = "Device"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Device; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } diff --git a/wgpu-core/src/global.rs b/wgpu-core/src/global.rs index 87271917c..950fabe2d 100644 --- a/wgpu-core/src/global.rs +++ b/wgpu-core/src/global.rs @@ -5,7 +5,6 @@ use wgt::Backend; use crate::{ hal_api::HalApi, hub::{HubReport, Hubs}, - id::SurfaceId, identity::GlobalIdentityHandlerFactory, instance::{Instance, Surface}, registry::{Registry, RegistryReport}, @@ -47,7 +46,7 @@ impl GlobalReport { pub struct Global { pub instance: Instance, - pub surfaces: Registry, + pub surfaces: Registry, pub(crate) hubs: Hubs, _phantom: PhantomData, } diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 22208fdf5..8494bef2b 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -2,10 +2,13 @@ The `wgpu_core` API uses identifiers of type [`Id`] to refer to resources of type `R`. For example, [`id::DeviceId`] is an alias for -`Id>`, and [`id::BufferId`] is an alias for -`Id>`. `Id` implements `Copy`, `Hash`, `Eq`, `Ord`, and +`Id`, and [`id::BufferId`] is an alias for +`Id`. `Id` implements `Copy`, `Hash`, `Eq`, `Ord`, and of course `Debug`. +[`id::DeviceId`]: crate::id::DeviceId +[`id::BufferId`]: crate::id::BufferId + Each `Id` contains not only an index for the resource it denotes but also a Backend indicating which `wgpu` backend it belongs to. You can use the [`gfx_select`] macro to dynamically dispatch on an id's @@ -43,7 +46,7 @@ impl Global { &self, device_id: id::DeviceId, desc: &resource::BufferDescriptor, - id_in: Input, + id_in: Input, ) -> (id::BufferId, Option) { /* ... */ } @@ -115,7 +118,6 @@ use crate::{ command::{CommandBuffer, RenderBundle}, device::{queue::Queue, Device}, hal_api::HalApi, - id, identity::GlobalIdentityHandlerFactory, instance::{Adapter, HalSurface, Surface}, pipeline::{ComputePipeline, RenderPipeline, ShaderModule}, @@ -177,23 +179,23 @@ impl HubReport { /// /// [`A::hub(global)`]: HalApi::hub pub struct Hub { - pub adapters: Registry>, - pub devices: Registry>, - pub queues: Registry>, - pub pipeline_layouts: Registry>, - pub shader_modules: Registry>, - pub bind_group_layouts: Registry>, - pub bind_groups: Registry>, - pub command_buffers: Registry>, - pub render_bundles: Registry>, - pub render_pipelines: Registry>, - pub compute_pipelines: Registry>, - pub query_sets: Registry>, - pub buffers: Registry>, - pub staging_buffers: Registry>, - pub textures: Registry>, - pub texture_views: Registry>, - pub samplers: Registry>, + pub adapters: Registry>, + pub devices: Registry>, + pub queues: Registry>, + pub pipeline_layouts: Registry>, + pub shader_modules: Registry>, + pub bind_group_layouts: Registry>, + pub bind_groups: Registry>, + pub command_buffers: Registry>, + pub render_bundles: Registry>, + pub render_pipelines: Registry>, + pub compute_pipelines: Registry>, + pub query_sets: Registry>, + pub buffers: Registry>, + pub staging_buffers: Registry>, + pub textures: Registry>, + pub texture_views: Registry>, + pub samplers: Registry>, } impl Hub { @@ -222,11 +224,7 @@ impl Hub { //TODO: instead of having a hacky `with_adapters` parameter, // we should have `clear_device(device_id)` that specifically destroys // everything related to a logical device. - pub(crate) fn clear( - &self, - surface_guard: &Storage, - with_adapters: bool, - ) { + pub(crate) fn clear(&self, surface_guard: &Storage, with_adapters: bool) { use hal::Surface; let mut devices = self.devices.write(); diff --git a/wgpu-core/src/id.rs b/wgpu-core/src/id.rs index f55a077f6..56eaf6105 100644 --- a/wgpu-core/src/id.rs +++ b/wgpu-core/src/id.rs @@ -1,6 +1,5 @@ use crate::{Epoch, Index}; use std::{ - any::Any, cmp::Ordering, fmt::{self, Debug}, hash::Hash, @@ -9,15 +8,74 @@ use std::{ use wgt::{Backend, WasmNotSendSync}; type IdType = u64; -type NonZeroId = std::num::NonZeroU64; type ZippedIndex = Index; +type NonZeroId = std::num::NonZeroU64; const INDEX_BITS: usize = std::mem::size_of::() * 8; const EPOCH_BITS: usize = INDEX_BITS - BACKEND_BITS; const BACKEND_BITS: usize = 3; const BACKEND_SHIFT: usize = INDEX_BITS * 2 - BACKEND_BITS; pub const EPOCH_MASK: u32 = (1 << (EPOCH_BITS)) - 1; -type Dummy = hal::api::Empty; + +/// The raw underlying representation of an identifier. +#[repr(transparent)] +#[cfg_attr(any(feature = "serde", feature = "trace"), derive(serde::Serialize))] +#[cfg_attr(any(feature = "serde", feature = "replay"), derive(serde::Deserialize))] +#[cfg_attr(feature = "trace", serde(into = "SerialId"))] +#[cfg_attr(feature = "replay", serde(from = "SerialId"))] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct RawId(NonZeroId); + +impl RawId { + #[doc(hidden)] + #[inline] + pub fn from_non_zero(non_zero: NonZeroId) -> Self { + Self(non_zero) + } + + #[doc(hidden)] + #[inline] + pub fn into_non_zero(self) -> NonZeroId { + self.0 + } + + /// Zip together an identifier and return its raw underlying representation. + pub fn zip(index: Index, epoch: Epoch, backend: Backend) -> RawId { + assert_eq!(0, epoch >> EPOCH_BITS); + assert_eq!(0, (index as IdType) >> INDEX_BITS); + let v = index as IdType + | ((epoch as IdType) << INDEX_BITS) + | ((backend as IdType) << BACKEND_SHIFT); + Self(NonZeroId::new(v).unwrap()) + } + + /// Unzip a raw identifier into its components. + #[allow(trivial_numeric_casts)] + pub fn unzip(self) -> (Index, Epoch, Backend) { + ( + (self.0.get() as ZippedIndex) as Index, + (((self.0.get() >> INDEX_BITS) as ZippedIndex) & (EPOCH_MASK as ZippedIndex)) as Index, + self.backend(), + ) + } + + pub fn backend(self) -> Backend { + match self.0.get() >> (BACKEND_SHIFT) as u8 { + 0 => Backend::Empty, + 1 => Backend::Vulkan, + 2 => Backend::Metal, + 3 => Backend::Dx12, + 4 => Backend::Gl, + _ => unreachable!(), + } + } +} + +/// Coerce a slice of identifiers into a slice of raw identifiers. +pub fn into_raw_slice(ids: &[Id]) -> &[RawId] { + // SAFETY: Any Id is repr(transparent) over `RawId`. + unsafe { std::slice::from_raw_parts(ids.as_ptr().cast(), ids.len()) } +} /// An identifier for a wgpu object. /// @@ -49,21 +107,13 @@ type Dummy = hal::api::Empty; /// [`Registry`]: crate::hub::Registry /// [`Empty`]: hal::api::Empty #[repr(transparent)] -#[cfg_attr(feature = "trace", derive(serde::Serialize), serde(into = "SerialId"))] +#[cfg_attr(any(feature = "serde", feature = "trace"), derive(serde::Serialize))] +#[cfg_attr(any(feature = "serde", feature = "replay"), derive(serde::Deserialize))] #[cfg_attr( - feature = "replay", - derive(serde::Deserialize), - serde(from = "SerialId") + any(feature = "serde", feature = "trace", feature = "replay"), + serde(transparent) )] -#[cfg_attr( - all(feature = "serde", not(feature = "trace")), - derive(serde::Serialize) -)] -#[cfg_attr( - all(feature = "serde", not(feature = "replay")), - derive(serde::Deserialize) -)] -pub struct Id(NonZeroId, PhantomData); +pub struct Id(RawId, PhantomData); // This type represents Id in a more readable (and editable) way. #[allow(dead_code)] @@ -72,39 +122,40 @@ enum SerialId { // The only variant forces RON to not ignore "Id" Id(Index, Epoch, Backend), } + #[cfg(feature = "trace")] -impl From> for SerialId -where - T: 'static + WasmNotSendSync, -{ - fn from(id: Id) -> Self { +impl From for SerialId { + fn from(id: RawId) -> Self { let (index, epoch, backend) = id.unzip(); Self::Id(index, epoch, backend) } } + #[cfg(feature = "replay")] -impl From for Id -where - T: 'static + WasmNotSendSync, -{ +impl From for RawId { fn from(id: SerialId) -> Self { match id { - SerialId::Id(index, epoch, backend) => TypedId::zip(index, epoch, backend), + SerialId::Id(index, epoch, backend) => RawId::zip(index, epoch, backend), } } } impl Id where - T: 'static + WasmNotSendSync, + T: Marker, { /// # Safety /// /// The raw id must be valid for the type. - pub unsafe fn from_raw(raw: NonZeroId) -> Self { + pub unsafe fn from_raw(raw: RawId) -> Self { Self(raw, PhantomData) } + /// Coerce the identifiers into its raw underlying representation. + pub fn into_raw(self) -> RawId { + self.0 + } + #[allow(dead_code)] pub(crate) fn dummy(index: u32) -> Self { Id::zip(index, 1, Backend::Empty) @@ -115,24 +166,53 @@ where self.backend() != Backend::Empty } + /// Get the backend this identifier corresponds to. + #[inline] pub fn backend(self) -> Backend { - match self.0.get() >> (BACKEND_SHIFT) as u8 { - 0 => Backend::Empty, - 1 => Backend::Vulkan, - 2 => Backend::Metal, - 3 => Backend::Dx12, - 4 => Backend::Gl, - _ => unreachable!(), - } + self.0.backend() + } + + /// Transmute this identifier to one with a different marker trait. + /// + /// Legal use is governed through a sealed trait, however it's correctness + /// depends on the current implementation of `wgpu-core`. + #[inline] + pub const fn transmute>(self) -> Id { + Id(self.0, PhantomData) + } + + #[inline] + pub fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self { + Id(RawId::zip(index, epoch, backend), PhantomData) + } + + #[inline] + pub fn unzip(self) -> (Index, Epoch, Backend) { + self.0.unzip() } } -impl Copy for Id where T: 'static + WasmNotSendSync {} +pub(crate) mod transmute { + // This trait is effectively sealed to prevent illegal transmutes. + pub trait Transmute: super::Marker {} + + // Self-transmute is always legal. + impl Transmute for T where T: super::Marker {} + + // TODO: Remove these once queues have their own identifiers. + impl Transmute for super::markers::Device {} + impl Transmute for super::markers::Queue {} + impl Transmute for super::markers::CommandEncoder {} + impl Transmute for super::markers::CommandBuffer {} +} + +impl Copy for Id where T: Marker {} impl Clone for Id where - T: 'static + WasmNotSendSync, + T: Marker, { + #[inline] fn clone(&self) -> Self { *self } @@ -140,7 +220,7 @@ where impl Debug for Id where - T: 'static + WasmNotSendSync, + T: Marker, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let (index, epoch, backend) = self.unzip(); @@ -159,8 +239,9 @@ where impl Hash for Id where - T: 'static + WasmNotSendSync, + T: Marker, { + #[inline] fn hash(&self, state: &mut H) { self.0.hash(state); } @@ -168,19 +249,21 @@ where impl PartialEq for Id where - T: 'static + WasmNotSendSync, + T: Marker, { + #[inline] fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } -impl Eq for Id where T: 'static + WasmNotSendSync {} +impl Eq for Id where T: Marker {} impl PartialOrd for Id where - T: 'static + WasmNotSendSync, + T: Marker, { + #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } @@ -188,78 +271,73 @@ where impl Ord for Id where - T: 'static + WasmNotSendSync, + T: Marker, { + #[inline] fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) } } -/// Trait carrying methods for direct `Id` access. +/// Marker trait used to determine which types uniquely identify a resource. /// -/// Most `wgpu-core` clients should not use this trait. Unusual clients that -/// need to construct `Id` values directly, or access their components, like the -/// WGPU recording player, may use this trait to do so. -pub trait TypedId: Copy + Debug + Any + 'static + WasmNotSendSync + Eq + Hash { - fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self; - fn unzip(self) -> (Index, Epoch, Backend); - fn into_raw(self) -> NonZeroId; -} +/// For example, `Device` will have the same type of identifier as +/// `Device` because `Device` for any `T` defines the same maker type. +pub trait Marker: 'static + WasmNotSendSync {} -#[allow(trivial_numeric_casts)] -impl TypedId for Id -where - T: 'static + WasmNotSendSync, -{ - fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self { - assert_eq!(0, epoch >> EPOCH_BITS); - assert_eq!(0, (index as IdType) >> INDEX_BITS); - let v = index as IdType - | ((epoch as IdType) << INDEX_BITS) - | ((backend as IdType) << BACKEND_SHIFT); - Id(NonZeroId::new(v).unwrap(), PhantomData) - } +// This allows `()` to be used as a marker type for tests. +// +// We don't want these in production code, since they essentially remove type +// safety, like how identifiers across different types can be compared. +#[cfg(test)] +impl Marker for () {} - fn unzip(self) -> (Index, Epoch, Backend) { - ( - (self.0.get() as ZippedIndex) as Index, - (((self.0.get() >> INDEX_BITS) as ZippedIndex) & (EPOCH_MASK as ZippedIndex)) as Index, - self.backend(), - ) - } +/// Define identifiers for each resource. +macro_rules! ids { + ($( + $(#[$($meta:meta)*])* + pub type $name:ident $marker:ident; + )*) => { + /// Marker types for each resource. + pub mod markers { + $( + #[derive(Debug)] + pub enum $marker {} + impl super::Marker for $marker {} + )* + } - fn into_raw(self) -> NonZeroId { - self.0 + $( + $(#[$($meta)*])* + pub type $name = Id; + )* } } -pub type AdapterId = Id>; -pub type SurfaceId = Id; -// Device -pub type DeviceId = Id>; -pub type QueueId = DeviceId; -// Resource -pub type BufferId = Id>; -pub type StagingBufferId = Id>; -pub type TextureViewId = Id>; -pub type TextureId = Id>; -pub type SamplerId = Id>; -// Binding model -pub type BindGroupLayoutId = Id>; -pub type PipelineLayoutId = Id>; -pub type BindGroupId = Id>; -// Pipeline -pub type ShaderModuleId = Id>; -pub type RenderPipelineId = Id>; -pub type ComputePipelineId = Id>; -// Command -pub type CommandEncoderId = CommandBufferId; -pub type CommandBufferId = Id>; -pub type RenderPassEncoderId = *mut crate::command::RenderPass; -pub type ComputePassEncoderId = *mut crate::command::ComputePass; -pub type RenderBundleEncoderId = *mut crate::command::RenderBundleEncoder; -pub type RenderBundleId = Id>; -pub type QuerySetId = Id>; +ids! { + pub type AdapterId Adapter; + pub type SurfaceId Surface; + pub type DeviceId Device; + pub type QueueId Queue; + pub type BufferId Buffer; + pub type StagingBufferId StagingBuffer; + pub type TextureViewId TextureView; + pub type TextureId Texture; + pub type SamplerId Sampler; + pub type BindGroupLayoutId BindGroupLayout; + pub type PipelineLayoutId PipelineLayout; + pub type BindGroupId BindGroup; + pub type ShaderModuleId ShaderModule; + pub type RenderPipelineId RenderPipeline; + pub type ComputePipelineId ComputePipeline; + pub type CommandEncoderId CommandEncoder; + pub type CommandBufferId CommandBuffer; + pub type RenderPassEncoderId RenderPassEncoder; + pub type ComputePassEncoderId ComputePassEncoder; + pub type RenderBundleEncoderId RenderBundleEncoder; + pub type RenderBundleId RenderBundle; + pub type QuerySetId QuerySet; +} #[test] fn test_id_backend() { @@ -270,7 +348,7 @@ fn test_id_backend() { Backend::Dx12, Backend::Gl, ] { - let id: Id<()> = Id::zip(1, 0, b); + let id = crate::id::Id::<()>::zip(1, 0, b); let (_id, _epoch, backend) = id.unzip(); assert_eq!(id.backend(), b); assert_eq!(backend, b); @@ -292,7 +370,7 @@ fn test_id() { for &i in &indexes { for &e in &epochs { for &b in &backends { - let id: Id<()> = Id::zip(i, e, b); + let id = crate::id::Id::<()>::zip(i, e, b); let (index, epoch, backend) = id.unzip(); assert_eq!(index, i); assert_eq!(epoch, e); diff --git a/wgpu-core/src/identity.rs b/wgpu-core/src/identity.rs index 3f421dd69..44989a6d4 100644 --- a/wgpu-core/src/identity.rs +++ b/wgpu-core/src/identity.rs @@ -2,7 +2,7 @@ use parking_lot::Mutex; use wgt::Backend; use crate::{ - id::{self}, + id::{self, Id, Marker}, Epoch, FastHashMap, Index, }; use std::{fmt::Debug, marker::PhantomData, sync::Arc}; @@ -47,10 +47,10 @@ impl IdentityValues { /// /// The backend is incorporated into the id, so that ids allocated with /// different `backend` values are always distinct. - pub fn alloc(&mut self, backend: Backend) -> I { + pub fn alloc(&mut self, backend: Backend) -> Id { self.count += 1; match self.free.pop() { - Some((index, epoch)) => I::zip(index, epoch + 1, backend), + Some((index, epoch)) => Id::zip(index, epoch + 1, backend), None => { let epoch = 1; let used = self.used.entry(epoch).or_insert_with(Default::default); @@ -60,12 +60,12 @@ impl IdentityValues { 0 }; used.push(index); - I::zip(index, epoch, backend) + Id::zip(index, epoch, backend) } } } - pub fn mark_as_used(&mut self, id: I) -> I { + pub fn mark_as_used(&mut self, id: Id) -> Id { self.count += 1; let (index, epoch, _backend) = id.unzip(); let used = self.used.entry(epoch).or_insert_with(Default::default); @@ -74,7 +74,7 @@ impl IdentityValues { } /// Free `id`. It will never be returned from `alloc` again. - pub fn release(&mut self, id: I) { + pub fn release(&mut self, id: Id) { let (index, epoch, _backend) = id.unzip(); self.free.push((index, epoch)); self.count -= 1; @@ -86,24 +86,24 @@ impl IdentityValues { } #[derive(Debug)] -pub struct IdentityManager { +pub struct IdentityManager { pub(super) values: Mutex, - _phantom: PhantomData, + _phantom: PhantomData, } -impl IdentityManager { - pub fn process(&self, backend: Backend) -> I { +impl IdentityManager { + pub fn process(&self, backend: Backend) -> Id { self.values.lock().alloc(backend) } - pub fn mark_as_used(&self, id: I) -> I { + pub fn mark_as_used(&self, id: Id) -> Id { self.values.lock().mark_as_used(id) } - pub fn free(&self, id: I) { + pub fn free(&self, id: Id) { self.values.lock().release(id) } } -impl IdentityManager { +impl IdentityManager { pub fn new() -> Self { Self { values: Mutex::new(IdentityValues::default()), @@ -115,7 +115,7 @@ impl IdentityManager { /// A type that can produce [`IdentityManager`] filters for ids of type `I`. /// /// See the module-level documentation for details. -pub trait IdentityHandlerFactory { +pub trait IdentityHandlerFactory { type Input: Copy; /// Create an [`IdentityManager`] implementation that can /// transform proto-ids into ids of type `I`. @@ -123,11 +123,11 @@ pub trait IdentityHandlerFactory { /// and are not generated by wgpu /// /// [`IdentityManager`]: IdentityManager - fn spawn(&self) -> Arc> { + fn spawn(&self) -> Arc> { Arc::new(IdentityManager::new()) } fn autogenerate_ids() -> bool; - fn input_to_id(id_in: Self::Input) -> I; + fn input_to_id(id_in: Self::Input) -> Id; } /// A global identity handler factory based on [`IdentityManager`]. @@ -138,13 +138,13 @@ pub trait IdentityHandlerFactory { #[derive(Debug)] pub struct IdentityManagerFactory; -impl IdentityHandlerFactory for IdentityManagerFactory { +impl IdentityHandlerFactory for IdentityManagerFactory { type Input = (); fn autogenerate_ids() -> bool { true } - fn input_to_id(_id_in: Self::Input) -> I { + fn input_to_id(_id_in: Self::Input) -> Id { unreachable!("It should not be called") } } @@ -152,23 +152,25 @@ impl IdentityHandlerFactory for IdentityManagerFactory { /// A factory that can build [`IdentityManager`]s for all resource /// types. pub trait GlobalIdentityHandlerFactory: - IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory - + IdentityHandlerFactory + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory + + IdentityHandlerFactory { } @@ -178,8 +180,7 @@ pub type Input = >::Input; #[test] fn test_epoch_end_of_life() { - use id::TypedId as _; - let man = IdentityManager::::new(); + let man = IdentityManager::::new(); let forced_id = man.mark_as_used(id::BufferId::zip(0, 1, Backend::Empty)); assert_eq!(forced_id.unzip().0, 0); let id1 = man.process(Backend::Empty); diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 158a30577..cb5871d6b 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -6,6 +6,7 @@ use crate::{ device::{queue::Queue, resource::Device, DeviceDescriptor}, global::Global, hal_api::HalApi, + id::markers, id::{AdapterId, DeviceId, QueueId, SurfaceId}, identity::{GlobalIdentityHandlerFactory, Input}, present::Presentation, @@ -149,18 +150,20 @@ impl Instance { pub struct Surface { pub(crate) presentation: Mutex>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo, pub(crate) raw: AnySurface, } -impl Resource for Surface { +impl Resource for Surface { const TYPE: ResourceType = "Surface"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Surface; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } @@ -190,7 +193,7 @@ impl Surface { pub struct Adapter { pub(crate) raw: hal::ExposedAdapter, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, } impl Adapter { @@ -382,14 +385,16 @@ impl Adapter { } } -impl Resource for Adapter { +impl Resource for Adapter { const TYPE: ResourceType = "Adapter"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Adapter; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -478,7 +483,7 @@ impl Global { &self, display_handle: raw_window_handle::RawDisplayHandle, window_handle: raw_window_handle::RawWindowHandle, - id_in: Input, + id_in: Input, ) -> Result { profiling::scope!("Instance::create_surface"); @@ -526,7 +531,7 @@ impl Global { raw: hal_surface, }; - let (id, _) = self.surfaces.prepare::(id_in).assign(surface); + let (id, _) = self.surfaces.prepare::(id_in).assign(surface); Ok(id) } @@ -537,7 +542,7 @@ impl Global { pub unsafe fn instance_create_surface_metal( &self, layer: *mut std::ffi::c_void, - id_in: Input, + id_in: Input, ) -> SurfaceId { profiling::scope!("Instance::create_surface_metal"); @@ -561,7 +566,7 @@ impl Global { }, }; - let (id, _) = self.surfaces.prepare::(id_in).assign(surface); + let (id, _) = self.surfaces.prepare::(id_in).assign(surface); id } @@ -572,7 +577,7 @@ impl Global { pub unsafe fn instance_create_surface_from_visual( &self, visual: *mut std::ffi::c_void, - id_in: Input, + id_in: Input, ) -> SurfaceId { profiling::scope!("Instance::instance_create_surface_from_visual"); @@ -592,7 +597,7 @@ impl Global { }, }; - let (id, _) = self.surfaces.prepare::(id_in).assign(surface); + let (id, _) = self.surfaces.prepare::(id_in).assign(surface); id } @@ -603,7 +608,7 @@ impl Global { pub unsafe fn instance_create_surface_from_surface_handle( &self, surface_handle: *mut std::ffi::c_void, - id_in: Input, + id_in: Input, ) -> SurfaceId { profiling::scope!("Instance::instance_create_surface_from_surface_handle"); @@ -625,7 +630,7 @@ impl Global { }, }; - let (id, _) = self.surfaces.prepare::(id_in).assign(surface); + let (id, _) = self.surfaces.prepare::(id_in).assign(surface); id } @@ -636,7 +641,7 @@ impl Global { pub unsafe fn instance_create_surface_from_swap_chain_panel( &self, swap_chain_panel: *mut std::ffi::c_void, - id_in: Input, + id_in: Input, ) -> SurfaceId { profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel"); @@ -658,7 +663,7 @@ impl Global { }, }; - let (id, _) = self.surfaces.prepare::(id_in).assign(surface); + let (id, _) = self.surfaces.prepare::(id_in).assign(surface); id } @@ -703,7 +708,7 @@ impl Global { &self, _: A, instance: &Option, - inputs: &AdapterInputs>, + inputs: &AdapterInputs>, list: &mut Vec, ) { let inst = match *instance { @@ -722,12 +727,15 @@ impl Global { for raw in hal_adapters { let adapter = Adapter::new(raw); log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info); - let (id, _) = hub.adapters.prepare::(id_backend).assign(adapter); + let (id, _) = hub.adapters.prepare::(id_backend).assign(adapter); list.push(id); } } - pub fn enumerate_adapters(&self, inputs: AdapterInputs>) -> Vec { + pub fn enumerate_adapters( + &self, + inputs: AdapterInputs>, + ) -> Vec { profiling::scope!("Instance::enumerate_adapters"); api_log!("Instance::enumerate_adapters"); @@ -758,7 +766,7 @@ impl Global { fn select( &self, selected: &mut usize, - new_id: Option>, + new_id: Option>, mut list: Vec>, ) -> Option { match selected.checked_sub(list.len()) { @@ -771,7 +779,7 @@ impl Global { log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info); let (id, _) = HalApi::hub(self) .adapters - .prepare::(new_id.unwrap()) + .prepare::(new_id.unwrap()) .assign(adapter); Some(id) } @@ -781,7 +789,7 @@ impl Global { pub fn request_adapter( &self, desc: &RequestAdapterOptions, - inputs: AdapterInputs>, + inputs: AdapterInputs>, ) -> Result { profiling::scope!("Instance::request_adapter"); api_log!("Instance::request_adapter"); @@ -947,24 +955,23 @@ impl Global { pub unsafe fn create_adapter_from_hal( &self, hal_adapter: hal::ExposedAdapter, - input: Input, + input: Input, ) -> AdapterId { profiling::scope!("Instance::create_adapter_from_hal"); - let fid = A::hub(self).adapters.prepare::(input); + let fid = A::hub(self).adapters.prepare::(input); - let (id, _adapter): (crate::id::Id>, Arc>) = - match A::VARIANT { - #[cfg(vulkan)] - Backend::Vulkan => fid.assign(Adapter::new(hal_adapter)), - #[cfg(metal)] - Backend::Metal => fid.assign(Adapter::new(hal_adapter)), - #[cfg(dx12)] - Backend::Dx12 => fid.assign(Adapter::new(hal_adapter)), - #[cfg(gles)] - Backend::Gl => fid.assign(Adapter::new(hal_adapter)), - _ => unreachable!(), - }; + let (id, _adapter): (_, Arc>) = match A::VARIANT { + #[cfg(vulkan)] + Backend::Vulkan => fid.assign(Adapter::new(hal_adapter)), + #[cfg(metal)] + Backend::Metal => fid.assign(Adapter::new(hal_adapter)), + #[cfg(dx12)] + Backend::Dx12 => fid.assign(Adapter::new(hal_adapter)), + #[cfg(gles)] + Backend::Gl => fid.assign(Adapter::new(hal_adapter)), + _ => unreachable!(), + }; resource_log!("Created Adapter {:?}", id); id } @@ -1065,15 +1072,15 @@ impl Global { adapter_id: AdapterId, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, - device_id_in: Input, - queue_id_in: Input, + device_id_in: Input, + queue_id_in: Input, ) -> (DeviceId, QueueId, Option) { profiling::scope!("Adapter::request_device"); api_log!("Adapter::request_device"); let hub = A::hub(self); - let device_fid = hub.devices.prepare::(device_id_in); - let queue_fid = hub.queues.prepare::(queue_id_in); + let device_fid = hub.devices.prepare::(device_id_in); + let queue_fid = hub.queues.prepare::(queue_id_in); let error = loop { let adapter = match hub.adapters.get(adapter_id) { @@ -1114,14 +1121,14 @@ impl Global { hal_device: OpenDevice, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, - device_id_in: Input, - queue_id_in: Input, + device_id_in: Input, + queue_id_in: Input, ) -> (DeviceId, QueueId, Option) { profiling::scope!("Global::create_device_from_hal"); let hub = A::hub(self); - let devices_fid = hub.devices.prepare::(device_id_in); - let queues_fid = hub.queues.prepare::(queue_id_in); + let devices_fid = hub.devices.prepare::(device_id_in); + let queues_fid = hub.queues.prepare::(queue_id_in); let error = loop { let adapter = match hub.adapters.get(adapter_id) { diff --git a/wgpu-core/src/pipeline.rs b/wgpu-core/src/pipeline.rs index b6c3bf5bf..c40eb1d82 100644 --- a/wgpu-core/src/pipeline.rs +++ b/wgpu-core/src/pipeline.rs @@ -5,7 +5,7 @@ use crate::{ command::ColorAttachmentError, device::{Device, DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext}, hal_api::HalApi, - id::{ComputePipelineId, PipelineLayoutId, RenderPipelineId, ShaderModuleId}, + id::{PipelineLayoutId, ShaderModuleId}, resource::{Resource, ResourceInfo, ResourceType}, resource_log, validation, Label, }; @@ -50,7 +50,7 @@ pub struct ShaderModule { pub(crate) raw: Option, pub(crate) device: Arc>, pub(crate) interface: Option, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) label: String, } @@ -70,14 +70,16 @@ impl Drop for ShaderModule { } } -impl Resource for ShaderModule { +impl Resource for ShaderModule { const TYPE: ResourceType = "ShaderModule"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::ShaderModule; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } @@ -267,7 +269,7 @@ pub struct ComputePipeline { pub(crate) device: Arc>, pub(crate) _shader_module: Arc>, pub(crate) late_sized_buffer_groups: ArrayVec, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, } impl Drop for ComputePipeline { @@ -288,14 +290,16 @@ impl Drop for ComputePipeline { } } -impl Resource for ComputePipeline { +impl Resource for ComputePipeline { const TYPE: ResourceType = "ComputePipeline"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::ComputePipeline; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -515,7 +519,7 @@ pub struct RenderPipeline { pub(crate) strip_index_format: Option, pub(crate) vertex_steps: Vec, pub(crate) late_sized_buffer_groups: ArrayVec, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, } impl Drop for RenderPipeline { @@ -536,14 +540,16 @@ impl Drop for RenderPipeline { } } -impl Resource for RenderPipeline { +impl Resource for RenderPipeline { const TYPE: ResourceType = "RenderPipeline"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::RenderPipeline; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 00a2953ea..081ab736d 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -23,6 +23,7 @@ use crate::{ global::Global, hal_api::HalApi, hal_label, + id::markers, id::{SurfaceId, TextureId}, identity::{GlobalIdentityHandlerFactory, Input}, init_tracker::TextureInitTracker, @@ -125,13 +126,13 @@ impl Global { pub fn surface_get_current_texture( &self, surface_id: SurfaceId, - texture_id_in: Input, + texture_id_in: Input, ) -> Result { profiling::scope!("SwapChain::get_next_texture"); let hub = A::hub(self); - let fid = hub.textures.prepare::(texture_id_in); + let fid = hub.textures.prepare::(texture_id_in); let surface = self .surfaces diff --git a/wgpu-core/src/registry.rs b/wgpu-core/src/registry.rs index feb32903a..c2b8c38d9 100644 --- a/wgpu-core/src/registry.rs +++ b/wgpu-core/src/registry.rs @@ -4,7 +4,7 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use wgt::Backend; use crate::{ - id, + id::{self, Id, Marker}, identity::{IdentityHandlerFactory, IdentityManager}, resource::Resource, storage::{Element, InvalidId, Storage}, @@ -37,14 +37,14 @@ impl RegistryReport { /// any other dependent resource /// #[derive(Debug)] -pub struct Registry> { - identity: Arc>, - storage: RwLock>, +pub struct Registry { + identity: Arc>, + storage: RwLock>, backend: Backend, } -impl> Registry { - pub(crate) fn new>(backend: Backend, factory: &F) -> Self { +impl Registry { + pub(crate) fn new>(backend: Backend, factory: &F) -> Self { Self { identity: factory.spawn(), storage: RwLock::new(Storage::new()), @@ -52,25 +52,25 @@ impl> Registry { } } - pub(crate) fn without_backend>(factory: &F) -> Self { + pub(crate) fn without_backend>(factory: &F) -> Self { Self::new(Backend::Empty, factory) } } #[must_use] -pub(crate) struct FutureId<'a, I: id::TypedId, T: Resource> { - id: I, - identity: Arc>, - data: &'a RwLock>, +pub(crate) struct FutureId<'a, T: Resource> { + id: Id, + identity: Arc>, + data: &'a RwLock>, } -impl> FutureId<'_, I, T> { +impl FutureId<'_, T> { #[allow(dead_code)] - pub fn id(&self) -> I { + pub fn id(&self) -> Id { self.id } - pub fn into_id(self) -> I { + pub fn into_id(self) -> Id { self.id } @@ -82,7 +82,7 @@ impl> FutureId<'_, I, T> { /// Assign a new resource to this ID. /// /// Registers it with the registry, and fills out the resource info. - pub fn assign(self, value: T) -> (I, Arc) { + pub fn assign(self, value: T) -> (Id, Arc) { let mut data = self.data.write(); data.insert(self.id, self.init(value)); (self.id, data.get(self.id).unwrap().clone()) @@ -94,73 +94,76 @@ impl> FutureId<'_, I, T> { /// /// This _will_ leak the ID, and it will not be recycled again. /// See https://github.com/gfx-rs/wgpu/issues/4912. - pub fn assign_existing(self, value: &Arc) -> I { + pub fn assign_existing(self, value: &Arc) -> Id { let mut data = self.data.write(); debug_assert!(!data.contains(self.id)); data.insert(self.id, value.clone()); self.id } - pub fn assign_error(self, label: &str) -> I { + pub fn assign_error(self, label: &str) -> Id { self.data.write().insert_error(self.id, label); self.id } } -impl> Registry { - pub(crate) fn prepare(&self, id_in: F::Input) -> FutureId +impl Registry { + pub(crate) fn prepare(&self, id_in: F::Input) -> FutureId where - F: IdentityHandlerFactory, + F: IdentityHandlerFactory, + T::Marker: id::transmute::Transmute, { FutureId { id: if F::autogenerate_ids() { self.identity.process(self.backend) } else { - self.identity.mark_as_used(F::input_to_id(id_in)) + self.identity + .mark_as_used(F::input_to_id(id_in).transmute()) }, identity: self.identity.clone(), data: &self.storage, } } - pub(crate) fn request(&self) -> FutureId { + + pub(crate) fn request(&self) -> FutureId { FutureId { id: self.identity.process(self.backend), identity: self.identity.clone(), data: &self.storage, } } - pub(crate) fn try_get(&self, id: I) -> Result>, InvalidId> { + pub(crate) fn try_get(&self, id: Id) -> Result>, InvalidId> { self.read().try_get(id).map(|o| o.cloned()) } - pub(crate) fn get(&self, id: I) -> Result, InvalidId> { + pub(crate) fn get(&self, id: Id) -> Result, InvalidId> { self.read().get_owned(id) } - pub(crate) fn read<'a>(&'a self) -> RwLockReadGuard<'a, Storage> { + pub(crate) fn read<'a>(&'a self) -> RwLockReadGuard<'a, Storage> { self.storage.read() } - pub(crate) fn write<'a>(&'a self) -> RwLockWriteGuard<'a, Storage> { + pub(crate) fn write<'a>(&'a self) -> RwLockWriteGuard<'a, Storage> { self.storage.write() } - pub fn unregister_locked(&self, id: I, storage: &mut Storage) -> Option> { + pub fn unregister_locked(&self, id: Id, storage: &mut Storage) -> Option> { storage.remove(id) } - pub fn force_replace(&self, id: I, mut value: T) { + pub fn force_replace(&self, id: Id, mut value: T) { let mut storage = self.storage.write(); value.as_info_mut().set_id(id, &self.identity); storage.force_replace(id, value) } - pub fn force_replace_with_error(&self, id: I, label: &str) { + pub fn force_replace_with_error(&self, id: Id, label: &str) { let mut storage = self.storage.write(); storage.remove(id); storage.insert_error(id, label); } - pub(crate) fn unregister(&self, id: I) -> Option> { + pub(crate) fn unregister(&self, id: Id) -> Option> { let value = self.storage.write().remove(id); //Returning None is legal if it's an error ID value } - pub fn label_for_resource(&self, id: I) -> String { + pub fn label_for_resource(&self, id: Id) -> String { let guard = self.storage.read(); let type_name = guard.kind(); diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 85384939f..fad1aa610 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -8,10 +8,7 @@ use crate::{ }, global::Global, hal_api::HalApi, - id::{ - AdapterId, BufferId, DeviceId, QuerySetId, SamplerId, StagingBufferId, SurfaceId, - TextureId, TextureViewId, TypedId, - }, + id::{AdapterId, BufferId, DeviceId, Id, Marker, SurfaceId, TextureId}, identity::{GlobalIdentityHandlerFactory, IdentityManager}, init_tracker::{BufferInitTracker, TextureInitTracker}, resource, resource_log, @@ -59,9 +56,9 @@ use std::{ /// [`Device`]: crate::device::resource::Device /// [`Buffer`]: crate::resource::Buffer #[derive(Debug)] -pub struct ResourceInfo { - id: Option, - identity: Option>>, +pub struct ResourceInfo { + id: Option>, + identity: Option>>, /// The index of the last queue submission in which the resource /// was used. /// @@ -75,7 +72,7 @@ pub struct ResourceInfo { pub(crate) label: String, } -impl Drop for ResourceInfo { +impl Drop for ResourceInfo { fn drop(&mut self) { if let Some(identity) = self.identity.as_ref() { let id = self.id.as_ref().unwrap(); @@ -84,7 +81,7 @@ impl Drop for ResourceInfo { } } -impl ResourceInfo { +impl ResourceInfo { #[allow(unused_variables)] pub(crate) fn new(label: &str) -> Self { Self { @@ -97,7 +94,7 @@ impl ResourceInfo { pub(crate) fn label(&self) -> &dyn Debug where - Id: Debug, + Id: Debug, { if !self.label.is_empty() { return &self.label; @@ -110,11 +107,11 @@ impl ResourceInfo { &"" } - pub(crate) fn id(&self) -> Id { + pub(crate) fn id(&self) -> Id { self.id.unwrap() } - pub(crate) fn set_id(&mut self, id: Id, identity: &Arc>) { + pub(crate) fn set_id(&mut self, id: Id, identity: &Arc>) { self.id = Some(id); self.identity = Some(identity.clone()); } @@ -133,10 +130,11 @@ impl ResourceInfo { pub(crate) type ResourceType = &'static str; -pub trait Resource: 'static + WasmNotSendSync { +pub trait Resource: 'static + Sized + WasmNotSendSync { + type Marker: Marker; const TYPE: ResourceType; - fn as_info(&self) -> &ResourceInfo; - fn as_info_mut(&mut self) -> &mut ResourceInfo; + fn as_info(&self) -> &ResourceInfo; + fn as_info_mut(&mut self) -> &mut ResourceInfo; fn label(&self) -> String { self.as_info().label.clone() } @@ -377,7 +375,7 @@ pub struct Buffer { pub(crate) size: wgt::BufferAddress, pub(crate) initialization_status: RwLock, pub(crate) sync_mapped_writes: Mutex>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) map_state: Mutex>, pub(crate) bind_groups: Mutex>>>, } @@ -592,14 +590,16 @@ pub enum CreateBufferError { MissingDownlevelFlags(#[from] MissingDownlevelFlags), } -impl Resource for Buffer { +impl Resource for Buffer { const TYPE: ResourceType = "Buffer"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Buffer; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -693,7 +693,7 @@ pub struct StagingBuffer { pub(crate) device: Arc>, pub(crate) size: wgt::BufferAddress, pub(crate) is_coherent: bool, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, } impl Drop for StagingBuffer { @@ -708,14 +708,16 @@ impl Drop for StagingBuffer { } } -impl Resource for StagingBuffer { +impl Resource for StagingBuffer { const TYPE: ResourceType = "StagingBuffer"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::StagingBuffer; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } @@ -773,7 +775,7 @@ pub struct Texture { pub(crate) format_features: wgt::TextureFormatFeatures, pub(crate) initialization_status: RwLock, pub(crate) full_range: TextureSelector, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, pub(crate) clear_mode: RwLock>, pub(crate) views: Mutex>>>, pub(crate) bind_groups: Mutex>>>, @@ -1166,14 +1168,16 @@ pub enum CreateTextureError { MissingDownlevelFlags(#[from] MissingDownlevelFlags), } -impl Resource for Texture { +impl Resource for Texture { const TYPE: ResourceType = "Texture"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Texture; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -1251,7 +1255,7 @@ pub struct TextureView { pub(crate) render_extent: Result, pub(crate) samples: u32, pub(crate) selector: TextureSelector, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo>, } impl Drop for TextureView { @@ -1329,14 +1333,16 @@ pub enum CreateTextureViewError { #[non_exhaustive] pub enum TextureViewDestroyError {} -impl Resource for TextureView { +impl Resource for TextureView { const TYPE: ResourceType = "TextureView"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::TextureView; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -1374,7 +1380,7 @@ pub struct SamplerDescriptor<'a> { pub struct Sampler { pub(crate) raw: Option, pub(crate) device: Arc>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo, /// `true` if this is a comparison sampler pub(crate) comparison: bool, /// `true` if this is a filtering sampler @@ -1448,14 +1454,16 @@ pub enum CreateSamplerError { MissingFeatures(#[from] MissingFeatures), } -impl Resource for Sampler { +impl Resource for Sampler { const TYPE: ResourceType = "Sampler"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::Sampler; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } @@ -1479,7 +1487,7 @@ pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor>; pub struct QuerySet { pub(crate) raw: Option, pub(crate) device: Arc>, - pub(crate) info: ResourceInfo, + pub(crate) info: ResourceInfo, pub(crate) desc: wgt::QuerySetDescriptor<()>, } @@ -1500,14 +1508,16 @@ impl Drop for QuerySet { } } -impl Resource for QuerySet { +impl Resource for QuerySet { const TYPE: ResourceType = "QuerySet"; - fn as_info(&self) -> &ResourceInfo { + type Marker = crate::id::markers::QuerySet; + + fn as_info(&self) -> &ResourceInfo { &self.info } - fn as_info_mut(&mut self) -> &mut ResourceInfo { + fn as_info_mut(&mut self) -> &mut ResourceInfo { &mut self.info } } diff --git a/wgpu-core/src/storage.rs b/wgpu-core/src/storage.rs index 3e7a8f44f..62e7af7c8 100644 --- a/wgpu-core/src/storage.rs +++ b/wgpu-core/src/storage.rs @@ -1,8 +1,11 @@ -use std::{marker::PhantomData, ops, sync::Arc}; +use std::ops; +use std::sync::Arc; use wgt::Backend; -use crate::{id, resource::Resource, Epoch, Index}; +use crate::id::Id; +use crate::resource::Resource; +use crate::{Epoch, Index}; /// An entry in a `Storage::map` table. #[derive(Debug)] @@ -30,47 +33,41 @@ pub(crate) struct InvalidId; /// values, so you should use an id allocator like `IdentityManager` /// that keeps the index values dense and close to zero. #[derive(Debug)] -pub struct Storage +pub struct Storage where - T: Resource, - I: id::TypedId, + T: Resource, { pub(crate) map: Vec>, kind: &'static str, - _phantom: PhantomData, } -impl ops::Index for Storage +impl ops::Index> for Storage where - T: Resource, - I: id::TypedId, + T: Resource, { type Output = Arc; - fn index(&self, id: I) -> &Arc { + fn index(&self, id: Id) -> &Arc { self.get(id).unwrap() } } -impl Storage +impl Storage where - T: Resource, - I: id::TypedId, + T: Resource, { pub(crate) fn new() -> Self { Self { map: Vec::new(), kind: T::TYPE, - _phantom: PhantomData, } } } -impl Storage +impl Storage where - T: Resource, - I: id::TypedId, + T: Resource, { #[allow(dead_code)] - pub(crate) fn contains(&self, id: I) -> bool { + pub(crate) fn contains(&self, id: Id) -> bool { let (index, epoch, _) = id.unzip(); match self.map.get(index as usize) { Some(&Element::Vacant) => false, @@ -88,7 +85,7 @@ where /// This function is primarily intended for the `as_hal` family of functions /// where you may need to fallibly get a object backed by an id that could /// be in a different hub. - pub(crate) fn try_get(&self, id: I) -> Result>, InvalidId> { + pub(crate) fn try_get(&self, id: Id) -> Result>, InvalidId> { let (index, epoch, _) = id.unzip(); let (result, storage_epoch) = match self.map.get(index as usize) { Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch), @@ -106,7 +103,7 @@ where /// Get a reference to an item behind a potentially invalid ID. /// Panics if there is an epoch mismatch, or the entry is empty. - pub(crate) fn get(&self, id: I) -> Result<&Arc, InvalidId> { + pub(crate) fn get(&self, id: Id) -> Result<&Arc, InvalidId> { let (index, epoch, _) = id.unzip(); let (result, storage_epoch) = match self.map.get(index as usize) { Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch), @@ -124,11 +121,11 @@ where /// Get an owned reference to an item behind a potentially invalid ID. /// Panics if there is an epoch mismatch, or the entry is empty. - pub(crate) fn get_owned(&self, id: I) -> Result, InvalidId> { + pub(crate) fn get_owned(&self, id: Id) -> Result, InvalidId> { Ok(Arc::clone(self.get(id)?)) } - pub(crate) fn label_for_invalid_id(&self, id: I) -> &str { + pub(crate) fn label_for_invalid_id(&self, id: Id) -> &str { let (index, _, _) = id.unzip(); match self.map.get(index as usize) { Some(Element::Error(_, label)) => label, @@ -161,13 +158,13 @@ where } } - pub(crate) fn insert(&mut self, id: I, value: Arc) { + pub(crate) fn insert(&mut self, id: Id, value: Arc) { log::trace!("User is inserting {}{:?}", T::TYPE, id); let (index, epoch, _backend) = id.unzip(); self.insert_impl(index as usize, epoch, Element::Occupied(value, epoch)) } - pub(crate) fn insert_error(&mut self, id: I, label: &str) { + pub(crate) fn insert_error(&mut self, id: Id, label: &str) { log::trace!("User is insering as error {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); self.insert_impl( @@ -177,7 +174,7 @@ where ) } - pub(crate) fn replace_with_error(&mut self, id: I) -> Result, InvalidId> { + pub(crate) fn replace_with_error(&mut self, id: Id) -> Result, InvalidId> { let (index, epoch, _) = id.unzip(); match std::mem::replace( &mut self.map[index as usize], @@ -192,13 +189,13 @@ where } } - pub(crate) fn force_replace(&mut self, id: I, value: T) { + pub(crate) fn force_replace(&mut self, id: Id, value: T) { log::trace!("User is replacing {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); self.map[index as usize] = Element::Occupied(Arc::new(value), epoch); } - pub(crate) fn remove(&mut self, id: I) -> Option> { + pub(crate) fn remove(&mut self, id: Id) -> Option> { log::trace!("User is removing {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); match std::mem::replace(&mut self.map[index as usize], Element::Vacant) { @@ -211,13 +208,13 @@ where } } - pub(crate) fn iter(&self, backend: Backend) -> impl Iterator)> { + pub(crate) fn iter(&self, backend: Backend) -> impl Iterator, &Arc)> { self.map .iter() .enumerate() .filter_map(move |(index, x)| match *x { Element::Occupied(ref value, storage_epoch) => { - Some((I::zip(index as Index, storage_epoch, backend), value)) + Some((Id::zip(index as Index, storage_epoch, backend), value)) } _ => None, }) diff --git a/wgpu-core/src/track/buffer.rs b/wgpu-core/src/track/buffer.rs index 2c2a6937f..a9d61f9e0 100644 --- a/wgpu-core/src/track/buffer.rs +++ b/wgpu-core/src/track/buffer.rs @@ -10,7 +10,7 @@ use std::{borrow::Cow, marker::PhantomData, sync::Arc}; use super::{PendingTransition, ResourceTracker}; use crate::{ hal_api::HalApi, - id::{BufferId, TypedId}, + id::BufferId, resource::{Buffer, Resource}, snatch::SnatchGuard, storage::Storage, @@ -26,7 +26,6 @@ use wgt::{strict_assert, strict_assert_eq}; impl ResourceUses for BufferUses { const EXCLUSIVE: Self = Self::EXCLUSIVE; - type Id = BufferId; type Selector = (); fn bits(self) -> u16 { @@ -92,7 +91,7 @@ impl BufferBindGroupState { /// Adds the given resource with the given state. pub fn add_single<'a>( &self, - storage: &'a Storage, BufferId>, + storage: &'a Storage>, id: BufferId, state: BufferUses, ) -> Option<&'a Arc>> { @@ -110,7 +109,7 @@ impl BufferBindGroupState { pub(crate) struct BufferUsageScope { state: Vec, - metadata: ResourceMetadata>, + metadata: ResourceMetadata>, } impl BufferUsageScope { @@ -248,7 +247,7 @@ impl BufferUsageScope { /// the vectors will be extended. A call to set_size is not needed. pub fn merge_single<'a>( &mut self, - storage: &'a Storage, BufferId>, + storage: &'a Storage>, id: BufferId, new_state: BufferUses, ) -> Result<&'a Arc>, UsageConflict> { @@ -288,12 +287,12 @@ pub(crate) struct BufferTracker { start: Vec, end: Vec, - metadata: ResourceMetadata>, + metadata: ResourceMetadata>, temp: Vec>, } -impl ResourceTracker> for BufferTracker { +impl ResourceTracker> for BufferTracker { /// Try to remove the buffer `id` from this tracker if it is otherwise unused. /// /// A buffer is 'otherwise unused' when the only references to it are: @@ -654,11 +653,11 @@ impl BufferStateProvider<'_> { unsafe fn insert_or_merge( start_states: Option<&mut [BufferUses]>, current_states: &mut [BufferUses], - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index32: u32, index: usize, state_provider: BufferStateProvider<'_>, - metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer>, + metadata_provider: ResourceMetadataProvider<'_, A, Buffer>, ) -> Result<(), UsageConflict> { let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; @@ -709,11 +708,11 @@ unsafe fn insert_or_merge( unsafe fn insert_or_barrier_update( start_states: Option<&mut [BufferUses]>, current_states: &mut [BufferUses], - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index: usize, start_state_provider: BufferStateProvider<'_>, end_state_provider: Option>, - metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer>, + metadata_provider: ResourceMetadataProvider<'_, A, Buffer>, barriers: &mut Vec>, ) { let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; @@ -743,11 +742,11 @@ unsafe fn insert_or_barrier_update( unsafe fn insert( start_states: Option<&mut [BufferUses]>, current_states: &mut [BufferUses], - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index: usize, start_state_provider: BufferStateProvider<'_>, end_state_provider: Option>, - metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer>, + metadata_provider: ResourceMetadataProvider<'_, A, Buffer>, ) { let new_start_state = unsafe { start_state_provider.get_state(index) }; let new_end_state = @@ -777,7 +776,7 @@ unsafe fn merge( index32: u32, index: usize, state_provider: BufferStateProvider<'_>, - metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer>, + metadata_provider: ResourceMetadataProvider<'_, A, Buffer>, ) -> Result<(), UsageConflict> { let current_state = unsafe { current_states.get_unchecked_mut(index) }; let new_state = unsafe { state_provider.get_state(index) }; diff --git a/wgpu-core/src/track/metadata.rs b/wgpu-core/src/track/metadata.rs index 3464170eb..76f658206 100644 --- a/wgpu-core/src/track/metadata.rs +++ b/wgpu-core/src/track/metadata.rs @@ -1,6 +1,6 @@ //! The `ResourceMetadata` type. -use crate::{hal_api::HalApi, id::TypedId, resource::Resource, Epoch}; +use crate::{hal_api::HalApi, resource::Resource, Epoch}; use bit_vec::BitVec; use std::{borrow::Cow, marker::PhantomData, mem, sync::Arc}; use wgt::strict_assert; @@ -13,7 +13,7 @@ use wgt::strict_assert; /// members, but a bit vector tracks occupancy, so iteration touches /// only occupied elements. #[derive(Debug)] -pub(super) struct ResourceMetadata> { +pub(super) struct ResourceMetadata { /// If the resource with index `i` is a member, `owned[i]` is `true`. owned: BitVec, @@ -21,10 +21,10 @@ pub(super) struct ResourceMetadata> { resources: Vec>>, /// This tells Rust that this type should be covariant with `A`. - _phantom: PhantomData<(A, I)>, + _phantom: PhantomData, } -impl> ResourceMetadata { +impl ResourceMetadata { pub(super) fn new() -> Self { Self { owned: BitVec::default(), @@ -172,15 +172,15 @@ impl> ResourceMetadata { /// /// This is used to abstract over the various places /// trackers can get new resource metadata from. -pub(super) enum ResourceMetadataProvider<'a, A: HalApi, I: TypedId, T: Resource> { +pub(super) enum ResourceMetadataProvider<'a, A: HalApi, T: Resource> { /// Comes directly from explicit values. Direct { resource: Cow<'a, Arc> }, /// Comes from another metadata tracker. Indirect { - metadata: &'a ResourceMetadata, + metadata: &'a ResourceMetadata, }, } -impl> ResourceMetadataProvider<'_, A, I, T> { +impl ResourceMetadataProvider<'_, A, T> { /// Get the epoch and an owned refcount from this. /// /// # Safety diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index c13e815cb..68975c931 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -104,7 +104,7 @@ mod texture; use crate::{ binding_model, command, conv, hal_api::HalApi, - id::{self, TypedId}, + id::{self, Id}, pipeline, resource, snatch::SnatchGuard, storage::Storage, @@ -182,8 +182,6 @@ pub(crate) trait ResourceUses: /// All flags that are exclusive. const EXCLUSIVE: Self; - /// The relevant resource ID type. - type Id: Copy + fmt::Debug + TypedId; /// The selector used by this resource. type Selector: fmt::Debug; @@ -320,8 +318,8 @@ impl fmt::Display for InvalidUse { pub(crate) struct BindGroupStates { pub buffers: BufferBindGroupState, pub textures: TextureBindGroupState, - pub views: StatelessBindGroupSate>, - pub samplers: StatelessBindGroupSate>, + pub views: StatelessBindGroupSate>, + pub samplers: StatelessBindGroupSate>, } impl BindGroupStates { @@ -354,20 +352,19 @@ pub(crate) struct RenderBundleScope { pub buffers: RwLock>, pub textures: RwLock>, // Don't need to track views and samplers, they are never used directly, only by bind groups. - pub bind_groups: RwLock>>, - pub render_pipelines: - RwLock>>, - pub query_sets: RwLock>>, + pub bind_groups: RwLock>>, + pub render_pipelines: RwLock>>, + pub query_sets: RwLock>>, } impl RenderBundleScope { /// Create the render bundle scope and pull the maximum IDs from the hubs. pub fn new( - buffers: &Storage, id::BufferId>, - textures: &Storage, id::TextureId>, - bind_groups: &Storage, id::BindGroupId>, - render_pipelines: &Storage, id::RenderPipelineId>, - query_sets: &Storage, id::QuerySetId>, + buffers: &Storage>, + textures: &Storage>, + bind_groups: &Storage>, + render_pipelines: &Storage>, + query_sets: &Storage>, ) -> Self { let value = Self { buffers: RwLock::new(BufferUsageScope::new()), @@ -424,8 +421,8 @@ pub(crate) struct UsageScope { impl UsageScope { /// Create the render bundle scope and pull the maximum IDs from the hubs. pub fn new( - buffers: &Storage, id::BufferId>, - textures: &Storage, id::TextureId>, + buffers: &Storage>, + textures: &Storage>, ) -> Self { let mut value = Self { buffers: BufferUsageScope::new(), @@ -481,25 +478,24 @@ impl UsageScope { } } -pub(crate) trait ResourceTracker +pub(crate) trait ResourceTracker where - Id: TypedId, - R: resource::Resource, + R: resource::Resource, { - fn remove_abandoned(&mut self, id: Id) -> bool; + fn remove_abandoned(&mut self, id: Id) -> bool; } /// A full double sided tracker used by CommandBuffers and the Device. pub(crate) struct Tracker { pub buffers: BufferTracker, pub textures: TextureTracker, - pub views: StatelessTracker>, - pub samplers: StatelessTracker>, - pub bind_groups: StatelessTracker>, - pub compute_pipelines: StatelessTracker>, - pub render_pipelines: StatelessTracker>, - pub bundles: StatelessTracker>, - pub query_sets: StatelessTracker>, + pub views: StatelessTracker>, + pub samplers: StatelessTracker>, + pub bind_groups: StatelessTracker>, + pub compute_pipelines: StatelessTracker>, + pub render_pipelines: StatelessTracker>, + pub bundles: StatelessTracker>, + pub query_sets: StatelessTracker>, } impl Tracker { @@ -520,15 +516,15 @@ impl Tracker { /// Pull the maximum IDs from the hubs. pub fn set_size( &mut self, - buffers: Option<&Storage, id::BufferId>>, - textures: Option<&Storage, id::TextureId>>, - views: Option<&Storage, id::TextureViewId>>, - samplers: Option<&Storage, id::SamplerId>>, - bind_groups: Option<&Storage, id::BindGroupId>>, - compute_pipelines: Option<&Storage, id::ComputePipelineId>>, - render_pipelines: Option<&Storage, id::RenderPipelineId>>, - bundles: Option<&Storage, id::RenderBundleId>>, - query_sets: Option<&Storage, id::QuerySetId>>, + buffers: Option<&Storage>>, + textures: Option<&Storage>>, + views: Option<&Storage>>, + samplers: Option<&Storage>>, + bind_groups: Option<&Storage>>, + compute_pipelines: Option<&Storage>>, + render_pipelines: Option<&Storage>>, + bundles: Option<&Storage>>, + query_sets: Option<&Storage>>, ) { if let Some(buffers) = buffers { self.buffers.set_size(buffers.len()); diff --git a/wgpu-core/src/track/stateless.rs b/wgpu-core/src/track/stateless.rs index 6795890cc..c1380e124 100644 --- a/wgpu-core/src/track/stateless.rs +++ b/wgpu-core/src/track/stateless.rs @@ -4,24 +4,27 @@ * distinction between a usage scope and a full tracker. !*/ -use std::{marker::PhantomData, sync::Arc}; +use std::sync::Arc; use parking_lot::Mutex; use crate::{ - hal_api::HalApi, id::TypedId, resource::Resource, resource_log, storage::Storage, + hal_api::HalApi, id::Id, resource::Resource, resource_log, storage::Storage, track::ResourceMetadata, }; use super::ResourceTracker; +/// Satisfy clippy. +type Pair = (Id<::Marker>, Arc); + /// Stores all the resources that a bind group stores. #[derive(Debug)] -pub(crate) struct StatelessBindGroupSate> { - resources: Mutex)>>, +pub(crate) struct StatelessBindGroupSate { + resources: Mutex>>, } -impl> StatelessBindGroupSate { +impl StatelessBindGroupSate { pub fn new() -> Self { Self { resources: Mutex::new(Vec::new()), @@ -58,7 +61,7 @@ impl> StatelessBindGroupSate { } /// Adds the given resource. - pub fn add_single<'a>(&self, storage: &'a Storage, id: Id) -> Option<&'a T> { + pub fn add_single<'a>(&self, storage: &'a Storage, id: Id) -> Option<&'a T> { let resource = storage.get(id).ok()?; let mut resources = self.resources.lock(); @@ -70,14 +73,11 @@ impl> StatelessBindGroupSate { /// Stores all resource state within a command buffer or device. #[derive(Debug)] -pub(crate) struct StatelessTracker> { - metadata: ResourceMetadata, - _phantom: PhantomData, +pub(crate) struct StatelessTracker { + metadata: ResourceMetadata, } -impl> ResourceTracker - for StatelessTracker -{ +impl ResourceTracker for StatelessTracker { /// Try to remove the given resource from the tracker iff we have the last reference to the /// resource and the epoch matches. /// @@ -85,7 +85,7 @@ impl> ResourceTracker /// /// If the ID is higher than the length of internal vectors, /// false will be returned. - fn remove_abandoned(&mut self, id: Id) -> bool { + fn remove_abandoned(&mut self, id: Id) -> bool { let index = id.unzip().0 as usize; if index >= self.metadata.size() { @@ -120,11 +120,10 @@ impl> ResourceTracker } } -impl> StatelessTracker { +impl StatelessTracker { pub fn new() -> Self { Self { metadata: ResourceMetadata::new(), - _phantom: PhantomData, } } @@ -164,7 +163,7 @@ impl> StatelessTracker { /// /// If the ID is higher than the length of internal vectors, /// the vectors will be extended. A call to set_size is not needed. - pub fn insert_single(&mut self, id: Id, resource: Arc) { + pub fn insert_single(&mut self, id: Id, resource: Arc) { let (index32, _epoch, _) = id.unzip(); let index = index32 as usize; @@ -181,7 +180,11 @@ impl> StatelessTracker { /// /// If the ID is higher than the length of internal vectors, /// the vectors will be extended. A call to set_size is not needed. - pub fn add_single<'a>(&mut self, storage: &'a Storage, id: Id) -> Option<&'a Arc> { + pub fn add_single<'a>( + &mut self, + storage: &'a Storage, + id: Id, + ) -> Option<&'a Arc> { let resource = storage.get(id).ok()?; let (index32, _epoch, _) = id.unzip(); @@ -222,7 +225,7 @@ impl> StatelessTracker { } } - pub fn get(&self, id: Id) -> Option<&Arc> { + pub fn get(&self, id: Id) -> Option<&Arc> { let index = id.unzip().0 as usize; if index > self.metadata.size() { return None; diff --git a/wgpu-core/src/track/texture.rs b/wgpu-core/src/track/texture.rs index 94574596a..f42740bf4 100644 --- a/wgpu-core/src/track/texture.rs +++ b/wgpu-core/src/track/texture.rs @@ -22,7 +22,7 @@ use super::{range::RangedStates, PendingTransition, PendingTransitionList, ResourceTracker}; use crate::{ hal_api::HalApi, - id::{TextureId, TypedId}, + id::TextureId, resource::{Resource, Texture, TextureInner}, snatch::SnatchGuard, track::{ @@ -50,7 +50,6 @@ pub struct TextureSelector { impl ResourceUses for TextureUses { const EXCLUSIVE: Self = Self::EXCLUSIVE; - type Id = TextureId; type Selector = TextureSelector; fn bits(self) -> u16 { @@ -232,7 +231,7 @@ impl TextureStateSet { #[derive(Debug)] pub(crate) struct TextureUsageScope { set: TextureStateSet, - metadata: ResourceMetadata>, + metadata: ResourceMetadata>, } impl TextureUsageScope { @@ -387,14 +386,14 @@ pub(crate) struct TextureTracker { start_set: TextureStateSet, end_set: TextureStateSet, - metadata: ResourceMetadata>, + metadata: ResourceMetadata>, temp: Vec>, _phantom: PhantomData, } -impl ResourceTracker> for TextureTracker { +impl ResourceTracker> for TextureTracker { /// Try to remove the given resource from the tracker iff we have the last reference to the /// resource and the epoch matches. /// @@ -864,10 +863,10 @@ impl<'a> TextureStateProvider<'a> { unsafe fn insert_or_merge( texture_selector: &TextureSelector, current_state_set: &mut TextureStateSet, - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index: usize, state_provider: TextureStateProvider<'_>, - metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture>, + metadata_provider: ResourceMetadataProvider<'_, A, Texture>, ) -> Result<(), UsageConflict> { let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; @@ -920,11 +919,11 @@ unsafe fn insert_or_barrier_update( texture_selector: &TextureSelector, start_state: Option<&mut TextureStateSet>, current_state_set: &mut TextureStateSet, - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index: usize, start_state_provider: TextureStateProvider<'_>, end_state_provider: Option>, - metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture>, + metadata_provider: ResourceMetadataProvider<'_, A, Texture>, barriers: &mut Vec>, ) { let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; @@ -973,11 +972,11 @@ unsafe fn insert( texture_selector: Option<&TextureSelector>, start_state: Option<&mut TextureStateSet>, end_state: &mut TextureStateSet, - resource_metadata: &mut ResourceMetadata>, + resource_metadata: &mut ResourceMetadata>, index: usize, start_state_provider: TextureStateProvider<'_>, end_state_provider: Option>, - metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture>, + metadata_provider: ResourceMetadataProvider<'_, A, Texture>, ) { let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) }; match start_layers { @@ -1060,7 +1059,7 @@ unsafe fn merge( current_state_set: &mut TextureStateSet, index: usize, state_provider: TextureStateProvider<'_>, - metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture>, + metadata_provider: ResourceMetadataProvider<'_, A, Texture>, ) -> Result<(), UsageConflict> { let current_simple = unsafe { current_state_set.simple.get_unchecked_mut(index) }; let current_state = if *current_simple == TextureUses::COMPLEX { diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 62f619d64..3aec48fb6 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -24,7 +24,6 @@ use std::{ }; use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*}; use wgc::device::DeviceLostClosure; -use wgc::id::TypedId; use wgt::WasmNotSendSync; const LABEL: &str = "label"; @@ -604,7 +603,7 @@ impl crate::Context for ContextWgpuCore { id: queue_id, error_sink, }; - ready(Ok((device_id, device, device_id, queue))) + ready(Ok((device_id, device, device_id.transmute(), queue))) } fn instance_poll_all_devices(&self, force_wait: bool) -> bool { @@ -1805,7 +1804,8 @@ impl crate::Context for ContextWgpuCore { if let Err(cause) = wgc::gfx_select!( encoder => self.0.command_encoder_run_compute_pass(*encoder, pass_data) ) { - let name = wgc::gfx_select!(encoder => self.0.command_buffer_label(*encoder)); + let name = + wgc::gfx_select!(encoder => self.0.command_buffer_label(encoder.transmute())); self.handle_error( &encoder_data.error_sink, cause, @@ -1888,7 +1888,8 @@ impl crate::Context for ContextWgpuCore { if let Err(cause) = wgc::gfx_select!(encoder => self.0.command_encoder_run_render_pass(*encoder, pass_data)) { - let name = wgc::gfx_select!(encoder => self.0.command_buffer_label(*encoder)); + let name = + wgc::gfx_select!(encoder => self.0.command_buffer_label(encoder.transmute())); self.handle_error( &encoder_data.error_sink, cause, @@ -2922,10 +2923,10 @@ impl crate::Context for ContextWgpuCore { impl From for wgc::id::Id where - T: 'static + WasmNotSendSync, + T: wgc::id::Marker, { fn from(id: ObjectId) -> Self { - let id = id.id(); + let id = wgc::id::RawId::from_non_zero(id.id()); // SAFETY: The id was created via the impl below unsafe { Self::from_raw(id) } } @@ -2933,10 +2934,10 @@ where impl From> for ObjectId where - T: 'static + WasmNotSendSync, + T: wgc::id::Marker, { fn from(id: wgc::id::Id) -> Self { - let id = id.into_raw(); + let id = id.into_raw().into_non_zero(); Self::from_global_id(id) } }