use super::device::DeviceInner;
use super::{Device, Error, Result, check};
use crate::raw::bindings::*;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryPropertyFlags(pub u32);
impl MemoryPropertyFlags {
pub const DEVICE_LOCAL: Self = Self(0x1);
pub const HOST_VISIBLE: Self = Self(0x2);
pub const HOST_COHERENT: Self = Self(0x4);
pub const HOST_CACHED: Self = Self(0x8);
pub const LAZILY_ALLOCATED: Self = Self(0x10);
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
}
impl std::ops::BitOr for MemoryPropertyFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
pub struct DeviceMemory {
pub(crate) handle: VkDeviceMemory,
pub(crate) size: u64,
pub(crate) device: Arc<DeviceInner>,
}
impl DeviceMemory {
pub fn allocate(device: &Device, size: u64, memory_type_index: u32) -> Result<Self> {
let allocate = device
.inner
.dispatch
.vkAllocateMemory
.ok_or(Error::MissingFunction("vkAllocateMemory"))?;
let info = VkMemoryAllocateInfo {
sType: VkStructureType::STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
pNext: std::ptr::null(),
allocationSize: size,
memoryTypeIndex: memory_type_index,
};
let mut handle: VkDeviceMemory = 0;
check(unsafe { allocate(device.inner.handle, &info, std::ptr::null(), &mut handle) })?;
Ok(Self {
handle,
size,
device: Arc::clone(&device.inner),
})
}
pub fn raw(&self) -> VkDeviceMemory {
self.handle
}
pub fn size(&self) -> u64 {
self.size
}
pub fn map(&mut self) -> Result<MappedMemory<'_>> {
let map = self
.device
.dispatch
.vkMapMemory
.ok_or(Error::MissingFunction("vkMapMemory"))?;
let mut ptr: *mut std::ffi::c_void = std::ptr::null_mut();
check(unsafe { map(self.device.handle, self.handle, 0, self.size, 0, &mut ptr) })?;
Ok(MappedMemory {
ptr,
size: self.size,
memory: self,
})
}
}
impl Drop for DeviceMemory {
fn drop(&mut self) {
if let Some(free) = self.device.dispatch.vkFreeMemory {
unsafe { free(self.device.handle, self.handle, std::ptr::null()) };
}
}
}
pub struct MappedMemory<'a> {
ptr: *mut std::ffi::c_void,
size: u64,
memory: &'a mut DeviceMemory,
}
impl<'a> MappedMemory<'a> {
pub fn as_ptr(&self) -> *mut std::ffi::c_void {
self.ptr
}
pub fn as_slice_mut(&mut self) -> &mut [u8] {
unsafe { std::slice::from_raw_parts_mut(self.ptr.cast::<u8>(), self.size as usize) }
}
pub fn as_slice(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.ptr.cast::<u8>(), self.size as usize) }
}
}
impl<'a> Drop for MappedMemory<'a> {
fn drop(&mut self) {
if let Some(unmap) = self.memory.device.dispatch.vkUnmapMemory {
unsafe { unmap(self.memory.device.handle, self.memory.handle) };
}
}
}