diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 2c82843dc7..015ebeb4d8 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -374,8 +374,8 @@ impl LifetimeTracker { token: &mut Token>, ) { if !self.suspected_resources.render_bundles.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.render_bundles.write(token); + let mut trackers = trackers.lock(); while let Some(id) = self.suspected_resources.render_bundles.pop() { if trackers.bundles.remove_abandoned(id) { @@ -390,8 +390,8 @@ impl LifetimeTracker { } if !self.suspected_resources.bind_groups.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.bind_groups.write(token); + let mut trackers = trackers.lock(); while let Some(id) = self.suspected_resources.bind_groups.pop() { if trackers.bind_groups.remove_abandoned(id) { @@ -414,8 +414,8 @@ impl LifetimeTracker { } if !self.suspected_resources.texture_views.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.texture_views.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.texture_views.drain(..) { if trackers.views.remove_abandoned(id) { @@ -444,8 +444,8 @@ impl LifetimeTracker { } if !self.suspected_resources.textures.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.textures.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.textures.drain(..) { if trackers.textures.remove_abandoned(id) { @@ -466,8 +466,8 @@ impl LifetimeTracker { } if !self.suspected_resources.samplers.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.samplers.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.samplers.drain(..) { if trackers.samplers.remove_abandoned(id) { @@ -488,8 +488,8 @@ impl LifetimeTracker { } if !self.suspected_resources.buffers.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.buffers.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.buffers.drain(..) { if trackers.buffers.remove_abandoned(id) { @@ -521,8 +521,8 @@ impl LifetimeTracker { } if !self.suspected_resources.compute_pipelines.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.compute_pipelines.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.compute_pipelines.drain(..) { if trackers.compute_pipes.remove_abandoned(id) { @@ -543,8 +543,8 @@ impl LifetimeTracker { } if !self.suspected_resources.render_pipelines.is_empty() { - let mut trackers = trackers.lock(); let (mut guard, _) = hub.render_pipelines.write(token); + let mut trackers = trackers.lock(); for id in self.suspected_resources.render_pipelines.drain(..) { if trackers.render_pipes.remove_abandoned(id) { diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 39b7264299..995c214041 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -211,6 +211,16 @@ fn fire_map_callbacks>(callback } } +/// Structure describing a logical device. Some members are internally mutable, +/// stored behind mutexes. +/// TODO: establish clear order of locking for these: +/// `mem_allocator`, `desc_allocator`, `life_tracke`, `trackers`, +/// `render_passes`, `framebuffers`, `pending_writes`, `trace`. +/// +/// Currently, the rules are: +/// 1. `life_tracker` is locked after `hub.devices`, enforced by the type system +/// 1. `self.trackers` is locked last (unenforced) +/// 1. `self.trace` is locked last (unenforced) #[derive(Debug)] pub struct Device { pub(crate) raw: B::Device, @@ -222,6 +232,7 @@ pub struct Device { //Note: The submission index here corresponds to the last submission that is done. pub(crate) life_guard: LifeGuard, pub(crate) active_submission_index: SubmissionIndex, + /// Has to be locked temporarily only (locked last) pub(crate) trackers: Mutex, pub(crate) render_passes: Mutex>, pub(crate) framebuffers: Mutex>, @@ -448,7 +459,8 @@ impl Device { let mut flags = Uf::empty(); let map_flags = desc.usage & (Bu::MAP_READ | Bu::MAP_WRITE); - let map_copy_flags = desc.usage & (Bu::MAP_READ | Bu::MAP_WRITE | Bu::COPY_SRC | Bu::COPY_DST); + let map_copy_flags = + desc.usage & (Bu::MAP_READ | Bu::MAP_WRITE | Bu::COPY_SRC | Bu::COPY_DST); if map_flags.is_empty() || !(desc.usage - map_copy_flags).is_empty() { flags |= Uf::FAST_DEVICE_ACCESS; }