mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-26 00:33:51 +00:00
Snatch the raw texture when destroying it
This commit is contained in:
parent
95c451a3b8
commit
4b82121501
@ -736,32 +736,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.get_and_mark_destroyed(texture_id)
|
||||
.map_err(|_| resource::DestroyError::Invalid)?;
|
||||
|
||||
let device = &texture.device;
|
||||
|
||||
#[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(())
|
||||
texture.destroy()
|
||||
}
|
||||
|
||||
pub fn texture_drop<A: HalApi>(&self, texture_id: id::TextureId, wait: bool) {
|
||||
|
@ -15,8 +15,8 @@ use crate::{
|
||||
},
|
||||
pipeline::{ComputePipeline, RenderPipeline},
|
||||
resource::{
|
||||
self, Buffer, DestroyedBuffer, QuerySet, Resource, Sampler, StagingBuffer, Texture,
|
||||
TextureView,
|
||||
self, Buffer, DestroyedBuffer, DestroyedTexture, QuerySet, Resource, Sampler,
|
||||
StagingBuffer, Texture, TextureView,
|
||||
},
|
||||
track::{ResourceTracker, Tracker},
|
||||
FastHashMap, SubmissionIndex,
|
||||
@ -43,6 +43,7 @@ pub(crate) struct ResourceMaps<A: HalApi> {
|
||||
pub render_bundles: FastHashMap<RenderBundleId, Arc<RenderBundle<A>>>,
|
||||
pub query_sets: FastHashMap<QuerySetId, Arc<QuerySet<A>>>,
|
||||
pub destroyed_buffers: FastHashMap<BufferId, Arc<DestroyedBuffer<A>>>,
|
||||
pub destroyed_textures: FastHashMap<TextureId, Arc<DestroyedTexture<A>>>,
|
||||
}
|
||||
|
||||
impl<A: HalApi> ResourceMaps<A> {
|
||||
@ -61,6 +62,7 @@ impl<A: HalApi> ResourceMaps<A> {
|
||||
render_bundles: FastHashMap::default(),
|
||||
query_sets: FastHashMap::default(),
|
||||
destroyed_buffers: FastHashMap::default(),
|
||||
destroyed_textures: FastHashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +81,7 @@ impl<A: HalApi> ResourceMaps<A> {
|
||||
render_bundles,
|
||||
query_sets,
|
||||
destroyed_buffers,
|
||||
destroyed_textures,
|
||||
} = self;
|
||||
buffers.clear();
|
||||
staging_buffers.clear();
|
||||
@ -93,6 +96,7 @@ impl<A: HalApi> ResourceMaps<A> {
|
||||
render_bundles.clear();
|
||||
query_sets.clear();
|
||||
destroyed_buffers.clear();
|
||||
destroyed_textures.clear();
|
||||
}
|
||||
|
||||
pub(crate) fn extend(&mut self, mut other: Self) {
|
||||
@ -110,6 +114,7 @@ impl<A: HalApi> ResourceMaps<A> {
|
||||
render_bundles,
|
||||
query_sets,
|
||||
destroyed_buffers,
|
||||
destroyed_textures,
|
||||
} = self;
|
||||
buffers.extend(other.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());
|
||||
query_sets.extend(other.query_sets.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) => {
|
||||
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) => {
|
||||
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(
|
||||
&mut self,
|
||||
trackers: &Mutex<Tracker<A>>,
|
||||
@ -913,6 +948,10 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "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
|
||||
|
@ -16,8 +16,8 @@ use crate::{
|
||||
identity::{GlobalIdentityHandlerFactory, Input},
|
||||
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
|
||||
resource::{
|
||||
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, Resource, ResourceInfo,
|
||||
ResourceType, StagingBuffer, Texture, TextureInner,
|
||||
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, Resource,
|
||||
ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner,
|
||||
},
|
||||
resource_log, track, FastHashMap, SubmissionIndex,
|
||||
};
|
||||
@ -164,6 +164,7 @@ pub enum TempResource<A: HalApi> {
|
||||
Buffer(Arc<Buffer<A>>),
|
||||
StagingBuffer(Arc<StagingBuffer<A>>),
|
||||
DestroyedBuffer(Arc<DestroyedBuffer<A>>),
|
||||
DestroyedTexture(Arc<DestroyedTexture<A>>),
|
||||
Texture(Arc<Texture<A>>),
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
@ -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)]
|
||||
pub enum TextureErrorDimension {
|
||||
X,
|
||||
|
Loading…
Reference in New Issue
Block a user