bort_vma/allocator.rs
1use ash::prelude::VkResult;
2use ash::vk;
3use std::mem;
4
5use crate::definitions::*;
6use crate::ffi;
7
8/// Main allocator object
9pub struct Allocator {
10 /// Pointer to internal VmaAllocator instance
11 pub(crate) internal: ffi::VmaAllocator,
12}
13
14// Allocator is internally thread safe unless AllocatorCreateFlags::EXTERNALLY_SYNCHRONIZED is used (then you need to add synchronization!)
15unsafe impl Send for Allocator {}
16unsafe impl Sync for Allocator {}
17
18/// Represents single memory allocation.
19///
20/// It may be either dedicated block of `ash::vk::DeviceMemory` or a specific region of a
21/// bigger block of this type plus unique offset.
22///
23/// Although the library provides convenience functions that create a Vulkan buffer or image,
24/// allocate memory for it and bind them together, binding of the allocation to a buffer or an
25/// image is out of scope of the allocation itself.
26///
27/// Allocation object can exist without buffer/image bound, binding can be done manually by
28/// the user, and destruction of it can be done independently of destruction of the allocation.
29///
30/// The object also remembers its size and some other information. To retrieve this information,
31/// use `Allocator::get_allocation_info`.
32///
33/// Some kinds allocations can be in lost state.
34pub struct Allocation(pub(crate) ffi::VmaAllocation);
35unsafe impl Send for Allocation {}
36unsafe impl Sync for Allocation {}
37
38impl Allocator {
39 /// Constructor a new `Allocator` using the provided options.
40 pub fn new(mut create_info: AllocatorCreateInfo) -> VkResult<Self> {
41 unsafe extern "system" fn get_instance_proc_addr_stub(
42 _instance: ash::vk::Instance,
43 _p_name: *const ::std::os::raw::c_char,
44 ) -> ash::vk::PFN_vkVoidFunction {
45 panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported")
46 }
47
48 unsafe extern "system" fn get_get_device_proc_stub(
49 _device: ash::vk::Device,
50 _p_name: *const ::std::os::raw::c_char,
51 ) -> ash::vk::PFN_vkVoidFunction {
52 panic!("VMA_DYNAMIC_VULKAN_FUNCTIONS is unsupported")
53 }
54
55 #[cfg(feature = "loaded")]
56 let routed_functions = ffi::VmaVulkanFunctions {
57 vkGetInstanceProcAddr: get_instance_proc_addr_stub,
58 vkGetDeviceProcAddr: get_get_device_proc_stub,
59 vkGetPhysicalDeviceProperties: create_info
60 .instance
61 .fp_v1_0()
62 .get_physical_device_properties,
63 vkGetPhysicalDeviceMemoryProperties: create_info
64 .instance
65 .fp_v1_0()
66 .get_physical_device_memory_properties,
67 vkAllocateMemory: create_info.device.fp_v1_0().allocate_memory,
68 vkFreeMemory: create_info.device.fp_v1_0().free_memory,
69 vkMapMemory: create_info.device.fp_v1_0().map_memory,
70 vkUnmapMemory: create_info.device.fp_v1_0().unmap_memory,
71 vkFlushMappedMemoryRanges: create_info.device.fp_v1_0().flush_mapped_memory_ranges,
72 vkInvalidateMappedMemoryRanges: create_info
73 .device
74 .fp_v1_0()
75 .invalidate_mapped_memory_ranges,
76 vkBindBufferMemory: create_info.device.fp_v1_0().bind_buffer_memory,
77 vkBindImageMemory: create_info.device.fp_v1_0().bind_image_memory,
78 vkGetBufferMemoryRequirements: create_info
79 .device
80 .fp_v1_0()
81 .get_buffer_memory_requirements,
82 vkGetImageMemoryRequirements: create_info
83 .device
84 .fp_v1_0()
85 .get_image_memory_requirements,
86 vkCreateBuffer: create_info.device.fp_v1_0().create_buffer,
87 vkDestroyBuffer: create_info.device.fp_v1_0().destroy_buffer,
88 vkCreateImage: create_info.device.fp_v1_0().create_image,
89 vkDestroyImage: create_info.device.fp_v1_0().destroy_image,
90 vkCmdCopyBuffer: create_info.device.fp_v1_0().cmd_copy_buffer,
91 vkGetBufferMemoryRequirements2KHR: create_info
92 .device
93 .fp_v1_1()
94 .get_buffer_memory_requirements2,
95 vkGetImageMemoryRequirements2KHR: create_info
96 .device
97 .fp_v1_1()
98 .get_image_memory_requirements2,
99 vkBindBufferMemory2KHR: create_info.device.fp_v1_1().bind_buffer_memory2,
100 vkBindImageMemory2KHR: create_info.device.fp_v1_1().bind_image_memory2,
101 vkGetPhysicalDeviceMemoryProperties2KHR: create_info
102 .instance
103 .fp_v1_1()
104 .get_physical_device_memory_properties2,
105 vkGetDeviceBufferMemoryRequirements: create_info
106 .device
107 .fp_v1_3()
108 .get_device_buffer_memory_requirements,
109 vkGetDeviceImageMemoryRequirements: create_info
110 .device
111 .fp_v1_3()
112 .get_device_image_memory_requirements,
113 };
114 #[cfg(feature = "loaded")]
115 {
116 create_info.inner.pVulkanFunctions = &routed_functions;
117 }
118 unsafe {
119 let mut internal: ffi::VmaAllocator = mem::zeroed();
120 ffi::vmaCreateAllocator(&create_info.inner as *const _, &mut internal).result()?;
121
122 Ok(Allocator { internal })
123 }
124 }
125
126 /// The allocator fetches `ash::vk::PhysicalDeviceProperties` from the physical device.
127 /// You can get it here, without fetching it again on your own.
128 pub unsafe fn get_physical_device_properties(&self) -> VkResult<vk::PhysicalDeviceProperties> {
129 let mut properties = vk::PhysicalDeviceProperties::default();
130 ffi::vmaGetPhysicalDeviceProperties(
131 self.internal,
132 &mut properties as *mut _ as *mut *const _,
133 );
134
135 Ok(properties)
136 }
137
138 /// The allocator fetches `ash::vk::PhysicalDeviceMemoryProperties` from the physical device.
139 /// You can get it here, without fetching it again on your own.
140 pub unsafe fn get_memory_properties(&self) -> &vk::PhysicalDeviceMemoryProperties {
141 let mut properties: *const vk::PhysicalDeviceMemoryProperties = std::ptr::null();
142 ffi::vmaGetMemoryProperties(self.internal, &mut properties);
143
144 &*properties
145 }
146
147 /// Sets index of the current frame.
148 ///
149 /// This function must be used if you make allocations with `AllocationCreateFlags::CAN_BECOME_LOST` and
150 /// `AllocationCreateFlags::CAN_MAKE_OTHER_LOST` flags to inform the allocator when a new frame begins.
151 /// Allocations queried using `Allocator::get_allocation_info` cannot become lost
152 /// in the current frame.
153 pub unsafe fn set_current_frame_index(&self, frame_index: u32) {
154 ffi::vmaSetCurrentFrameIndex(self.internal, frame_index);
155 }
156
157 /// Retrieves statistics from current state of the `Allocator`.
158 pub fn calculate_statistics(&self) -> VkResult<ffi::VmaTotalStatistics> {
159 unsafe {
160 let mut vma_stats: ffi::VmaTotalStatistics = mem::zeroed();
161 ffi::vmaCalculateStatistics(self.internal, &mut vma_stats);
162 Ok(vma_stats)
163 }
164 }
165
166 /// Retrieves information about current memory usage and budget for all memory heaps.
167 ///
168 /// This function is called "get" not "calculate" because it is very fast, suitable to be called
169 /// every frame or every allocation. For more detailed statistics use vmaCalculateStatistics().
170 ///
171 /// Note that when using allocator from multiple threads, returned information may immediately
172 /// become outdated.
173 pub fn get_heap_budgets(&self) -> VkResult<Vec<ffi::VmaBudget>> {
174 unsafe {
175 let len = self.get_memory_properties().memory_heap_count as usize;
176 let mut vma_budgets: Vec<ffi::VmaBudget> = Vec::with_capacity(len);
177 ffi::vmaGetHeapBudgets(self.internal, vma_budgets.as_mut_ptr());
178 vma_budgets.set_len(len);
179 Ok(vma_budgets)
180 }
181 }
182
183 /// Frees memory previously allocated using `Allocator::allocate_memory`,
184 /// `Allocator::allocate_memory_for_buffer`, or `Allocator::allocate_memory_for_image`.
185 pub unsafe fn free_memory(&self, allocation: &mut Allocation) {
186 ffi::vmaFreeMemory(self.internal, allocation.0);
187 }
188
189 /// Frees memory and destroys multiple allocations.
190 ///
191 /// Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding.
192 /// It is just a general purpose function to free memory and destroy allocations made using e.g. `Allocator::allocate_memory',
193 /// 'Allocator::allocate_memory_pages` and other functions.
194 ///
195 /// It may be internally optimized to be more efficient than calling 'Allocator::free_memory` `allocations.len()` times.
196 ///
197 /// Allocations in 'allocations' slice can come from any memory pools and types.
198 pub unsafe fn free_memory_pages(&self, allocations: &mut [Allocation]) {
199 ffi::vmaFreeMemoryPages(
200 self.internal,
201 allocations.len(),
202 allocations.as_ptr() as *mut _,
203 );
204 }
205
206 /// Returns current information about specified allocation and atomically marks it as used in current frame.
207 ///
208 /// Current parameters of given allocation are returned in the result object, available through accessors.
209 ///
210 /// This function also atomically "touches" allocation - marks it as used in current frame,
211 /// just like `Allocator::touch_allocation`.
212 ///
213 /// If the allocation is in lost state, `allocation.get_device_memory` returns `ash::vk::DeviceMemory::null()`.
214 ///
215 /// Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient,
216 /// you can avoid calling it too often.
217 ///
218 /// If you just want to check if allocation is not lost, `Allocator::touch_allocation` will work faster.
219 pub fn get_allocation_info(&self, allocation: &Allocation) -> AllocationInfo {
220 unsafe {
221 let mut allocation_info: ffi::VmaAllocationInfo = mem::zeroed();
222 ffi::vmaGetAllocationInfo(self.internal, allocation.0, &mut allocation_info);
223 allocation_info.into()
224 }
225 }
226
227 /// Sets user data in given allocation to new value.
228 ///
229 /// If the allocation was created with `AllocationCreateFlags::USER_DATA_COPY_STRING`,
230 /// `user_data` must be either null, or pointer to a null-terminated string. The function
231 /// makes local copy of the string and sets it as allocation's user data. String
232 /// passed as user data doesn't need to be valid for whole lifetime of the allocation -
233 /// you can free it after this call. String previously pointed by allocation's
234 /// user data is freed from memory.
235 ///
236 /// If the flag was not used, the value of pointer `user_data` is just copied to
237 /// allocation's user data. It is opaque, so you can use it however you want - e.g.
238 /// as a pointer, ordinal number or some handle to you own data.
239 pub unsafe fn set_allocation_user_data(
240 &self,
241 allocation: &mut Allocation,
242 user_data: *mut ::std::os::raw::c_void,
243 ) {
244 ffi::vmaSetAllocationUserData(self.internal, allocation.0, user_data);
245 }
246
247 /// Maps memory represented by given allocation and returns pointer to it.
248 ///
249 /// Maps memory represented by given allocation to make it accessible to CPU code.
250 /// When succeeded, result is a pointer to first byte of this memory.
251 ///
252 /// If the allocation is part of bigger `ash::vk::DeviceMemory` block, the pointer is
253 /// correctly offseted to the beginning of region assigned to this particular
254 /// allocation.
255 ///
256 /// Mapping is internally reference-counted and synchronized, so despite raw Vulkan
257 /// function `ash::vk::Device::MapMemory` cannot be used to map same block of
258 /// `ash::vk::DeviceMemory` multiple times simultaneously, it is safe to call this
259 /// function on allocations assigned to the same memory block. Actual Vulkan memory
260 /// will be mapped on first mapping and unmapped on last unmapping.
261 ///
262 /// If the function succeeded, you must call `Allocator::unmap_memory` to unmap the
263 /// allocation when mapping is no longer needed or before freeing the allocation, at
264 /// the latest.
265 ///
266 /// It also safe to call this function multiple times on the same allocation. You
267 /// must call `Allocator::unmap_memory` same number of times as you called
268 /// `Allocator::map_memory`.
269 ///
270 /// It is also safe to call this function on allocation created with
271 /// `AllocationCreateFlags::MAPPED` flag. Its memory stays mapped all the time.
272 /// You must still call `Allocator::unmap_memory` same number of times as you called
273 /// `Allocator::map_memory`. You must not call `Allocator::unmap_memory` additional
274 /// time to free the "0-th" mapping made automatically due to `AllocationCreateFlags::MAPPED` flag.
275 ///
276 /// This function fails when used on allocation made in memory type that is not
277 /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE`.
278 ///
279 /// This function always fails when called for allocation that was created with
280 /// `AllocationCreateFlags::CAN_BECOME_LOST` flag. Such allocations cannot be mapped.
281 pub unsafe fn map_memory(&self, allocation: &mut Allocation) -> VkResult<*mut u8> {
282 let mut mapped_data: *mut ::std::os::raw::c_void = ::std::ptr::null_mut();
283 ffi::vmaMapMemory(self.internal, allocation.0, &mut mapped_data).result()?;
284
285 Ok(mapped_data as *mut u8)
286 }
287
288 /// Unmaps memory represented by given allocation, mapped previously using `Allocator::map_memory`.
289 pub unsafe fn unmap_memory(&self, allocation: &mut Allocation) {
290 ffi::vmaUnmapMemory(self.internal, allocation.0);
291 }
292
293 /// Flushes memory of given allocation.
294 ///
295 /// Calls `ash::vk::Device::FlushMappedMemoryRanges` for memory associated with given range of given allocation.
296 ///
297 /// - `offset` must be relative to the beginning of allocation.
298 /// - `size` can be `ash::vk::WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
299 /// - `offset` and `size` don't have to be aligned; hey are internally rounded down/up to multiple of `nonCoherentAtomSize`.
300 /// - If `size` is 0, this call is ignored.
301 /// - If memory type that the `allocation` belongs to is not `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` or it is `ash::vk::MemoryPropertyFlags::HOST_COHERENT`, this call is ignored.
302 pub fn flush_allocation(
303 &self,
304 allocation: &Allocation,
305 offset: usize,
306 size: usize,
307 ) -> VkResult<()> {
308 unsafe {
309 ffi::vmaFlushAllocation(
310 self.internal,
311 allocation.0,
312 offset as vk::DeviceSize,
313 size as vk::DeviceSize,
314 )
315 .result()
316 }
317 }
318
319 /// Invalidates memory of given allocation.
320 ///
321 /// Calls `ash::vk::Device::invalidate_mapped_memory_ranges` for memory associated with given range of given allocation.
322 ///
323 /// - `offset` must be relative to the beginning of allocation.
324 /// - `size` can be `ash::vk::WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
325 /// - `offset` and `size` don't have to be aligned. They are internally rounded down/up to multiple of `nonCoherentAtomSize`.
326 /// - If `size` is 0, this call is ignored.
327 /// - If memory type that the `allocation` belongs to is not `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` or it is `ash::vk::MemoryPropertyFlags::HOST_COHERENT`, this call is ignored.
328 pub fn invalidate_allocation(
329 &self,
330 allocation: &Allocation,
331 offset: usize,
332 size: usize,
333 ) -> VkResult<()> {
334 unsafe {
335 ffi::vmaInvalidateAllocation(
336 self.internal,
337 allocation.0,
338 offset as vk::DeviceSize,
339 size as vk::DeviceSize,
340 )
341 .result()
342 }
343 }
344
345 /// Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.
346 ///
347 /// `memory_type_bits` bit mask, where each bit set means that a memory type with that index should be checked.
348 ///
349 /// Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
350 /// `VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are `HOST_VISIBLE` and `HOST_COHERENT`.
351 ///
352 /// Possible error values:
353 ///
354 /// - `ash::vk::Result::ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.
355 /// - `ash::vk::Result::ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
356 /// `VMA_ASSERT` is also fired in that case.
357 /// - Other value: Error returned by Vulkan, e.g. memory mapping failure.
358 pub unsafe fn check_corruption(
359 &self,
360 memory_types: ash::vk::MemoryPropertyFlags,
361 ) -> VkResult<()> {
362 ffi::vmaCheckCorruption(self.internal, memory_types.as_raw()).result()
363 }
364
365 /// Binds buffer to allocation.
366 ///
367 /// Binds specified buffer to region of memory represented by specified allocation.
368 /// Gets `ash::vk::DeviceMemory` handle and offset from the allocation.
369 ///
370 /// If you want to create a buffer, allocate memory for it and bind them together separately,
371 /// you should use this function for binding instead of `ash::vk::Device::bind_buffer_memory`,
372 /// because it ensures proper synchronization so that when a `ash::vk::DeviceMemory` object is
373 /// used by multiple allocations, calls to `ash::vk::Device::bind_buffer_memory()` or
374 /// `ash::vk::Device::map_memory()` won't happen from multiple threads simultaneously
375 /// (which is illegal in Vulkan).
376 ///
377 /// It is recommended to use function `Allocator::create_buffer` instead of this one.
378 pub unsafe fn bind_buffer_memory(
379 &self,
380 allocation: &Allocation,
381 buffer: ash::vk::Buffer,
382 ) -> VkResult<()> {
383 ffi::vmaBindBufferMemory(self.internal, allocation.0, buffer).result()
384 }
385
386 /// Binds buffer to allocation with additional parameters.
387 ///
388 /// * `allocation`
389 /// * `allocation_local_offset` - Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
390 /// * `buffer`
391 /// * `next` - A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
392 ///
393 /// This function is similar to vmaBindImageMemory(), but it provides additional parameters.
394 ///
395 /// If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
396 /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails.
397 pub unsafe fn bind_buffer_memory2(
398 &self,
399 allocation: &Allocation,
400 allocation_local_offset: vk::DeviceSize,
401 buffer: ash::vk::Buffer,
402 next: *const ::std::os::raw::c_void,
403 ) -> VkResult<()> {
404 ffi::vmaBindBufferMemory2(
405 self.internal,
406 allocation.0,
407 allocation_local_offset,
408 buffer,
409 next,
410 )
411 .result()
412 }
413
414 /// Binds image to allocation.
415 ///
416 /// Binds specified image to region of memory represented by specified allocation.
417 /// Gets `ash::vk::DeviceMemory` handle and offset from the allocation.
418 ///
419 /// If you want to create a image, allocate memory for it and bind them together separately,
420 /// you should use this function for binding instead of `ash::vk::Device::bind_image_memory`,
421 /// because it ensures proper synchronization so that when a `ash::vk::DeviceMemory` object is
422 /// used by multiple allocations, calls to `ash::vk::Device::bind_image_memory()` or
423 /// `ash::vk::Device::map_memory()` won't happen from multiple threads simultaneously
424 /// (which is illegal in Vulkan).
425 ///
426 /// It is recommended to use function `Allocator::create_image` instead of this one.
427 pub unsafe fn bind_image_memory(
428 &self,
429 allocation: &Allocation,
430 image: ash::vk::Image,
431 ) -> VkResult<()> {
432 ffi::vmaBindImageMemory(self.internal, allocation.0, image).result()
433 }
434
435 /// Binds image to allocation with additional parameters.
436 ///
437 /// * `allocation`
438 /// * `allocation_local_offset` - Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
439 /// * `image`
440 /// * `next` - A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
441 ///
442 /// This function is similar to vmaBindImageMemory(), but it provides additional parameters.
443 ///
444 /// If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
445 /// or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails.
446 pub unsafe fn bind_image_memory2(
447 &self,
448 allocation: &Allocation,
449 allocation_local_offset: vk::DeviceSize,
450 image: ash::vk::Image,
451 next: *const ::std::os::raw::c_void,
452 ) -> VkResult<()> {
453 ffi::vmaBindImageMemory2(
454 self.internal,
455 allocation.0,
456 allocation_local_offset,
457 image,
458 next,
459 )
460 .result()
461 }
462
463 /// Destroys Vulkan buffer and frees allocated memory.
464 ///
465 /// This is just a convenience function equivalent to:
466 ///
467 /// ```ignore
468 /// ash::vk::Device::destroy_buffer(buffer, None);
469 /// Allocator::free_memory(allocator, allocation);
470 /// ```
471 ///
472 /// It it safe to pass null as `buffer` and/or `allocation`.
473 pub unsafe fn destroy_buffer(&self, buffer: ash::vk::Buffer, allocation: &mut Allocation) {
474 ffi::vmaDestroyBuffer(self.internal, buffer, allocation.0);
475 }
476
477 /// Destroys Vulkan image and frees allocated memory.
478 ///
479 /// This is just a convenience function equivalent to:
480 ///
481 /// ```ignore
482 /// ash::vk::Device::destroy_image(image, None);
483 /// Allocator::free_memory(allocator, allocation);
484 /// ```
485 ///
486 /// It it safe to pass null as `image` and/or `allocation`.
487 pub unsafe fn destroy_image(&self, image: ash::vk::Image, allocation: &mut Allocation) {
488 ffi::vmaDestroyImage(self.internal, image, allocation.0);
489 }
490 /// Flushes memory of given set of allocations."]
491 ///
492 /// Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations."]
493 /// For more information, see documentation of vmaFlushAllocation()."]
494 ///
495 /// * `allocations`
496 /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero.
497 /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations.
498 pub unsafe fn flush_allocations<'a>(
499 &self,
500 allocations: impl IntoIterator<Item = &'a Allocation>,
501 offsets: Option<&[vk::DeviceSize]>,
502 sizes: Option<&[vk::DeviceSize]>,
503 ) -> VkResult<()> {
504 let allocations: Vec<ffi::VmaAllocation> = allocations.into_iter().map(|a| a.0).collect();
505 ffi::vmaFlushAllocations(
506 self.internal,
507 allocations.len() as u32,
508 allocations.as_ptr() as *mut _,
509 offsets.map_or(std::ptr::null(), |offsets| offsets.as_ptr()),
510 sizes.map_or(std::ptr::null(), |sizes| sizes.as_ptr()),
511 )
512 .result()
513 }
514
515 /// Invalidates memory of given set of allocations."]
516 ///
517 /// Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations."]
518 /// For more information, see documentation of vmaInvalidateAllocation()."]
519 ///
520 /// * `allocations`
521 /// * `offsets` - If not None, it must be a slice of offsets of regions to flush, relative to the beginning of respective allocations. None means all ofsets are zero.
522 /// * `sizes` - If not None, it must be a slice of sizes of regions to flush in respective allocations. None means `VK_WHOLE_SIZE` for all allocations.
523 pub unsafe fn invalidate_allocations<'a>(
524 &self,
525 allocations: impl IntoIterator<Item = &'a Allocation>,
526 offsets: Option<&[vk::DeviceSize]>,
527 sizes: Option<&[vk::DeviceSize]>,
528 ) -> VkResult<()> {
529 let allocations: Vec<ffi::VmaAllocation> = allocations.into_iter().map(|a| a.0).collect();
530 ffi::vmaInvalidateAllocations(
531 self.internal,
532 allocations.len() as u32,
533 allocations.as_ptr() as *mut _,
534 offsets.map_or(std::ptr::null(), |offsets| offsets.as_ptr()),
535 sizes.map_or(std::ptr::null(), |sizes| sizes.as_ptr()),
536 )
537 .result()
538 }
539}
540
541/// Custom `Drop` implementation to clean up internal allocation instance
542impl Drop for Allocator {
543 fn drop(&mut self) {
544 unsafe {
545 ffi::vmaDestroyAllocator(self.internal);
546 self.internal = std::ptr::null_mut();
547 }
548 }
549}