mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +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)
|
.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) {
|
||||||
|
@ -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
|
||||||
|
@ -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>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user