diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 27528cf98f..0d25140f42 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -14,6 +14,7 @@ use crate::device::{ all_buffer_stages, all_image_stages, }; use crate::hub::{HUB, Storage}; +use crate::resource::TexturePlacement; use crate::swap_chain::{SwapChainLink, SwapImageEpoch}; use crate::track::TrackerSet; use crate::conv; @@ -218,14 +219,15 @@ pub fn command_encoder_begin_render_pass( if view.is_owned_by_swap_chain { let link = match HUB.textures .read() - [view.texture_id.value].swap_chain_link + [view.texture_id.value].placement { - Some(ref link) => SwapChainLink { + TexturePlacement::SwapChain(ref link) => SwapChainLink { swap_chain_id: link.swap_chain_id.clone(), epoch: *link.epoch.lock(), image_index: link.image_index, }, - None => unreachable!() + TexturePlacement::Memory(_) | + TexturePlacement::Void => unreachable!() }; swap_chain_links.push(link); } diff --git a/wgpu-native/src/command/transfer.rs b/wgpu-native/src/command/transfer.rs index 7eab24346f..76d11d4268 100644 --- a/wgpu-native/src/command/transfer.rs +++ b/wgpu-native/src/command/transfer.rs @@ -1,5 +1,6 @@ use crate::device::{all_buffer_stages, all_image_stages}; use crate::hub::HUB; +use crate::resource::TexturePlacement; use crate::swap_chain::SwapChainLink; use crate::conv; use crate::{ @@ -135,7 +136,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture( range: dst_texture.full_range.clone(), }); - if let Some(ref link) = dst_texture.swap_chain_link { + if let TexturePlacement::SwapChain(ref link) = dst_texture.placement { cmb.swap_chain_links.push(SwapChainLink { swap_chain_id: link.swap_chain_id.clone(), epoch: *link.epoch.lock(), @@ -203,7 +204,11 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer( families: None, range: src_texture.full_range.clone(), }); - assert!(src_texture.swap_chain_link.is_none()); //TODO + match src_texture.placement { + TexturePlacement::SwapChain(_) => unimplemented!(), + TexturePlacement::Void => unreachable!(), + TexturePlacement::Memory(_) => (), + } let (dst_buffer, dst_usage) = cmb.trackers.buffers .get_with_replaced_usage( @@ -295,7 +300,7 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture( range: dst_texture.full_range.clone(), }); - if let Some(ref link) = dst_texture.swap_chain_link { + if let TexturePlacement::SwapChain(ref link) = dst_texture.placement { cmb.swap_chain_links.push(SwapChainLink { swap_chain_id: link.swap_chain_id.clone(), epoch: *link.epoch.lock(), diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 066421580d..65a69d3f2e 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -7,11 +7,11 @@ use crate::{ }; use crate::{ BufferId, CommandBufferId, AdapterId, DeviceId, QueueId, - TextureId, TextureViewId, SurfaceId, + BindGroupId, TextureId, TextureViewId, SurfaceId, }; #[cfg(feature = "local")] use crate::{ - BindGroupId, BindGroupLayoutId, PipelineLayoutId, SamplerId, SwapChainId, + BindGroupLayoutId, PipelineLayoutId, SamplerId, SwapChainId, ShaderModuleId, CommandEncoderId, RenderPipelineId, ComputePipelineId, }; @@ -78,8 +78,8 @@ enum ResourceId { } enum NativeResource { - Buffer(B::Buffer), - Image(B::Image), + Buffer(B::Buffer, B::Memory), + Image(B::Image, B::Memory), ImageView(B::ImageView), Framebuffer(B::Framebuffer), } @@ -140,17 +140,19 @@ impl DestroyedResources { for resource in self.free.drain(..) { match resource { - NativeResource::Buffer(raw) => unsafe { - device.destroy_buffer(raw) + NativeResource::Buffer(raw, memory) => unsafe { + device.destroy_buffer(raw); + device.free_memory(memory); }, - NativeResource::Image(raw) => unsafe { - device.destroy_image(raw) + NativeResource::Image(raw, memory) => unsafe { + device.destroy_image(raw); + device.free_memory(memory); }, NativeResource::ImageView(raw) => unsafe { - device.destroy_image_view(raw) + device.destroy_image_view(raw); }, NativeResource::Framebuffer(raw) => unsafe { - device.destroy_framebuffer(raw) + device.destroy_framebuffer(raw); }, } } @@ -177,12 +179,18 @@ impl DestroyedResources { ResourceId::Buffer(id) => { trackers.buffers.remove(id); let buf = HUB.buffers.unregister(id); - (buf.life_guard, NativeResource::Buffer(buf.raw)) + (buf.life_guard, NativeResource::Buffer(buf.raw, buf.memory)) } ResourceId::Texture(id) => { trackers.textures.remove(id); let tex = HUB.textures.unregister(id); - (tex.life_guard, NativeResource::Image(tex.raw)) + let memory = match tex.placement { + // swapchain-owned images don't need explicit destruction + resource::TexturePlacement::SwapChain(_) => continue, + resource::TexturePlacement::Memory(mem) => mem, + resource::TexturePlacement::Void => unreachable!(), + }; + (tex.life_guard, NativeResource::Image(tex.raw, memory)) } ResourceId::TextureView(id) => { trackers.views.remove(id); @@ -555,7 +563,7 @@ pub fn device_create_texture( levels: 0 .. 1, //TODO: mips layers: 0 .. desc.array_size as u16, }, - swap_chain_link: None, + placement: resource::TexturePlacement::Memory(memory), life_guard: LifeGuard::new(), } } @@ -940,6 +948,11 @@ pub extern "C" fn wgpu_device_create_bind_group( HUB.bind_groups.register_local(bind_group) } +#[no_mangle] +pub extern "C" fn wgpu_bind_group_destroy(bind_group_id: BindGroupId) { + HUB.bind_groups.unregister(bind_group_id); +} + pub fn device_create_shader_module( device_id: DeviceId, @@ -1029,6 +1042,7 @@ pub extern "C" fn wgpu_queue_submit( let mut command_buffer_guard = HUB.command_buffers.write(); let buffer_guard = HUB.buffers.read(); let texture_guard = HUB.textures.read(); + let texture_view_guard = HUB.texture_views.read(); // finish all the command buffers first for &cmb_id in command_buffer_ids { @@ -1045,6 +1059,10 @@ pub extern "C" fn wgpu_queue_submit( texture_guard[id].life_guard.submission_index .store(old_submit_index, Ordering::Release); } + for id in comb.trackers.views.used() { + texture_view_guard[id].life_guard.submission_index + .store(old_submit_index, Ordering::Release); + } // execute resource transitions let mut transit = device.com_allocator.extend(comb); @@ -1519,7 +1537,7 @@ pub fn device_create_swap_chain( levels: 0 .. 1, layers: 0 .. 1, }, - swap_chain_link: None, + placement: resource::TexturePlacement::Void, life_guard: LifeGuard::new(), }) .collect() @@ -1553,7 +1571,7 @@ pub fn swap_chain_populate_textures( ) .unwrap() }; - texture.swap_chain_link = Some(swap_chain::SwapChainLink { + texture.placement = resource::TexturePlacement::SwapChain(swap_chain::SwapChainLink { swap_chain_id, //TODO: strongly epoch: Mutex::new(0), image_index: i as hal::SwapImageIndex, diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index fd6826a917..a67c975f1f 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -105,13 +105,29 @@ pub struct TextureDescriptor { pub usage: TextureUsageFlags, } +pub(crate) enum TexturePlacement { + SwapChain(SwapChainLink>), + Memory(B::Memory), + Void, +} + +impl TexturePlacement { + pub fn as_swap_chain(&self) -> &SwapChainLink> { + match *self { + TexturePlacement::SwapChain(ref link) => link, + TexturePlacement::Memory(_) | + TexturePlacement::Void => panic!("Expected swap chain link!"), + } + } +} + pub struct Texture { pub(crate) raw: B::Image, pub(crate) device_id: Stored, pub(crate) kind: hal::image::Kind, pub(crate) format: TextureFormat, pub(crate) full_range: hal::image::SubresourceRange, - pub(crate) swap_chain_link: Option>>, + pub(crate) placement: TexturePlacement, pub(crate) life_guard: LifeGuard, } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index f561d0d05f..f239fa4829 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -10,6 +10,7 @@ use crate::track::{TrackPermit}; use hal; use hal::{Device as _Device, Swapchain as _Swapchain}; use log::{trace, warn}; +use parking_lot::Mutex; use std::{iter, mem}; @@ -22,6 +23,12 @@ pub(crate) struct SwapChainLink { pub image_index: hal::SwapImageIndex, } +impl SwapChainLink> { + pub fn bump_epoch(&self) { + *self.epoch.lock() += 1; + } +} + pub struct Surface { pub(crate) raw: B::Surface, pub(crate) swap_chain: Option>, @@ -144,10 +151,7 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture( } mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available); - match HUB.textures.read()[frame.texture_id.value].swap_chain_link { - Some(ref link) => *link.epoch.lock() += 1, - None => unreachable!(), - } + HUB.textures.read()[frame.texture_id.value].placement.as_swap_chain().bump_epoch(); SwapChainOutput { texture_id: frame.texture_id.value, @@ -173,10 +177,7 @@ pub extern "C" fn wgpu_swap_chain_present( let texture_guard = HUB.textures.read(); let texture = &texture_guard[frame.texture_id.value]; - match texture.swap_chain_link { - Some(ref link) => *link.epoch.lock() += 1, - None => unreachable!(), - } + texture.placement.as_swap_chain().bump_epoch(); //TODO: support for swapchain being sampled or read by the shader? diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index d9ee7ca38b..6ed5eb1e17 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -144,6 +144,11 @@ impl DummyTracker { self.query(I::new(index, epoch), ref_count); } } + + /// Return an iterator over used resources keys. + pub fn used<'a>(&'a self) -> impl 'a + Iterator { + self.map.iter().map(|(&index, &(_, epoch))| I::new(index, epoch)) + } } impl + PartialEq> Tracker { diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index e3b95692c0..4ed2bcb30c 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -83,6 +83,12 @@ pub struct BindGroup { id: wgn::BindGroupId, } +impl Drop for BindGroup { + fn drop(&mut self) { + wgn::wgpu_bind_group_destroy(self.id); + } +} + pub struct ShaderModule { id: wgn::ShaderModuleId, }