Skip to content

Commit 342ba6f

Browse files
committed
ash: MyBuffer abstraction with explicit destroy
1 parent 032b938 commit 342ba6f

File tree

12 files changed

+348
-93
lines changed

12 files changed

+348
-93
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use crate::ash_renderer::device::MyDevice;
2+
use ash::vk;
3+
use bytemuck::NoUninit;
4+
use gpu_allocator::MemoryLocation;
5+
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme};
6+
use std::borrow::Cow;
7+
use std::sync::Arc;
8+
9+
pub struct MyBuffer {
10+
pub buffer: vk::Buffer,
11+
pub allocation: Allocation,
12+
pub name: String,
13+
destroyed: bool,
14+
}
15+
16+
#[derive(Clone)]
17+
pub struct BufferCreateInfo<'a> {
18+
pub usage: vk::BufferUsageFlags,
19+
pub location: MemoryLocation,
20+
pub name: Option<Cow<'a, str>>,
21+
}
22+
23+
impl MyBuffer {
24+
pub fn from_data<T: NoUninit>(
25+
device: &Arc<MyDevice>,
26+
info: BufferCreateInfo<'_>,
27+
data: &T,
28+
) -> anyhow::Result<Self> {
29+
Self::from_slice(device, info, bytemuck::bytes_of(data))
30+
}
31+
32+
pub fn from_slice<T: NoUninit>(
33+
device: &Arc<MyDevice>,
34+
info: BufferCreateInfo<'_>,
35+
data: &[T],
36+
) -> anyhow::Result<Self> {
37+
unsafe {
38+
let buffer = device.create_buffer(
39+
&vk::BufferCreateInfo::default()
40+
.size(size_of_val(data) as u64)
41+
.usage(vk::BufferUsageFlags::STORAGE_BUFFER),
42+
None,
43+
)?;
44+
let name = info.name.map(|a| a.into_owned()).unwrap_or_default();
45+
let mut allocation = device.borrow_allocator().allocate(&AllocationCreateDesc {
46+
name: &name,
47+
requirements: device.get_buffer_memory_requirements(buffer),
48+
location: MemoryLocation::CpuToGpu,
49+
linear: true,
50+
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
51+
})?;
52+
device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())?;
53+
let mapped = &mut allocation.mapped_slice_mut().unwrap()[..size_of_val(data)];
54+
mapped.copy_from_slice(bytemuck::cast_slice(data));
55+
Ok(Self {
56+
buffer,
57+
allocation,
58+
name,
59+
destroyed: false,
60+
})
61+
}
62+
}
63+
64+
/// Destroy this buffer
65+
///
66+
/// # Safety
67+
/// Buffer must not be in use
68+
pub unsafe fn destroy(&mut self, device: &Arc<MyDevice>) {
69+
if !self.destroyed {
70+
self.destroyed = true;
71+
unsafe {
72+
device.destroy_buffer(self.buffer, None);
73+
}
74+
}
75+
}
76+
}
77+
78+
impl Drop for MyBuffer {
79+
fn drop(&mut self) {
80+
if !self.destroyed {
81+
panic!("dropping Buffer {} without destroying it", &self.name);
82+
}
83+
}
84+
}

generated/graphics/ash/cargo-gpu/mygraphics/src/ash_renderer/global_descriptor_set.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct GlobalDescriptorSet {
4141
pub layout: Arc<GlobalDescriptorSetLayout>,
4242
pub pool: vk::DescriptorPool,
4343
pub set: vk::DescriptorSet,
44+
destroyed: bool,
4445
}
4546

4647
impl GlobalDescriptorSet {
@@ -82,19 +83,29 @@ impl GlobalDescriptorSet {
8283
layout: layout.clone(),
8384
pool,
8485
set,
86+
destroyed: false,
8587
})
8688
}
8789
}
90+
91+
pub fn destroy(&mut self) {
92+
if !self.destroyed {
93+
self.destroyed = true;
94+
unsafe {
95+
let device = &self.layout.device;
96+
device
97+
.reset_descriptor_pool(self.pool, vk::DescriptorPoolResetFlags::empty())
98+
.ok();
99+
device.destroy_descriptor_pool(self.pool, None);
100+
}
101+
}
102+
}
88103
}
89104

