From 089294fc5145299c1f9f5d537ce9fdd019c4063c Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 25 Sep 2021 15:22:50 -0400 Subject: [PATCH] Skip mismatched epochs in the remove_abandoned check --- wgpu-core/src/device/life.rs | 22 +++++++++++----------- wgpu-core/src/track/mod.rs | 13 ++++++++++--- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 8971e4940..ae8069233 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -22,17 +22,17 @@ use std::mem; /// A struct that keeps lists of resources that are no longer needed by the user. #[derive(Debug, Default)] pub(super) struct SuspectedResources { - pub(crate) buffers: Vec>, - pub(crate) textures: Vec>, - pub(crate) texture_views: Vec>, - pub(crate) samplers: Vec>, - pub(crate) bind_groups: Vec>, - pub(crate) compute_pipelines: Vec>, - pub(crate) render_pipelines: Vec>, - pub(crate) bind_group_layouts: Vec>, - pub(crate) pipeline_layouts: Vec>, - pub(crate) render_bundles: Vec>, - pub(crate) query_sets: Vec>, + pub(super) buffers: Vec>, + pub(super) textures: Vec>, + pub(super) texture_views: Vec>, + pub(super) samplers: Vec>, + pub(super) bind_groups: Vec>, + pub(super) compute_pipelines: Vec>, + pub(super) render_pipelines: Vec>, + pub(super) bind_group_layouts: Vec>, + pub(super) pipeline_layouts: Vec>, + pub(super) render_bundles: Vec>, + pub(super) query_sets: Vec>, } impl SuspectedResources { diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index 0d0453a66..120ce3873 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -235,10 +235,17 @@ impl ResourceTracker { let (index, epoch, backend) = id.0.unzip(); debug_assert_eq!(backend, self.backend); match self.map.entry(index) { + // This code explicitly ignores requests for IDs that are no longer valid, + // i.e. corresponding to removed entries, or entries that got re-filled + // with new elements (having different epochs). + // This is needed because of the asynchronous nature of the device internals. + // As such, by the time a resource is added to the suspected list, it may + // already be fully removed from all the trackers (and be a stale ID). + // see https://github.com/gfx-rs/wgpu/issues/1996 Entry::Occupied(e) => { - if e.get().ref_count.load() == 1 { - let res = e.remove(); - assert_eq!(res.epoch, epoch, "Epoch mismatch for {:?}", id); + // see https://github.com/gfx-rs/wgpu/issues/1996 + if e.get().epoch == epoch && e.get().ref_count.load() == 1 { + e.remove(); true } else { false