diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index b99887e058..91e796f338 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -225,7 +225,7 @@ impl Global { let device = &cmd_buf.device; if !device.is_valid() { - return Err(ClearError::InvalidDevice(cmd_buf.device_id.value.0)); + return Err(ClearError::InvalidDevice(cmd_buf.device.as_info().id())); } let (encoder, tracker) = cmd_buf_data.open_encoder_and_tracker(); diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 877ef19031..8e8d2bb455 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -371,11 +371,11 @@ impl Global { let device = &cmd_buf.device; if !device.is_valid() { return Err(ComputePassErrorInner::InvalidDevice( - cmd_buf.device_id.value.0, + cmd_buf.device.as_info().id(), )) .map_pass_err(init_scope); } - + 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/command/render.rs b/wgpu-core/src/command/render.rs index 284d61e33f..02704b3e5e 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -1307,11 +1307,11 @@ impl Global { occlusion_query_set_id, }); } - + let device = &cmd_buf.device; if !device.is_valid() { return Err(RenderPassErrorInner::InvalidDevice( - cmd_buf.device_id.value.0, + cmd_buf.device.as_info().id(), )) .map_pass_err(init_scope); } diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 4afbc97ed8..9e24e16c4e 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -7,13 +7,13 @@ use crate::{ error::{ErrorFormatter, PrettyError}, global::Global, hal_api::HalApi, - id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid}, + id::{BufferId, CommandEncoderId, DeviceId, TextureId}, identity::GlobalIdentityHandlerFactory, init_tracker::{ has_copy_partial_init_tracker_coverage, MemoryInitKind, TextureInitRange, TextureInitTrackerAction, }, - resource::{Texture, TextureErrorDimension}, + resource::{Resource, Texture, TextureErrorDimension}, storage::Storage, track::{TextureSelector, Tracker}, }; @@ -579,7 +579,7 @@ impl Global { let device = &cmd_buf.device; if !device.is_valid() { - return Err(TransferError::InvalidDevice(cmd_buf.device_id.value.0).into()); + return Err(TransferError::InvalidDevice(cmd_buf.device.as_info().id()).into()); } #[cfg(feature = "trace")] @@ -733,9 +733,9 @@ impl Global { let cmd_buf = CommandBuffer::get_encoder(hub, command_encoder_id)?; let device = &cmd_buf.device; if !device.is_valid() { - return Err(TransferError::InvalidDevice(cmd_buf.device_id.value.0).into()); + return Err(TransferError::InvalidDevice(cmd_buf.device.as_info().id()).into()); } - + let mut cmd_buf_data = cmd_buf.data.lock(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); @@ -891,9 +891,9 @@ impl Global { let cmd_buf = CommandBuffer::get_encoder(hub, command_encoder_id)?; let device = &cmd_buf.device; if !device.is_valid() { - return Err(TransferError::InvalidDevice(cmd_buf.device_id.value.0).into()); + return Err(TransferError::InvalidDevice(cmd_buf.device.as_info().id()).into()); } - + let mut cmd_buf_data = cmd_buf.data.lock(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); @@ -912,7 +912,6 @@ impl Global { let texture_guard = hub.textures.read(); - if copy_size.width == 0 || copy_size.height == 0 || copy_size.depth_or_array_layers == 0 { log::trace!("Ignoring copy_texture_to_buffer of size 0"); return Ok(()); @@ -1062,9 +1061,9 @@ impl Global { let cmd_buf = CommandBuffer::get_encoder(hub, command_encoder_id)?; let device = &cmd_buf.device; if !device.is_valid() { - return Err(TransferError::InvalidDevice(cmd_buf.device_id.value.0).into()); + return Err(TransferError::InvalidDevice(cmd_buf.device.as_info().id()).into()); } - + let mut cmd_buf_data = cmd_buf.data.lock(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); @@ -1082,7 +1081,6 @@ impl Global { let texture_guard = hub.textures.read(); - if copy_size.width == 0 || copy_size.height == 0 || copy_size.depth_or_array_layers == 0 { log::trace!("Ignoring copy_texture_to_texture of size 0"); return Ok(()); diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 4d4e5ac2f8..d7817aff88 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -95,9 +95,9 @@ impl Global { device_id: DeviceId, ) -> Result { let hub = A::hub(self); - + let device = hub.devices.get(device_id).map_err(|_| InvalidDevice)?; - if !device.valid { + if !device.is_valid() { return Err(InvalidDevice); } @@ -109,9 +109,9 @@ impl Global { device_id: DeviceId, ) -> Result { let hub = A::hub(self); - + let device = hub.devices.get(device_id).map_err(|_| InvalidDevice)?; - if !device.valid { + if !device.is_valid() { return Err(InvalidDevice); } @@ -123,9 +123,9 @@ impl Global { device_id: DeviceId, ) -> Result { let hub = A::hub(self); - + let device = hub.devices.get(device_id).map_err(|_| InvalidDevice)?; - if !device.valid { + if !device.is_valid() { return Err(InvalidDevice); } @@ -144,15 +144,18 @@ impl Global { let fid = hub.buffers.prepare::(id_in); let device = match hub.devices.get(device_id) { - Ok(device) => device, + Ok(device) => { + if !device.is_valid() { + let id = fid.assign_error(desc.label.borrow_or_default()); + return (id, Some(DeviceError::Invalid.into())); + } + device + } Err(_) => { let id = fid.assign_error(desc.label.borrow_or_default()); return (id, Some(DeviceError::Invalid.into())); } }; - if !device.valid { - break DeviceError::Invalid.into(); - } if desc.usage.is_empty() { // Per spec, `usage` must not be zero. @@ -475,7 +478,7 @@ impl Global { pub fn buffer_drop(&self, buffer_id: id::BufferId, wait: bool) { profiling::scope!("Buffer::drop"); - + log::debug!("Buffer {:?} is asked to be dropped", buffer_id); let hub = A::hub(self); @@ -531,7 +534,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } #[cfg(feature = "trace")] @@ -543,7 +546,7 @@ impl Global { Ok(texture) => texture, Err(error) => break error, }; - + let (id, resource) = fid.assign(texture); log::info!("Created Texture {:?} with {:?}", id, desc); @@ -583,7 +586,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -656,7 +659,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -735,7 +738,7 @@ impl Global { pub fn texture_drop(&self, texture_id: id::TextureId, wait: bool) { profiling::scope!("Texture::drop"); - + log::debug!("Texture {:?} is asked to be dropped", texture_id); let hub = A::hub(self); @@ -803,7 +806,7 @@ impl Global { Ok(view) => view, Err(e) => break e, }; - + let (id, resource) = fid.assign(view); log::info!("Created TextureView {:?}", id); device.trackers.lock().views.insert_single(id, resource); @@ -825,7 +828,7 @@ impl Global { wait: bool, ) -> Result<(), resource::TextureViewDestroyError> { profiling::scope!("TextureView::drop"); - + log::debug!("TextureView {:?} is asked to be dropped", texture_view_id); let hub = A::hub(self); @@ -868,7 +871,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -885,7 +888,7 @@ impl Global { let (id, resource) = fid.assign(sampler); log::info!("Created Sampler {:?}", id); device.trackers.lock().samplers.insert_single(id, resource); - + return (id, None); }; @@ -931,7 +934,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -972,12 +975,11 @@ impl Global { }; layout.compatible_layout = compatible_layout; - let (id, _) = fid.assign(layout); - if let Some(dupe) = compatible_layout { - log::info!("Created BindGroupLayout (duplicate of {dupe:?}) -> {:?}", id); - log::trace!( - "Device::create_bind_group_layout (duplicate of {dupe:?}) -> {:?}", - id.0 + let (id, layout) = fid.assign(layout); + if let Some(dupe) = layout.compatible_layout.as_ref() { + log::info!( + "Created BindGroupLayout (duplicate of {dupe:?}) -> {:?}", + id ); } else { log::info!("Created BindGroupLayout {:?}", id); @@ -996,7 +998,7 @@ impl Global { pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) { profiling::scope!("BindGroupLayout::drop"); - + log::debug!( "BindGroupLayout {:?} is asked to be dropped", bind_group_layout_id @@ -1032,7 +1034,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1064,7 +1066,7 @@ impl Global { pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) { profiling::scope!("PipelineLayout::drop"); - + log::debug!( "PipelineLayout {:?} is asked to be dropped", pipeline_layout_id @@ -1096,7 +1098,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1141,7 +1143,7 @@ impl Global { pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) { profiling::scope!("BindGroup::drop"); - + log::debug!("BindGroup {:?} is asked to be dropped", bind_group_id); let hub = A::hub(self); @@ -1175,7 +1177,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1207,7 +1209,7 @@ impl Global { Ok(shader) => shader, Err(e) => break e, }; - + let (id, _) = fid.assign(shader); log::info!("Created ShaderModule {:?} with {:?}", id, desc); return (id, None); @@ -1243,7 +1245,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1278,9 +1280,9 @@ impl Global { pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) { profiling::scope!("ShaderModule::drop"); - + log::debug!("ShaderModule {:?} is asked to be dropped", shader_module_id); - + let hub = A::hub(self); hub.shader_modules.unregister(shader_module_id); } @@ -1301,7 +1303,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid, }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid; } let queue = match hub.queues.get(device.queue_id.read().unwrap()) { @@ -1341,7 +1343,7 @@ impl Global { pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) { profiling::scope!("CommandEncoder::drop"); - + log::debug!( "CommandEncoder {:?} is asked to be dropped", command_encoder_id @@ -1358,7 +1360,7 @@ impl Global { pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) { profiling::scope!("CommandBuffer::drop"); - + log::debug!( "CommandBuffer {:?} is asked to be dropped", command_buffer_id @@ -1400,7 +1402,7 @@ impl Global { Ok(device) => device, Err(_) => break command::RenderBundleError::INVALID_DEVICE, }; - if !device.valid { + if !device.is_valid() { break command::RenderBundleError::INVALID_DEVICE; } @@ -1439,9 +1441,9 @@ impl Global { pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) { profiling::scope!("RenderBundle::drop"); - + log::debug!("RenderBundle {:?} is asked to be dropped", render_bundle_id); - + let hub = A::hub(self); if let Some(bundle) = hub.render_bundles.unregister(render_bundle_id) { @@ -1469,7 +1471,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1497,13 +1499,13 @@ impl Global { return (id, None); }; - let id = fid.assign_error(""); + let id = fid.assign_error(""); (id, Some(error)) } pub fn query_set_drop(&self, query_set_id: id::QuerySetId) { profiling::scope!("QuerySet::drop"); - + log::debug!("QuerySet {:?} is asked to be dropped", query_set_id); let hub = A::hub(self); @@ -1549,7 +1551,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } #[cfg(feature = "trace")] @@ -1566,7 +1568,7 @@ impl Global { Ok(pair) => pair, Err(e) => break e, }; - + let (id, resource) = fid.assign(pipeline); log::info!("Created RenderPipeline {:?} with {:?}", id, desc); @@ -1625,12 +1627,12 @@ impl Global { pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) { profiling::scope!("RenderPipeline::drop"); - + log::debug!( "RenderPipeline {:?} is asked to be dropped", render_pipeline_id ); - + let hub = A::hub(self); if let Some(pipeline) = hub.render_pipelines.unregister(render_pipeline_id) { @@ -1669,7 +1671,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -1747,12 +1749,12 @@ impl Global { pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) { profiling::scope!("ComputePipeline::drop"); - + log::debug!( "ComputePipeline {:?} is asked to be dropped", compute_pipeline_id ); - + let hub = A::hub(self); if let Some(pipeline) = hub.compute_pipelines.unregister(compute_pipeline_id) { @@ -1898,7 +1900,7 @@ impl Global { Ok(device) => device, Err(_) => break DeviceError::Invalid.into(), }; - if !device.valid { + if !device.is_valid() { break DeviceError::Invalid.into(); } @@ -2159,9 +2161,9 @@ impl Global { log::trace!("Device::start_capture"); let hub = A::hub(self); - + if let Ok(device) = hub.devices.get(id) { - if !device.valid { + if !device.is_valid() { return; } unsafe { device.raw().start_capture() }; @@ -2172,9 +2174,9 @@ impl Global { log::trace!("Device::stop_capture"); let hub = A::hub(self); - + if let Ok(device) = hub.devices.get(id) { - if !device.valid { + if !device.is_valid() { return; } unsafe { device.raw().stop_capture() }; @@ -2183,7 +2185,7 @@ impl Global { pub fn device_drop(&self, device_id: DeviceId) { profiling::scope!("Device::drop"); - + log::debug!("Device {:?} is asked to be dropped", device_id); let hub = A::hub(self); @@ -2202,22 +2204,20 @@ impl Global { drop(device); } } - + pub fn device_destroy(&self, device_id: DeviceId) { log::trace!("Device::destroy {device_id:?}"); let hub = A::hub(self); - let mut token = Token::root(); - let (mut device_guard, _) = hub.devices.write(&mut token); - if let Ok(device) = device_guard.get_mut(device_id) { + if let Ok(device) = hub.devices.get(device_id) { // Follow the steps at // https://gpuweb.github.io/gpuweb/#dom-gpudevice-destroy. // It's legal to call destroy multiple times, but if the device // is already invalid, there's nothing more to do. There's also // no need to return an error. - if !device.valid { + if !device.is_valid() { return; } @@ -2239,45 +2239,11 @@ impl Global { log::trace!("Device::lose {device_id:?}"); let hub = A::hub(self); - let mut token = Token::root(); - - let (mut device_guard, _) = hub.devices.write(&mut token); - if let Ok(device) = device_guard.get_mut(device_id) { + if let Ok(device) = hub.devices.get(device_id) { device.lose(reason); } } - /// Exit the unreferenced, inactive device `device_id`. - fn exit_device(&self, device_id: DeviceId) { - let hub = A::hub(self); - let mut token = Token::root(); - let mut free_adapter_id = None; - { - let (device, mut _token) = hub.devices.unregister(device_id, &mut token); - if let Some(mut device) = device { - // The things `Device::prepare_to_die` takes care are mostly - // unnecessary here. We know our queue is empty, so we don't - // need to wait for submissions or triage them. We know we were - // just polled, so `life_tracker.free_resources` is empty. - debug_assert!(device.lock_life(&mut _token).queue_empty()); - device.pending_writes.deactivate(); - - // Adapter is only referenced by the device and itself. - // This isn't a robust way to destroy them, we should find a better one. - if device.adapter_id.ref_count.load() == 1 { - free_adapter_id = Some(device.adapter_id.value.0); - } - - device.dispose(); - } - } - - let hub = A::hub(self); - if let Some(queue) = hub.queues.unregister(queue_id) { - drop(queue); - } - } - pub fn queue_drop(&self, queue_id: QueueId) { profiling::scope!("Queue::drop"); log::debug!("Queue {:?} is asked to be dropped", queue_id); @@ -2343,8 +2309,8 @@ impl Global { } }; - let device = &device_guard[buffer.device_id.value]; - if !device.valid { + let device = &buffer.device; + if !device.is_valid() { return Err((op, BufferAccessError::Invalid)); } diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 70e13d441f..20c4cc67df 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -46,7 +46,7 @@ use std::{ iter, num::NonZeroU32, sync::{ - atomic::{AtomicU64, Ordering}, + atomic::{AtomicBool, AtomicU64, Ordering}, Arc, }, }; @@ -107,7 +107,7 @@ pub struct Device { /// Error enums, we wouldn't need this. For now, we need it. All the call /// sites where we check it are areas that should be revisited if we start /// using ref-counted references for internal access. - pub(crate) valid: bool, + pub(crate) valid: AtomicBool, /// All live resources allocated with this [`Device`]. /// @@ -252,7 +252,7 @@ impl Device { command_allocator: Mutex::new(Some(com_alloc)), active_submission_index: AtomicU64::new(0), fence: RwLock::new(Some(fence)), - valid: true, + valid: AtomicBool::new(true), trackers: Mutex::new(Tracker::new()), life_tracker: Mutex::new(life::LifetimeTracker::new()), temp_suspected: Mutex::new(Some(life::ResourceMaps::new::())), @@ -279,9 +279,9 @@ impl Device { } pub fn is_valid(&self) -> bool { - self.valid + self.valid.load(Ordering::Acquire) } - + pub(crate) fn release_queue(&self, queue: A::Queue) { self.queue_to_drop.write().replace(queue); } @@ -3175,12 +3175,12 @@ impl Device { }) } - pub(crate) fn lose(&mut self, _reason: Option<&str>) { + pub(crate) fn lose(&self, _reason: Option<&str>) { // Follow the steps at https://gpuweb.github.io/gpuweb/#lose-the-device. // Mark the device explicitly as invalid. This is checked in various // places to prevent new work from being submitted. - self.valid = false; + self.valid.store(false, Ordering::Release); // The following steps remain in "lose the device": // 1) Resolve the GPUDevice device.lost promise. diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index c19dfd1eb7..12573c1ef2 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -723,7 +723,7 @@ impl Global { pub fn surface_drop(&self, id: SurfaceId) { profiling::scope!("Surface::drop"); - + log::info!("Surface::drop {id:?}"); fn unconfigure( diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index d84a5a2099..3b4df90b53 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -136,11 +136,11 @@ impl Global { let (device, config) = if let Some(ref present) = *surface.presentation.lock() { match present.device.downcast_clone::() { Some(device) => { - if !device.is_valid() { - return Err(DeviceError::Invalid.into()); - } - (device, present.config.clone()) - }, + if !device.is_valid() { + return Err(DeviceError::Invalid.into()); + } + (device, present.config.clone()) + } None => return Err(SurfaceError::NotConfigured), } } else { diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index e627cd6747..7f0a6db6aa 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -1923,7 +1923,7 @@ impl crate::context::Context for Context { // the device.lost promise, which will require a different invocation pattern // with a callback. } - + fn queue_drop(&self, _queue: &Self::QueueId, _queue_data: &Self::QueueData) { // Queue is dropped automatically } diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index 5da6ee5463..04b42fe2fc 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -2441,7 +2441,7 @@ where let device_data = downcast_ref(device_data); Context::device_lose(self, &device, device_data) } - + fn queue_drop(&self, queue: &ObjectId, queue_data: &crate::Data) { let queue = ::from(*queue); let queue_data = downcast_ref(queue_data);