90105
impl Drop for GlobalDescriptorSet {
91106
fn drop(&mut self) {
92-
let device = &self.layout.device;
93-
unsafe {
94-
device
95-
.reset_descriptor_pool(self.pool, vk::DescriptorPoolResetFlags::empty())
96-
.ok();
97-
device.destroy_descriptor_pool(self.pool, None);
107+
if !self.destroyed {
108+
panic!("dropping GlobalDescriptorSet without destroying it");
98109
}
99110
}
100111
}

generated/graphics/ash/cargo-gpu/mygraphics/src/ash_renderer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use winit::{
1111
event_loop::{ControlFlow, EventLoop},
1212
};
1313

14+
pub mod buffer;
1415
pub mod device;
1516
pub mod global_descriptor_set;
1617
pub mod render_pipeline;

generated/graphics/ash/cargo-gpu/mygraphics/src/ash_renderer/renderer.rs

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ash_renderer::buffer::{BufferCreateInfo, MyBuffer};
12
use crate::ash_renderer::device::MyDevice;
23
use crate::ash_renderer::get_shaders;
34
use crate::ash_renderer::global_descriptor_set::{GlobalDescriptorSet, GlobalDescriptorSetLayout};
@@ -6,8 +7,8 @@ use crate::ash_renderer::single_command_buffer::SingleCommandBuffer;
67
use crate::ash_renderer::swapchain::DrawFrame;
78
use ash::vk;
89
use gpu_allocator::MemoryLocation;
9-
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
1010
use mygraphics_shaders::ShaderConstants;
11+
use std::borrow::Cow;
1112
use std::sync::Arc;
1213

1314
/// The renderer manages our command buffer and submits the commands, using [`MyRenderPipeline`] for drawing.
@@ -46,28 +47,17 @@ impl MyRenderer {
4647
let pipeline = self.pipeline.get_pipeline()?;
4748
let cmd = self.command.cmd;
4849

49-
let buffer = device.create_buffer(
50-
&vk::BufferCreateInfo::default()
51-
.size(size_of::<ShaderConstants>() as u64)
52-
.usage(vk::BufferUsageFlags::STORAGE_BUFFER),
53-
None,
50+
let mut buffer = MyBuffer::from_data(
51+
device,
52+
BufferCreateInfo {
53+
usage: vk::BufferUsageFlags::STORAGE_BUFFER,
54+
location: MemoryLocation::CpuToGpu,
55+
name: Some(Cow::from("ShaderConstants")),
56+
},
57+
shader_constants,
5458
)?;
55-
let mut allocation = device.borrow_allocator().allocate(&AllocationCreateDesc {
56-
name: "ShaderConstants",
57-
requirements: device.get_buffer_memory_requirements(buffer),
58-
location: MemoryLocation::CpuToGpu,
59-
linear: true,
60-
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
61-
})?;
62-
{
63-
let mapped =
64-
&mut allocation.mapped_slice_mut().unwrap()[..size_of::<ShaderConstants>()];
65-
mapped.copy_from_slice(bytemuck::bytes_of(shader_constants));
66-
}
67-
device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())?;
68-
69-
let descriptor_set =
70-
GlobalDescriptorSet::new(&self.global_descriptor_set_layout, buffer)?;
59+
let mut descriptor_set =
60+
GlobalDescriptorSet::new(&self.global_descriptor_set_layout, buffer.buffer)?;
7161

7262
device.reset_command_pool(self.command.pool, vk::CommandPoolResetFlags::default())?;
7363

@@ -143,9 +133,8 @@ impl MyRenderer {
143133
// finish rendering, but start recording the next one already while waiting. For simplicity's sake,
144134
// we just wait immediately.
145135
self.device.device_wait_idle()?;
146-
drop(descriptor_set);
147-
self.device.destroy_buffer(buffer, None);
148-
drop(allocation);
136+
descriptor_set.destroy();
137+
buffer.destroy(device);
149138
Ok(())
150139
}
151140
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use crate::ash_renderer::device::MyDevice;
2+
use ash::vk;
3+
use bytemuck::NoUninit;
4+
use gpu_allocator::MemoryLocation;
5+
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme};
6+
use std::borrow::Cow;
7+
use std::sync::Arc;
8+
9+
pub struct MyBuffer {
10+
pub buffer: vk::Buffer,
11+
pub allocation: Allocation,
12+
pub name: String,
13+
destroyed: bool,
14+
}
15+
16+
#[derive(Clone)]
17+
pub struct BufferCreateInfo<'a> {
18+
pub usage: vk::BufferUsageFlags,
19+
pub location: MemoryLocation,
20+
pub name: Option<Cow<'a, str>>,
21+
}
22+
23+
impl MyBuffer {
24+
pub fn from_data<T: NoUninit>(
25+
device: &Arc<MyDevice>,
26+
info: BufferCreateInfo<'_>,
27+
data: &T,
28+
) -> anyhow::Result<Self> {
29+
Self::from_slice(device, info, bytemuck::bytes_of(data))
30+
}
31+
32+
pub fn from_slice<T: NoUninit>(
33+
device: &Arc<MyDevice>,
34+
info: BufferCreateInfo<'_>,
35+
data: &[T],
36+
) -> anyhow::Result<Self> {
37+
unsafe {
38+
let buffer = device.create_buffer(
39+
&vk::BufferCreateInfo::default()
40+
.size(size_of_val(data) as u64)
41+
.usage(vk::BufferUsageFlags::STORAGE_BUFFER),
42+
None,
43+
)?;
44+
let name = info.name.map(|a| a.into_owned()).unwrap_or_default();
45+
let mut allocation = device.borrow_allocator().allocate(&AllocationCreateDesc {
46+
name: &name,
47+
requirements: device.get_buffer_memory_requirements(buffer),
48+
location: MemoryLocation::CpuToGpu,
49+
linear: true,
50+
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
51+
})?;
52+
device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())?;
53+
let mapped = &mut allocation.mapped_slice_mut().unwrap()[..size_of_val(data)];
54+
mapped.copy_from_slice(bytemuck::cast_slice(data));
55+
Ok(Self {
56+
buffer,
57+
allocation,
58+
name,
59+
destroyed: false,
60+
})
61+
}
62+
}
63+
64+
/// Destroy this buffer
65+
///
66+
/// # Safety
67+
/// Buffer must not be in use
68+
pub unsafe fn destroy(&mut self, device: &Arc<MyDevice>) {
69+
if !self.destroyed {
70+
self.destroyed = true;
71+
unsafe {
72+
device.destroy_buffer(self.buffer, None);
73+
}
74+
}
75+
}
76+
}
77+
78+
impl Drop for MyBuffer {
79+
fn drop(&mut self) {
80+
if !self.destroyed {
81+
panic!("dropping Buffer {} without destroying it", &self.name);
82+
}
83+
}
84+
}

