use super::{AllocError, tlsf::Tlsf};
use crate::{core as vk, load::CallError};
use std::ffi::c_void;
pub(super) struct Mapping {
pub pointer: *mut c_void,
pub references: u32,
}
impl Default for Mapping {
fn default() -> Self {
Self {
pointer: std::ptr::null_mut(),
references: 0,
}
}
}
impl Mapping {
pub unsafe fn acquire(
&mut self,
device: &vk::Device,
memory: vk::DeviceMemory,
size: u64,
) -> Result<*mut c_void, AllocError> {
if size > isize::MAX as u64 {
return Err(AllocError::InvalidRange);
}
let count = self
.references
.checked_add(1)
.ok_or(AllocError::InvalidRange)?;
if self.references == 0 {
if device.fp().unmap_memory.is_none() {
return Err(CallError::MissingCommand("vkUnmapMemory").into());
}
let pointer = unsafe { device.map_memory(memory, 0, size, vk::MemoryMapFlags::empty()) }?;
if pointer.is_null() {
unsafe { device.unmap_memory(memory) }?;
return Err(CallError::InvalidOutput("vkMapMemory returned a null pointer").into());
}
self.pointer = pointer;
}
self.references = count;
Ok(self.pointer)
}
pub unsafe fn release(
&mut self,
device: &vk::Device,
memory: vk::DeviceMemory,
) -> Result<(), AllocError> {
let count = self
.references
.checked_sub(1)
.ok_or(AllocError::NotMapped)?;
if count == 0 {
unsafe { device.unmap_memory(memory) }?;
self.pointer = std::ptr::null_mut();
}
self.references = count;
Ok(())
}
}
pub(super) struct Block {
pub handle: vk::DeviceMemory,
pub size: u64,
pub memory_type_index: u32,
pub metadata: Tlsf,
pub mapping: Mapping,
}