diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 928c2a6bcf..93fcc6a4ee 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -519,8 +519,7 @@ impl LifetimeTracker { } if !self.suspected_resources.pipeline_layouts.is_empty() { - let (mut guard, mut token) = hub.pipeline_layouts.write(token); - let (bgl_guard, _) = hub.bind_group_layouts.read(&mut token); + let (mut guard, _) = hub.pipeline_layouts.write(token); for Stored { value: id, @@ -533,23 +532,23 @@ impl LifetimeTracker { trace.map(|t| t.lock().add(trace::Action::DestroyPipelineLayout(id.0))); let layout = hub.pipeline_layouts.unregister_locked(id.0, &mut *guard); - for &bgl_id in layout.bind_group_layout_ids.iter() { - bgl_guard[bgl_id].multi_ref_count.dec(); - } + self.suspected_resources + .bind_group_layouts + .extend_from_slice(&layout.bind_group_layout_ids); self.free_resources.pipeline_layouts.push(layout.raw); } } } if !self.suspected_resources.bind_group_layouts.is_empty() { - self.suspected_resources.bind_group_layouts.sort(); - self.suspected_resources.bind_group_layouts.dedup(); let (mut guard, _) = hub.bind_group_layouts.write(token); for id in self.suspected_resources.bind_group_layouts.drain(..) { //Note: this has to happen after all the suspected pipelines are destroyed //Note: nothing else can bump the refcount since the guard is locked exclusively - if guard[id].multi_ref_count.is_empty() { + //Note: same BGL can appear multiple times in the list, but only the last + // encounter could drop the refcount to 0. + if guard[id].multi_ref_count.dec_and_check_empty() { #[cfg(feature = "trace")] trace.map(|t| t.lock().add(trace::Action::DestroyBindGroupLayout(id.0))); let layout = hub.bind_group_layouts.unregister_locked(id.0, &mut *guard); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 33accfd86e..78c28f362a 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1525,10 +1525,7 @@ impl Global { let device_id = { let (mut bind_group_layout_guard, _) = hub.bind_group_layouts.write(&mut token); match bind_group_layout_guard.get_mut(bind_group_layout_id) { - Ok(layout) => { - layout.multi_ref_count.dec(); - layout.device_id.value - } + Ok(layout) => layout.device_id.value, Err(InvalidId) => { hub.bind_group_layouts .unregister_locked(bind_group_layout_id, &mut *bind_group_layout_guard); diff --git a/wgpu-core/src/lib.rs b/wgpu-core/src/lib.rs index 4944602450..46a40289a7 100644 --- a/wgpu-core/src/lib.rs +++ b/wgpu-core/src/lib.rs @@ -152,12 +152,8 @@ impl MultiRefCount { unsafe { self.0.as_ref() }.fetch_add(1, Ordering::AcqRel); } - fn dec(&self) { - unsafe { self.0.as_ref() }.fetch_sub(1, Ordering::AcqRel); - } - - fn is_empty(&self) -> bool { - unsafe { self.0.as_ref() }.load(Ordering::Acquire) == 0 + fn dec_and_check_empty(&self) -> bool { + unsafe { self.0.as_ref() }.fetch_sub(1, Ordering::AcqRel) == 1 } }