gfx_memory/allocator/
dedicated.rs1use crate::{
2 allocator::{Allocator, Kind},
3 block::Block,
4 mapping::MappedRange,
5 memory::Memory,
6 AtomSize, Size,
7};
8use hal::{device::Device as _, Backend};
9use std::ptr::NonNull;
10
11#[derive(Debug)]
13pub struct DedicatedBlock<B: Backend> {
14 memory: Memory<B>,
15 ptr: Option<NonNull<u8>>,
16}
17
18unsafe impl<B: Backend> Send for DedicatedBlock<B> {}
19unsafe impl<B: Backend> Sync for DedicatedBlock<B> {}
20
21impl<B: Backend> DedicatedBlock<B> {
22 pub fn unwrap_memory(self) -> Memory<B> {
25 assert_eq!(self.ptr, None);
26 self.memory
27 }
28
29 pub fn from_memory(memory: Memory<B>) -> Self {
31 DedicatedBlock { memory, ptr: None }
32 }
33
34 pub fn size(&self) -> Size {
36 self.memory.size()
37 }
38}
39
40impl<B: Backend> Block<B> for DedicatedBlock<B> {
41 fn properties(&self) -> hal::memory::Properties {
42 self.memory.properties()
43 }
44
45 fn memory(&self) -> &B::Memory {
46 self.memory.raw()
47 }
48
49 fn segment(&self) -> hal::memory::Segment {
50 hal::memory::Segment {
51 offset: 0,
52 size: Some(self.memory.size()),
53 }
54 }
55
56 fn map<'a>(
57 &'a mut self,
58 _device: &B::Device,
59 segment: hal::memory::Segment,
60 ) -> Result<MappedRange<'a, B>, hal::device::MapError> {
61 let requested_range = segment.offset..match segment.size {
62 Some(s) => segment.offset + s,
63 None => self.memory.size(),
64 };
65 let mapping_range = match self.memory.non_coherent_atom_size {
66 Some(atom) => crate::align_range(&requested_range, atom),
67 None => requested_range.clone(),
68 };
69
70 Ok(unsafe {
71 MappedRange::from_raw(
72 &self.memory,
73 self.ptr
74 .ok_or(hal::device::MapError::MappingFailed)?
76 .as_ptr()
77 .offset(mapping_range.start as isize),
78 mapping_range,
79 requested_range,
80 )
81 })
82 }
83}
84
85#[derive(Debug)]
94pub struct DedicatedAllocator {
95 memory_type: hal::MemoryTypeId,
96 memory_properties: hal::memory::Properties,
97 non_coherent_atom_size: Option<AtomSize>,
98 used: Size,
99}
100
101impl DedicatedAllocator {
102 pub fn new(
105 memory_type: hal::MemoryTypeId,
106 memory_properties: hal::memory::Properties,
107 non_coherent_atom_size: Size,
108 ) -> Self {
109 DedicatedAllocator {
110 memory_type,
111 memory_properties,
112 non_coherent_atom_size: if crate::is_non_coherent_visible(memory_properties) {
113 AtomSize::new(non_coherent_atom_size)
114 } else {
115 None
116 },
117 used: 0,
118 }
119 }
120}
121
122impl<B: Backend> Allocator<B> for DedicatedAllocator {
123 type Block = DedicatedBlock<B>;
124
125 const KIND: Kind = Kind::Dedicated;
126
127 fn alloc(
128 &mut self,
129 device: &B::Device,
130 size: Size,
131 _align: Size,
132 ) -> Result<(DedicatedBlock<B>, Size), hal::device::AllocationError> {
133 let size = match self.non_coherent_atom_size {
134 Some(atom) => crate::align_size(size, atom),
135 None => size,
136 };
137 log::trace!("Allocate block of size: {}", size);
138
139 let (memory, ptr) = unsafe {
140 super::allocate_memory_helper(
141 device,
142 self.memory_type,
143 size,
144 self.memory_properties,
145 self.non_coherent_atom_size,
146 )?
147 };
148
149 self.used += size;
150 Ok((DedicatedBlock { memory, ptr }, size))
151 }
152
153 fn free(&mut self, device: &B::Device, block: DedicatedBlock<B>) -> Size {
154 let size = block.memory.size();
155 log::trace!("Free block of size: {}", size);
156 self.used -= size;
157 unsafe {
158 device.unmap_memory(block.memory.raw());
159 device.free_memory(block.memory.into_raw());
160 }
161 size
162 }
163}
164
165impl Drop for DedicatedAllocator {
166 fn drop(&mut self) {
167 if self.used != 0 {
168 log::error!("Not all allocation from DedicatedAllocator was freed");
169 }
170 }
171}