mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
Early texture destruction
This commit is contained in:
parent
c4c8e3b224
commit
c87a94f976
@ -149,6 +149,9 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
self.device_maintain_ids::<B>(device).unwrap();
|
||||
self.device_create_texture::<B>(device, &desc, id).unwrap();
|
||||
}
|
||||
A::FreeTexture(id) => {
|
||||
self.texture_destroy::<B>(id).unwrap();
|
||||
}
|
||||
A::DestroyTexture(id) => {
|
||||
self.texture_drop::<B>(id, true);
|
||||
}
|
||||
|
@ -460,6 +460,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TextureUse::COPY_DST,
|
||||
)
|
||||
.unwrap();
|
||||
let &(ref dst_raw, _) = dst_texture
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(TransferError::InvalidTexture(destination.texture))?;
|
||||
if !dst_texture.usage.contains(TextureUsage::COPY_DST) {
|
||||
Err(TransferError::MissingCopyDstUsageFlag)?
|
||||
}
|
||||
@ -518,7 +522,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
);
|
||||
cmb_raw.copy_buffer_to_image(
|
||||
src_raw,
|
||||
&dst_texture.raw,
|
||||
dst_raw,
|
||||
hal::image::Layout::TransferDstOptimal,
|
||||
iter::once(region),
|
||||
);
|
||||
@ -568,6 +572,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TextureUse::COPY_SRC,
|
||||
)
|
||||
.unwrap();
|
||||
let &(ref src_raw, _) = src_texture
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(TransferError::InvalidTexture(source.texture))?;
|
||||
if !src_texture.usage.contains(TextureUsage::COPY_SRC) {
|
||||
Err(TransferError::MissingCopySrcUsageFlag)?
|
||||
}
|
||||
@ -639,7 +647,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
src_barriers.chain(dst_barrier),
|
||||
);
|
||||
cmb_raw.copy_image_to_buffer(
|
||||
&src_texture.raw,
|
||||
src_raw,
|
||||
hal::image::Layout::TransferSrcOptimal,
|
||||
dst_raw,
|
||||
iter::once(region),
|
||||
@ -699,6 +707,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TextureUse::COPY_SRC,
|
||||
)
|
||||
.unwrap();
|
||||
let &(ref src_raw, _) = src_texture
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(TransferError::InvalidTexture(source.texture))?;
|
||||
if !src_texture.usage.contains(TextureUsage::COPY_SRC) {
|
||||
Err(TransferError::MissingCopySrcUsageFlag)?
|
||||
}
|
||||
@ -714,6 +726,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TextureUse::COPY_DST,
|
||||
)
|
||||
.unwrap();
|
||||
let &(ref dst_raw, _) = dst_texture
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(TransferError::InvalidTexture(destination.texture))?;
|
||||
if !dst_texture.usage.contains(TextureUsage::COPY_DST) {
|
||||
Err(TransferError::MissingCopyDstUsageFlag)?
|
||||
}
|
||||
@ -749,9 +765,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
barriers,
|
||||
);
|
||||
cmb_raw.copy_image(
|
||||
&src_texture.raw,
|
||||
src_raw,
|
||||
hal::image::Layout::TransferSrcOptimal,
|
||||
&dst_texture.raw,
|
||||
dst_raw,
|
||||
hal::image::Layout::TransferDstOptimal,
|
||||
iter::once(region),
|
||||
);
|
||||
|
@ -247,7 +247,7 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
||||
for (res, memory) in temp_resources {
|
||||
match res {
|
||||
TempResource::Buffer(raw) => last_resources.buffers.push((raw, memory)),
|
||||
//TempResource::Image(raw) => last_resources.images.push((raw, memory)),
|
||||
TempResource::Image(raw) => last_resources.images.push((raw, memory)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,7 +357,7 @@ impl<B: hal::Backend> LifetimeTracker<B> {
|
||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources);
|
||||
match temp_resource {
|
||||
TempResource::Buffer(raw) => resources.buffers.push((raw, memory)),
|
||||
//TempResource::Image(raw) => resources.images.push((raw, memory)),
|
||||
TempResource::Image(raw) => resources.images.push((raw, memory)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,7 +456,7 @@ impl<B: GfxBackend> LifetimeTracker<B> {
|
||||
.find(|a| a.index == submit_index)
|
||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
|
||||
.images
|
||||
.push((res.raw, res.memory));
|
||||
.extend(res.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
.map_err(DeviceError::from_bind)?;
|
||||
|
||||
Ok(resource::Texture {
|
||||
raw: image,
|
||||
raw: Some((image, memory)),
|
||||
device_id: Stored {
|
||||
value: id::Valid(self_id),
|
||||
ref_count: self.life_guard.add_ref(),
|
||||
@ -600,7 +600,6 @@ impl<B: GfxBackend> Device<B> {
|
||||
levels: 0..desc.mip_level_count as hal::image::Level,
|
||||
layers: 0..kind.num_layers(),
|
||||
},
|
||||
memory,
|
||||
life_guard: LifeGuard::new(),
|
||||
})
|
||||
}
|
||||
@ -888,9 +887,11 @@ impl<B: hal::Backend> Device<B> {
|
||||
}
|
||||
|
||||
pub(crate) fn destroy_texture(&self, texture: resource::Texture<B>) {
|
||||
unsafe {
|
||||
self.mem_allocator.lock().free(&self.raw, texture.memory);
|
||||
self.raw.destroy_image(texture.raw);
|
||||
if let Some((raw, memory)) = texture.raw {
|
||||
unsafe {
|
||||
self.mem_allocator.lock().free(&self.raw, memory);
|
||||
self.raw.destroy_image(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1357,6 +1358,52 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.register_error(id_in, &mut Token::root())
|
||||
}
|
||||
|
||||
pub fn texture_destroy<B: GfxBackend>(
|
||||
&self,
|
||||
texture_id: id::TextureId,
|
||||
) -> Result<(), resource::DestroyError> {
|
||||
span!(_guard, INFO, "Texture::destroy");
|
||||
|
||||
let hub = B::hub(self);
|
||||
let mut token = Token::root();
|
||||
|
||||
//TODO: lock pending writes separately, keep the device read-only
|
||||
let (mut device_guard, mut token) = hub.devices.write(&mut token);
|
||||
|
||||
tracing::info!("Buffer {:?} is destroyed", texture_id);
|
||||
let (mut texture_guard, _) = hub.textures.write(&mut token);
|
||||
let texture = texture_guard
|
||||
.get_mut(texture_id)
|
||||
.map_err(|_| resource::DestroyError::Invalid)?;
|
||||
|
||||
let device = &mut device_guard[texture.device_id.value];
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref trace) = device.trace {
|
||||
trace.lock().add(trace::Action::FreeTexture(texture_id));
|
||||
}
|
||||
|
||||
let (raw, memory) = texture
|
||||
.raw
|
||||
.take()
|
||||
.ok_or(resource::DestroyError::AlreadyDestroyed)?;
|
||||
let temp = queue::TempResource::Image(raw);
|
||||
|
||||
if device.pending_writes.dst_textures.contains(&texture_id) {
|
||||
device.pending_writes.temp_resources.push((temp, memory));
|
||||
} else {
|
||||
let last_submit_index = texture.life_guard.submission_index.load(Ordering::Acquire);
|
||||
drop(texture_guard);
|
||||
device.lock_life(&mut token).schedule_resource_destruction(
|
||||
temp,
|
||||
memory,
|
||||
last_submit_index,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn texture_drop<B: GfxBackend>(&self, texture_id: id::TextureId, wait: bool) {
|
||||
span!(_guard, INFO, "Texture::drop");
|
||||
|
||||
@ -1421,6 +1468,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let texture = texture_guard
|
||||
.get(texture_id)
|
||||
.map_err(|_| resource::CreateTextureViewError::InvalidTexture)?;
|
||||
let &(ref texture_raw, _) = texture
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(resource::CreateTextureViewError::InvalidTexture)?;
|
||||
let device = &device_guard[texture.device_id.value];
|
||||
|
||||
let view_kind = match desc.dimension {
|
||||
@ -1477,7 +1528,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
device
|
||||
.raw
|
||||
.create_image_view(
|
||||
&texture.raw,
|
||||
texture_raw,
|
||||
view_kind,
|
||||
conv::map_texture_format(format, device.private_features),
|
||||
hal::format::Swizzle::NO,
|
||||
|
@ -32,7 +32,7 @@ struct StagingData<B: hal::Backend> {
|
||||
#[derive(Debug)]
|
||||
pub enum TempResource<B: hal::Backend> {
|
||||
Buffer(B::Buffer),
|
||||
//Image(B::Image),
|
||||
Image(B::Image),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -68,9 +68,9 @@ impl<B: hal::Backend> PendingWrites<B> {
|
||||
TempResource::Buffer(buffer) => unsafe {
|
||||
device.destroy_buffer(buffer);
|
||||
},
|
||||
/*TempResource::Image(image) => unsafe {
|
||||
TempResource::Image(image) => unsafe {
|
||||
device.destroy_image(image);
|
||||
},*/
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -371,6 +371,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TextureUse::COPY_DST,
|
||||
)
|
||||
.unwrap();
|
||||
let &(ref dst_raw, _) = dst
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok_or(TransferError::InvalidTexture(destination.texture))?;
|
||||
|
||||
if !dst.usage.contains(wgt::TextureUsage::COPY_DST) {
|
||||
Err(TransferError::MissingCopyDstUsageFlag)?
|
||||
@ -438,7 +442,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
);
|
||||
stage.cmdbuf.copy_buffer_to_image(
|
||||
&stage.buffer,
|
||||
&dst.raw,
|
||||
dst_raw,
|
||||
hal::image::Layout::TransferDstOptimal,
|
||||
iter::once(region),
|
||||
);
|
||||
@ -545,7 +549,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
}
|
||||
for id in cmdbuf.trackers.textures.used() {
|
||||
if !texture_guard[id].life_guard.use_at(submit_index) {
|
||||
let texture = &texture_guard[id];
|
||||
if texture.raw.is_none() {
|
||||
return Err(QueueSubmitError::DestroyedTexture(id.0))?;
|
||||
}
|
||||
if !texture.life_guard.use_at(submit_index) {
|
||||
device.temp_suspected.textures.push(id);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ pub enum Action<'a> {
|
||||
FreeBuffer(id::BufferId),
|
||||
DestroyBuffer(id::BufferId),
|
||||
CreateTexture(id::TextureId, crate::resource::TextureDescriptor<'a>),
|
||||
FreeTexture(id::TextureId),
|
||||
DestroyTexture(id::TextureId),
|
||||
CreateTextureView {
|
||||
id: id::TextureViewId,
|
||||
|
@ -204,7 +204,7 @@ pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Texture<B: hal::Backend> {
|
||||
pub(crate) raw: B::Image,
|
||||
pub(crate) raw: Option<(B::Image, MemoryBlock<B>)>,
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
pub(crate) usage: wgt::TextureUsage,
|
||||
pub(crate) aspects: hal::format::Aspects,
|
||||
@ -212,7 +212,6 @@ pub struct Texture<B: hal::Backend> {
|
||||
pub(crate) kind: hal::image::Kind,
|
||||
pub(crate) format: wgt::TextureFormat,
|
||||
pub(crate) full_range: TextureSelector,
|
||||
pub(crate) memory: MemoryBlock<B>,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
@ -314,7 +313,7 @@ pub struct TextureView<B: hal::Backend> {
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum CreateTextureViewError {
|
||||
#[error("parent texture is invalid")]
|
||||
#[error("parent texture is invalid or destroyed")]
|
||||
InvalidTexture,
|
||||
#[error("not enough memory left")]
|
||||
OutOfMemory,
|
||||
|
@ -152,11 +152,12 @@ impl PendingTransition<TextureState> {
|
||||
tex: &'a resource::Texture<B>,
|
||||
) -> hal::memory::Barrier<'a, B> {
|
||||
tracing::trace!("\ttexture -> {:?}", self);
|
||||
let &(ref target, _) = tex.raw.as_ref().expect("Texture is destroyed");
|
||||
let aspects = tex.aspects;
|
||||
hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(self.usage.start, aspects)
|
||||
..conv::map_texture_state(self.usage.end, aspects),
|
||||
target: &tex.raw,
|
||||
target,
|
||||
range: hal::image::SubresourceRange {
|
||||
aspects,
|
||||
level_start: self.selector.levels.start,
|
||||
|
Loading…
Reference in New Issue
Block a user