diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index e172511e21..bf5bf9ad58 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -1,4 +1,5 @@ use crate::resource::Resource; +use crate::snatch::SnatchGuard; use crate::{ api_log, binding_model::BindError, @@ -533,6 +534,8 @@ pub enum RenderPassErrorInner { Encoder(#[from] CommandEncoderError), #[error("Attachment texture view {0:?} is invalid")] InvalidAttachment(id::TextureViewId), + #[error("Attachment texture view {0:?} is invalid")] + InvalidResolveTarget(id::TextureViewId), #[error("The format of the depth-stencil attachment ({0:?}) is not a depth-stencil format")] InvalidDepthStencilAttachmentFormat(wgt::TextureFormat), #[error("The format of the {location} ({format:?}) is not resolvable")] @@ -789,6 +792,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { buffer_guard: &'a Storage, id::BufferId>, texture_guard: &'a Storage, id::TextureId>, query_set_guard: &'a Storage, id::QuerySetId>, + snatch_guard: &SnatchGuard<'a>, ) -> Result { profiling::scope!("RenderPassInfo::start"); @@ -993,7 +997,9 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { depth_stencil = Some(hal::DepthStencilAttachment { target: hal::Attachment { - view: view.raw(), + view: view + .raw(snatch_guard) + .ok_or_else(|| RenderPassErrorInner::InvalidAttachment(view.info.id()))?, usage, }, depth_ops: at.depth.hal_ops(), @@ -1102,14 +1108,18 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { .push(resolve_view.to_render_attachment(hal::TextureUses::COLOR_TARGET)); hal_resolve_target = Some(hal::Attachment { - view: resolve_view.raw(), + view: resolve_view.raw(snatch_guard).ok_or_else(|| { + RenderPassErrorInner::InvalidResolveTarget(resolve_view.info.id()) + })?, usage: hal::TextureUses::COLOR_TARGET, }); } colors.push(Some(hal::ColorAttachment { target: hal::Attachment { - view: color_view.raw(), + view: color_view.raw(snatch_guard).ok_or_else(|| { + RenderPassErrorInner::InvalidAttachment(color_view.info.id()) + })?, usage: hal::TextureUses::COLOR_TARGET, }, resolve_target: hal_resolve_target, @@ -1209,6 +1219,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { fn finish( mut self, raw: &mut A::CommandEncoder, + snatch_guard: &SnatchGuard, ) -> Result<(UsageScope, SurfacesInDiscardState), RenderPassErrorInner> { profiling::scope!("RenderPassInfo::finish"); unsafe { @@ -1256,7 +1267,9 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { color_attachments: &[], depth_stencil_attachment: Some(hal::DepthStencilAttachment { target: hal::Attachment { - view: view.raw(), + view: view.raw(snatch_guard).ok_or_else(|| { + RenderPassErrorInner::InvalidAttachment(view.info.id()) + })?, usage: hal::TextureUses::DEPTH_STENCIL_WRITE, }, depth_ops, @@ -1386,6 +1399,7 @@ impl Global { &*buffer_guard, &*texture_guard, &*query_set_guard, + &snatch_guard, ) .map_pass_err(pass_scope)?; @@ -2366,7 +2380,7 @@ impl Global { log::trace!("Merging renderpass into cmd_buf {:?}", encoder_id); let (trackers, pending_discard_init_fixups) = - info.finish(raw).map_pass_err(pass_scope)?; + info.finish(raw, &snatch_guard).map_pass_err(pass_scope)?; encoder.close().map_pass_err(pass_scope)?; (trackers, pending_discard_init_fixups) diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index c3b3706108..9435993eab 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -818,6 +818,12 @@ impl Global { }; let (id, resource) = fid.assign(view); + + { + let mut views = texture.views.lock(); + views.push(Arc::downgrade(&resource)); + } + api_log!("Texture::create_view({texture_id:?}) -> {id:?}"); device.trackers.lock().views.insert_single(id, resource); return (id, None); diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 2600051b39..68f5b6d0c4 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -595,6 +595,7 @@ impl Device { }, info: ResourceInfo::new(desc.label.borrow_or_default()), clear_mode: RwLock::new(clear_mode), + views: Mutex::new(Vec::new()), } } @@ -1177,7 +1178,7 @@ impl Device { }; Ok(TextureView { - raw: Some(raw), + raw: Snatchable::new(raw), parent: texture.clone(), device: self.clone(), desc: resource::HalTextureViewDescriptor { @@ -2126,7 +2127,9 @@ impl Device { )?; let res_index = hal_textures.len(); hal_textures.push(hal::TextureBinding { - view: view.raw(), + view: view + .raw(&snatch_guard) + .ok_or(Error::InvalidTextureView(id))?, usage: internal_use, }); (res_index, 1) @@ -2152,7 +2155,9 @@ impl Device { &mut used_texture_ranges, )?; hal_textures.push(hal::TextureBinding { - view: view.raw(), + view: view + .raw(&snatch_guard) + .ok_or(Error::InvalidTextureView(id))?, usage: internal_use, }); } diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index d7b34497a2..44b741b8c4 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -32,7 +32,7 @@ use crate::{ }; use hal::{Queue as _, Surface as _}; -use parking_lot::RwLock; +use parking_lot::{Mutex, RwLock}; use thiserror::Error; use wgt::SurfaceStatus as Status; @@ -231,6 +231,7 @@ impl Global { clear_mode: RwLock::new(resource::TextureClearMode::Surface { clear_view: Some(clear_view), }), + views: Mutex::new(Vec::new()), }; let (id, resource) = fid.assign(texture); diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 39b026feb3..ceab4b2326 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -34,7 +34,7 @@ use std::{ ptr::NonNull, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, - Arc, + Arc, Weak, }, }; @@ -741,6 +741,7 @@ pub struct Texture { pub(crate) full_range: TextureSelector, pub(crate) info: ResourceInfo, pub(crate) clear_mode: RwLock>, + pub(crate) views: Mutex>>>, } impl Drop for Texture { @@ -852,8 +853,14 @@ impl Texture { } }; + let views = { + let mut guard = self.views.lock(); + std::mem::take(&mut *guard) + }; + queue::TempResource::DestroyedTexture(Arc::new(DestroyedTexture { raw: Some(raw), + views, device: Arc::clone(&self.device), submission_index: self.info.submission_index(), id: self.info.id.unwrap(), @@ -970,6 +977,7 @@ impl Global { #[derive(Debug)] pub struct DestroyedTexture { raw: Option, + views: Vec>>, device: Arc>, label: String, pub(crate) id: TextureId, @@ -988,6 +996,24 @@ impl DestroyedTexture { impl Drop for DestroyedTexture { fn drop(&mut self) { + let device = &self.device; + for view in self.views.drain(..) { + if let Some(view) = view.upgrade() { + if let Some(raw_view) = view.raw.snatch(device.snatchable_lock.write()) { + resource_log!("Destroy raw TextureView (destroyed) {:?}", view.label()); + + #[cfg(feature = "trace")] + if let Some(t) = self.device.trace.lock().as_mut() { + t.add(trace::Action::DestroyTextureView(view.info.id())); + } + + unsafe { + use hal::Device; + self.device.raw().destroy_texture_view(raw_view); + } + } + } + } if let Some(raw) = self.raw.take() { resource_log!("Destroy raw Texture (destroyed) {:?}", self.label()); @@ -1170,7 +1196,7 @@ pub enum TextureViewNotRenderableReason { #[derive(Debug)] pub struct TextureView { - pub(crate) raw: Option, + pub(crate) raw: Snatchable, // if it's a surface texture - it's none pub(crate) parent: Arc>, pub(crate) device: Arc>, @@ -1203,8 +1229,8 @@ impl Drop for TextureView { } impl TextureView { - pub(crate) fn raw(&self) -> &A::TextureView { - self.raw.as_ref().unwrap() + pub(crate) fn raw<'a>(&'a self, snatch_guard: &'a SnatchGuard) -> Option<&'a A::TextureView> { + self.raw.get(snatch_guard) } }