rendy_memory/allocator/
dedicated.rs1use std::{ops::Range, ptr::NonNull};
2
3use {
4 crate::{
5 allocator::{Allocator, Kind},
6 block::Block,
7 mapping::{mapped_fitting_range, MappedRange},
8 memory::*,
9 },
10 gfx_hal::{device::Device as _, Backend},
11};
12
13#[derive(Debug)]
15pub struct DedicatedBlock<B: Backend> {
16 memory: Memory<B>,
17 mapping: Option<(NonNull<u8>, Range<u64>)>,
18}
19
20unsafe impl<B> Send for DedicatedBlock<B> where B: Backend {}
21unsafe impl<B> Sync for DedicatedBlock<B> where B: Backend {}
22
23impl<B> DedicatedBlock<B>
24where
25 B: Backend,
26{
27 pub fn unwrap_memory(self) -> Memory<B> {
30 assert!(self.mapping.is_none());
31 self.memory
32 }
33
34 pub fn from_memory(memory: Memory<B>) -> Self {
36 DedicatedBlock {
37 memory,
38 mapping: None,
39 }
40 }
41}
42
43impl<B> Block<B> for DedicatedBlock<B>
44where
45 B: Backend,
46{
47 #[inline]
48 fn properties(&self) -> gfx_hal::memory::Properties {
49 self.memory.properties()
50 }
51
52 #[inline]
53 fn memory(&self) -> &B::Memory {
54 self.memory.raw()
55 }
56
57 #[inline]
58 fn range(&self) -> Range<u64> {
59 0..self.memory.size()
60 }
61
62 fn map<'a>(
63 &'a mut self,
64 device: &B::Device,
65 range: Range<u64>,
66 ) -> Result<MappedRange<'a, B>, gfx_hal::device::MapError> {
67 assert!(
68 range.start < range.end,
69 "Memory mapping region must have valid size"
70 );
71
72 if !self.memory.host_visible() {
73 return Err(gfx_hal::device::MapError::MappingFailed);
75 }
76
77 unsafe {
78 if let Some(ptr) = self
79 .mapping
80 .clone()
81 .and_then(|mapping| mapped_fitting_range(mapping.0, mapping.1, range.clone()))
82 {
83 Ok(MappedRange::from_raw(&self.memory, ptr, range))
84 } else {
85 self.unmap(device);
86 let ptr = device.map_memory(self.memory.raw(), range.clone())?;
87 let ptr = NonNull::new(ptr).expect("Memory mapping shouldn't return nullptr");
88 let mapping = MappedRange::from_raw(&self.memory, ptr, range);
89 self.mapping = Some((mapping.ptr(), mapping.range()));
90 Ok(mapping)
91 }
92 }
93 }
94
95 fn unmap(&mut self, device: &B::Device) {
96 if self.mapping.take().is_some() {
97 unsafe {
98 device.unmap_memory(self.memory.raw());
100 }
101 }
102 }
103}
104
105#[derive(Debug)]
114pub struct DedicatedAllocator {
115 memory_type: gfx_hal::MemoryTypeId,
116 memory_properties: gfx_hal::memory::Properties,
117 used: u64,
118}
119
120impl DedicatedAllocator {
121 pub fn properties_required() -> gfx_hal::memory::Properties {
123 gfx_hal::memory::Properties::empty()
124 }
125
126 pub fn new(
129 memory_type: gfx_hal::MemoryTypeId,
130 memory_properties: gfx_hal::memory::Properties,
131 ) -> Self {
132 DedicatedAllocator {
133 memory_type,
134 memory_properties,
135 used: 0,
136 }
137 }
138}
139
140impl<B> Allocator<B> for DedicatedAllocator
141where
142 B: Backend,
143{
144 type Block = DedicatedBlock<B>;
145
146 fn kind() -> Kind {
147 Kind::Dedicated
148 }
149
150 #[inline]
151 fn alloc(
152 &mut self,
153 device: &B::Device,
154 size: u64,
155 _align: u64,
156 ) -> Result<(DedicatedBlock<B>, u64), gfx_hal::device::AllocationError> {
157 let memory = unsafe {
158 Memory::from_raw(
159 device.allocate_memory(self.memory_type, size)?,
160 size,
161 self.memory_properties,
162 )
163 };
164
165 self.used += size;
166
167 Ok((DedicatedBlock::from_memory(memory), size))
168 }
169
170 #[inline]
171 fn free(&mut self, device: &B::Device, mut block: DedicatedBlock<B>) -> u64 {
172 block.unmap(device);
173 let size = block.memory.size();
174 self.used -= size;
175 unsafe {
176 device.free_memory(block.memory.into_raw());
177 }
178 size
179 }
180}
181
182impl Drop for DedicatedAllocator {
183 fn drop(&mut self) {
184 if self.used > 0 {
185 log::error!("Not all allocation from DedicatedAllocator was freed");
186 }
187 }
188}