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}