Early texture destruction

This commit is contained in:
Dzmitry Malyshau 2020-10-08 23:21:11 -04:00
parent c4c8e3b224
commit c87a94f976
8 changed files with 101 additions and 22 deletions

View File

@ -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);
}

View File

@ -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),
);

View File

@ -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);
}
}
}

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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,