1use std::ffi::CStr;
2use std::sync::Arc;
3
4use crate::ffi;
5use crate::Allocation;
6use crate::AllocationCreateInfo;
7use crate::Allocator;
8use crate::PoolCreateInfo;
9use ash::prelude::VkResult;
10use ash::vk;
11#[derive(Clone, Copy)]
12pub struct PoolHandle(ffi::VmaPool);
13
14pub struct AllocatorPool {
16 allocator: Arc<Allocator>,
17 pub(crate) pool: PoolHandle,
18}
19unsafe impl Send for AllocatorPool {}
20unsafe impl Sync for AllocatorPool {}
21
22impl Allocator {
23 pub fn create_pool(self: &Arc<Self>, create_info: &PoolCreateInfo) -> VkResult<AllocatorPool> {
25 unsafe {
26 let mut ffi_pool: ffi::VmaPool = std::mem::zeroed();
27 let raw_info = ffi::VmaPoolCreateInfo {
28 memoryTypeIndex: create_info.memory_type_index,
29 flags: create_info.flags.bits(),
30 blockSize: create_info.block_size,
31 minBlockCount: create_info.min_block_count,
32 maxBlockCount: create_info.max_block_count,
33 priority: create_info.priority,
34 minAllocationAlignment: create_info.min_allocation_alignment,
35 pMemoryAllocateNext: create_info.memory_allocate_next as *mut std::ffi::c_void,
36 };
37 ffi::vmaCreatePool(self.internal, &raw_info, &mut ffi_pool).result()?;
38 Ok(AllocatorPool {
39 pool: PoolHandle(ffi_pool),
40 allocator: self.clone(),
41 })
42 }
43 }
44
45 pub fn default_pool(self: &Arc<Self>) -> AllocatorPool {
46 AllocatorPool {
47 pool: PoolHandle(std::ptr::null_mut()),
48 allocator: self.clone(),
49 }
50 }
51}
52
53impl Drop for AllocatorPool {
54 fn drop(&mut self) {
55 unsafe {
56 ffi::vmaDestroyPool(self.allocator.internal, self.pool.0);
57 }
58 }
59}
60
61impl AllocatorPool {
62 pub fn set_name(&self, name: Option<&CStr>) {
63 if self.pool.0.is_null() {
64 return;
65 }
66 unsafe {
67 ffi::vmaSetPoolName(
68 self.allocator.internal,
69 self.pool.0,
70 name.map_or(std::ptr::null(), CStr::as_ptr),
71 );
72 }
73 }
74 pub fn name(&self) -> Option<&CStr> {
75 if self.pool.0.is_null() {
76 return None;
77 }
78 let mut ptr: *const ::std::os::raw::c_char = std::ptr::null();
79 unsafe {
80 ffi::vmaGetPoolName(self.allocator.internal, self.pool.0, &mut ptr);
81 if ptr.is_null() {
82 return None;
83 }
84 Some(CStr::from_ptr(ptr))
85 }
86 }
87 pub fn get_statistics(&self) -> VkResult<ffi::VmaStatistics> {
89 unsafe {
90 let mut pool_stats: ffi::VmaStatistics = std::mem::zeroed();
91 ffi::vmaGetPoolStatistics(self.allocator.internal, self.pool.0, &mut pool_stats);
92 Ok(pool_stats)
93 }
94 }
95
96 pub fn calculate_statistics(&self) -> VkResult<ffi::VmaDetailedStatistics> {
98 unsafe {
99 let mut pool_stats: ffi::VmaDetailedStatistics = std::mem::zeroed();
100 ffi::vmaCalculatePoolStatistics(self.allocator.internal, self.pool.0, &mut pool_stats);
101 Ok(pool_stats)
102 }
103 }
104
105 pub fn check_corruption(&self) -> VkResult<()> {
118 unsafe { ffi::vmaCheckPoolCorruption(self.allocator.internal, self.pool.0).result() }
119 }
120}
121
122pub trait Alloc {
123 fn allocator(&self) -> &Allocator;
124 fn pool(&self) -> PoolHandle;
125 unsafe fn find_memory_type_index(
140 &self,
141 memory_type_bits: u32,
142 allocation_info: &AllocationCreateInfo,
143 ) -> VkResult<u32> {
144 let mut memory_type_index: u32 = 0;
145 let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into();
146 allocation_info.pool = self.pool().0;
147 ffi::vmaFindMemoryTypeIndex(
148 self.allocator().internal,
149 memory_type_bits,
150 &allocation_info,
151 &mut memory_type_index,
152 )
153 .result()?;
154
155 Ok(memory_type_index)
156 }
157
158 unsafe fn find_memory_type_index_for_buffer_info(
169 &self,
170 buffer_info: &ash::vk::BufferCreateInfo,
171 allocation_info: &AllocationCreateInfo,
172 ) -> VkResult<u32> {
173 let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into();
174 allocation_info.pool = self.pool().0;
175 let mut memory_type_index: u32 = 0;
176 ffi::vmaFindMemoryTypeIndexForBufferInfo(
177 self.allocator().internal,
178 buffer_info,
179 &allocation_info,
180 &mut memory_type_index,
181 )
182 .result()?;
183
184 Ok(memory_type_index)
185 }
186
187 unsafe fn find_memory_type_index_for_image_info(
198 &self,
199 image_info: ash::vk::ImageCreateInfo,
200 allocation_info: &AllocationCreateInfo,
201 ) -> VkResult<u32> {
202 let mut allocation_info: ffi::VmaAllocationCreateInfo = allocation_info.into();
203 allocation_info.pool = self.pool().0;
204 let mut memory_type_index: u32 = 0;
205 ffi::vmaFindMemoryTypeIndexForImageInfo(
206 self.allocator().internal,
207 &image_info,
208 &allocation_info,
209 &mut memory_type_index,
210 )
211 .result()?;
212
213 Ok(memory_type_index)
214 }
215
216 unsafe fn allocate_memory(
223 &self,
224 memory_requirements: &ash::vk::MemoryRequirements,
225 create_info: &AllocationCreateInfo,
226 ) -> VkResult<Allocation> {
227 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
228 create_info.pool = self.pool().0;
229 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
230 ffi::vmaAllocateMemory(
231 self.allocator().internal,
232 memory_requirements,
233 &create_info,
234 &mut allocation,
235 std::ptr::null_mut(),
236 )
237 .result()?;
238
239 Ok(Allocation(allocation))
240 }
241
242 unsafe fn allocate_memory_pages(
252 &self,
253 memory_requirements: &ash::vk::MemoryRequirements,
254 create_info: &AllocationCreateInfo,
255 allocation_count: usize,
256 ) -> VkResult<Vec<Allocation>> {
257 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
258 create_info.pool = self.pool().0;
259 let mut allocations: Vec<ffi::VmaAllocation> = vec![std::mem::zeroed(); allocation_count];
260 ffi::vmaAllocateMemoryPages(
261 self.allocator().internal,
262 memory_requirements,
263 &create_info,
264 allocation_count,
265 allocations.as_mut_ptr(),
266 std::ptr::null_mut(),
267 )
268 .result()?;
269
270 let allocations: Vec<Allocation> = allocations
271 .into_iter()
272 .map(|alloc| Allocation(alloc))
273 .collect();
274
275 Ok(allocations)
276 }
277
278 unsafe fn allocate_memory_for_buffer(
282 &self,
283 buffer: ash::vk::Buffer,
284 create_info: &AllocationCreateInfo,
285 ) -> VkResult<Allocation> {
286 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
287 create_info.pool = self.pool().0;
288 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
289 let mut allocation_info: ffi::VmaAllocationInfo = std::mem::zeroed();
290 ffi::vmaAllocateMemoryForBuffer(
291 self.allocator().internal,
292 buffer,
293 &create_info,
294 &mut allocation,
295 &mut allocation_info,
296 )
297 .result()?;
298
299 Ok(Allocation(allocation))
300 }
301
302 unsafe fn allocate_memory_for_image(
306 &self,
307 image: ash::vk::Image,
308 create_info: &AllocationCreateInfo,
309 ) -> VkResult<Allocation> {
310 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
311 create_info.pool = self.pool().0;
312 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
313 ffi::vmaAllocateMemoryForImage(
314 self.allocator().internal,
315 image,
316 &create_info,
317 &mut allocation,
318 std::ptr::null_mut(),
319 )
320 .result()?;
321
322 Ok(Allocation(allocation))
323 }
324
325 unsafe fn create_buffer(
339 &self,
340 buffer_info: &ash::vk::BufferCreateInfo,
341 create_info: &AllocationCreateInfo,
342 ) -> VkResult<(ash::vk::Buffer, Allocation)> {
343 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
344 create_info.pool = self.pool().0;
345 let mut buffer = vk::Buffer::null();
346 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
347 ffi::vmaCreateBuffer(
348 self.allocator().internal,
349 &*buffer_info,
350 &create_info,
351 &mut buffer,
352 &mut allocation,
353 std::ptr::null_mut(),
354 )
355 .result()?;
356
357 Ok((buffer, Allocation(allocation)))
358 }
359 unsafe fn create_buffer_with_alignment(
365 &self,
366 buffer_info: &ash::vk::BufferCreateInfo,
367 create_info: &AllocationCreateInfo,
368 min_alignment: vk::DeviceSize,
369 ) -> VkResult<(ash::vk::Buffer, Allocation)> {
370 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
371 create_info.pool = self.pool().0;
372 let mut buffer = vk::Buffer::null();
373 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
374 ffi::vmaCreateBufferWithAlignment(
375 self.allocator().internal,
376 &*buffer_info,
377 &create_info,
378 min_alignment,
379 &mut buffer,
380 &mut allocation,
381 std::ptr::null_mut(),
382 )
383 .result()?;
384
385 Ok((buffer, Allocation(allocation)))
386 }
387 unsafe fn create_image(
405 &self,
406 image_info: &ash::vk::ImageCreateInfo,
407 create_info: &AllocationCreateInfo,
408 ) -> VkResult<(ash::vk::Image, Allocation)> {
409 let mut create_info: ffi::VmaAllocationCreateInfo = create_info.into();
410 create_info.pool = self.pool().0;
411 let mut image = vk::Image::null();
412 let mut allocation: ffi::VmaAllocation = std::mem::zeroed();
413 ffi::vmaCreateImage(
414 self.allocator().internal,
415 &*image_info,
416 &create_info,
417 &mut image,
418 &mut allocation,
419 std::ptr::null_mut(),
420 )
421 .result()?;
422
423 Ok((image, Allocation(allocation)))
424 }
425}
426
427impl Alloc for AllocatorPool {
428 fn allocator(&self) -> &Allocator {
429 self.allocator.as_ref()
430 }
431
432 fn pool(&self) -> PoolHandle {
433 self.pool
434 }
435}
436impl Alloc for Allocator {
437 fn allocator(&self) -> &Allocator {
438 self
439 }
440
441 fn pool(&self) -> PoolHandle {
442 PoolHandle(std::ptr::null_mut())
443 }
444}