1use super::{AllocError, host::Identity};
4use crate as vk;
5
6pub struct Allocation {
8 pub(crate) handle: vk::DeviceMemory,
9 pub(crate) size: u64,
10 pub(crate) offset: u64,
11 pub(crate) block_size: u64,
12 pub(crate) reserved_size: u64,
13 pub(crate) memory_type_index: u32,
14 pub(crate) heap_index: u32,
15 pub(crate) flags: vk::MemoryPropertyFlags,
16 pub(crate) atom: u64,
17 pub(super) owner: Identity,
18 pub(crate) serial: u64,
19}
20
21impl Allocation {
22 pub fn handle(&self) -> vk::DeviceMemory {
23 self.handle
24 }
25
26 pub fn offset(&self) -> u64 {
27 self.offset
28 }
29
30 pub fn size(&self) -> u64 {
31 self.size
32 }
33
34 pub fn reserved_size(&self) -> u64 {
36 self.reserved_size
37 }
38
39 pub fn memory_type_index(&self) -> u32 {
40 self.memory_type_index
41 }
42
43 pub fn heap_index(&self) -> u32 {
44 self.heap_index
45 }
46
47 pub fn is_host_coherent(&self) -> bool {
48 self.flags.as_raw() & vk::MemoryPropertyFlagBits::HOST_COHERENT_BIT.as_raw() != 0
49 }
50
51 pub fn is_host_visible(&self) -> bool {
52 self.flags.as_raw() & vk::MemoryPropertyFlagBits::HOST_VISIBLE_BIT.as_raw() != 0
53 }
54
55 pub fn is_freed(&self) -> bool {
56 self.handle.is_null()
57 }
58
59 pub fn mapped_range(
65 &self,
66 offset: u64,
67 size: u64,
68 ) -> Result<Option<vk::MappedMemoryRange<'static>>, AllocError> {
69 if self.is_freed() {
70 return Err(AllocError::UnknownAllocation);
71 }
72 if !self.is_host_visible() {
73 return Err(AllocError::NotHostVisible);
74 }
75 let end = if size == vk::WHOLE_SIZE {
76 self.size
77 } else {
78 offset.checked_add(size).ok_or(AllocError::InvalidRange)?
79 };
80 if offset > self.size || end > self.size || end < offset {
81 return Err(AllocError::InvalidRange);
82 }
83 if offset == end || self.is_host_coherent() {
84 return Ok(None);
85 }
86 let absolute_end = self
87 .offset
88 .checked_add(end)
89 .ok_or(AllocError::InvalidRange)?;
90 let start = self
91 .offset
92 .checked_add(offset)
93 .ok_or(AllocError::InvalidRange)?
94 & !(self.atom - 1);
95 let rounded = absolute_end
96 .checked_add(self.atom - 1)
97 .map(|v| v & !(self.atom - 1))
98 .unwrap_or(self.block_size)
99 .min(self.block_size);
100 Ok(Some(vk::MappedMemoryRange {
101 memory: self.handle,
102 offset: start,
103 size: rounded - start,
104 ..Default::default()
105 }))
106 }
107}
108
109#[cfg(test)]
110#[path = "../../../test/rs/mem/test_allocation.rs"]
111mod tests;