Free memory objects

This commit is contained in:
Dzmitry Malyshau
2019-02-26 15:10:43 -05:00
parent f0e245e4dc
commit cdc9d65395
7 changed files with 83 additions and 30 deletions

View File

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

View File

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

View File

@@ -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<B: hal::Backend> {
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<B: hal::Backend> DestroyedResources<B> {
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<back::Backend> {
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,

View File

@@ -105,13 +105,29 @@ pub struct TextureDescriptor {
pub usage: TextureUsageFlags,
}
pub(crate) enum TexturePlacement<B: hal::Backend> {
SwapChain(SwapChainLink<Mutex<SwapImageEpoch>>),
Memory(B::Memory),
Void,
}
impl<B: hal::Backend> TexturePlacement<B> {
pub fn as_swap_chain(&self) -> &SwapChainLink<Mutex<SwapImageEpoch>> {
match *self {
TexturePlacement::SwapChain(ref link) => link,
TexturePlacement::Memory(_) |
TexturePlacement::Void => panic!("Expected swap chain link!"),
}
}
}
pub struct Texture<B: hal::Backend> {
pub(crate) raw: B::Image,
pub(crate) device_id: Stored<DeviceId>,
pub(crate) kind: hal::image::Kind,
pub(crate) format: TextureFormat,
pub(crate) full_range: hal::image::SubresourceRange,
pub(crate) swap_chain_link: Option<SwapChainLink<Mutex<SwapImageEpoch>>>,
pub(crate) placement: TexturePlacement<B>,
pub(crate) life_guard: LifeGuard,
}

View File

@@ -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<E> {
pub image_index: hal::SwapImageIndex,
}
impl SwapChainLink<Mutex<SwapImageEpoch>> {
pub fn bump_epoch(&self) {
*self.epoch.lock() += 1;
}
}
pub struct Surface<B: hal::Backend> {
pub(crate) raw: B::Surface,
pub(crate) swap_chain: Option<SwapChain<B>>,
@@ -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?

View File

@@ -144,6 +144,11 @@ impl<I: NewId> DummyTracker<I> {
self.query(I::new(index, epoch), ref_count);
}
}
/// Return an iterator over used resources keys.
pub fn used<'a>(&'a self) -> impl 'a + Iterator<Item = I> {
self.map.iter().map(|(&index, &(_, epoch))| I::new(index, epoch))
}
}
impl<I: NewId, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {

View File

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