1use super::*;
2
3#[derive(Clone, Copy, Debug)]
8pub struct BufferAllocation {
9 address: vk::DeviceAddress,
10 size: vk::DeviceSize,
11 ptr: Option<*mut c_void>,
12}
13
14impl BufferAllocation {
15 #[must_use]
16 pub fn device_address(&self) -> vk::DeviceAddress {
17 self.address
18 }
19
20 #[must_use]
21 pub fn size(&self) -> vk::DeviceSize {
22 self.size
23 }
24
25 #[must_use]
26 pub fn as_ptr<T>(&self) -> *const T {
27 if let Some(ptr) = self.ptr {
28 ptr.cast()
29 } else {
30 null()
31 }
32 }
33
34 #[must_use]
35 pub fn as_mut_ptr<T>(&self) -> *mut T {
36 if let Some(ptr) = self.ptr {
37 ptr.cast()
38 } else {
39 null_mut()
40 }
41 }
42
43 #[must_use]
44 pub unsafe fn as_slice<T>(&self, len: usize) -> &[T] {
45 if let Some(ptr) = self.ptr {
46 std::slice::from_raw_parts(ptr.cast(), len)
47 } else {
48 &[]
49 }
50 }
51
52 #[must_use]
53 pub unsafe fn as_mut_slice<T>(&mut self, len: usize) -> &mut [T] {
54 if let Some(ptr) = self.ptr {
55 std::slice::from_raw_parts_mut(ptr.cast(), len)
56 } else {
57 &mut []
58 }
59 }
60}
61
62#[derive(Debug)]
63pub struct BufferAllocations {
64 memory: vk::DeviceMemory,
65 allocations: Vec<BufferAllocation>,
66}
67
68impl BufferAllocations {
69 pub unsafe fn allocate(
70 physical_device: &PhysicalDevice,
71 device: &Device,
72 buffers: &[vk::Buffer],
73 buffer_create_infos: &[vk::BufferCreateInfo],
74 property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
75 ) -> Result<Self> {
76 ensure!(!buffers.is_empty());
78 ensure!(!buffer_create_infos.is_empty());
79 ensure!(buffers.len() == buffer_create_infos.len());
80 ensure!(buffer_create_infos
81 .iter()
82 .all(|info| info.s_type == vk::StructureType::BufferCreateInfo));
83 ensure!(buffer_create_infos.iter().all(|info| info.p_next.is_null()));
84 ensure!(buffer_create_infos
85 .iter()
86 .all(|info| info.flags == vk::BufferCreateFlags::empty()));
87 ensure!(buffer_create_infos.iter().all(|info| info.size > 0));
88 ensure!(buffer_create_infos.iter().all(|info| info
89 .usage
90 .contains(vk::BufferUsageFlagBits::ShaderDeviceAddress)));
91 ensure!(buffer_create_infos
92 .iter()
93 .all(|info| info.sharing_mode == vk::SharingMode::Exclusive));
94 ensure!(buffer_create_infos.iter().all(
95 |info| info.queue_family_index_count == 0 && info.p_queue_family_indices.is_null()
96 ));
97 ensure!(property_flags.into() != vk::MemoryPropertyFlags::empty());
98
99 let mut memory_requirements = vec![];
101 for &buffer_create_info in buffer_create_infos {
102 let device_buffer_memory_requirements = vk::DeviceBufferMemoryRequirements {
103 s_type: vk::StructureType::DeviceBufferMemoryRequirements,
104 p_next: null(),
105 p_create_info: addr_of!(buffer_create_info).cast(),
106 };
107 let mut memory_requirements2 = vk::MemoryRequirements2 {
108 s_type: vk::StructureType::MemoryRequirements2,
109 p_next: null_mut(),
110 memory_requirements: zeroed(),
111 };
112 device.get_device_buffer_memory_requirements(
113 &device_buffer_memory_requirements,
114 &mut memory_requirements2,
115 );
116 memory_requirements.push(memory_requirements2.memory_requirements);
117 }
118
119 ensure!(memory_requirements
121 .iter()
122 .all(|req| req.alignment == memory_requirements[0].alignment));
123 ensure!(memory_requirements
124 .iter()
125 .all(|req| req.memory_type_bits == memory_requirements[0].memory_type_bits));
126 let alignment = memory_requirements[0].alignment;
127 let memory_type_bits = memory_requirements[0].memory_type_bits;
128
129 let memory_type_index = memory_type_index(
131 &physical_device.memory_properties,
132 property_flags,
133 memory_type_bits,
134 );
135
136 let allocation_size = memory_requirements
138 .iter()
139 .map(|req| aligned_size(req.size, alignment))
140 .sum::<vk::DeviceSize>();
141
142 let device_memory = {
144 let memory_allocate_flags_info = vk::MemoryAllocateFlagsInfo {
145 s_type: vk::StructureType::MemoryAllocateFlagsInfo,
146 p_next: null(),
147 flags: vk::MemoryAllocateFlagBits::DeviceAddress.into(),
148 device_mask: 0,
149 };
150 device
151 .allocate_memory(&vk::MemoryAllocateInfo {
152 s_type: vk::StructureType::MemoryAllocateInfo,
153 p_next: addr_of!(memory_allocate_flags_info).cast(),
154 allocation_size,
155 memory_type_index,
156 })
157 .with_context(|| {
158 format!("Allocating device memory for {} buffers", buffers.len())
159 })?
160 };
161
162 let mut memory_ptr = None;
164 if property_flags
165 .into()
166 .contains(vk::MemoryPropertyFlagBits::HostVisible)
167 {
168 let ptr = device
169 .map_memory2_khr(&vk::MemoryMapInfoKHR {
170 s_type: vk::StructureType::MemoryMapInfoKHR,
171 p_next: null(),
172 flags: vk::MemoryMapFlags::empty(),
173 memory: device_memory,
174 offset: 0,
175 size: allocation_size,
176 })
177 .with_context(|| format!("Mapping buffer size={allocation_size}"))?;
178 memory_ptr = Some(ptr);
179 }
180
181 let mut allocations = vec![];
183 let mut memory_offset = 0;
184 for (buffer_index, (buffer, requirements)) in
185 buffers.iter().zip(memory_requirements).enumerate()
186 {
187 let aligned_size = aligned_size(requirements.size, alignment);
189
190 device
192 .bind_buffer_memory2(
193 1,
194 &vk::BindBufferMemoryInfo {
195 s_type: vk::StructureType::BindBufferMemoryInfo,
196 p_next: null(),
197 buffer: *buffer,
198 memory: device_memory,
199 memory_offset,
200 },
201 )
202 .with_context(|| {
203 format!(
204 "Binding buffer {buffer_index} \
205 size={aligned_size} into \
206 device memory offset={memory_offset}"
207 )
208 })?;
209
210 let device_address = device.get_buffer_device_address(&vk::BufferDeviceAddressInfo {
212 s_type: vk::StructureType::BufferDeviceAddressInfo,
213 p_next: null(),
214 buffer: *buffer,
215 });
216
217 let buffer_ptr = memory_ptr.map(|ptr| ptr.add(memory_offset as _));
219
220 memory_offset += aligned_size;
222
223 allocations.push(BufferAllocation {
225 address: device_address,
226 size: requirements.size,
227 ptr: buffer_ptr,
228 });
229 }
230
231 Ok(Self {
232 memory: device_memory,
233 allocations,
234 })
235 }
236
237 pub unsafe fn free(self, device: &Device) {
238 device.free_memory(self.memory);
239 }
240
241 #[must_use]
242 pub fn allocations(&self) -> &[BufferAllocation] {
243 &self.allocations
244 }
245}
246
247#[derive(Debug)]
252pub struct ImageAllocations {
253 memory: vk::DeviceMemory,
254}
255
256impl ImageAllocations {
257 pub unsafe fn allocate(
258 physical_device: &PhysicalDevice,
259 device: &Device,
260 images: &[vk::Image],
261 image_create_infos: &[vk::ImageCreateInfo],
262 property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
263 ) -> Result<Self> {
264 ensure!(!images.is_empty());
266 ensure!(!image_create_infos.is_empty());
267 ensure!(images.len() == image_create_infos.len());
268 ensure!(image_create_infos
269 .iter()
270 .all(|info| info.s_type == vk::StructureType::ImageCreateInfo));
271 ensure!(image_create_infos.iter().all(|info| info.p_next.is_null()));
272 ensure!(image_create_infos
273 .iter()
274 .all(|info| info.flags == vk::ImageCreateFlags::empty()));
275 ensure!(image_create_infos
276 .iter()
277 .all(|info| info.extent.width > 0 && info.extent.height > 0 && info.extent.depth > 0));
278 ensure!(image_create_infos.iter().all(|info| info.mip_levels > 0));
279 ensure!(image_create_infos.iter().all(|info| info.array_layers > 0));
280 ensure!(image_create_infos
281 .iter()
282 .all(|info| info.tiling == vk::ImageTiling::Optimal));
283 ensure!(image_create_infos
284 .iter()
285 .all(|info| info.sharing_mode == vk::SharingMode::Exclusive));
286 ensure!(image_create_infos.iter().all(
287 |info| info.queue_family_index_count == 0 && info.p_queue_family_indices.is_null()
288 ));
289 ensure!(image_create_infos
290 .iter()
291 .all(|info| info.initial_layout == vk::ImageLayout::Undefined));
292
293 let mut memory_requirements = vec![];
295 for &image_create_info in image_create_infos {
296 let device_image_memory_requirements = vk::DeviceImageMemoryRequirements {
297 s_type: vk::StructureType::DeviceImageMemoryRequirements,
298 p_next: null(),
299 p_create_info: &image_create_info,
300 plane_aspect: zeroed(),
301 };
302 let mut memory_requirements2 = vk::MemoryRequirements2 {
303 s_type: vk::StructureType::MemoryRequirements2,
304 p_next: null_mut(),
305 memory_requirements: zeroed(),
306 };
307 device.get_device_image_memory_requirements(
308 &device_image_memory_requirements,
309 &mut memory_requirements2,
310 );
311 memory_requirements.push(memory_requirements2.memory_requirements);
312 }
313
314 ensure!(memory_requirements
316 .iter()
317 .all(|req| req.alignment == memory_requirements[0].alignment));
318 ensure!(memory_requirements
319 .iter()
320 .all(|req| req.memory_type_bits == memory_requirements[0].memory_type_bits));
321 let alignment = memory_requirements[0].alignment;
322 let memory_type_bits = memory_requirements[0].memory_type_bits;
323
324 let memory_type_index = memory_type_index(
326 &physical_device.memory_properties,
327 property_flags,
328 memory_type_bits,
329 );
330
331 let allocation_size = memory_requirements
333 .iter()
334 .map(|req| aligned_size(req.size, alignment))
335 .sum::<vk::DeviceSize>();
336
337 let device_memory = device
339 .allocate_memory(&vk::MemoryAllocateInfo {
340 s_type: vk::StructureType::MemoryAllocateInfo,
341 p_next: null(),
342 allocation_size,
343 memory_type_index,
344 })
345 .with_context(|| {
346 format!(
347 "\
348 Allocating device memory for {} images",
349 images.len()
350 )
351 })?;
352
353 let mut memory_offset = 0;
355 for (image_index, (image, requirements)) in
356 images.iter().zip(memory_requirements).enumerate()
357 {
358 let aligned_size = aligned_size(requirements.size, alignment);
360
361 device
363 .bind_image_memory2(
364 1,
365 &vk::BindImageMemoryInfo {
366 s_type: vk::StructureType::BindImageMemoryInfo,
367 p_next: null(),
368 image: *image,
369 memory: device_memory,
370 memory_offset,
371 },
372 )
373 .with_context(|| {
374 format!(
375 "\
376 Binding image {image_index} \
377 size={aligned_size} into \
378 device memory offset={memory_offset}"
379 )
380 })?;
381
382 memory_offset += aligned_size;
384 }
385
386 Ok(Self {
387 memory: device_memory,
388 })
389 }
390
391 pub unsafe fn free(self, device: &Device) {
392 device.free_memory(self.memory);
393 }
394}
395
396fn memory_type_index(
401 memory: &vk::PhysicalDeviceMemoryProperties,
402 property_flags: impl Into<vk::MemoryPropertyFlags> + Copy,
403 memory_type_bits: u32,
404) -> u32 {
405 for memory_type_index in 0..memory.memory_type_count {
406 let memory_type = memory.memory_types[memory_type_index as usize];
407 let type_matches = (1 << memory_type_index) & memory_type_bits != 0;
408 let property_matches = memory_type.property_flags.contains(property_flags);
409 if type_matches && property_matches {
410 debug!(
411 "index={}, type={:?}, heap={:?}",
412 memory_type_index,
413 &memory.memory_types[memory_type_index as usize].property_flags,
414 &memory.memory_heaps[memory_type.heap_index as usize].flags
415 );
416 return memory_type_index;
417 }
418 }
419 panic!("Unable to find suitable memory type for the buffer, memory_type_bits=0b{memory_type_bits:b}");
420}