buffers
This commit is contained in:
parent
55d22e3164
commit
d91ba8c1b7
|
|
@ -5,13 +5,10 @@ use std::{
|
|||
};
|
||||
|
||||
use ash::{prelude::VkResult, vk};
|
||||
use itertools::Itertools;
|
||||
use vk_mem::Alloc;
|
||||
|
||||
use crate::{
|
||||
define_device_owned_handle,
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
Device,
|
||||
device::{Allocation, DeviceObject, QueueFlags},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -21,9 +18,7 @@ pub struct BufferDesc {
|
|||
pub size: u64,
|
||||
pub usage: vk::BufferUsageFlags,
|
||||
pub queue_families: QueueFlags,
|
||||
|
||||
pub mem_usage: vk_mem::MemoryUsage,
|
||||
pub alloc_flags: vk_mem::AllocationCreateFlags,
|
||||
pub mem_location: gpu_allocator::MemoryLocation,
|
||||
}
|
||||
|
||||
impl std::hash::Hash for BufferDesc {
|
||||
|
|
@ -32,8 +27,7 @@ impl std::hash::Hash for BufferDesc {
|
|||
self.size.hash(state);
|
||||
self.usage.hash(state);
|
||||
self.queue_families.hash(state);
|
||||
self.mem_usage.hash(state);
|
||||
self.alloc_flags.bits().hash(state);
|
||||
self.mem_location.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,17 +39,7 @@ impl std::fmt::Debug for BufferDesc {
|
|||
.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(" | ")
|
||||
)
|
||||
})
|
||||
.field("mem_location", &self.mem_location)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -69,8 +53,7 @@ impl PartialEq for BufferDesc {
|
|||
&& 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()
|
||||
&& self.mem_location == other.mem_location
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,109 +65,91 @@ impl Default for BufferDesc {
|
|||
size: Default::default(),
|
||||
usage: Default::default(),
|
||||
queue_families: QueueFlags::empty(),
|
||||
alloc_flags: vk_mem::AllocationCreateFlags::empty(),
|
||||
mem_usage: vk_mem::MemoryUsage::Auto,
|
||||
mem_location: gpu_allocator::MemoryLocation::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct Buffer {
|
||||
buffer: DeviceObject<vk::Buffer>,
|
||||
desc: BufferDesc,
|
||||
alloc: Allocation,
|
||||
}
|
||||
|
||||
impl Eq for Buffer {}
|
||||
impl PartialEq for Buffer {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner == other.inner
|
||||
*self.buffer == *other.buffer
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn new(device: Device, desc: BufferDesc) -> VkResult<Self> {
|
||||
let queue_families = device.queue_families().family_indices(desc.queue_families);
|
||||
pub fn new(device: Device, desc: BufferDesc) -> crate::Result<Self> {
|
||||
let (buffer, requirements) = Self::new_raw(device.clone(), &desc)?;
|
||||
|
||||
let alloc =
|
||||
device
|
||||
.alloc2
|
||||
.lock()
|
||||
.allocate(&gpu_allocator::vulkan::AllocationCreateDesc {
|
||||
name: desc.name.as_deref().unwrap_or_default(),
|
||||
requirements,
|
||||
location: desc.mem_location,
|
||||
linear: true,
|
||||
allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
buffer: DeviceObject::new(buffer, device.clone(), desc.name.clone()),
|
||||
desc,
|
||||
alloc: Allocation::Owned(DeviceObject::new_without_name(alloc, device)),
|
||||
})
|
||||
}
|
||||
|
||||
fn new_raw(
|
||||
device: Device,
|
||||
desc: &BufferDesc,
|
||||
) -> crate::Result<(vk::Buffer, vk::MemoryRequirements)> {
|
||||
let queue_families = device.queues.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()
|
||||
let create_info = 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()
|
||||
},
|
||||
)?
|
||||
};
|
||||
.sharing_mode(sharing_mode);
|
||||
|
||||
Ok(Self::construct(
|
||||
device, buffer, desc.name, allocation, desc.size,
|
||||
)?)
|
||||
let buffer = unsafe { device.dev().create_buffer(&create_info, None)? };
|
||||
let mem_reqs = unsafe { device.dev().get_buffer_memory_requirements(buffer) };
|
||||
|
||||
Ok((buffer, mem_reqs))
|
||||
}
|
||||
|
||||
#[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) -> Option<&[u8]> {
|
||||
if let Some(alloc) = self.alloc.allocation() {
|
||||
alloc.mapped_slice()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
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 map_mut(&mut self) -> Option<&mut [u8]> {
|
||||
if let Some(alloc) = self.alloc.allocation_mut() {
|
||||
alloc.mapped_slice_mut()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buffer(&self) -> vk::Buffer {
|
||||
self.handle()
|
||||
*self.buffer
|
||||
}
|
||||
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
|
||||
self.desc.size
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,14 @@ impl Allocation {
|
|||
Allocation::Unmanaged => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn allocation_mut(&mut self) -> Option<&mut GpuAllocation> {
|
||||
match self {
|
||||
Allocation::Owned(obj) => Some(obj),
|
||||
Allocation::Shared(arc) => Arc::get_mut(arc).map(|alloc| &mut alloc.inner),
|
||||
Allocation::Unmanaged => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DeviceInner {
|
||||
|
|
|
|||
Loading…
Reference in a new issue