Skip to content

Commit bc65d84

Browse files
authored
Remove the Destroyed state from Storage (#4970)
* Remove the Destroyed state from Storage It used to be how we handled destroying buffers and textures but we moved to different approach. * Explicit check for destroyed textures/buffers in a few entry points This used to be checked automatically when getting the resource from the registry, but has to be done manually now that we track we track the destroyed state in the resources.
1 parent b30c0c2 commit bc65d84

File tree

5 files changed

+41
-50
lines changed

5 files changed

+41
-50
lines changed

wgpu-core/src/device/global.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
489489

490490
let buffer = hub
491491
.buffers
492-
.write()
493-
.get_and_mark_destroyed(buffer_id)
492+
.get(buffer_id)
494493
.map_err(|_| resource::DestroyError::Invalid)?;
495494

496495
let _ = buffer.unmap();
@@ -732,8 +731,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
732731

733732
let texture = hub
734733
.textures
735-
.write()
736-
.get_and_mark_destroyed(texture_id)
734+
.get(texture_id)
737735
.map_err(|_| resource::DestroyError::Invalid)?;
738736

739737
texture.destroy()
@@ -799,6 +797,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
799797
Err(_) => break resource::CreateTextureViewError::InvalidTexture,
800798
};
801799
let device = &texture.device;
800+
{
801+
let snatch_guard = device.snatchable_lock.read();
802+
if texture.is_destroyed(&snatch_guard) {
803+
break resource::CreateTextureViewError::InvalidTexture;
804+
}
805+
}
802806
#[cfg(feature = "trace")]
803807
if let Some(ref mut trace) = *device.trace.lock() {
804808
trace.add(trace::Action::CreateTextureView {
@@ -2386,6 +2390,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
23862390
},
23872391
));
23882392
}
2393+
2394+
let snatch_guard = device.snatchable_lock.read();
2395+
if buffer.is_destroyed(&snatch_guard) {
2396+
return Err((op, BufferAccessError::Destroyed));
2397+
}
2398+
23892399
{
23902400
let map_state = &mut *buffer.map_state.lock();
23912401
*map_state = match *map_state {
@@ -2410,10 +2420,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
24102420
let mut trackers = buffer.device.as_ref().trackers.lock();
24112421
trackers.buffers.set_single(&buffer, internal_use);
24122422
//TODO: Check if draining ALL buffers is correct!
2413-
let snatch_guard = device.snatchable_lock.read();
24142423
let _ = trackers.buffers.drain_transitions(&snatch_guard);
24152424
}
24162425

2426+
drop(snatch_guard);
2427+
24172428
buffer
24182429
};
24192430

@@ -2438,6 +2449,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
24382449
.get(buffer_id)
24392450
.map_err(|_| BufferAccessError::Invalid)?;
24402451

