Snatch texture views of destroyed textures (#5131)

This commit is contained in:
Nicolas Silva 2024-01-24 20:55:20 +01:00 committed by GitHub
parent b0e4734a7e
commit 7d0f656dd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 65 additions and 13 deletions

View File

@ -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<Buffer<A>, id::BufferId>,
texture_guard: &'a Storage<Texture<A>, id::TextureId>,
query_set_guard: &'a Storage<QuerySet<A>, id::QuerySetId>,
snatch_guard: &SnatchGuard<'a>,
) -> Result<Self, RenderPassErrorInner> {
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<A>, SurfacesInDiscardState<A>), 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<G: GlobalIdentityHandlerFactory> Global<G> {
&*buffer_guard,
&*texture_guard,
&*query_set_guard,
&snatch_guard,
)
.map_pass_err(pass_scope)?;
@ -2366,7 +2380,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
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)

View File

@ -818,6 +818,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
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);

View File

@ -595,6 +595,7 @@ impl<A: HalApi> Device<A> {
},
info: ResourceInfo::new(desc.label.borrow_or_default()),
clear_mode: RwLock::new(clear_mode),
views: Mutex::new(Vec::new()),
}
}
@ -1177,7 +1178,7 @@ impl<A: HalApi> Device<A> {
};
Ok(TextureView {
raw: Some(raw),
raw: Snatchable::new(raw),
parent: texture.clone(),
device: self.clone(),
desc: resource::HalTextureViewDescriptor {
@ -2126,7 +2127,9 @@ impl<A: HalApi> Device<A> {
)?;
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<A: HalApi> Device<A> {
&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,
});
}

View File

@ -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<G: GlobalIdentityHandlerFactory> Global<G> {
clear_mode: RwLock::new(resource::TextureClearMode::Surface {
clear_view: Some(clear_view),
}),
views: Mutex::new(Vec::new()),
};
let (id, resource) = fid.assign(texture);

View File

@ -34,7 +34,7 @@ use std::{
ptr::NonNull,
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering},
Arc,
Arc, Weak,
},
};
@ -741,6 +741,7 @@ pub struct Texture<A: HalApi> {
pub(crate) full_range: TextureSelector,
pub(crate) info: ResourceInfo<TextureId>,
pub(crate) clear_mode: RwLock<TextureClearMode<A>>,
pub(crate) views: Mutex<Vec<Weak<TextureView<A>>>>,
}
impl<A: HalApi> Drop for Texture<A> {
@ -852,8 +853,14 @@ impl<A: HalApi> Texture<A> {
}
};
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<G: GlobalIdentityHandlerFactory> Global<G> {
#[derive(Debug)]
pub struct DestroyedTexture<A: HalApi> {
raw: Option<A::Texture>,
views: Vec<Weak<TextureView<A>>>,
device: Arc<Device<A>>,
label: String,
pub(crate) id: TextureId,
@ -988,6 +996,24 @@ impl<A: HalApi> DestroyedTexture<A> {
impl<A: HalApi> Drop for DestroyedTexture<A> {
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<A: HalApi> {
pub(crate) raw: Option<A::TextureView>,
pub(crate) raw: Snatchable<A::TextureView>,
// if it's a surface texture - it's none
pub(crate) parent: Arc<Texture<A>>,
pub(crate) device: Arc<Device<A>>,
@ -1203,8 +1229,8 @@ impl<A: HalApi> Drop for TextureView<A> {
}
impl<A: HalApi> TextureView<A> {
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)
}
}