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