From da34c918d38669b7ae2918c21aa6b89d31b43a7c Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 23 Jul 2020 01:36:09 -0400 Subject: [PATCH] Carry RefCount in future suspects in order to prevent early removal --- wgpu-core/src/device/life.rs | 28 +++++++++++++++------------- wgpu-core/src/device/mod.rs | 22 ++++++++++++++-------- wgpu-core/src/swap_chain.rs | 13 +++++++------ 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 99dcb182a..b65832aad 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -132,17 +132,15 @@ impl NonReferencedResources { heaps_mutex: &Mutex>, descriptor_allocator_mutex: &Mutex>, ) { - if !self.buffers.is_empty() { + if !self.buffers.is_empty() || !self.images.is_empty() { let mut heaps = heaps_mutex.lock(); for (raw, memory) in self.buffers.drain(..) { log::trace!("Buffer {:?} is destroyed with memory {:?}", raw, memory); device.destroy_buffer(raw); heaps.free(device, memory); } - } - if !self.images.is_empty() { - let mut heaps = heaps_mutex.lock(); for (raw, memory) in self.images.drain(..) { + log::trace!("Image {:?} is destroyed with memory {:?}", raw, memory); device.destroy_image(raw); heaps.free(device, memory); } @@ -204,14 +202,14 @@ pub enum WaitIdleError { /// 3. When `ActiveSubmission` is retired, the mapped buffers associated with it are moved to `ready_to_map` vector. /// 4. Finally, `handle_mapping` issues all the callbacks. #[derive(Debug)] -pub struct LifetimeTracker { +pub(crate) struct LifetimeTracker { /// Resources that the user has requested be mapped, but are still in use. mapped: Vec>, /// Buffers can be used in a submission that is yet to be made, by the /// means of `write_buffer()`, so we have a special place for them. - pub future_suspected_buffers: Vec, + pub future_suspected_buffers: Vec>, /// Textures can be used in the upcoming submission by `write_texture`. - pub future_suspected_textures: Vec, + pub future_suspected_textures: Vec>, /// Resources that are suspected for destruction. pub suspected_resources: SuspectedResources, /// Resources that are not referenced any more but still used by GPU. @@ -246,12 +244,16 @@ impl LifetimeTracker { ) { let mut last_resources = NonReferencedResources::new(); last_resources.buffers.extend(temp_buffers); - self.suspected_resources - .buffers - .extend(self.future_suspected_buffers.drain(..)); - self.suspected_resources - .textures - .extend(self.future_suspected_textures.drain(..)); + self.suspected_resources.buffers.extend( + self.future_suspected_buffers + .drain(..) + .map(|stored| stored.value), + ); + self.suspected_resources.textures.extend( + self.future_suspected_textures + .drain(..) + .map(|stored| stored.value), + ); self.suspected_resources.extend(new_suspects); self.active.alloc().init(ActiveSubmission { index, diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index f2f9d2a92..7864062b6 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -881,18 +881,21 @@ impl Global { let mut token = Token::root(); log::info!("Buffer {:?} is dropped", buffer_id); - let device_id = { + let (ref_count, device_id) = { let (mut buffer_guard, _) = hub.buffers.write(&mut token); let buffer = &mut buffer_guard[buffer_id]; - buffer.life_guard.ref_count.take(); - buffer.device_id.value + let ref_count = buffer.life_guard.ref_count.take().unwrap(); + (ref_count, buffer.device_id.value) }; let (device_guard, mut token) = hub.devices.read(&mut token); device_guard[device_id] .lock_life(&mut token) .future_suspected_buffers - .push(buffer_id); + .push(Stored { + value: buffer_id, + ref_count, + }); } pub fn device_create_texture( @@ -936,18 +939,21 @@ impl Global { let hub = B::hub(self); let mut token = Token::root(); - let device_id = { + let (ref_count, device_id) = { let (mut texture_guard, _) = hub.textures.write(&mut token); let texture = &mut texture_guard[texture_id]; - texture.life_guard.ref_count.take(); - texture.device_id.value + let ref_count = texture.life_guard.ref_count.take().unwrap(); + (ref_count, texture.device_id.value) }; let (device_guard, mut token) = hub.devices.read(&mut token); device_guard[device_id] .lock_life(&mut token) .future_suspected_textures - .push(texture_id); + .push(Stored { + value: texture_id, + ref_count, + }); } pub fn texture_create_view( diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index ffd8b7861..8b43ff7f7 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -41,10 +41,7 @@ use crate::{ resource, span, LifeGuard, PrivateFeatures, Stored, SubmissionIndex, }; -use hal::{ - self, device::Device as _, queue::CommandQueue as _, - window::PresentationSurface as _, -}; +use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _}; use thiserror::Error; use wgt::{SwapChainDescriptor, SwapChainStatus}; @@ -129,12 +126,16 @@ impl Global { Err(err) => ( None, match err { - hal::window::AcquireError::OutOfMemory(_) => return Err(SwapChainError::OutOfMemory), + hal::window::AcquireError::OutOfMemory(_) => { + return Err(SwapChainError::OutOfMemory) + } hal::window::AcquireError::NotReady => unreachable!(), // we always set a timeout hal::window::AcquireError::Timeout => SwapChainStatus::Timeout, hal::window::AcquireError::OutOfDate => SwapChainStatus::Outdated, hal::window::AcquireError::SurfaceLost(_) => SwapChainStatus::Lost, - hal::window::AcquireError::DeviceLost(_) => return Err(SwapChainError::DeviceLost), + hal::window::AcquireError::DeviceLost(_) => { + return Err(SwapChainError::DeviceLost) + } }, ), };