vk_mem/
definitions.rs

1use crate::ffi::{self};
2use ash::vk;
3use ash::vk::PhysicalDevice;
4use ash::{Device, Instance};
5use bitflags::bitflags;
6use std::marker::PhantomData;
7
8/// Intended usage of memory.
9#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
10pub enum MemoryUsage {
11    /// No intended memory usage specified.
12    /// Use other members of `AllocationCreateInfo` to specify your requirements.
13    Unknown,
14
15    /// Memory will be used on device only, so fast access from the device is preferred.
16    /// It usually means device-local GPU (video) memory.
17    /// No need to be mappable on host.
18    /// It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`.
19    ///
20    /// Usage:
21    ///
22    /// - Resources written and read by device, e.g. images used as attachments.
23    /// - Resources transferred from host once (immutable) or infrequently and read by
24    ///   device multiple times, e.g. textures to be sampled, vertex buffers, uniform
25    ///   (constant) buffers, and majority of other types of resources used on GPU.
26    ///
27    /// Allocation may still end up in `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` memory on some implementations.
28    /// In such case, you are free to map it.
29    /// You can use `AllocationCreateFlags::MAPPED` with this usage type.
30    #[deprecated(since = "0.3")]
31    GpuOnly,
32
33    /// Memory will be mappable on host.
34    /// It usually means CPU (system) memory.
35    /// Guarantees to be `ash::vk::MemoryPropertyFlags::HOST_VISIBLE` and `ash::vk::MemoryPropertyFlags::HOST_COHERENT`.
36    /// CPU access is typically uncached. Writes may be write-combined.
37    /// Resources created in this pool may still be accessible to the device, but access to them can be slow.
38    /// It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`.
39    ///
40    /// Usage: Staging copy of resources used as transfer source.
41    #[deprecated(since = "0.3")]
42    CpuOnly,
43
44    /// Memory that is both mappable on host (guarantees to be `ash::vk::MemoryPropertyFlags::HOST_VISIBLE`) and preferably fast to access by GPU.
45    /// CPU access is typically uncached. Writes may be write-combined.
46    ///
47    /// Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers,
48    /// uniform buffers updated every frame or every draw call.
49    #[deprecated(since = "0.3")]
50    CpuToGpu,
51
52    /// Memory mappable on host (guarantees to be `ash::vk::MemoryPropertFlags::HOST_VISIBLE`) and cached.
53    /// It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`.
54    ///
55    /// Usage:
56    ///
57    /// - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.
58    /// - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection.
59    #[deprecated(since = "0.3")]
60    GpuToCpu,
61
62    /// Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
63    #[deprecated(since = "0.3")]
64    CpuCopy,
65
66    /// Lazily allocated GPU memory having (guarantees to be `ash::vk::MemoryPropertFlags::LAZILY_ALLOCATED`).
67    /// Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.
68    ///
69    /// Usage:
70    ///
71    /// -  Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.
72    /// Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
73    GpuLazy,
74
75    /// Selects best memory type automatically.
76    /// This flag is recommended for most common use cases.
77    ///
78    /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
79    /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
80    /// in VmaAllocationCreateInfo::flags.
81    ///
82    /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
83    /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
84    /// and not with generic memory allocation functions.
85    Auto,
86
87    /// Selects best memory type automatically with preference for GPU (device) memory.
88    ///
89    /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
90    /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
91    /// in VmaAllocationCreateInfo::flags.
92    ///
93    /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
94    /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
95    /// and not with generic memory allocation functions.
96    AutoPreferDevice,
97
98    /// Selects best memory type automatically with preference for CPU (host) memory.
99    ///
100    /// When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
101    /// you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
102    /// in VmaAllocationCreateInfo::flags.
103    ///
104    /// It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
105    /// vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
106    /// and not with generic memory allocation functions.
107    AutoPreferHost,
108}
109
110bitflags! {
111    /// Flags for configuring `Allocator` construction.
112    pub struct AllocatorCreateFlags: u32 {
113        /// No allocator configuration other than defaults.
114        const NONE = 0;
115
116        /// Allocator and all objects created from it will not be synchronized internally,
117        /// so you must guarantee they are used from only one thread at a time or synchronized
118        /// externally by you. Using this flag may increase performance because internal
119        /// mutexes are not used.
120        const EXTERNALLY_SYNCHRONIZED = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT as u32;
121
122        /// Enables usage of `VK_KHR_dedicated_allocation` extension.
123        ///
124        /// Using this extenion will automatically allocate dedicated blocks of memory for
125        /// some buffers and images instead of suballocating place for them out of bigger
126        /// memory blocks (as if you explicitly used `AllocationCreateFlags::DEDICATED_MEMORY` flag) when it is
127        /// recommended by the driver. It may improve performance on some GPUs.
128        ///
129        /// You may set this flag only if you found out that following device extensions are
130        /// supported, you enabled them while creating Vulkan device passed as
131        /// `AllocatorCreateInfo::device`, and you want them to be used internally by this
132        /// library:
133        ///
134        /// - VK_KHR_get_memory_requirements2
135        /// - VK_KHR_dedicated_allocation
136        ///
137        /// When this flag is set, you can experience following warnings reported by Vulkan
138        /// validation layer. You can ignore them.
139        /// `> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.`
140        const KHR_DEDICATED_ALLOCATION = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT as u32;
141
142        /// Enables usage of VK_KHR_bind_memory2 extension.
143        ///
144        /// The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
145        /// When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
146        ///
147        /// You may set this flag only if you found out that this device extension is supported,
148        /// you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
149        /// and you want it to be used internally by this library.
150        ///
151        /// The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,
152        /// which allow to pass a chain of `pNext` structures while binding.
153        /// This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2().
154        const KHR_BIND_MEMORY2 = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT as u32;
155
156        /// Enables usage of VK_EXT_memory_budget extension.
157        ///
158        /// You may set this flag only if you found out that this device extension is supported,
159        /// you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
160        /// and you want it to be used internally by this library, along with another instance extension
161        /// VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).
162        ///
163        /// The extension provides query for current memory usage and budget, which will probably
164        /// be more accurate than an estimation used by the library otherwise.
165        const EXT_MEMORY_BUDGET = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT as u32;
166
167        /// Enables usage of VK_AMD_device_coherent_memory extension.
168        ///
169        /// You may set this flag only if you:
170        ///
171        /// - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
172        /// - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,
173        /// - want it to be used internally by this library.
174        ///
175        /// The extension and accompanying device feature provide access to memory types with
176        /// `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags.
177        /// They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR.
178        ///
179        /// When the extension is not enabled, such memory types are still enumerated, but their usage is illegal.
180        /// To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type,
181        /// returning `VK_ERROR_FEATURE_NOT_PRESENT`.
182        const AMD_DEVICE_COHERENT_MEMORY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT as u32;
183
184        /// You may set this flag only if you:
185        ///
186        /// 1. (For Vulkan version < 1.2) Found as available and enabled device extension
187        /// VK_KHR_buffer_device_address.
188        /// This extension is promoted to core Vulkan 1.2.
189        /// 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`.
190        ///
191        /// When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA.
192        /// The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to
193        /// allocated memory blocks wherever it might be needed.
194        ///
195        /// For more information, see documentation chapter \ref enabling_buffer_device_address.
196        const BUFFER_DEVICE_ADDRESS = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT as u32;
197
198        /// Enables usage of VK_EXT_memory_priority extension in the library.
199        ///
200        /// You may set this flag only if you found available and enabled this device extension,
201        /// along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,
202        /// while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
203        ///
204        /// When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority
205        /// are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored.
206        ///
207        /// A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
208        /// Larger values are higher priority. The granularity of the priorities is implementation-dependent.
209        /// It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`.
210        /// The value to be used for default priority is 0.5.
211        /// For more details, see the documentation of the VK_EXT_memory_priority extension.
212        const EXT_MEMORY_PRIORITY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT as u32;
213
214        /// Enables usage of VK_KHR_maintenance4 extension in the library.
215        ///
216        /// You may set this flag only if you found available and enabled this device extension,
217        /// while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
218        const KHR_MAINTENANCE4 = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT as u32;
219        /// Enables usage of VK_KHR_maintenance5 extension in the library.
220        ///
221        /// You may set this flag only if you found available and enabled this device extension,
222        /// while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
223        const KHR_MAINTENANCE5 = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT as u32;
224    }
225}
226
227bitflags! {
228    /// Flags for configuring `Allocation` construction.
229    #[derive(Clone, Copy)]
230    pub struct AllocationCreateFlags: u32 {
231        /// Set this flag if the allocation should have its own memory block.
232        ///
233        /// Use it for special, big resources, like fullscreen images used as attachments.
234        const DEDICATED_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT as u32;
235
236        /// Set this flag to only try to allocate from existing `ash::vk::DeviceMemory` blocks and never create new such block.
237        ///
238        /// If new allocation cannot be placed in any of the existing blocks, allocation
239        /// fails with `ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY` error.
240        ///
241        /// You should not use `AllocationCreateFlags::DEDICATED_MEMORY` and `AllocationCreateFlags::NEVER_ALLOCATE` at the same time. It makes no sense.
242        const NEVER_ALLOCATE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT as u32;
243
244        /// Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
245        ///
246        /// Pointer to mapped memory will be returned through `Allocation::get_mapped_data()`.
247        ///
248        /// Is it valid to use this flag for allocation made from memory type that is not
249        /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
250        /// useful if you need an allocation that is efficient to use on GPU
251        /// (`ash::vk::MemoryPropertyFlags::DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
252        /// support it (e.g. Intel GPU).
253        ///
254        /// You should not use this flag together with `AllocationCreateFlags::CAN_BECOME_LOST`.
255        const MAPPED = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT as u32;
256
257        /// Set this flag to treat `AllocationCreateInfo::user_data` as pointer to a
258        /// null-terminated string. Instead of copying pointer value, a local copy of the
259        /// string is made and stored in allocation's user data. The string is automatically
260        /// freed together with the allocation. It is also used in `Allocator::build_stats_string`.
261        #[deprecated(since = "0.3", note = "Consider using vmaSetAllocationName() instead.")]
262        const USER_DATA_COPY_STRING = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT as u32;
263
264        /// Allocation will be created from upper stack in a double stack pool.
265        ///
266        /// This flag is only allowed for custom pools created with `AllocatorPoolCreateFlags::LINEAR_ALGORITHM` flag.
267        const UPPER_ADDRESS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as u32;
268
269        /// Create both buffer/image and allocation, but don't bind them together.
270        /// It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
271        /// The flag is meaningful only with functions that bind by default, such as `Allocator::create_buffer`
272        /// or `Allocator::create_image`. Otherwise it is ignored.
273        ///
274        /// If you want to make sure the new buffer/image is not tied to the new memory allocation
275        /// through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block,
276        /// use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT.
277        const DONT_BIND = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DONT_BIND_BIT as u32;
278
279        /// Create allocation only if additional device memory required for it, if any, won't exceed
280        /// memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
281        const WITHIN_BUDGET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT as u32;
282
283        /// Set this flag if the allocated memory will have aliasing resources.
284        ///
285        /// Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
286        /// Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
287        const CAN_ALIAS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT as u32;
288
289        /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
290        ///
291        /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
292        /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
293        /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
294        /// This includes allocations created in custom_memory_pools.
295        ///
296        /// Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number,
297        /// never read or accessed randomly, so a memory type can be selected that is uncached and write-combined.
298        ///
299        /// Violating this declaration may work correctly, but will likely be very slow.
300        /// Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;`
301        /// Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once.
302        const HOST_ACCESS_SEQUENTIAL_WRITE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT as u32;
303
304        /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
305        ///
306        /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
307        /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
308        /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
309        /// This includes allocations created in custom_memory_pools.
310        ///
311        /// Declares that mapped memory can be read, written, and accessed in random order,
312        /// so a `HOST_CACHED` memory type is required.
313        const HOST_ACCESS_RANDOM = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT as u32;
314
315        /// Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
316        /// it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected
317        /// if it may improve performance.
318        ///
319        /// By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type
320        /// (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and
321        /// issue an explicit transfer to write/read your data.
322        /// To prepare for this possibility, don't forget to add appropriate flags like
323        /// `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image.
324        const HOST_ACCESS_ALLOW_TRANSFER_INSTEAD = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT as u32;
325
326        /// Allocation strategy that chooses smallest possible free range for the allocation
327        /// to minimize memory usage and fragmentation, possibly at the expense of allocation time.
328        const STRATEGY_MIN_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32;
329
330        /// Alias to `STRATEGY_MIN_MEMORY`.
331        const STRATEGY_BEST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32;
332
333        /// Allocation strategy that chooses first suitable free range for the allocation -
334        /// not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
335        /// to minimize allocation time, possibly at the expense of allocation quality.
336        const STRATEGY_MIN_TIME = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32;
337
338        /// Alias to `STRATEGY_MIN_TIME`.
339        const STRATEGY_FIRST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32;
340
341        /// Allocation strategy that chooses always the lowest offset in available space.
342        /// This is not the most efficient strategy but achieves highly packed data.
343        /// Used internally by defragmentation, not recomended in typical usage.
344        const STRATEGY_MIN_OFFSET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as u32;
345    }
346}
347
348bitflags! {
349    /// Flags for configuring `AllocatorPool` construction.
350    #[derive(Default, Clone, Copy)]
351    pub struct AllocatorPoolCreateFlags: u32 {
352        /// Use this flag if you always allocate only buffers and linear images or only optimal images
353        /// out of this pool and so buffer-image granularity can be ignored.
354        ///
355        /// This is an optional optimization flag.
356        ///
357        /// If you always allocate using `Allocator::create_buffer`, `Allocator::create_image`,
358        /// `Allocator::allocate_memory_for_buffer`, then you don't need to use it because allocator
359        /// knows exact type of your allocations so it can handle buffer-image granularity
360        /// in the optimal way.
361        ///
362        /// If you also allocate using `Allocator::allocate_memory_for_image` or `Allocator::allocate_memory`,
363        /// exact type of such allocations is not known, so allocator must be conservative
364        /// in handling buffer-image granularity, which can lead to suboptimal allocation
365        /// (wasted memory). In that case, if you can make sure you always allocate only
366        /// buffers and linear images or only optimal images out of this pool, use this flag
367        /// to make allocator disregard buffer-image granularity and so make allocations
368        /// faster and more optimal.
369        const IGNORE_BUFFER_IMAGE_GRANULARITY = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT as u32;
370
371        /// Enables alternative, linear allocation algorithm in this pool.
372        ///
373        /// Specify this flag to enable linear allocation algorithm, which always creates
374        /// new allocations after last one and doesn't reuse space from allocations freed in
375        /// between. It trades memory consumption for simplified algorithm and data
376        /// structure, which has better performance and uses less memory for metadata.
377        ///
378        /// By using this flag, you can achieve behavior of free-at-once, stack,
379        /// ring buffer, and double stack.
380        ///
381        /// When using this flag, you must specify PoolCreateInfo::max_block_count == 1 (or 0 for default).
382        const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT as u32;
383
384        /// Bit mask to extract only `*_ALGORITHM` bits from entire set of flags.
385        const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_ALGORITHM_MASK as u32;
386    }
387}
388
389pub struct AllocatorCreateInfo<'a> {
390    /// Vulkan physical device. It must be valid throughout whole lifetime of created allocator.
391    pub(crate) physical_device: PhysicalDevice,
392
393    /// Vulkan device.
394    /// It must be valid throughout the whole lifetime of created allocator.
395    pub(crate) device: &'a Device,
396
397    /// Handle to Vulkan instance object.
398    /// Must be valid throughout the whole lifetime of created allocator.
399    pub(crate) instance: &'a Instance,
400
401    /// Flags for created allocator.
402    pub flags: AllocatorCreateFlags,
403
404    /// Preferred size of a single [`vk::DeviceMemory`] block to be allocated from large heaps > 1 GiB. Optional.
405    /// Set to 0 to use default, which is currently 256 MiB.
406    pub preferred_large_heap_block_size: vk::DeviceSize,
407
408    /// Custom CPU memory allocation callbacks. Optional.
409    /// When specified, will also be used for all CPU-side memory allocations.
410    pub allocation_callbacks: Option<&'a vk::AllocationCallbacks<'a>>,
411
412    /// Informative callbacks for [`vk::AllocateMemory`], [`vk::FreeMemory`]. Optional.
413    pub device_memory_callbacks: Option<&'a ffi::VmaDeviceMemoryCallbacks>,
414
415    /// An empty array, or an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
416    /// When it is not empty, it must be an array of [`vk::PhysicalDeviceMemoryProperties::memoryHeapCount`] elements, defining limit on
417    /// maximum number of bytes that can be allocated out of particular Vulkan memory
418    /// heap.
419    ///
420    /// Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that
421    /// heap. This is also the default in case of `pHeapSizeLimit` = NULL.
422    ///
423    /// If there is a limit defined for a heap:
424    /// - If user tries to allocate more memory from that heap using this allocator,
425    ///   the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
426    /// - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the
427    ///   value of this limit will be reported instead when using vmaGetMemoryProperties().
428    ///
429    /// Warning! Using this feature may not be equivalent to installing a GPU with
430    /// smaller amount of memory, because graphics driver doesn't necessary fail new
431    /// allocations with [`VK_ERROR_OUT_OF_DEVICE_MEMORY`] result when memory capacity is
432    /// exceeded. It may return success and just silently migrate some device memory
433    /// blocks to system RAM. This driver behavior can also be controlled using
434    /// VK_AMD_memory_overallocation_behavior extension.
435    pub heap_size_limits: &'a [ash::vk::DeviceSize],
436    /// Optional. Vulkan version that the application uses.
437    /// It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like:
438    /// `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
439    /// The patch version number specified is ignored. Only the major and minor versions are considered.
440    /// Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation.
441    /// Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
442    /// It must match the Vulkan version used by the application and supported on the selected physical device,
443    /// so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance`
444    /// and no higher than `VkPhysicalDeviceProperties::apiVersion` found on the physical device used.
445    pub vulkan_api_version: u32,
446    /// Either an empty array or an array of external memory handle types for each Vulkan memory type.
447    /// If not empty, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount`
448    /// elements, defining external memory handle types of particular Vulkan memory type,
449    /// to be passed using `VkExportMemoryAllocateInfoKHR`.
450    ///
451    /// Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type.
452    /// This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL.
453    pub type_external_memory_handle_types: &'a [vk::ExternalMemoryHandleTypeFlagsKHR],
454}
455
456impl<'a> AllocatorCreateInfo<'a> {
457    pub fn new(
458        instance: &'a ash::Instance,
459        device: &'a ash::Device,
460        physical_device: ash::vk::PhysicalDevice,
461    ) -> AllocatorCreateInfo<'a> {
462        AllocatorCreateInfo {
463            physical_device,
464            device,
465            instance,
466            flags: AllocatorCreateFlags::empty(),
467            preferred_large_heap_block_size: 0,
468            allocation_callbacks: None,
469            device_memory_callbacks: None,
470            heap_size_limits: &[],
471            vulkan_api_version: 0,
472            type_external_memory_handle_types: &[],
473        }
474    }
475}
476
477#[derive(Clone)]
478pub struct PoolCreateInfo<'a> {
479    ///  Vulkan memory type index to allocate this pool from.
480    pub memory_type_index: u32,
481    pub flags: AllocatorPoolCreateFlags,
482    /// Size of a single [`vk::DeviceMemory`] block to be allocated as part of this pool, in bytes. Optional.
483    /// Specify nonzero to set explicit, constant size of memory blocks used by this pool.
484    /// Leave 0 to use default and let the library manage block sizes automatically.
485    /// Sizes of particular blocks may vary.
486    /// In this case, the pool will also support dedicated allocations.
487    pub block_size: vk::DeviceSize,
488    /// Minimum number of blocks to be always allocated in this pool, even if they stay empty.
489    /// Set to 0 to have no preallocated blocks and allow the pool be completely empty.
490    pub min_block_count: usize,
491    /// Maximum number of blocks that can be allocated in this pool. Optional.
492    /// Set to 0 to use default, which is [`usize::MAX`], which means no limit.
493    /// Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
494    /// throughout whole lifetime of this pool.
495    pub max_block_count: usize,
496    /// A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations.
497    /// It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object.
498    /// Otherwise, this variable is ignored.
499    pub priority: f32,
500    /// Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
501    /// Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
502    /// It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,
503    /// e.g. when doing interop with OpenGL.
504    pub min_allocation_alignment: vk::DeviceSize,
505    /// Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional.
506    /// If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`.
507    /// It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`.
508    /// Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool.
509    /// Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,
510    /// can be attached automatically by this library when using other, more convenient of its features.
511    pub memory_allocate_next: *const std::ffi::c_void,
512    pub _marker: PhantomData<&'a mut ()>,
513}
514impl<'a> PoolCreateInfo<'a> {
515    pub fn push_next<T: vk::ExtendsMemoryAllocateInfo>(&mut self, next: &'a mut T) {
516        let info = vk::MemoryAllocateInfo {
517            p_next: self.memory_allocate_next,
518            ..Default::default()
519        };
520        let info = info.push_next(next);
521        self.memory_allocate_next = info.p_next;
522    }
523}
524impl Default for PoolCreateInfo<'_> {
525    fn default() -> Self {
526        Self {
527            memory_type_index: 0,
528            flags: AllocatorPoolCreateFlags::empty(),
529            block_size: 0,
530            min_block_count: 0,
531            max_block_count: 0,
532            priority: 0.0,
533            min_allocation_alignment: 0,
534            memory_allocate_next: std::ptr::null_mut(),
535            _marker: PhantomData,
536        }
537    }
538}
539
540#[derive(Clone)]
541pub struct AllocationCreateInfo {
542    pub flags: AllocationCreateFlags,
543    /// Intended usage of memory.
544    ///
545    /// You can leave `MemoryUsage::Unknown` if you specify memory requirements in other way.
546    ///
547    /// If `pool` is not null, this member is ignored.
548    pub usage: MemoryUsage,
549    /// Flags that must be set in a Memory Type chosen for an allocation.
550    ///
551    /// Leave 0 if you specify memory requirements in other way.
552    ///
553    /// If `pool` is not null, this member is ignored.
554    pub required_flags: vk::MemoryPropertyFlags,
555    /// Flags that preferably should be set in a memory type chosen for an allocation."]
556    ///
557    /// Set to 0 if no additional flags are preferred.
558    /// If `pool` is not null, this member is ignored.
559    pub preferred_flags: vk::MemoryPropertyFlags,
560    /// Bitmask containing one bit set for every memory type acceptable for this allocation.
561    ///
562    /// Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
563    /// it meets other requirements specified by this structure, with no further
564    /// restrictions on memory type index.
565    ///
566    /// If `pool` is not null, this member is ignored.
567    pub memory_type_bits: u32,
568    /// Custom general-purpose pointer that will be stored in `Allocation`,
569    /// can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
570    ///
571    /// If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
572    /// null or pointer to a null-terminated string. The string will be then copied to
573    /// internal buffer, so it doesn't need to be valid after allocation call.
574    pub user_data: usize,
575    /// A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
576    ///
577    /// It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object
578    /// and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
579    /// Otherwise, it has the priority of a memory block where it is placed and this variable is ignored.
580    pub priority: f32,
581}
582
583impl Default for AllocationCreateInfo {
584    fn default() -> Self {
585        Self {
586            flags: AllocationCreateFlags::empty(),
587            usage: MemoryUsage::Unknown,
588            required_flags: vk::MemoryPropertyFlags::empty(),
589            preferred_flags: vk::MemoryPropertyFlags::empty(),
590            memory_type_bits: 0,
591            user_data: 0,
592            priority: 0.0,
593        }
594    }
595}
596
597impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo {
598    fn from(info: &AllocationCreateInfo) -> Self {
599        let usage = match info.usage {
600            MemoryUsage::Unknown => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN,
601            #[allow(deprecated)]
602            MemoryUsage::GpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_ONLY,
603            #[allow(deprecated)]
604            MemoryUsage::CpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_ONLY,
605            #[allow(deprecated)]
606            MemoryUsage::CpuToGpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU,
607            #[allow(deprecated)]
608            MemoryUsage::GpuToCpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_TO_CPU,
609            #[allow(deprecated)]
610            MemoryUsage::CpuCopy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_COPY,
611            MemoryUsage::GpuLazy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED,
612            MemoryUsage::Auto => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
613            MemoryUsage::AutoPreferDevice => {
614                ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE
615            }
616            MemoryUsage::AutoPreferHost => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
617        };
618        ffi::VmaAllocationCreateInfo {
619            flags: info.flags.bits(),
620            usage,
621            requiredFlags: info.required_flags,
622            preferredFlags: info.preferred_flags,
623            memoryTypeBits: info.memory_type_bits,
624            pool: std::ptr::null_mut(),
625            pUserData: info.user_data as _,
626            priority: info.priority,
627        }
628    }
629}
630
631/// Parameters of `Allocation` objects, that can be retrieved using `Allocator::get_allocation_info`.
632#[derive(Debug, Clone)]
633pub struct AllocationInfo {
634    /// Memory type index that this allocation was allocated from. It never changes.
635    pub memory_type: u32,
636    /// Handle to Vulkan memory object.
637    ///
638    /// Same memory object can be shared by multiple allocations.
639    ///
640    /// It can change after the allocation is moved during \\ref defragmentation.
641    pub device_memory: vk::DeviceMemory,
642    /// Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation.
643    ///
644    /// You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function
645    /// vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,
646    /// not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation
647    /// and apply this offset automatically.
648    ///
649    /// It can change after the allocation is moved during \\ref defragmentation.
650    pub offset: vk::DeviceSize,
651    /// Size of this allocation, in bytes. It never changes.
652    ///
653    /// Allocation size returned in this variable may be greater than the size
654    /// requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the
655    /// allocation is accessible for operations on memory e.g. using a pointer after
656    /// mapping with vmaMapMemory(), but operations on the resource e.g. using
657    /// `vkCmdCopyBuffer` must be limited to the size of the resource.
658    pub size: vk::DeviceSize,
659    /// Pointer to the beginning of this allocation as mapped data.
660    ///
661    /// If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
662    /// created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null.
663    ///
664    /// It can change after call to vmaMapMemory(), vmaUnmapMemory().
665    /// It can also change after the allocation is moved during defragmentation.
666    pub mapped_data: *mut ::std::os::raw::c_void,
667    /// Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
668    ///
669    /// It can change after call to vmaSetAllocationUserData() for this allocation.
670    pub user_data: usize,
671}
672
673impl From<&ffi::VmaAllocationInfo> for AllocationInfo {
674    fn from(info: &ffi::VmaAllocationInfo) -> Self {
675        Self {
676            memory_type: info.memoryType,
677            device_memory: info.deviceMemory,
678            offset: info.offset,
679            size: info.size,
680            mapped_data: info.pMappedData,
681            user_data: info.pUserData as _,
682        }
683    }
684}
685impl From<ffi::VmaAllocationInfo> for AllocationInfo {
686    fn from(info: ffi::VmaAllocationInfo) -> Self {
687        (&info).into()
688    }
689}
690
691/// Extended parameters of a VmaAllocation object that can be retrieved using `Allocation::get_allocation_info2`.
692#[derive(Debug, Clone)]
693pub struct AllocationInfo2 {
694    /// Basic parameters of the allocation.
695    ///
696    /// If you need only these, you can use function vmaGetAllocationInfo() and structure #VmaAllocationInfo instead.
697    pub allocation_info: AllocationInfo,
698    /// Size of the `VkDeviceMemory` block that the allocation belongs to.
699    ///
700    /// In case of an allocation with dedicated memory, it will be equal to `allocationInfo.size`.
701    pub block_size: u64,
702    /// `true` if the allocation has dedicated memory, `false` if it was placed as part of a larger memory block.
703    ///
704    /// When `true`, it also means `VkMemoryDedicatedAllocateInfo` was used when creating the allocation
705    /// (if VK_KHR_dedicated_allocation extension or Vulkan version >= 1.1 is enabled).
706    pub dedicated_memory: bool,
707}
708
709impl From<&ffi::VmaAllocationInfo2> for AllocationInfo2 {
710    fn from(info: &ffi::VmaAllocationInfo2) -> Self {
711        Self {
712            allocation_info: info.allocationInfo.into(),
713            block_size: info.blockSize,
714            dedicated_memory: info.dedicatedMemory != 0,
715        }
716    }
717}
718impl From<ffi::VmaAllocationInfo2> for AllocationInfo2 {
719    fn from(info: ffi::VmaAllocationInfo2) -> Self {
720        (&info).into()
721    }
722}
723
724bitflags! {
725    /// Flags for configuring `VirtualBlock` construction
726    #[derive(Default)]
727    pub struct VirtualBlockCreateFlags: u32 {
728        /// Enables alternative, linear allocation algorithm in this pool.
729        ///
730        /// Specify this flag to enable linear allocation algorithm, which always creates
731        /// new allocations after last one and doesn't reuse space from allocations freed in
732        /// between. It trades memory consumption for simplified algorithm and data
733        /// structure, which has better performance and uses less memory for metadata.
734        ///
735        /// By using this flag, you can achieve behavior of free-at-once, stack,
736        /// ring buffer, and double stack.
737        const VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = ffi::VmaVirtualBlockCreateFlagBits::VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT as u32;
738    }
739}
740
741bitflags! {
742    /// Flags for configuring `VirtualBlock` construction
743    #[derive(Clone, Copy, Debug)]
744    pub struct VirtualAllocationCreateFlags: u32 {
745        /// Allocation will be created from upper stack in a double stack pool.
746        ///
747        /// This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag.
748        const VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = ffi::VmaVirtualAllocationCreateFlagBits::VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as u32;
749        /// Allocation strategy that tries to minimize memory usage.
750        const VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = ffi::VmaVirtualAllocationCreateFlagBits::VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32;
751        /// Allocation strategy that tries to minimize allocation time.
752        const VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = ffi::VmaVirtualAllocationCreateFlagBits::VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32;
753        /// Allocation strategy that chooses always the lowest offset in available space.
754        /// This is not the most efficient strategy but achieves highly packed data.
755        const VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = ffi::VmaVirtualAllocationCreateFlagBits::VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as u32;
756        /// A bit mask to extract only `STRATEGY` bits from entire set of flags.
757        ///
758        /// These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits.
759        const VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = ffi::VmaVirtualAllocationCreateFlagBits::VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK as u32;
760    }
761}
762
763#[derive(Debug, Clone, Copy)]
764pub struct VirtualAllocationCreateInfo {
765    /// Size of the allocation.
766    ///
767    /// Cannot be zero.
768    pub size: u64,
769    /// Required alignment of the allocation. Optional.
770    ///
771    /// Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset.
772    pub alignment: u64,
773    /// Custom pointer to be associated with the allocation. Optional.
774    ///
775    /// It can be any value and can be used for user-defined purposes. It can be fetched or changed later.
776    pub user_data: usize,
777    /// Flags to configure allocation behavior for this allocation
778    pub flags: VirtualAllocationCreateFlags,
779}
780
781/// Parameters of created VirtualBlock, to be passed to VirtualBlock::new()
782#[derive(Default)]
783pub struct VirtualBlockCreateInfo<'a> {
784    /// Total size of the virtual block.
785    ///
786    /// Sizes can be expressed in bytes or any units you want as long as you are consistent in using them.
787    /// For example, if you allocate from some array of structures, 1 can mean single instance of entire structure.
788    pub size: vk::DeviceSize,
789
790    pub flags: VirtualBlockCreateFlags,
791    /// Custom CPU memory allocation callbacks. Optional.
792    /// When specified, they will be used for all CPU-side memory allocations.
793    pub allocation_callbacks: Option<&'a vk::AllocationCallbacks<'a>>,
794}
795
796/// Parameters of `VirtualAllocation` objects, that can be retrieved using `VirtualBlock::get_allocation_info`.
797#[derive(Debug, Clone, Copy)]
798pub struct VirtualAllocationInfo {
799    /// Offset of the allocation.
800    ///
801    /// Offset at which the allocation was made.
802    pub offset: vk::DeviceSize,
803    /// Size of the allocation.
804    ///
805    /// Same value as passed in VirtualAllocationCreateInfo::size.
806    pub size: vk::DeviceSize,
807    /// Custom pointer associated with the allocation
808    ///
809    /// It can change after call to vmaSetAllocationUserData() for this allocation.
810    pub user_data: usize,
811}
812
813impl From<&ffi::VmaVirtualAllocationInfo> for VirtualAllocationInfo {
814    fn from(info: &ffi::VmaVirtualAllocationInfo) -> Self {
815        Self {
816            offset: info.offset,
817            size: info.size,
818            user_data: info.pUserData as _,
819        }
820    }
821}
822impl From<ffi::VmaVirtualAllocationInfo> for VirtualAllocationInfo {
823    fn from(info: ffi::VmaVirtualAllocationInfo) -> Self {
824        (&info).into()
825    }
826}
827
828impl From<&VirtualAllocationCreateInfo> for ffi::VmaVirtualAllocationCreateInfo {
829    fn from(info: &VirtualAllocationCreateInfo) -> Self {
830        ffi::VmaVirtualAllocationCreateInfo {
831            size: info.size,
832            alignment: info.alignment,
833            flags: info.flags.bits(),
834            pUserData: info.user_data as _,
835        }
836    }
837}
838
839impl From<VirtualAllocationCreateInfo> for ffi::VmaVirtualAllocationCreateInfo {
840    fn from(info: VirtualAllocationCreateInfo) -> Self {
841        (&info).into()
842    }
843}