Snatch the raw texture when destroying it

This commit is contained in:
Nicolas Silva 2024-01-02 12:33:14 +01:00 committed by Teodor Tanasoaia
parent 95c451a3b8
commit 4b82121501
4 changed files with 121 additions and 30 deletions

View File

@ -736,32 +736,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.get_and_mark_destroyed(texture_id) .get_and_mark_destroyed(texture_id)
.map_err(|_| resource::DestroyError::Invalid)?; .map_err(|_| resource::DestroyError::Invalid)?;
let device = &texture.device; texture.destroy()
#[cfg(feature = "trace")]
if let Some(ref mut trace) = *device.trace.lock() {
trace.add(trace::Action::FreeTexture(texture_id));
}
let last_submit_index = texture.info.submission_index();
let snatch_guard = texture.device.snatchable_lock.read();
if let Some(resource::TextureInner::Native { .. }) = texture.inner.get(&snatch_guard) {
let temp = queue::TempResource::Texture(texture.clone());
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);
}
}
Ok(())
} }
pub fn texture_drop<A: HalApi>(&self, texture_id: id::TextureId, wait: bool) { pub fn texture_drop<A: HalApi>(&self, texture_id: id::TextureId, wait: bool) {

View File

@ -15,8 +15,8 @@ use crate::{
}, },
pipeline::{ComputePipeline, RenderPipeline}, pipeline::{ComputePipeline, RenderPipeline},
resource::{ resource::{
self, Buffer, DestroyedBuffer, QuerySet, Resource, Sampler, StagingBuffer, Texture, self, Buffer, DestroyedBuffer, DestroyedTexture, QuerySet, Resource, Sampler,
TextureView, StagingBuffer, Texture, TextureView,
}, },
track::{ResourceTracker, Tracker}, track::{ResourceTracker, Tracker},
FastHashMap, SubmissionIndex, FastHashMap, SubmissionIndex,
@ -43,6 +43,7 @@ pub(crate) struct ResourceMaps<A: HalApi> {
pub render_bundles: FastHashMap<RenderBundleId, Arc<RenderBundle<A>>>, pub render_bundles: FastHashMap<RenderBundleId, Arc<RenderBundle<A>>>,
pub query_sets: FastHashMap<QuerySetId, Arc<QuerySet<A>>>, pub query_sets: FastHashMap<QuerySetId, Arc<QuerySet<A>>>,
pub destroyed_buffers: FastHashMap<BufferId, Arc<DestroyedBuffer<A>>>, pub destroyed_buffers: FastHashMap<BufferId, Arc<DestroyedBuffer<A>>>,
pub destroyed_textures: FastHashMap<TextureId, Arc<DestroyedTexture<A>>>,
} }
impl<A: HalApi> ResourceMaps<A> { impl<A: HalApi> ResourceMaps<A> {
@ -61,6 +62,7 @@ impl<A: HalApi> ResourceMaps<A> {
render_bundles: FastHashMap::default(), render_bundles: FastHashMap::default(),
query_sets: FastHashMap::default(), query_sets: FastHashMap::default(),
destroyed_buffers: FastHashMap::default(), destroyed_buffers: FastHashMap::default(),
destroyed_textures: FastHashMap::default(),
} }
} }
@ -79,6 +81,7 @@ impl<A: HalApi> ResourceMaps<A> {
render_bundles, render_bundles,
query_sets, query_sets,
destroyed_buffers, destroyed_buffers,
destroyed_textures,
} = self; } = self;
buffers.clear(); buffers.clear();
staging_buffers.clear(); staging_buffers.clear();
@ -93,6 +96,7 @@ impl<A: HalApi> ResourceMaps<A> {
render_bundles.clear(); render_bundles.clear();
query_sets.clear(); query_sets.clear();
destroyed_buffers.clear(); destroyed_buffers.clear();
destroyed_textures.clear();
} }
pub(crate) fn extend(&mut self, mut other: Self) { pub(crate) fn extend(&mut self, mut other: Self) {
@ -110,6 +114,7 @@ impl<A: HalApi> ResourceMaps<A> {
render_bundles, render_bundles,
query_sets, query_sets,
destroyed_buffers, destroyed_buffers,
destroyed_textures,
} = self; } = self;
buffers.extend(other.buffers.drain()); buffers.extend(other.buffers.drain());
staging_buffers.extend(other.staging_buffers.drain()); staging_buffers.extend(other.staging_buffers.drain());
@ -124,6 +129,7 @@ impl<A: HalApi> ResourceMaps<A> {
render_bundles.extend(other.render_bundles.drain()); render_bundles.extend(other.render_bundles.drain());
query_sets.extend(other.query_sets.drain()); query_sets.extend(other.query_sets.drain());
destroyed_buffers.extend(other.destroyed_buffers.drain()); destroyed_buffers.extend(other.destroyed_buffers.drain());
destroyed_textures.extend(other.destroyed_textures.drain());
} }
} }
@ -298,6 +304,11 @@ impl<A: HalApi> LifetimeTracker<A> {
TempResource::Texture(raw) => { TempResource::Texture(raw) => {
last_resources.textures.insert(raw.as_info().id(), raw); last_resources.textures.insert(raw.as_info().id(), raw);
} }
TempResource::DestroyedTexture(destroyed) => {
last_resources
.destroyed_textures
.insert(destroyed.id, destroyed);
}
} }
} }
@ -404,6 +415,9 @@ impl<A: HalApi> LifetimeTracker<A> {
TempResource::Texture(raw) => { TempResource::Texture(raw) => {
resources.textures.insert(raw.as_info().id(), raw); resources.textures.insert(raw.as_info().id(), raw);
} }
TempResource::DestroyedTexture(destroyed) => {
resources.destroyed_textures.insert(destroyed.id, destroyed);
}
} }
} }
@ -680,6 +694,27 @@ impl<A: HalApi> LifetimeTracker<A> {
} }
} }
fn triage_suspected_destroyed_textures(
&mut self,
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
) {
for (id, texture) in self.suspected_resources.destroyed_textures.drain() {
let submit_index = texture.submission_index;
if let Some(resources) = self.active.iter_mut().find(|a| a.index == submit_index) {
resources
.last_resources
.destroyed_textures
.insert(id, texture);
} else {
self.free_resources.destroyed_textures.insert(id, texture);
}
#[cfg(feature = "trace")]
if let Some(ref mut t) = *trace {
t.add(trace::Action::DestroyTexture(id));
}
}
}
fn triage_suspected_compute_pipelines( fn triage_suspected_compute_pipelines(
&mut self, &mut self,
trackers: &Mutex<Tracker<A>>, trackers: &Mutex<Tracker<A>>,
@ -913,6 +948,10 @@ impl<A: HalApi> LifetimeTracker<A> {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
&mut trace, &mut trace,
); );
self.triage_suspected_destroyed_textures(
#[cfg(feature = "trace")]
&mut trace,
);
} }
/// Determine which buffers are ready to map, and which must wait for the /// Determine which buffers are ready to map, and which must wait for the

