diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index a711c20fe9..d7cf7fbcea 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -734,11 +734,12 @@ impl Global { if let resource::TextureInner::Native { ref raw } = *texture.inner().as_ref().unwrap() { if !raw.is_none() { let temp = queue::TempResource::Texture(texture.clone()); - let mut pending_writes = device.pending_writes.lock(); - let pending_writes = pending_writes.as_mut().unwrap(); + let mut guard = device.pending_writes.lock(); + let pending_writes = guard.as_mut().unwrap(); if pending_writes.dst_textures.contains_key(&texture_id) { pending_writes.temp_resources.push(temp); } else { + drop(guard); device .lock_life() .schedule_resource_destruction(temp, last_submit_index); @@ -763,7 +764,6 @@ impl Global { let device = &texture.device; { - let mut life_lock = device.lock_life(); if device .pending_writes .lock() @@ -772,9 +772,13 @@ impl Global { .dst_textures .contains_key(&texture_id) { - life_lock.future_suspected_textures.push(texture.clone()); + device + .lock_life() + .future_suspected_textures + .push(texture.clone()); } else { - life_lock + device + .lock_life() .suspected_resources .insert(texture_id, texture.clone()); } diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 9dfa412e1a..3902d6190c 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -1147,9 +1147,9 @@ impl Global { // a temporary one, since the chains are not finished. let mut temp_suspected = device.temp_suspected.lock(); { - let mut suspected = temp_suspected.take().unwrap(); + let mut suspected = + temp_suspected.replace(ResourceMaps::new::()).unwrap(); suspected.clear(); - temp_suspected.replace(ResourceMaps::new::()); } // finish all the command buffers first diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 09e9038114..035b2ea554 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -312,18 +312,19 @@ impl Device { ) -> Result<(UserClosures, bool), WaitIdleError> { profiling::scope!("Device::maintain"); { - let mut life_tracker = self.lock_life(); - // Normally, `temp_suspected` exists only to save heap // allocations: it's cleared at the start of the function // call, and cleared by the end. But `Global::queue_submit` is // fallible; if it exits early, it may leave some resources in // `temp_suspected`. - { - let temp_suspected = self.temp_suspected.lock().take().unwrap(); - life_tracker.suspected_resources.extend(temp_suspected); - } - self.temp_suspected.lock().replace(ResourceMaps::new::()); + let temp_suspected = self + .temp_suspected + .lock() + .replace(ResourceMaps::new::()) + .unwrap(); + + let mut life_tracker = self.lock_life(); + life_tracker.suspected_resources.extend(temp_suspected); life_tracker.triage_suspected( hub, @@ -397,7 +398,11 @@ impl Device { } pub(crate) fn untrack(&self, trackers: &Tracker) { - let mut temp_suspected = self.temp_suspected.lock().take().unwrap(); + let mut temp_suspected = self + .temp_suspected + .lock() + .replace(ResourceMaps::new::()) + .unwrap(); temp_suspected.clear(); // As the tracker is cleared/dropped, we need to consider all the resources // that it references for destruction in the next GC pass. @@ -444,7 +449,6 @@ impl Device { } } self.lock_life().suspected_resources.extend(temp_suspected); - self.temp_suspected.lock().replace(ResourceMaps::new::()); } pub(crate) fn create_buffer( @@ -3203,8 +3207,8 @@ impl Device { &self, submission_index: SubmissionIndex, ) -> Result<(), WaitIdleError> { - let fence = self.fence.read(); - let fence = fence.as_ref().unwrap(); + let guard = self.fence.read(); + let fence = guard.as_ref().unwrap(); let last_done_index = unsafe { self.raw .as_ref() @@ -3221,6 +3225,7 @@ impl Device { .wait(fence, submission_index, !0) .map_err(DeviceError::from)? }; + drop(guard); let closures = self.lock_life().triage_submissions( submission_index, self.command_allocator.lock().as_mut().unwrap(), @@ -3277,9 +3282,8 @@ impl Device { self.valid.store(false, Ordering::Release); // 1) Resolve the GPUDevice device.lost promise. - let mut life_tracker = self.lock_life(); - if life_tracker.device_lost_closure.is_some() { - let device_lost_closure = life_tracker.device_lost_closure.take().unwrap(); + let closure = self.lock_life().device_lost_closure.take(); + if let Some(device_lost_closure) = closure { device_lost_closure.call(DeviceLostReason::Unknown, message.to_string()); } @@ -3310,7 +3314,6 @@ impl Device { /// Wait for idle and remove resources that we can, before we die. pub(crate) fn prepare_to_die(&self) { self.pending_writes.lock().as_mut().unwrap().deactivate(); - let mut life_tracker = self.lock_life(); let current_index = self.active_submission_index.load(Ordering::Relaxed); if let Err(error) = unsafe { let fence = self.fence.read(); @@ -3322,6 +3325,7 @@ impl Device { } { log::error!("failed to wait for the device: {:?}", error); } + let mut life_tracker = self.lock_life(); let _ = life_tracker.triage_submissions( current_index, self.command_allocator.lock().as_mut().unwrap(),