2452+
{
2453+
let snatch_guard = buffer.device.snatchable_lock.read();
2454+
if buffer.is_destroyed(&snatch_guard) {
2455+
return Err(BufferAccessError::Destroyed);
2456+
}
2457+
}
2458+
24412459
let range_size = if let Some(size) = size {
24422460
size
24432461
} else if offset > buffer.size {
@@ -2500,6 +2518,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
25002518
.get(buffer_id)
25012519
.map_err(|_| BufferAccessError::Invalid)?;
25022520

2521+
let snatch_guard = buffer.device.snatchable_lock.read();
2522+
if buffer.is_destroyed(&snatch_guard) {
2523+
return Err(BufferAccessError::Destroyed);
2524+
}
2525+
drop(snatch_guard);
2526+
25032527
if !buffer.device.is_valid() {
25042528
return Err(DeviceError::Lost.into());
25052529
}

wgpu-core/src/device/queue.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,8 +1158,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
11581158
// it, so make sure to set_size on it.
11591159
used_surface_textures.set_size(hub.textures.read().len());
11601160

1161-
// TODO: ideally we would use `get_and_mark_destroyed` but the code here
1162-
// wants to consume the command buffer.
11631161
#[allow(unused_mut)]
11641162
let mut cmdbuf = match command_buffer_guard.replace_with_error(cmb_id) {
11651163
Ok(cmdbuf) => cmdbuf,

wgpu-core/src/registry.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub struct RegistryReport {
1515
pub num_allocated: usize,
1616
pub num_kept_from_user: usize,
1717
pub num_released_from_user: usize,
18-
pub num_destroyed_from_user: usize,
1918
pub num_error: usize,
2019
pub element_size: usize,
2120
}
@@ -192,7 +191,6 @@ impl<I: id::TypedId, T: Resource<I>> Registry<I, T> {
192191
for element in storage.map.iter() {
193192
match *element {
194193
Element::Occupied(..) => report.num_kept_from_user += 1,
195-
Element::Destroyed(..) => report.num_destroyed_from_user += 1,
196194
Element::Vacant => report.num_released_from_user += 1,
197195
Element::Error(..) => report.num_error += 1,
198196
}

wgpu-core/src/resource.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,10 @@ impl<A: HalApi> Buffer<A> {
433433
self.raw.get(guard)
434434
}
435435

436+
pub(crate) fn is_destroyed(&self, guard: &SnatchGuard) -> bool {
437+
self.raw.get(guard).is_none()
438+
}
439+
436440
// Note: This must not be called while holding a lock.
437441
pub(crate) fn unmap(self: &Arc<Self>) -> Result<(), BufferAccessError> {
438442
if let Some((mut operation, status)) = self.unmap_inner()? {
@@ -818,6 +822,10 @@ impl<A: HalApi> Texture<A> {
818822
self.inner.get(snatch_guard)?.raw()
819823
}
820824

825+
pub(crate) fn is_destroyed(&self, guard: &SnatchGuard) -> bool {
826+
self.inner.get(guard).is_none()
827+
}
828+
821829
pub(crate) fn inner_mut<'a>(
822830
&'a self,
823831
guard: &mut ExclusiveSnatchGuard,

wgpu-core/src/storage.rs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ pub(crate) enum Element<T> {
1414
/// epoch.
1515
Occupied(Arc<T>, Epoch),
1616

17-
/// Like `Occupied`, but the resource has been marked as destroyed
18-
/// and hasn't been dropped yet.
19-
Destroyed(Epoch),
20-
2117
/// Like `Occupied`, but an error occurred when creating the
2218
/// resource.
2319
///
@@ -78,11 +74,9 @@ where
7874
let (index, epoch, _) = id.unzip();
7975
match self.map.get(index as usize) {
8076
Some(&Element::Vacant) => false,
81-
Some(
82-
&Element::Occupied(_, storage_epoch)
83-
| &Element::Destroyed(storage_epoch)
84-
| &Element::Error(storage_epoch, _),
85-
) => storage_epoch == epoch,
77+
Some(&Element::Occupied(_, storage_epoch) | &Element::Error(storage_epoch, _)) => {
78+
storage_epoch == epoch
79+
}
8680
None => false,
8781
}
8882
}
@@ -99,9 +93,7 @@ where
9993
let (result, storage_epoch) = match self.map.get(index as usize) {
10094
Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch),
10195
Some(&Element::Vacant) => return Ok(None),
102-
Some(&Element::Error(epoch, ..)) | Some(&Element::Destroyed(.., epoch)) => {
103-
(Err(InvalidId), epoch)
104-
}
96+
Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
10597
None => return Err(InvalidId),
10698
};
10799
assert_eq!(
@@ -120,7 +112,6 @@ where
120112
Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch),
121113
Some(&Element::Vacant) => panic!("{}[{:?}] does not exist", self.kind, id),
122114
Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
123-
Some(&Element::Destroyed(.., epoch)) => (Err(InvalidId), epoch),
124115
None => return Err(InvalidId),
125116
};
126117
assert_eq!(
@@ -151,14 +142,6 @@ where
151142
}
152143
match std::mem::replace(&mut self.map[index], element) {
153144
Element::Vacant => {}
154-
Element::Destroyed(storage_epoch) => {
155-
assert_ne!(
156-
epoch,
157-
storage_epoch,
158-
"Index {index:?} of {} is already occupied",
159-
T::TYPE
160-
);
161-
}
162145
Element::Occupied(_, storage_epoch) => {
163146
assert_ne!(
164147
epoch,
@@ -209,22 +192,6 @@ where
209192
}
210193
}
211194

212-
pub(crate) fn get_and_mark_destroyed(&mut self, id: I) -> Result<Arc<T>, InvalidId> {
213-
let (index, epoch, _) = id.unzip();
214-
let slot = &mut self.map[index as usize];
215-
// borrowck dance: we have to move the element out before we can replace it
216-
// with another variant with the same value.
217-
if let &mut Element::Occupied(_, e) = slot {
218-
if let Element::Occupied(value, storage_epoch) =
219-
std::mem::replace(slot, Element::Destroyed(e))
220-
{
221-
debug_assert_eq!(storage_epoch, epoch);
222-
return Ok(value);
223-
}
224-
}
225-
Err(InvalidId)
226-
}
227-
228195
pub(crate) fn force_replace(&mut self, id: I, value: T) {
229196
log::trace!("User is replacing {}{:?}", T::TYPE, id);
230197
let (index, epoch, _) = id.unzip();
@@ -239,10 +206,6 @@ where
239206
assert_eq!(epoch, storage_epoch);
240207
Some(value)
241208
}
242-
Element::Destroyed(storage_epoch) => {
243-
assert_eq!(epoch, storage_epoch);
244-
None
245-
}
246209
Element::Error(..) => None,
247210
Element::Vacant => panic!("Cannot remove a vacant resource"),
248211
}

0 commit comments

Comments
 (0)