generated/graphics/ash/spirv-builder/mygraphics/src/ash_renderer/global_descriptor_set.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct GlobalDescriptorSet {
4141
pub layout: Arc<GlobalDescriptorSetLayout>,
4242
pub pool: vk::DescriptorPool,
4343
pub set: vk::DescriptorSet,
44+
destroyed: bool,
4445
}
4546

4647
impl GlobalDescriptorSet {
@@ -82,19 +83,29 @@ impl GlobalDescriptorSet {
8283
layout: layout.clone(),
8384
pool,
8485
set,
86+
destroyed: false,
8587
})
8688
}
8789
}
90+
91+
pub fn destroy(&mut self) {
92+
if !self.destroyed {
93+
self.destroyed = true;
94+
unsafe {
95+
let device = &self.layout.device;
96+
device
97+
.reset_descriptor_pool(self.pool, vk::DescriptorPoolResetFlags::empty())
98+
.ok();
99+
device.destroy_descriptor_pool(self.pool, None);
100+
}
101+
}
102+
}
88103
}
89104

90105
impl Drop for GlobalDescriptorSet {
91106
fn drop(&mut self) {
92-
let device = &self.layout.device;
93-
unsafe {
94-
device
95-
.reset_descriptor_pool(self.pool, vk::DescriptorPoolResetFlags::empty())
96-
.ok();
97-
device.destroy_descriptor_pool(self.pool, None);
107+
if !self.destroyed {
108+
panic!("dropping GlobalDescriptorSet without destroying it");
98109
}
99110
}
100111
}

generated/graphics/ash/spirv-builder/mygraphics/src/ash_renderer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use winit::{
1111
event_loop::{ControlFlow, EventLoop},
1212
};
1313

14+
pub mod buffer;
1415
pub mod device;
1516
pub mod global_descriptor_set;
1617
pub mod render_pipeline;

0 commit comments

Comments
 (0)