use super::AllocError;
use crate::core as vk;
use std::sync::Arc;
pub struct Allocation {
pub(crate) handle: vk::DeviceMemory,
pub(crate) size: u64,
pub(crate) offset: u64,
pub(crate) block_size: u64,
pub(crate) reserved_size: u64,
pub(crate) memory_type_index: u32,
pub(crate) heap_index: u32,
pub(crate) flags: vk::MemoryPropertyFlags,
pub(crate) atom: u64,
pub(crate) owner: Arc<()>,
pub(crate) serial: u64,
}
impl Allocation {
pub fn handle(&self) -> vk::DeviceMemory {
self.handle
}
pub fn offset(&self) -> u64 {
self.offset
}
pub fn size(&self) -> u64 {
self.size
}
pub fn reserved_size(&self) -> u64 {
self.reserved_size
}
pub fn memory_type_index(&self) -> u32 {
self.memory_type_index
}
pub fn heap_index(&self) -> u32 {
self.heap_index
}
pub fn is_host_coherent(&self) -> bool {
self.flags.as_raw() & vk::MemoryPropertyFlagBits::HOST_COHERENT_BIT.as_raw() != 0
}
pub fn is_host_visible(&self) -> bool {
self.flags.as_raw() & vk::MemoryPropertyFlagBits::HOST_VISIBLE_BIT.as_raw() != 0
}
pub fn is_freed(&self) -> bool {
self.handle.is_null()
}
pub fn mapped_range(
&self,
offset: u64,
size: u64,
) -> Result<Option<vk::MappedMemoryRange>, AllocError> {
if self.is_freed() {
return Err(AllocError::UnknownAllocation);
}
if !self.is_host_visible() {
return Err(AllocError::NotHostVisible);
}
let end = if size == vk::WHOLE_SIZE {
self.size
} else {
offset.checked_add(size).ok_or(AllocError::InvalidRange)?
};
if offset > self.size || end > self.size || end < offset {
return Err(AllocError::InvalidRange);
}
if offset == end || self.is_host_coherent() {
return Ok(None);
}
let absolute_end = self
.offset
.checked_add(end)
.ok_or(AllocError::InvalidRange)?;
let start = self
.offset
.checked_add(offset)
.ok_or(AllocError::InvalidRange)?
& !(self.atom - 1);
let rounded = absolute_end
.checked_add(self.atom - 1)
.map(|v| v & !(self.atom - 1))
.unwrap_or(self.block_size)
.min(self.block_size);
Ok(Some(vk::MappedMemoryRange {
memory: self.handle,
offset: start,
size: rounded - start,
..Default::default()
}))
}
}
#[cfg(test)]
#[path = "../../../test/rs/memory/test_allocation.rs"]
mod tests;