bort_vma/
definitions.rs

1use crate::ffi;
2use ash::vk;
3use ash::vk::PhysicalDevice;
4use ash::{Device, Instance};
5use bitflags::bitflags;
6use std::ptr;
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    #[derive(Clone, Copy)]
113    pub struct AllocatorCreateFlags: u32 {
114        /// No allocator configuration other than defaults.
115        const NONE = 0;
116
117        /// Allocator and all objects created from it will not be synchronized internally,
118        /// so you must guarantee they are used from only one thread at a time or synchronized
119        /// externally by you. Using this flag may increase performance because internal
120        /// mutexes are not used.
121        const EXTERNALLY_SYNCHRONIZED = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT as u32;
122
123        /// Enables usage of `VK_KHR_dedicated_allocation` extension.
124        ///
125        /// Using this extenion will automatically allocate dedicated blocks of memory for
126        /// some buffers and images instead of suballocating place for them out of bigger
127        /// memory blocks (as if you explicitly used `AllocationCreateFlags::DEDICATED_MEMORY` flag) when it is
128        /// recommended by the driver. It may improve performance on some GPUs.
129        ///
130        /// You may set this flag only if you found out that following device extensions are
131        /// supported, you enabled them while creating Vulkan device passed as
132        /// `AllocatorCreateInfo::device`, and you want them to be used internally by this
133        /// library:
134        ///
135        /// - VK_KHR_get_memory_requirements2
136        /// - VK_KHR_dedicated_allocation
137        ///
138        /// When this flag is set, you can experience following warnings reported by Vulkan
139        /// validation layer. You can ignore them.
140        /// `> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.`
141        const KHR_DEDICATED_ALLOCATION = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT as u32;
142
143        /// Enables usage of VK_KHR_bind_memory2 extension.
144        ///
145        /// The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
146        /// When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
147        ///
148        /// You may set this flag only if you found out that this device extension is supported,
149        /// you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
150        /// and you want it to be used internally by this library.
151        ///
152        /// The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,
153        /// which allow to pass a chain of `pNext` structures while binding.
154        /// This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2().
155        const KHR_BIND_MEMORY2 = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT as u32;
156
157        /// Enables usage of VK_EXT_memory_budget extension.
158        ///
159        /// You may set this flag only if you found out that this device extension is supported,
160        /// you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
161        /// and you want it to be used internally by this library, along with another instance extension
162        /// VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).
163        ///
164        /// The extension provides query for current memory usage and budget, which will probably
165        /// be more accurate than an estimation used by the library otherwise.
166        const EXT_MEMORY_BUDGET = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT as u32;
167
168        /// Enables usage of VK_AMD_device_coherent_memory extension.
169        ///
170        /// You may set this flag only if you:
171        ///
172        /// - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
173        /// - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,
174        /// - want it to be used internally by this library.
175        ///
176        /// The extension and accompanying device feature provide access to memory types with
177        /// `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags.
178        /// They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR.
179        ///
180        /// When the extension is not enabled, such memory types are still enumerated, but their usage is illegal.
181        /// 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,
182        /// returning `VK_ERROR_FEATURE_NOT_PRESENT`.
183        const AMD_DEVICE_COHERENT_MEMORY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT as u32;
184
185        /// You may set this flag only if you:
186        ///
187        /// 1. (For Vulkan version < 1.2) Found as available and enabled device extension
188        /// VK_KHR_buffer_device_address.
189        /// This extension is promoted to core Vulkan 1.2.
190        /// 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`.
191        ///
192        /// When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA.
193        /// The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to
194        /// allocated memory blocks wherever it might be needed.
195        ///
196        /// For more information, see documentation chapter \ref enabling_buffer_device_address.
197        const BUFFER_DEVICE_ADDRESS = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT as u32;
198
199        /// Enables usage of VK_EXT_memory_priority extension in the library.
200        ///
201        /// You may set this flag only if you found available and enabled this device extension,
202        /// along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,
203        /// while creating Vulkan device passed as VmaAllocatorCreateInfo::device.
204        ///
205        /// When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority
206        /// are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored.
207        ///
208        /// A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
209        /// Larger values are higher priority. The granularity of the priorities is implementation-dependent.
210        /// It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`.
211        /// The value to be used for default priority is 0.5.
212        /// For more details, see the documentation of the VK_EXT_memory_priority extension.
213        const EXT_MEMORY_PRIORITY = ffi::VmaAllocatorCreateFlagBits::VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT as u32;
214
215    }
216}
217
218bitflags! {
219    /// Flags for configuring `Allocation` construction.
220    #[derive(Clone, Copy)]
221    pub struct AllocationCreateFlags: u32 {
222        /// Set this flag if the allocation should have its own memory block.
223        ///
224        /// Use it for special, big resources, like fullscreen images used as attachments.
225        const DEDICATED_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT as u32;
226
227        /// Set this flag to only try to allocate from existing `ash::vk::DeviceMemory` blocks and never create new such block.
228        ///
229        /// If new allocation cannot be placed in any of the existing blocks, allocation
230        /// fails with `ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY` error.
231        ///
232        /// You should not use `AllocationCreateFlags::DEDICATED_MEMORY` and `AllocationCreateFlags::NEVER_ALLOCATE` at the same time. It makes no sense.
233        const NEVER_ALLOCATE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT as u32;
234
235        /// Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
236        ///
237        /// Pointer to mapped memory will be returned through `Allocation::get_mapped_data()`.
238        ///
239        /// Is it valid to use this flag for allocation made from memory type that is not
240        /// `ash::vk::MemoryPropertyFlags::HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
241        /// useful if you need an allocation that is efficient to use on GPU
242        /// (`ash::vk::MemoryPropertyFlags::DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
243        /// support it (e.g. Intel GPU).
244        ///
245        /// You should not use this flag together with `AllocationCreateFlags::CAN_BECOME_LOST`.
246        const MAPPED = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT as u32;
247
248        /// Set this flag to treat `AllocationCreateInfo::user_data` as pointer to a
249        /// null-terminated string. Instead of copying pointer value, a local copy of the
250        /// string is made and stored in allocation's user data. The string is automatically
251        /// freed together with the allocation. It is also used in `Allocator::build_stats_string`.
252        #[deprecated(since = "0.3", note = "Consider using vmaSetAllocationName() instead.")]
253        const USER_DATA_COPY_STRING = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT as u32;
254
255        /// Allocation will be created from upper stack in a double stack pool.
256        ///
257        /// This flag is only allowed for custom pools created with `AllocatorPoolCreateFlags::LINEAR_ALGORITHM` flag.
258        const UPPER_ADDRESS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT as u32;
259
260        /// Create both buffer/image and allocation, but don't bind them together.
261        /// It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
262        /// The flag is meaningful only with functions that bind by default, such as `Allocator::create_buffer`
263        /// or `Allocator::create_image`. Otherwise it is ignored.
264        ///
265        /// If you want to make sure the new buffer/image is not tied to the new memory allocation
266        /// through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block,
267        /// use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT.
268        const DONT_BIND = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DONT_BIND_BIT as u32;
269
270        /// Create allocation only if additional device memory required for it, if any, won't exceed
271        /// memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
272        const WITHIN_BUDGET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT as u32;
273
274        /// Set this flag if the allocated memory will have aliasing resources.
275        ///
276        /// Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
277        /// Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
278        const CAN_ALIAS = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT as u32;
279
280        /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
281        ///
282        /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
283        /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
284        /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
285        /// This includes allocations created in custom_memory_pools.
286        ///
287        /// Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number,
288        /// never read or accessed randomly, so a memory type can be selected that is uncached and write-combined.
289        ///
290        /// Violating this declaration may work correctly, but will likely be very slow.
291        /// Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;`
292        /// Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once.
293        const HOST_ACCESS_SEQUENTIAL_WRITE = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT as u32;
294
295        /// Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
296        ///
297        /// - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
298        /// you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
299        /// - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
300        /// This includes allocations created in custom_memory_pools.
301        ///
302        /// Declares that mapped memory can be read, written, and accessed in random order,
303        /// so a `HOST_CACHED` memory type is required.
304        const HOST_ACCESS_RANDOM = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT as u32;
305
306        /// Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
307        /// it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected
308        /// if it may improve performance.
309        ///
310        /// By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type
311        /// (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and
312        /// issue an explicit transfer to write/read your data.
313        /// To prepare for this possibility, don't forget to add appropriate flags like
314        /// `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image.
315        const HOST_ACCESS_ALLOW_TRANSFER_INSTEAD = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT as u32;
316
317        /// Allocation strategy that chooses smallest possible free range for the allocation
318        /// to minimize memory usage and fragmentation, possibly at the expense of allocation time.
319        const STRATEGY_MIN_MEMORY = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32;
320
321        /// Alias to `STRATEGY_MIN_MEMORY`.
322        const STRATEGY_BEST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as u32;
323
324        /// Allocation strategy that chooses first suitable free range for the allocation -
325        /// not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
326        /// to minimize allocation time, possibly at the expense of allocation quality.
327        const STRATEGY_MIN_TIME = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32;
328
329        /// Alias to `STRATEGY_MIN_TIME`.
330        const STRATEGY_FIRST_FIT = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT as u32;
331
332        /// Allocation strategy that chooses always the lowest offset in available space.
333        /// This is not the most efficient strategy but achieves highly packed data.
334        /// Used internally by defragmentation, not recomended in typical usage.
335        const STRATEGY_MIN_OFFSET = ffi::VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT as u32;
336    }
337}
338
339bitflags! {
340    /// Flags for configuring `AllocatorPool` construction.
341    #[derive(Clone, Copy)]
342    pub struct AllocatorPoolCreateFlags: u32 {
343        /// Use this flag if you always allocate only buffers and linear images or only optimal images
344        /// out of this pool and so buffer-image granularity can be ignored.
345        ///
346        /// This is an optional optimization flag.
347        ///
348        /// If you always allocate using `Allocator::create_buffer`, `Allocator::create_image`,
349        /// `Allocator::allocate_memory_for_buffer`, then you don't need to use it because allocator
350        /// knows exact type of your allocations so it can handle buffer-image granularity
351        /// in the optimal way.
352        ///
353        /// If you also allocate using `Allocator::allocate_memory_for_image` or `Allocator::allocate_memory`,
354        /// exact type of such allocations is not known, so allocator must be conservative
355        /// in handling buffer-image granularity, which can lead to suboptimal allocation
356        /// (wasted memory). In that case, if you can make sure you always allocate only
357        /// buffers and linear images or only optimal images out of this pool, use this flag
358        /// to make allocator disregard buffer-image granularity and so make allocations
359        /// faster and more optimal.
360        const IGNORE_BUFFER_IMAGE_GRANULARITY = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT as u32;
361
362        /// Enables alternative, linear allocation algorithm in this pool.
363        ///
364        /// Specify this flag to enable linear allocation algorithm, which always creates
365        /// new allocations after last one and doesn't reuse space from allocations freed in
366        /// between. It trades memory consumption for simplified algorithm and data
367        /// structure, which has better performance and uses less memory for metadata.
368        ///
369        /// By using this flag, you can achieve behavior of free-at-once, stack,
370        /// ring buffer, and double stack.
371        ///
372        /// When using this flag, you must specify PoolCreateInfo::max_block_count == 1 (or 0 for default).
373        const LINEAR_ALGORITHM = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT as u32;
374
375        /// Bit mask to extract only `*_ALGORITHM` bits from entire set of flags.
376        const ALGORITHM_MASK = ffi::VmaPoolCreateFlagBits::VMA_POOL_CREATE_ALGORITHM_MASK as u32;
377    }
378}
379
380pub struct AllocatorCreateInfo<'a> {
381    pub(crate) inner: ffi::VmaAllocatorCreateInfo,
382    pub(crate) physical_device: PhysicalDevice,
383    pub(crate) device: &'a Device,
384    pub(crate) instance: &'a Instance,
385}
386
387impl<'a> AllocatorCreateInfo<'a> {
388    pub fn new(
389        instance: &'a ash::Instance,
390        device: &'a ash::Device,
391        physical_device: ash::vk::PhysicalDevice,
392    ) -> AllocatorCreateInfo<'a> {
393        AllocatorCreateInfo {
394            inner: ffi::VmaAllocatorCreateInfo {
395                flags: 0,
396                physicalDevice: physical_device,
397                instance: instance.handle(),
398                device: device.handle(),
399                preferredLargeHeapBlockSize: 0,
400                pAllocationCallbacks: ptr::null(),
401                pDeviceMemoryCallbacks: ptr::null(),
402                pHeapSizeLimit: ptr::null(),
403                pVulkanFunctions: ptr::null(),
404                vulkanApiVersion: 0,
405                pTypeExternalMemoryHandleTypes: ptr::null(),
406            },
407            physical_device,
408            device,
409            instance,
410        }
411    }
412
413    pub fn preferred_large_heap_block_size(mut self, size: u64) -> Self {
414        self.inner.preferredLargeHeapBlockSize = size;
415        self
416    }
417
418    pub fn flags(mut self, flags: AllocatorCreateFlags) -> Self {
419        self.inner.flags = flags.bits();
420        self
421    }
422
423    pub fn heap_size_limit(mut self, device_sizes: &'a [ash::vk::DeviceSize]) -> Self {
424        unsafe {
425            debug_assert!(
426                self.instance
427                    .get_physical_device_memory_properties(self.physical_device)
428                    .memory_heap_count
429                    == device_sizes.len() as u32
430            );
431        }
432        self.inner.pHeapSizeLimit = device_sizes.as_ptr();
433        self
434    }
435
436    pub fn allocation_callback(mut self, allocation: &'a ash::vk::AllocationCallbacks) -> Self {
437        self.inner.pAllocationCallbacks = allocation as *const _;
438        self
439    }
440
441    pub fn vulkan_api_version(mut self, version: u32) -> Self {
442        self.inner.vulkanApiVersion = version;
443        self
444    }
445
446    pub fn external_memory_handles(
447        mut self,
448        external_memory_handles: &'a [ash::vk::ExternalMemoryHandleTypeFlagsKHR],
449    ) -> Self {
450        unsafe {
451            debug_assert!(
452                self.instance
453                    .get_physical_device_memory_properties(self.physical_device)
454                    .memory_type_count
455                    == external_memory_handles.len() as u32
456            );
457        }
458        self.inner.pTypeExternalMemoryHandleTypes = external_memory_handles.as_ptr();
459        self
460    }
461}
462
463pub struct PoolCreateInfo<'a> {
464    pub(crate) inner: ffi::VmaPoolCreateInfo,
465    marker: ::std::marker::PhantomData<&'a ()>,
466}
467
468impl<'a> PoolCreateInfo<'a> {
469    pub fn new() -> PoolCreateInfo<'a> {
470        PoolCreateInfo {
471            inner: ffi::VmaPoolCreateInfo {
472                memoryTypeIndex: 0,
473                flags: 0,
474                blockSize: 0,
475                minBlockCount: 0,
476                maxBlockCount: 0,
477                priority: 0.0,
478                minAllocationAlignment: 0,
479                pMemoryAllocateNext: ptr::null_mut(),
480            },
481            marker: ::std::marker::PhantomData,
482        }
483    }
484
485    pub fn memory_type_index(mut self, index: u32) -> Self {
486        self.inner.memoryTypeIndex = index;
487        self
488    }
489
490    pub fn flags(mut self, flags: AllocatorPoolCreateFlags) -> Self {
491        self.inner.flags = flags.bits();
492        self
493    }
494
495    pub fn block_size(mut self, block_size: u64) -> Self {
496        self.inner.blockSize = block_size;
497        self
498    }
499
500    pub fn min_block_count(mut self, min_block_count: usize) -> Self {
501        self.inner.minBlockCount = min_block_count;
502        self
503    }
504
505    pub fn max_block_count(mut self, max_block_count: usize) -> Self {
506        self.inner.maxBlockCount = max_block_count;
507        self
508    }
509
510    pub fn priority(mut self, priority: f32) -> Self {
511        self.inner.priority = priority;
512        self
513    }
514
515    pub fn min_allocation_alignment(mut self, alignment: u64) -> Self {
516        self.inner.minAllocationAlignment = alignment;
517        self
518    }
519
520    pub fn memory_allocate(mut self, next: &'a mut ash::vk::MemoryAllocateInfo) -> Self {
521        self.inner.pMemoryAllocateNext = next as *mut ash::vk::MemoryAllocateInfo as *mut _;
522        self
523    }
524
525    // Getters
526
527    pub fn get_memory_type_index(&self) -> u32 {
528        self.inner.memoryTypeIndex
529    }
530
531    pub fn get_flags(&self) -> AllocatorPoolCreateFlags {
532        AllocatorPoolCreateFlags::from_bits(self.inner.flags).expect(
533            "allocator pool create flags should only contain bits from `AllocatorPoolCreateFlags`!",
534        )
535    }
536
537    pub fn get_block_size(&self) -> u64 {
538        self.inner.blockSize
539    }
540
541    pub fn get_min_block_count(&self) -> usize {
542        self.inner.minBlockCount
543    }
544
545    pub fn get_max_block_count(&self) -> usize {
546        self.inner.maxBlockCount
547    }
548
549    pub fn get_priority(&self) -> f32 {
550        self.inner.priority
551    }
552
553    pub fn get_min_allocation_alignment(&self) -> u64 {
554        self.inner.minAllocationAlignment
555    }
556}
557
558#[derive(Clone)]
559pub struct AllocationCreateInfo {
560    pub flags: AllocationCreateFlags,
561    /// Intended usage of memory.
562    ///
563    /// You can leave `MemoryUsage::Unknown` if you specify memory requirements in other way.
564    ///
565    /// If `pool` is not null, this member is ignored.
566    pub usage: MemoryUsage,
567    /// Flags that must be set in a Memory Type chosen for an allocation.
568    ///
569    /// Leave 0 if you specify memory requirements in other way.
570    ///
571    /// If `pool` is not null, this member is ignored.
572    pub required_flags: vk::MemoryPropertyFlags,
573    /// Flags that preferably should be set in a memory type chosen for an allocation."]
574    ///
575    /// Set to 0 if no additional flags are preferred.
576    /// If `pool` is not null, this member is ignored.
577    pub preferred_flags: vk::MemoryPropertyFlags,
578    /// Bitmask containing one bit set for every memory type acceptable for this allocation.
579    ///
580    /// Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
581    /// it meets other requirements specified by this structure, with no further
582    /// restrictions on memory type index.
583    ///
584    /// If `pool` is not null, this member is ignored.
585    pub memory_type_bits: u32,
586    /// Custom general-purpose pointer that will be stored in `Allocation`,
587    /// can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
588    ///
589    /// If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
590    /// null or pointer to a null-terminated string. The string will be then copied to
591    /// internal buffer, so it doesn't need to be valid after allocation call.
592    pub user_data: usize,
593    /// A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
594    ///
595    /// It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object
596    /// and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
597    /// Otherwise, it has the priority of a memory block where it is placed and this variable is ignored.
598    pub priority: f32,
599}
600
601impl Default for AllocationCreateInfo {
602    fn default() -> Self {
603        Self {
604            flags: AllocationCreateFlags::empty(),
605            usage: MemoryUsage::Unknown,
606            required_flags: vk::MemoryPropertyFlags::empty(),
607            preferred_flags: vk::MemoryPropertyFlags::empty(),
608            memory_type_bits: 0,
609            user_data: 0,
610            priority: 0.0,
611        }
612    }
613}
614
615impl From<&AllocationCreateInfo> for ffi::VmaAllocationCreateInfo {
616    fn from(info: &AllocationCreateInfo) -> Self {
617        let usage = match info.usage {
618            MemoryUsage::Unknown => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_UNKNOWN,
619            #[allow(deprecated)]
620            MemoryUsage::GpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_ONLY,
621            #[allow(deprecated)]
622            MemoryUsage::CpuOnly => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_ONLY,
623            #[allow(deprecated)]
624            MemoryUsage::CpuToGpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU,
625            #[allow(deprecated)]
626            MemoryUsage::GpuToCpu => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_TO_CPU,
627            #[allow(deprecated)]
628            MemoryUsage::CpuCopy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_COPY,
629            MemoryUsage::GpuLazy => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED,
630            MemoryUsage::Auto => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
631            MemoryUsage::AutoPreferDevice => {
632                ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE
633            }
634            MemoryUsage::AutoPreferHost => ffi::VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
635        };
636        ffi::VmaAllocationCreateInfo {
637            flags: info.flags.bits(),
638            usage,
639            requiredFlags: info.required_flags,
640            preferredFlags: info.preferred_flags,
641            memoryTypeBits: info.memory_type_bits,
642            pool: std::ptr::null_mut(),
643            pUserData: info.user_data as _,
644            priority: info.priority,
645        }
646    }
647}
648
649/// Parameters of `Allocation` objects, that can be retrieved using `Allocator::get_allocation_info`.
650#[derive(Debug, Clone)]
651pub struct AllocationInfo {
652    /// Memory type index that this allocation was allocated from. It never changes.
653    pub memory_type: u32,
654    /// Handle to Vulkan memory object.
655    ///
656    /// Same memory object can be shared by multiple allocations.
657    ///
658    /// It can change after the allocation is moved during \\ref defragmentation.
659    pub device_memory: vk::DeviceMemory,
660    /// Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation.
661    ///
662    /// 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
663    /// vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,
664    /// not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation
665    /// and apply this offset automatically.
666    ///
667    /// It can change after the allocation is moved during \\ref defragmentation.
668    pub offset: vk::DeviceSize,
669    /// Size of this allocation, in bytes. It never changes.
670    ///
671    /// Allocation size returned in this variable may be greater than the size
672    /// requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the
673    /// allocation is accessible for operations on memory e.g. using a pointer after
674    /// mapping with vmaMapMemory(), but operations on the resource e.g. using
675    /// `vkCmdCopyBuffer` must be limited to the size of the resource.
676    pub size: vk::DeviceSize,
677    /// Pointer to the beginning of this allocation as mapped data.
678    ///
679    /// If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
680    /// created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null.
681    ///
682    /// It can change after call to vmaMapMemory(), vmaUnmapMemory().
683    /// It can also change after the allocation is moved during defragmentation.
684    pub mapped_data: *mut ::std::os::raw::c_void,
685    /// Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
686    ///
687    /// It can change after call to vmaSetAllocationUserData() for this allocation.
688    pub user_data: usize,
689}
690
691impl From<&ffi::VmaAllocationInfo> for AllocationInfo {
692    fn from(info: &ffi::VmaAllocationInfo) -> Self {
693        Self {
694            memory_type: info.memoryType,
695            device_memory: info.deviceMemory,
696            offset: info.offset,
697            size: info.size,
698            mapped_data: info.pMappedData,
699            user_data: info.pUserData as _,
700        }
701    }
702}
703impl From<ffi::VmaAllocationInfo> for AllocationInfo {
704    fn from(info: ffi::VmaAllocationInfo) -> Self {
705        (&info).into()
706    }
707}