191 lines
5 KiB
Rust
191 lines
5 KiB
Rust
use std::{
|
|
borrow::Cow,
|
|
ops::{Deref, DerefMut},
|
|
sync::Arc,
|
|
};
|
|
|
|
use ash::{prelude::VkResult, vk};
|
|
use itertools::Itertools;
|
|
use vk_mem::Alloc;
|
|
|
|
use crate::{
|
|
define_device_owned_handle,
|
|
device::{DeviceOwned, QueueFlags},
|
|
Device,
|
|
};
|
|
|
|
#[derive(Clone)]
|
|
pub struct BufferDesc {
|
|
pub flags: vk::BufferCreateFlags,
|
|
pub name: Option<Cow<'static, str>>,
|
|
pub size: u64,
|
|
pub usage: vk::BufferUsageFlags,
|
|
pub queue_families: QueueFlags,
|
|
|
|
pub mem_usage: vk_mem::MemoryUsage,
|
|
pub alloc_flags: vk_mem::AllocationCreateFlags,
|
|
}
|
|
|
|
impl std::hash::Hash for BufferDesc {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
self.flags.hash(state);
|
|
self.size.hash(state);
|
|
self.usage.hash(state);
|
|
self.queue_families.hash(state);
|
|
self.mem_usage.hash(state);
|
|
self.alloc_flags.bits().hash(state);
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for BufferDesc {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("BufferDesc")
|
|
.field("flags", &self.flags)
|
|
.field("name", &self.name)
|
|
.field("size", &self.size)
|
|
.field("usage", &self.usage)
|
|
.field("queue_families", &self.queue_families)
|
|
.field("mem_usage", &self.mem_usage)
|
|
.field_with("alloc_flags", |f| {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
self.alloc_flags
|
|
.iter_names()
|
|
.map(|(name, _)| name)
|
|
.format(" | ")
|
|
)
|
|
})
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl Eq for BufferDesc {}
|
|
impl PartialEq for BufferDesc {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.flags == other.flags
|
|
// for hashmaps, `Eq` may be more strict than `Hash`
|
|
&& self.name == other.name
|
|
&& self.size == other.size
|
|
&& self.usage == other.usage
|
|
&& self.queue_families == other.queue_families
|
|
&& self.mem_usage == other.mem_usage
|
|
&& self.alloc_flags.bits() == other.alloc_flags.bits()
|
|
}
|
|
}
|
|
|
|
impl Default for BufferDesc {
|
|
fn default() -> Self {
|
|
Self {
|
|
flags: Default::default(),
|
|
name: Default::default(),
|
|
size: Default::default(),
|
|
usage: Default::default(),
|
|
queue_families: QueueFlags::empty(),
|
|
alloc_flags: vk_mem::AllocationCreateFlags::empty(),
|
|
mem_usage: vk_mem::MemoryUsage::Auto,
|
|
}
|
|
}
|
|
}
|
|
|
|
define_device_owned_handle! {
|
|
#[derive(Debug)]
|
|
pub Buffer(vk::Buffer) {
|
|
alloc: vk_mem::Allocation,
|
|
size: u64,
|
|
} => |this| unsafe {
|
|
this.device().clone().alloc().destroy_buffer(this.handle(), &mut this.alloc);
|
|
}
|
|
}
|
|
|
|
impl Eq for Buffer {}
|
|
impl PartialEq for Buffer {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.inner == other.inner
|
|
}
|
|
}
|
|
|
|
impl Buffer {
|
|
pub fn new(device: Device, desc: BufferDesc) -> VkResult<Self> {
|
|
let queue_families = device.queue_families().family_indices(desc.queue_families);
|
|
|
|
let sharing_mode = if queue_families.len() > 1 {
|
|
vk::SharingMode::CONCURRENT
|
|
} else {
|
|
vk::SharingMode::EXCLUSIVE
|
|
};
|
|
|
|
let (buffer, allocation) = unsafe {
|
|
device.alloc().create_buffer(
|
|
&vk::BufferCreateInfo::default()
|
|
.size(desc.size)
|
|
.usage(desc.usage)
|
|
.queue_family_indices(&queue_families)
|
|
.sharing_mode(sharing_mode),
|
|
&vk_mem::AllocationCreateInfo {
|
|
flags: desc.alloc_flags,
|
|
usage: desc.mem_usage,
|
|
..Default::default()
|
|
},
|
|
)?
|
|
};
|
|
|
|
Ok(Self::construct(
|
|
device, buffer, desc.name, allocation, desc.size,
|
|
)?)
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn map_arc(self: &mut Arc<Self>) -> VkResult<MappedBuffer<'_>> {
|
|
Arc::get_mut(self).map(Self::map).unwrap()
|
|
}
|
|
|
|
pub fn map(&mut self) -> VkResult<MappedBuffer<'_>> {
|
|
let bytes = unsafe {
|
|
let data = self.inner.dev().alloc().map_memory(&mut self.alloc)?;
|
|
let slice = core::slice::from_raw_parts_mut(data, self.size as usize);
|
|
|
|
slice
|
|
};
|
|
|
|
Ok(MappedBuffer { inner: self, bytes })
|
|
}
|
|
pub fn buffer(&self) -> vk::Buffer {
|
|
self.handle()
|
|
}
|
|
pub fn len(&self) -> u64 {
|
|
self.size
|
|
}
|
|
}
|
|
|
|
pub struct MappedBuffer<'a> {
|
|
bytes: &'a mut [u8],
|
|
inner: &'a mut Buffer,
|
|
}
|
|
|
|
impl Drop for MappedBuffer<'_> {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
self.inner
|
|
.inner
|
|
.dev()
|
|
.alloc()
|
|
.unmap_memory(&mut self.inner.alloc);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Deref for MappedBuffer<'_> {
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
self.bytes
|
|
}
|
|
}
|
|
|
|
impl DerefMut for MappedBuffer<'_> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
self.bytes
|
|
}
|
|
}
|