From 6931e5718024c7148c1c4f9107a2716bbfa65aee Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 7 Feb 2022 19:23:40 -0500 Subject: [PATCH] Don't recycle indices that reach EOL (#2462) --- wgpu-core/src/hub.rs | 22 ++++++++++++++++++++-- wgpu-core/src/id.rs | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 63d3a12d20..c513a608a8 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -79,8 +79,12 @@ impl IdentityManager { let (index, epoch, _backend) = id.unzip(); let pe = &mut self.epochs[index as usize]; assert_eq!(*pe, epoch); - *pe += 1; - self.free.push(index); + // If the epoch reaches EOL, the index doesn't go + // into the free list, will never be reused again. + if epoch < id::EPOCH_MASK { + *pe = epoch + 1; + self.free.push(index); + } } } @@ -1081,3 +1085,17 @@ fn _test_send_sync(global: &Global) { fn test_internal(_: T) {} test_internal(global) } + +#[test] +fn test_epoch_end_of_life() { + use id::TypedId as _; + let mut man = IdentityManager::default(); + man.epochs.push(id::EPOCH_MASK); + man.free.push(0); + let id1 = man.alloc::(Backend::Empty); + assert_eq!(id1.unzip().0, 0); + man.free(id1); + let id2 = man.alloc::(Backend::Empty); + // confirm that the index 0 is no longer re-used + assert_eq!(id2.unzip().0, 1); +} diff --git a/wgpu-core/src/id.rs b/wgpu-core/src/id.rs index e75d5278c6..e646eb1d54 100644 --- a/wgpu-core/src/id.rs +++ b/wgpu-core/src/id.rs @@ -3,7 +3,7 @@ use std::{cmp::Ordering, fmt, marker::PhantomData, num::NonZeroU64}; use wgt::Backend; const BACKEND_BITS: usize = 3; -const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1; +pub const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1; type Dummy = hal::api::Empty; #[repr(transparent)]