1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::{error::Error, sync::{RwLock}};
use ash::{version::DeviceV1_0, vk};
use gpu_allocator::{AllocationCreateDesc, MemoryLocation, VulkanAllocator};
pub struct Buffer<'a, 'b> {
pub buffer: vk::Buffer,
pub allocation: gpu_allocator::SubAllocation,
pub device_size: vk::DeviceSize,
device: &'a ash::Device,
allocator: &'b Option<RwLock<gpu_allocator::VulkanAllocator>>,
}
impl <'a, 'b> Buffer<'_, '_> {
pub fn new(
device: &'a ash::Device,
allocator: &'b Option<RwLock<VulkanAllocator>>,
device_size: vk::DeviceSize,
usage: vk::BufferUsageFlags,
memory_usage: MemoryLocation,
queue_family_indices: &[u32],
) -> Result<Buffer<'a, 'b>, Box<dyn Error>> {
let sharing_mode = match queue_family_indices.len() {
1 => vk::SharingMode::EXCLUSIVE,
_ => vk::SharingMode::CONCURRENT,
};
let create_info = vk::BufferCreateInfo::builder()
.size(device_size)
.usage(usage)
.sharing_mode(sharing_mode)
.queue_family_indices(queue_family_indices);
let buffer = unsafe { device.create_buffer(&create_info, None) }?;
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
let mut malloc = allocator.as_ref().unwrap().write().unwrap();
let allocation = malloc.allocate(&AllocationCreateDesc {
name: "Allocation",
requirements,
location: memory_usage,
linear: true,
})?;
unsafe { device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())?; }
Ok(Buffer {
buffer,
allocation,
device_size,
device,
allocator,
})
}
pub fn fill<T: Sized>(
&self,
data: &[T],
) -> Result<(), Box<dyn Error>> {
let data_ptr = self.allocation.mapped_ptr().unwrap().as_ptr() as *mut T;
unsafe { data_ptr.copy_from_nonoverlapping(data.as_ptr(), data.len()) };
Ok(())
}
}
impl <'a, 'b> Drop for Buffer<'a, 'b> {
fn drop(
&mut self
) {
let some = self.allocator.as_ref().unwrap();
let mut malloc = some.write().unwrap();
malloc.free(self.allocation.to_owned()).unwrap();
unsafe { self.device.destroy_buffer(self.buffer, None) };
}
}