Skip mismatched epochs in the remove_abandoned check

This commit is contained in:
Dzmitry Malyshau 2021-09-25 15:22:50 -04:00 committed by Dzmitry Malyshau
parent 180e3e3576
commit 089294fc51
2 changed files with 21 additions and 14 deletions

View File

@ -22,17 +22,17 @@ use std::mem;
/// A struct that keeps lists of resources that are no longer needed by the user. /// A struct that keeps lists of resources that are no longer needed by the user.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(super) struct SuspectedResources { pub(super) struct SuspectedResources {
pub(crate) buffers: Vec<id::Valid<id::BufferId>>, pub(super) buffers: Vec<id::Valid<id::BufferId>>,
pub(crate) textures: Vec<id::Valid<id::TextureId>>, pub(super) textures: Vec<id::Valid<id::TextureId>>,
pub(crate) texture_views: Vec<id::Valid<id::TextureViewId>>, pub(super) texture_views: Vec<id::Valid<id::TextureViewId>>,
pub(crate) samplers: Vec<id::Valid<id::SamplerId>>, pub(super) samplers: Vec<id::Valid<id::SamplerId>>,
pub(crate) bind_groups: Vec<id::Valid<id::BindGroupId>>, pub(super) bind_groups: Vec<id::Valid<id::BindGroupId>>,
pub(crate) compute_pipelines: Vec<id::Valid<id::ComputePipelineId>>, pub(super) compute_pipelines: Vec<id::Valid<id::ComputePipelineId>>,
pub(crate) render_pipelines: Vec<id::Valid<id::RenderPipelineId>>, pub(super) render_pipelines: Vec<id::Valid<id::RenderPipelineId>>,
pub(crate) bind_group_layouts: Vec<id::Valid<id::BindGroupLayoutId>>, pub(super) bind_group_layouts: Vec<id::Valid<id::BindGroupLayoutId>>,
pub(crate) pipeline_layouts: Vec<Stored<id::PipelineLayoutId>>, pub(super) pipeline_layouts: Vec<Stored<id::PipelineLayoutId>>,
pub(crate) render_bundles: Vec<id::Valid<id::RenderBundleId>>, pub(super) render_bundles: Vec<id::Valid<id::RenderBundleId>>,
pub(crate) query_sets: Vec<id::Valid<id::QuerySetId>>, pub(super) query_sets: Vec<id::Valid<id::QuerySetId>>,
} }
impl SuspectedResources { impl SuspectedResources {

View File

@ -235,10 +235,17 @@ impl<S: ResourceState> ResourceTracker<S> {
let (index, epoch, backend) = id.0.unzip(); let (index, epoch, backend) = id.0.unzip();
debug_assert_eq!(backend, self.backend); debug_assert_eq!(backend, self.backend);
match self.map.entry(index) { 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) => { Entry::Occupied(e) => {
if e.get().ref_count.load() == 1 { // see https://github.com/gfx-rs/wgpu/issues/1996
let res = e.remove(); if e.get().epoch == epoch && e.get().ref_count.load() == 1 {
assert_eq!(res.epoch, epoch, "Epoch mismatch for {:?}", id); e.remove();
true true
} else { } else {
false false