View File

@ -16,8 +16,8 @@ use crate::{
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange}, init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
resource::{ resource::{
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, Resource, ResourceInfo, Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, Resource,
ResourceType, StagingBuffer, Texture, TextureInner, ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner,
}, },
resource_log, track, FastHashMap, SubmissionIndex, resource_log, track, FastHashMap, SubmissionIndex,
}; };
@ -164,6 +164,7 @@ pub enum TempResource<A: HalApi> {
Buffer(Arc<Buffer<A>>), Buffer(Arc<Buffer<A>>),
StagingBuffer(Arc<StagingBuffer<A>>), StagingBuffer(Arc<StagingBuffer<A>>),
DestroyedBuffer(Arc<DestroyedBuffer<A>>), DestroyedBuffer(Arc<DestroyedBuffer<A>>),
DestroyedTexture(Arc<DestroyedTexture<A>>),
Texture(Arc<Texture<A>>), Texture(Arc<Texture<A>>),
} }

View File

@ -835,6 +835,50 @@ impl<A: HalApi> Texture<A> {
} }
} }
} }
pub(crate) fn destroy(self: &Arc<Self>) -> Result<(), DestroyError> {
let device = &self.device;
let texture_id = self.info.id();
#[cfg(feature = "trace")]
if let Some(ref mut trace) = *device.trace.lock() {
trace.add(trace::Action::FreeTexture(texture_id));
}
let temp = {
let snatch_guard = device.snatchable_lock.write();
let raw = match self.inner.snatch(snatch_guard) {
Some(TextureInner::Native { raw }) => raw,
Some(TextureInner::Surface { .. }) => {
return Ok(());
}
None => {
return Err(resource::DestroyError::AlreadyDestroyed);
}
};
queue::TempResource::DestroyedTexture(Arc::new(DestroyedTexture {
raw: Some(raw),
device: Arc::clone(&self.device),
submission_index: self.info.submission_index(),
id: self.info.id.unwrap(),
label: self.info.label.clone(),
}))
};
let mut pending_writes = device.pending_writes.lock();
let pending_writes = pending_writes.as_mut().unwrap();
if pending_writes.dst_textures.contains_key(&texture_id) {
pending_writes.temp_resources.push(temp);
} else {
let last_submit_index = self.info.submission_index();
device
.lock_life()
.schedule_resource_destruction(temp, last_submit_index);
}
Ok(())
}
} }
impl<G: GlobalIdentityHandlerFactory> Global<G> { impl<G: GlobalIdentityHandlerFactory> Global<G> {
@ -927,6 +971,38 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
} }
/// A texture that has been marked as destroyed and is staged for actual deletion soon.
#[derive(Debug)]
pub struct DestroyedTexture<A: HalApi> {
raw: Option<A::Texture>,
device: Arc<Device<A>>,
label: String,
pub(crate) id: TextureId,
pub(crate) submission_index: u64,
}
impl<A: HalApi> DestroyedTexture<A> {
pub fn label(&self) -> &dyn Debug {
if !self.label.is_empty() {
return &self.label;
}
&self.id
}
}
impl<A: HalApi> Drop for DestroyedTexture<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Deallocate raw Texture (destroyed) {:?}", self.label());
unsafe {
use hal::Device;
self.device.raw().destroy_texture(raw);
}
}
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum TextureErrorDimension { pub enum TextureErrorDimension {
X, X,