From c41e3fb5a69fcbc4feb7a0678cf3e7a403febdc5 Mon Sep 17 00:00:00 2001 From: Ilya Doroshenko Date: Mon, 26 Aug 2024 14:11:41 +0200 Subject: [PATCH] extra safety --- include/vk_mem_alloc.h | 5849 ++++++++++++++++++++-------------------- 1 file changed, 2920 insertions(+), 2929 deletions(-) diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h index a0c3bdd..fed962c 100644 --- a/include/vk_mem_alloc.h +++ b/include/vk_mem_alloc.h @@ -132,15 +132,15 @@ extern "C" { #endif #if !defined(VMA_VULKAN_VERSION) - #if defined(VK_VERSION_1_3) - #define VMA_VULKAN_VERSION 1003000 - #elif defined(VK_VERSION_1_2) - #define VMA_VULKAN_VERSION 1002000 - #elif defined(VK_VERSION_1_1) - #define VMA_VULKAN_VERSION 1001000 - #else - #define VMA_VULKAN_VERSION 1000000 - #endif +#if defined(VK_VERSION_1_3) +#define VMA_VULKAN_VERSION 1003000 +#elif defined(VK_VERSION_1_2) +#define VMA_VULKAN_VERSION 1002000 +#elif defined(VK_VERSION_1_1) +#define VMA_VULKAN_VERSION 1001000 +#else +#define VMA_VULKAN_VERSION 1000000 +#endif #endif #if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS @@ -163,83 +163,83 @@ extern "C" { extern PFN_vkCreateImage vkCreateImage; extern PFN_vkDestroyImage vkDestroyImage; extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; - #if VMA_VULKAN_VERSION >= 1001000 - extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; - extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; - extern PFN_vkBindBufferMemory2 vkBindBufferMemory2; - extern PFN_vkBindImageMemory2 vkBindImageMemory2; - extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; - #endif // #if VMA_VULKAN_VERSION >= 1001000 +#if VMA_VULKAN_VERSION >= 1001000 + extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; + extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; + extern PFN_vkBindBufferMemory2 vkBindBufferMemory2; + extern PFN_vkBindImageMemory2 vkBindImageMemory2; + extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; +#endif // #if VMA_VULKAN_VERSION >= 1001000 #endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES #if !defined(VMA_DEDICATED_ALLOCATION) - #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation - #define VMA_DEDICATED_ALLOCATION 1 - #else - #define VMA_DEDICATED_ALLOCATION 0 - #endif +#if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation +#define VMA_DEDICATED_ALLOCATION 1 +#else +#define VMA_DEDICATED_ALLOCATION 0 +#endif #endif #if !defined(VMA_BIND_MEMORY2) - #if VK_KHR_bind_memory2 - #define VMA_BIND_MEMORY2 1 - #else - #define VMA_BIND_MEMORY2 0 - #endif +#if VK_KHR_bind_memory2 +#define VMA_BIND_MEMORY2 1 +#else +#define VMA_BIND_MEMORY2 0 +#endif #endif #if !defined(VMA_MEMORY_BUDGET) - #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) - #define VMA_MEMORY_BUDGET 1 - #else - #define VMA_MEMORY_BUDGET 0 - #endif +#if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) +#define VMA_MEMORY_BUDGET 1 +#else +#define VMA_MEMORY_BUDGET 0 +#endif #endif -// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers. + // Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers. #if !defined(VMA_BUFFER_DEVICE_ADDRESS) - #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000 - #define VMA_BUFFER_DEVICE_ADDRESS 1 - #else - #define VMA_BUFFER_DEVICE_ADDRESS 0 - #endif +#if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000 +#define VMA_BUFFER_DEVICE_ADDRESS 1 +#else +#define VMA_BUFFER_DEVICE_ADDRESS 0 +#endif #endif // Defined to 1 when VK_EXT_memory_priority device extension is defined in Vulkan headers. #if !defined(VMA_MEMORY_PRIORITY) - #if VK_EXT_memory_priority - #define VMA_MEMORY_PRIORITY 1 - #else - #define VMA_MEMORY_PRIORITY 0 - #endif +#if VK_EXT_memory_priority +#define VMA_MEMORY_PRIORITY 1 +#else +#define VMA_MEMORY_PRIORITY 0 +#endif #endif // Defined to 1 when VK_KHR_maintenance4 device extension is defined in Vulkan headers. #if !defined(VMA_KHR_MAINTENANCE4) - #if VK_KHR_maintenance4 - #define VMA_KHR_MAINTENANCE4 1 - #else - #define VMA_KHR_MAINTENANCE4 0 - #endif +#if VK_KHR_maintenance4 +#define VMA_KHR_MAINTENANCE4 1 +#else +#define VMA_KHR_MAINTENANCE4 0 +#endif #endif // Defined to 1 when VK_KHR_maintenance5 device extension is defined in Vulkan headers. #if !defined(VMA_KHR_MAINTENANCE5) - #if VK_KHR_maintenance5 - #define VMA_KHR_MAINTENANCE5 1 - #else - #define VMA_KHR_MAINTENANCE5 0 - #endif +#if VK_KHR_maintenance5 +#define VMA_KHR_MAINTENANCE5 1 +#else +#define VMA_KHR_MAINTENANCE5 0 +#endif #endif // Defined to 1 when VK_KHR_external_memory device extension is defined in Vulkan headers. #if !defined(VMA_EXTERNAL_MEMORY) - #if VK_KHR_external_memory - #define VMA_EXTERNAL_MEMORY 1 - #else - #define VMA_EXTERNAL_MEMORY 0 - #endif +#if VK_KHR_external_memory +#define VMA_EXTERNAL_MEMORY 1 +#else +#define VMA_EXTERNAL_MEMORY 0 +#endif #endif // Define these macros to decorate all public functions with additional code, @@ -248,16 +248,16 @@ extern "C" { // #define VMA_CALL_PRE __declspec(dllexport) // #define VMA_CALL_POST __cdecl #ifndef VMA_CALL_PRE - #define VMA_CALL_PRE +#define VMA_CALL_PRE #endif #ifndef VMA_CALL_POST - #define VMA_CALL_POST +#define VMA_CALL_POST #endif // Define this macro to decorate pNext pointers with an attribute specifying the Vulkan // structure that will be extended via the pNext chain. #ifndef VMA_EXTENDS_VK_STRUCT - #define VMA_EXTENDS_VK_STRUCT(vkStruct) +#define VMA_EXTENDS_VK_STRUCT(vkStruct) #endif // Define this macro to decorate pointers with an attribute specifying the @@ -272,49 +272,49 @@ extern "C" { // this means the number of memory heaps available in the device associated // with the VmaAllocator being dealt with. #ifndef VMA_LEN_IF_NOT_NULL - #define VMA_LEN_IF_NOT_NULL(len) +#define VMA_LEN_IF_NOT_NULL(len) #endif // The VMA_NULLABLE macro is defined to be _Nullable when compiling with Clang. // see: https://clang.llvm.org/docs/AttributeReference.html#nullable #ifndef VMA_NULLABLE - #ifdef __clang__ - #define VMA_NULLABLE _Nullable - #else - #define VMA_NULLABLE - #endif +#ifdef __clang__ +#define VMA_NULLABLE _Nullable +#else +#define VMA_NULLABLE +#endif #endif // The VMA_NOT_NULL macro is defined to be _Nonnull when compiling with Clang. // see: https://clang.llvm.org/docs/AttributeReference.html#nonnull #ifndef VMA_NOT_NULL - #ifdef __clang__ - #define VMA_NOT_NULL _Nonnull - #else - #define VMA_NOT_NULL - #endif +#ifdef __clang__ +#define VMA_NOT_NULL _Nonnull +#else +#define VMA_NOT_NULL +#endif #endif // If non-dispatchable handles are represented as pointers then we can give // then nullability annotations #ifndef VMA_NOT_NULL_NON_DISPATCHABLE - #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) - #define VMA_NOT_NULL_NON_DISPATCHABLE VMA_NOT_NULL - #else - #define VMA_NOT_NULL_NON_DISPATCHABLE - #endif +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#define VMA_NOT_NULL_NON_DISPATCHABLE VMA_NOT_NULL +#else +#define VMA_NOT_NULL_NON_DISPATCHABLE +#endif #endif #ifndef VMA_NULLABLE_NON_DISPATCHABLE - #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) - #define VMA_NULLABLE_NON_DISPATCHABLE VMA_NULLABLE - #else - #define VMA_NULLABLE_NON_DISPATCHABLE - #endif +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#define VMA_NULLABLE_NON_DISPATCHABLE VMA_NULLABLE +#else +#define VMA_NULLABLE_NON_DISPATCHABLE +#endif #endif #ifndef VMA_STATS_STRING_ENABLED - #define VMA_STATS_STRING_ENABLED 1 +#define VMA_STATS_STRING_ENABLED 1 #endif //////////////////////////////////////////////////////////////////////////////// @@ -334,525 +334,525 @@ extern "C" { */ /// Flags for created #VmaAllocator. -typedef enum VmaAllocatorCreateFlagBits -{ - /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you. + typedef enum VmaAllocatorCreateFlagBits + { + /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you. - Using this flag may increase performance because internal mutexes are not used. - */ - VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, - /** \brief Enables usage of VK_KHR_dedicated_allocation extension. + Using this flag may increase performance because internal mutexes are not used. + */ + VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, + /** \brief Enables usage of VK_KHR_dedicated_allocation extension. - The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. - When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. - Using this extension will automatically allocate dedicated blocks of memory for - some buffers and images instead of suballocating place for them out of bigger - memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT - flag) when it is recommended by the driver. It may improve performance on some - GPUs. + Using this extension will automatically allocate dedicated blocks of memory for + some buffers and images instead of suballocating place for them out of bigger + memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT + flag) when it is recommended by the driver. It may improve performance on some + GPUs. - You may set this flag only if you found out that following device extensions are - supported, you enabled them while creating Vulkan device passed as - VmaAllocatorCreateInfo::device, and you want them to be used internally by this - library: + You may set this flag only if you found out that following device extensions are + supported, you enabled them while creating Vulkan device passed as + VmaAllocatorCreateInfo::device, and you want them to be used internally by this + library: - - VK_KHR_get_memory_requirements2 (device extension) - - VK_KHR_dedicated_allocation (device extension) + - VK_KHR_get_memory_requirements2 (device extension) + - VK_KHR_dedicated_allocation (device extension) - When this flag is set, you can experience following warnings reported by Vulkan - validation layer. You can ignore them. + When this flag is set, you can experience following warnings reported by Vulkan + validation layer. You can ignore them. - > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. - */ - VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002, - /** - Enables usage of VK_KHR_bind_memory2 extension. + > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. + */ + VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002, + /** + Enables usage of VK_KHR_bind_memory2 extension. - The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. - When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. - You may set this flag only if you found out that this device extension is supported, - you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, - and you want it to be used internally by this library. + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library. - The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`, - which allow to pass a chain of `pNext` structures while binding. - This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2(). - */ - VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004, - /** - Enables usage of VK_EXT_memory_budget extension. + The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`, + which allow to pass a chain of `pNext` structures while binding. + This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2(). + */ + VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004, + /** + Enables usage of VK_EXT_memory_budget extension. - You may set this flag only if you found out that this device extension is supported, - you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, - and you want it to be used internally by this library, along with another instance extension - VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted). + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library, along with another instance extension + VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted). - The extension provides query for current memory usage and budget, which will probably - be more accurate than an estimation used by the library otherwise. - */ - VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008, - /** - Enables usage of VK_AMD_device_coherent_memory extension. + The extension provides query for current memory usage and budget, which will probably + be more accurate than an estimation used by the library otherwise. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008, + /** + Enables usage of VK_AMD_device_coherent_memory extension. - You may set this flag only if you: + You may set this flag only if you: - - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, - - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device, - - want it to be used internally by this library. + - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device, + - want it to be used internally by this library. - The extension and accompanying device feature provide access to memory types with - `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags. - They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR. + The extension and accompanying device feature provide access to memory types with + `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags. + They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR. - When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. - 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, - returning `VK_ERROR_FEATURE_NOT_PRESENT`. - */ - VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010, - /** - Enables usage of "buffer device address" feature, which allows you to use function - `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader. + When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. + 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, + returning `VK_ERROR_FEATURE_NOT_PRESENT`. + */ + VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010, + /** + Enables usage of "buffer device address" feature, which allows you to use function + `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader. - You may set this flag only if you: + You may set this flag only if you: - 1. (For Vulkan version < 1.2) Found as available and enabled device extension - VK_KHR_buffer_device_address. - This extension is promoted to core Vulkan 1.2. - 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`. + 1. (For Vulkan version < 1.2) Found as available and enabled device extension + VK_KHR_buffer_device_address. + This extension is promoted to core Vulkan 1.2. + 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`. - When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA. - The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to - allocated memory blocks wherever it might be needed. + When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA. + The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to + allocated memory blocks wherever it might be needed. - For more information, see documentation chapter \ref enabling_buffer_device_address. - */ - VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020, - /** - Enables usage of VK_EXT_memory_priority extension in the library. + For more information, see documentation chapter \ref enabling_buffer_device_address. + */ + VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020, + /** + Enables usage of VK_EXT_memory_priority extension in the library. - You may set this flag only if you found available and enabled this device extension, - along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`, - while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + You may set this flag only if you found available and enabled this device extension, + along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. - When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority - are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored. + When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority + are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored. - A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. - Larger values are higher priority. The granularity of the priorities is implementation-dependent. - It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`. - The value to be used for default priority is 0.5. - For more details, see the documentation of the VK_EXT_memory_priority extension. - */ - VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 0x00000040, - /** - Enables usage of VK_KHR_maintenance4 extension in the library. + A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + Larger values are higher priority. The granularity of the priorities is implementation-dependent. + It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`. + The value to be used for default priority is 0.5. + For more details, see the documentation of the VK_EXT_memory_priority extension. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 0x00000040, + /** + Enables usage of VK_KHR_maintenance4 extension in the library. - You may set this flag only if you found available and enabled this device extension, - while creating Vulkan device passed as VmaAllocatorCreateInfo::device. - */ - VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT = 0x00000080, - /** - Enables usage of VK_KHR_maintenance5 extension in the library. + You may set this flag only if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + */ + VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT = 0x00000080, + /** + Enables usage of VK_KHR_maintenance5 extension in the library. - You should set this flag if you found available and enabled this device extension, - while creating Vulkan device passed as VmaAllocatorCreateInfo::device. - */ - VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100, + You should set this flag if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + */ + VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100, + + /** + Enables usage of VK_KHR_external_memory_win32 extension in the library. + + You should set this flag if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + */ + VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32 = 0x00000200, + + VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaAllocatorCreateFlagBits; + /// See #VmaAllocatorCreateFlagBits. + typedef VkFlags VmaAllocatorCreateFlags; + + /** @} */ /** - Enables usage of VK_KHR_external_memory_win32 extension in the library. - - You should set this flag if you found available and enabled this device extension, - while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + \addtogroup group_alloc + @{ */ - VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32 = 0x00000200, - VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaAllocatorCreateFlagBits; -/// See #VmaAllocatorCreateFlagBits. -typedef VkFlags VmaAllocatorCreateFlags; + /// \brief Intended usage of the allocated memory. + typedef enum VmaMemoryUsage + { + /** No intended memory usage specified. + Use other members of VmaAllocationCreateInfo to specify your requirements. + */ + VMA_MEMORY_USAGE_UNKNOWN = 0, + /** + \deprecated Obsolete, preserved for backward compatibility. + Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_GPU_ONLY = 1, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`. + */ + VMA_MEMORY_USAGE_CPU_ONLY = 2, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_CPU_TO_GPU = 3, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`. + */ + VMA_MEMORY_USAGE_GPU_TO_CPU = 4, + /** + \deprecated Obsolete, preserved for backward compatibility. + Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_CPU_COPY = 5, + /** + Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`. + Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. -/** @} */ + Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. -/** -\addtogroup group_alloc -@{ -*/ + Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + */ + VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, + /** + Selects best memory type automatically. + This flag is recommended for most common use cases. -/// \brief Intended usage of the allocated memory. -typedef enum VmaMemoryUsage -{ - /** No intended memory usage specified. - Use other members of VmaAllocationCreateInfo to specify your requirements. - */ - VMA_MEMORY_USAGE_UNKNOWN = 0, - /** - \deprecated Obsolete, preserved for backward compatibility. - Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. - */ - VMA_MEMORY_USAGE_GPU_ONLY = 1, - /** - \deprecated Obsolete, preserved for backward compatibility. - Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`. - */ - VMA_MEMORY_USAGE_CPU_ONLY = 2, - /** - \deprecated Obsolete, preserved for backward compatibility. - Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. - */ - VMA_MEMORY_USAGE_CPU_TO_GPU = 3, - /** - \deprecated Obsolete, preserved for backward compatibility. - Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`. - */ - VMA_MEMORY_USAGE_GPU_TO_CPU = 4, - /** - \deprecated Obsolete, preserved for backward compatibility. - Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. - */ - VMA_MEMORY_USAGE_CPU_COPY = 5, - /** - Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`. - Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. - Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO = 7, + /** + Selects best memory type automatically with preference for GPU (device) memory. - Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. - */ - VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, - /** - Selects best memory type automatically. - This flag is recommended for most common use cases. + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. - When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), - you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT - in VmaAllocationCreateInfo::flags. + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8, + /** + Selects best memory type automatically with preference for CPU (host) memory. - It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. - vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() - and not with generic memory allocation functions. - */ - VMA_MEMORY_USAGE_AUTO = 7, - /** - Selects best memory type automatically with preference for GPU (device) memory. + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. - When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), - you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT - in VmaAllocationCreateInfo::flags. + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9, - It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. - vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() - and not with generic memory allocation functions. - */ - VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8, - /** - Selects best memory type automatically with preference for CPU (host) memory. + VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF + } VmaMemoryUsage; - When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), - you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT - in VmaAllocationCreateInfo::flags. + /// Flags to be passed as VmaAllocationCreateInfo::flags. + typedef enum VmaAllocationCreateFlagBits + { + /** \brief Set this flag if the allocation should have its own memory block. - It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. - vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() - and not with generic memory allocation functions. - */ - VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9, + Use it for special, big resources, like fullscreen images used as attachments. - VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF -} VmaMemoryUsage; + If you use this flag while creating a buffer or an image, `VkMemoryDedicatedAllocateInfo` + structure is applied if possible. + */ + VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001, -/// Flags to be passed as VmaAllocationCreateInfo::flags. -typedef enum VmaAllocationCreateFlagBits -{ - /** \brief Set this flag if the allocation should have its own memory block. + /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block. - Use it for special, big resources, like fullscreen images used as attachments. + If new allocation cannot be placed in any of the existing blocks, allocation + fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error. - If you use this flag while creating a buffer or an image, `VkMemoryDedicatedAllocateInfo` - structure is applied if possible. - */ - VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001, + You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and + #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense. + */ + VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002, + /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. - /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block. + Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData. - If new allocation cannot be placed in any of the existing blocks, allocation - fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error. + It is valid to use this flag for allocation made from memory type that is not + `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is + useful if you need an allocation that is efficient to use on GPU + (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that + support it (e.g. Intel GPU). + */ + VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004, + /** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead. - You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and - #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense. - */ - VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002, - /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. + Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a + null-terminated string. Instead of copying pointer value, a local copy of the + string is made and stored in allocation's `pName`. The string is automatically + freed together with the allocation. It is also used in vmaBuildStatsString(). + */ + VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, + /** Allocation will be created from upper stack in a double stack pool. - Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData. + This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040, + /** Create both buffer/image and allocation, but don't bind them together. + It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. + The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage(). + Otherwise it is ignored. - It is valid to use this flag for allocation made from memory type that is not - `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is - useful if you need an allocation that is efficient to use on GPU - (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that - support it (e.g. Intel GPU). - */ - VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004, - /** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead. + If you want to make sure the new buffer/image is not tied to the new memory allocation + through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block, + use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT. + */ + VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080, + /** Create allocation only if additional device memory required for it, if any, won't exceed + memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + */ + VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100, + /** \brief Set this flag if the allocated memory will have aliasing resources. - Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a - null-terminated string. Instead of copying pointer value, a local copy of the - string is made and stored in allocation's `pName`. The string is automatically - freed together with the allocation. It is also used in vmaBuildStatsString(). - */ - VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, - /** Allocation will be created from upper stack in a double stack pool. + Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. + Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors. + */ + VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200, + /** + Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). - This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag. - */ - VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040, - /** Create both buffer/image and allocation, but don't bind them together. - It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. - The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage(). - Otherwise it is ignored. + - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + This includes allocations created in \ref custom_memory_pools. - If you want to make sure the new buffer/image is not tied to the new memory allocation - through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block, - use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT. - */ - VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080, - /** Create allocation only if additional device memory required for it, if any, won't exceed - memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. - */ - VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100, - /** \brief Set this flag if the allocated memory will have aliasing resources. + Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number, + never read or accessed randomly, so a memory type can be selected that is uncached and write-combined. - Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. - Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors. - */ - VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200, - /** - Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). + \warning Violating this declaration may work correctly, but will likely be very slow. + Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;` + Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400, + /** + Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). - - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, - you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. - - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. - This includes allocations created in \ref custom_memory_pools. + - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + This includes allocations created in \ref custom_memory_pools. - Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number, - never read or accessed randomly, so a memory type can be selected that is uncached and write-combined. + Declares that mapped memory can be read, written, and accessed in random order, + so a `HOST_CACHED` memory type is preferred. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 0x00000800, + /** + Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, + it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected + if it may improve performance. - \warning Violating this declaration may work correctly, but will likely be very slow. - Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;` - Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once. - */ - VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400, - /** - Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). - - - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, - you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. - - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. - This includes allocations created in \ref custom_memory_pools. - - Declares that mapped memory can be read, written, and accessed in random order, - so a `HOST_CACHED` memory type is preferred. - */ - VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 0x00000800, - /** - Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, - it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected - if it may improve performance. - - By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type - (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and - issue an explicit transfer to write/read your data. - To prepare for this possibility, don't forget to add appropriate flags like - `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image. - */ - VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 0x00001000, - /** Allocation strategy that chooses smallest possible free range for the allocation - to minimize memory usage and fragmentation, possibly at the expense of allocation time. - */ - VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 0x00010000, - /** Allocation strategy that chooses first suitable free range for the allocation - - not necessarily in terms of the smallest offset but the one that is easiest and fastest to find - to minimize allocation time, possibly at the expense of allocation quality. - */ - VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 0x00020000, - /** Allocation strategy that chooses always the lowest offset in available space. - This is not the most efficient strategy but achieves highly packed data. - Used internally by defragmentation, not recommended in typical usage. - */ - VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 0x00040000, - /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT. - */ - VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, - /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT. - */ - VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, - /** A bit mask to extract only `STRATEGY` bits from entire set of flags. - */ - VMA_ALLOCATION_CREATE_STRATEGY_MASK = + By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type + (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and + issue an explicit transfer to write/read your data. + To prepare for this possibility, don't forget to add appropriate flags like + `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 0x00001000, + /** Allocation strategy that chooses smallest possible free range for the allocation + to minimize memory usage and fragmentation, possibly at the expense of allocation time. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 0x00010000, + /** Allocation strategy that chooses first suitable free range for the allocation - + not necessarily in terms of the smallest offset but the one that is easiest and fastest to find + to minimize allocation time, possibly at the expense of allocation quality. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 0x00020000, + /** Allocation strategy that chooses always the lowest offset in available space. + This is not the most efficient strategy but achieves highly packed data. + Used internally by defragmentation, not recommended in typical usage. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 0x00040000, + /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT. + */ + VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, + /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT. + */ + VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, + /** A bit mask to extract only `STRATEGY` bits from entire set of flags. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT | VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT | VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, - VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaAllocationCreateFlagBits; -/// See #VmaAllocationCreateFlagBits. -typedef VkFlags VmaAllocationCreateFlags; + VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaAllocationCreateFlagBits; + /// See #VmaAllocationCreateFlagBits. + typedef VkFlags VmaAllocationCreateFlags; -/// Flags to be passed as VmaPoolCreateInfo::flags. -typedef enum VmaPoolCreateFlagBits -{ - /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. + /// Flags to be passed as VmaPoolCreateInfo::flags. + typedef enum VmaPoolCreateFlagBits + { + /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. - This is an optional optimization flag. + This is an optional optimization flag. - If you always allocate using vmaCreateBuffer(), vmaCreateImage(), - vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator - knows exact type of your allocations so it can handle Buffer-Image Granularity - in the optimal way. + If you always allocate using vmaCreateBuffer(), vmaCreateImage(), + vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator + knows exact type of your allocations so it can handle Buffer-Image Granularity + in the optimal way. - If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(), - exact type of such allocations is not known, so allocator must be conservative - in handling Buffer-Image Granularity, which can lead to suboptimal allocation - (wasted memory). In that case, if you can make sure you always allocate only - buffers and linear images or only optimal images out of this pool, use this flag - to make allocator disregard Buffer-Image Granularity and so make allocations - faster and more optimal. - */ - VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, + If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(), + exact type of such allocations is not known, so allocator must be conservative + in handling Buffer-Image Granularity, which can lead to suboptimal allocation + (wasted memory). In that case, if you can make sure you always allocate only + buffers and linear images or only optimal images out of this pool, use this flag + to make allocator disregard Buffer-Image Granularity and so make allocations + faster and more optimal. + */ + VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, - /** \brief Enables alternative, linear allocation algorithm in this pool. + /** \brief Enables alternative, linear allocation algorithm in this pool. - Specify this flag to enable linear allocation algorithm, which always creates - new allocations after last one and doesn't reuse space from allocations freed in - between. It trades memory consumption for simplified algorithm and data - structure, which has better performance and uses less memory for metadata. + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. - By using this flag, you can achieve behavior of free-at-once, stack, - ring buffer, and double stack. - For details, see documentation chapter \ref linear_algorithm. - */ - VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004, + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + */ + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004, - /** Bit mask to extract only `ALGORITHM` bits from entire set of flags. - */ - VMA_POOL_CREATE_ALGORITHM_MASK = + /** Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_POOL_CREATE_ALGORITHM_MASK = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT, - VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaPoolCreateFlagBits; -/// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits. -typedef VkFlags VmaPoolCreateFlags; + VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaPoolCreateFlagBits; + /// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits. + typedef VkFlags VmaPoolCreateFlags; -/// Flags to be passed as VmaDefragmentationInfo::flags. -typedef enum VmaDefragmentationFlagBits -{ - /* \brief Use simple but fast algorithm for defragmentation. - May not achieve best results but will require least time to compute and least allocations to copy. - */ - VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 0x1, - /* \brief Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified. - Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved. - */ - VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 0x2, - /* \brief Perform full defragmentation of memory. - Can result in notably more time to compute and allocations to copy, but will achieve best memory packing. - */ - VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 0x4, - /** \brief Use the most roboust algorithm at the cost of time to compute and number of copies to make. - Only available when bufferImageGranularity is greater than 1, since it aims to reduce - alignment issues between different types of resources. - Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT. - */ - VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8, + /// Flags to be passed as VmaDefragmentationInfo::flags. + typedef enum VmaDefragmentationFlagBits + { + /* \brief Use simple but fast algorithm for defragmentation. + May not achieve best results but will require least time to compute and least allocations to copy. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 0x1, + /* \brief Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified. + Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 0x2, + /* \brief Perform full defragmentation of memory. + Can result in notably more time to compute and allocations to copy, but will achieve best memory packing. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 0x4, + /** \brief Use the most roboust algorithm at the cost of time to compute and number of copies to make. + Only available when bufferImageGranularity is greater than 1, since it aims to reduce + alignment issues between different types of resources. + Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8, - /// A bit mask to extract only `ALGORITHM` bits from entire set of flags. - VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK = + /// A bit mask to extract only `ALGORITHM` bits from entire set of flags. + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT | VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT | VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT | VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT, - VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaDefragmentationFlagBits; -/// See #VmaDefragmentationFlagBits. -typedef VkFlags VmaDefragmentationFlags; + VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaDefragmentationFlagBits; + /// See #VmaDefragmentationFlagBits. + typedef VkFlags VmaDefragmentationFlags; -/// Operation performed on single defragmentation move. See structure #VmaDefragmentationMove. -typedef enum VmaDefragmentationMoveOperation -{ - /// Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass(). - VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0, - /// Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged. - VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1, - /// Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed. - VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2, -} VmaDefragmentationMoveOperation; + /// Operation performed on single defragmentation move. See structure #VmaDefragmentationMove. + typedef enum VmaDefragmentationMoveOperation + { + /// Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass(). + VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0, + /// Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged. + VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1, + /// Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed. + VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2, + } VmaDefragmentationMoveOperation; -/** @} */ + /** @} */ -/** -\addtogroup group_virtual -@{ -*/ - -/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. -typedef enum VmaVirtualBlockCreateFlagBits -{ - /** \brief Enables alternative, linear allocation algorithm in this virtual block. - - Specify this flag to enable linear allocation algorithm, which always creates - new allocations after last one and doesn't reuse space from allocations freed in - between. It trades memory consumption for simplified algorithm and data - structure, which has better performance and uses less memory for metadata. - - By using this flag, you can achieve behavior of free-at-once, stack, - ring buffer, and double stack. - For details, see documentation chapter \ref linear_algorithm. + /** + \addtogroup group_virtual + @{ */ - VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001, - /** \brief Bit mask to extract only `ALGORITHM` bits from entire set of flags. - */ - VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = + /// Flags to be passed as VmaVirtualBlockCreateInfo::flags. + typedef enum VmaVirtualBlockCreateFlagBits + { + /** \brief Enables alternative, linear allocation algorithm in this virtual block. + + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. + + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + */ + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001, + + /** \brief Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT, - VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaVirtualBlockCreateFlagBits; -/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits. -typedef VkFlags VmaVirtualBlockCreateFlags; + VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaVirtualBlockCreateFlagBits; + /// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits. + typedef VkFlags VmaVirtualBlockCreateFlags; -/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. -typedef enum VmaVirtualAllocationCreateFlagBits -{ - /** \brief Allocation will be created from upper stack in a double stack pool. + /// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. + typedef enum VmaVirtualAllocationCreateFlagBits + { + /** \brief Allocation will be created from upper stack in a double stack pool. - This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag. - */ - VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT, - /** \brief Allocation strategy that tries to minimize memory usage. - */ - VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, - /** \brief Allocation strategy that tries to minimize allocation time. - */ - VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, - /** Allocation strategy that chooses always the lowest offset in available space. - This is not the most efficient strategy but achieves highly packed data. - */ - VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, - /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags. + This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT, + /** \brief Allocation strategy that tries to minimize memory usage. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, + /** \brief Allocation strategy that tries to minimize allocation time. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, + /** Allocation strategy that chooses always the lowest offset in available space. + This is not the most efficient strategy but achieves highly packed data. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags. - These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits. - */ - VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK, + These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK, - VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaVirtualAllocationCreateFlagBits; -/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits. -typedef VkFlags VmaVirtualAllocationCreateFlags; + VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF + } VmaVirtualAllocationCreateFlagBits; + /// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits. + typedef VkFlags VmaVirtualAllocationCreateFlags; -/** @} */ + /** @} */ #endif // _VMA_ENUM_DECLARATIONS @@ -871,781 +871,781 @@ Call function vmaDestroyAllocator() to destroy it. It is recommended to create just one object of this type per `VkDevice` object, right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed. */ -VK_DEFINE_HANDLE(VmaAllocator) + VK_DEFINE_HANDLE(VmaAllocator) -/** @} */ + /** @} */ -/** -\addtogroup group_alloc -@{ -*/ + /** + \addtogroup group_alloc + @{ + */ -/** \struct VmaPool -\brief Represents custom memory pool + /** \struct VmaPool + \brief Represents custom memory pool -Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it. -Call function vmaDestroyPool() to destroy it. + Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it. + Call function vmaDestroyPool() to destroy it. -For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools). -*/ -VK_DEFINE_HANDLE(VmaPool) + For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools). + */ + VK_DEFINE_HANDLE(VmaPool) -/** \struct VmaAllocation -\brief Represents single memory allocation. + /** \struct VmaAllocation + \brief Represents single memory allocation. -It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type -plus unique offset. + It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type + plus unique offset. -There are multiple ways to create such object. -You need to fill structure VmaAllocationCreateInfo. -For more information see [Choosing memory type](@ref choosing_memory_type). + There are multiple ways to create such object. + You need to fill structure VmaAllocationCreateInfo. + For more information see [Choosing memory type](@ref choosing_memory_type). -Although the library provides convenience functions that create Vulkan buffer or image, -allocate memory for it and bind them together, -binding of the allocation to a buffer or an image is out of scope of the allocation itself. -Allocation object can exist without buffer/image bound, -binding can be done manually by the user, and destruction of it can be done -independently of destruction of the allocation. + Although the library provides convenience functions that create Vulkan buffer or image, + allocate memory for it and bind them together, + binding of the allocation to a buffer or an image is out of scope of the allocation itself. + Allocation object can exist without buffer/image bound, + binding can be done manually by the user, and destruction of it can be done + independently of destruction of the allocation. -The object also remembers its size and some other information. -To retrieve this information, use function vmaGetAllocationInfo() and inspect -returned structure VmaAllocationInfo. -*/ -VK_DEFINE_HANDLE(VmaAllocation) + The object also remembers its size and some other information. + To retrieve this information, use function vmaGetAllocationInfo() and inspect + returned structure VmaAllocationInfo. + */ + VK_DEFINE_HANDLE(VmaAllocation) -/** \struct VmaDefragmentationContext -\brief An opaque object that represents started defragmentation process. + /** \struct VmaDefragmentationContext + \brief An opaque object that represents started defragmentation process. -Fill structure #VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it. -Call function vmaEndDefragmentation() to destroy it. -*/ -VK_DEFINE_HANDLE(VmaDefragmentationContext) + Fill structure #VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it. + Call function vmaEndDefragmentation() to destroy it. + */ + VK_DEFINE_HANDLE(VmaDefragmentationContext) -/** @} */ + /** @} */ -/** -\addtogroup group_virtual -@{ -*/ + /** + \addtogroup group_virtual + @{ + */ -/** \struct VmaVirtualAllocation -\brief Represents single memory allocation done inside VmaVirtualBlock. + /** \struct VmaVirtualAllocation + \brief Represents single memory allocation done inside VmaVirtualBlock. -Use it as a unique identifier to virtual allocation within the single block. + Use it as a unique identifier to virtual allocation within the single block. -Use value `VK_NULL_HANDLE` to represent a null/invalid allocation. -*/ -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation) + Use value `VK_NULL_HANDLE` to represent a null/invalid allocation. + */ + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation) -/** @} */ + /** @} */ -/** -\addtogroup group_virtual -@{ -*/ + /** + \addtogroup group_virtual + @{ + */ -/** \struct VmaVirtualBlock -\brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory. + /** \struct VmaVirtualBlock + \brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory. -Fill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it. -For more information, see documentation chapter \ref virtual_allocator. + Fill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it. + For more information, see documentation chapter \ref virtual_allocator. -This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally. -*/ -VK_DEFINE_HANDLE(VmaVirtualBlock) + This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally. + */ + VK_DEFINE_HANDLE(VmaVirtualBlock) -/** @} */ + /** @} */ -/** -\addtogroup group_init -@{ -*/ + /** + \addtogroup group_init + @{ + */ -/// Callback function called after successful vkAllocateMemory. -typedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t memoryType, - VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, - VkDeviceSize size, - void* VMA_NULLABLE pUserData); + /// Callback function called after successful vkAllocateMemory. + typedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); -/// Callback function called before vkFreeMemory. -typedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t memoryType, - VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, - VkDeviceSize size, - void* VMA_NULLABLE pUserData); + /// Callback function called before vkFreeMemory. + typedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); -/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`. + /** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`. -Provided for informative purpose, e.g. to gather statistics about number of -allocations or total amount of memory allocated in Vulkan. + Provided for informative purpose, e.g. to gather statistics about number of + allocations or total amount of memory allocated in Vulkan. -Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. -*/ -typedef struct VmaDeviceMemoryCallbacks -{ - /// Optional, can be null. - PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate; - /// Optional, can be null. - PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree; - /// Optional, can be null. - void* VMA_NULLABLE pUserData; -} VmaDeviceMemoryCallbacks; + Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. + */ + typedef struct VmaDeviceMemoryCallbacks + { + /// Optional, can be null. + PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate; + /// Optional, can be null. + PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree; + /// Optional, can be null. + void* VMA_NULLABLE pUserData; + } VmaDeviceMemoryCallbacks; -/** \brief Pointers to some Vulkan functions - a subset used by the library. + /** \brief Pointers to some Vulkan functions - a subset used by the library. -Used in VmaAllocatorCreateInfo::pVulkanFunctions. -*/ -typedef struct VmaVulkanFunctions -{ - /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. - PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr; - /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. - PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr; - PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties; - PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties; - PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory; - PFN_vkFreeMemory VMA_NULLABLE vkFreeMemory; - PFN_vkMapMemory VMA_NULLABLE vkMapMemory; - PFN_vkUnmapMemory VMA_NULLABLE vkUnmapMemory; - PFN_vkFlushMappedMemoryRanges VMA_NULLABLE vkFlushMappedMemoryRanges; - PFN_vkInvalidateMappedMemoryRanges VMA_NULLABLE vkInvalidateMappedMemoryRanges; - PFN_vkBindBufferMemory VMA_NULLABLE vkBindBufferMemory; - PFN_vkBindImageMemory VMA_NULLABLE vkBindImageMemory; - PFN_vkGetBufferMemoryRequirements VMA_NULLABLE vkGetBufferMemoryRequirements; - PFN_vkGetImageMemoryRequirements VMA_NULLABLE vkGetImageMemoryRequirements; - PFN_vkCreateBuffer VMA_NULLABLE vkCreateBuffer; - PFN_vkDestroyBuffer VMA_NULLABLE vkDestroyBuffer; - PFN_vkCreateImage VMA_NULLABLE vkCreateImage; - PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage; - PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer; + Used in VmaAllocatorCreateInfo::pVulkanFunctions. + */ + typedef struct VmaVulkanFunctions + { + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr; + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr; + PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties; + PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory; + PFN_vkFreeMemory VMA_NULLABLE vkFreeMemory; + PFN_vkMapMemory VMA_NULLABLE vkMapMemory; + PFN_vkUnmapMemory VMA_NULLABLE vkUnmapMemory; + PFN_vkFlushMappedMemoryRanges VMA_NULLABLE vkFlushMappedMemoryRanges; + PFN_vkInvalidateMappedMemoryRanges VMA_NULLABLE vkInvalidateMappedMemoryRanges; + PFN_vkBindBufferMemory VMA_NULLABLE vkBindBufferMemory; + PFN_vkBindImageMemory VMA_NULLABLE vkBindImageMemory; + PFN_vkGetBufferMemoryRequirements VMA_NULLABLE vkGetBufferMemoryRequirements; + PFN_vkGetImageMemoryRequirements VMA_NULLABLE vkGetImageMemoryRequirements; + PFN_vkCreateBuffer VMA_NULLABLE vkCreateBuffer; + PFN_vkDestroyBuffer VMA_NULLABLE vkDestroyBuffer; + PFN_vkCreateImage VMA_NULLABLE vkCreateImage; + PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage; + PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer; #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 - /// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. - PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR; - /// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. - PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR; + /// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR; + /// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR; #endif #if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 - /// Fetch "vkBindBufferMemory2" on Vulkan >= 1.1, fetch "vkBindBufferMemory2KHR" when using VK_KHR_bind_memory2 extension. - PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR; - /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. - PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; + /// Fetch "vkBindBufferMemory2" on Vulkan >= 1.1, fetch "vkBindBufferMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR; + /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; #endif #if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 - /// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2. - PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; + /// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2. + PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; #endif #if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 - /// Fetch from "vkGetDeviceBufferMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceBufferMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. - PFN_vkGetDeviceBufferMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceBufferMemoryRequirements; - /// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. - PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements; + /// Fetch from "vkGetDeviceBufferMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceBufferMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. + PFN_vkGetDeviceBufferMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceBufferMemoryRequirements; + /// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. + PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements; #endif #ifdef VK_USE_PLATFORM_WIN32_KHR - PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR; + PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR; #else - void* VMA_NULLABLE vkGetMemoryWin32HandleKHR; + void* VMA_NULLABLE vkGetMemoryWin32HandleKHR; #endif -} VmaVulkanFunctions; + } VmaVulkanFunctions; -/// Description of a Allocator to be created. -typedef struct VmaAllocatorCreateInfo -{ - /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum. - VmaAllocatorCreateFlags flags; - /// Vulkan physical device. - /** It must be valid throughout whole lifetime of created allocator. */ - VkPhysicalDevice VMA_NOT_NULL physicalDevice; - /// Vulkan device. - /** It must be valid throughout whole lifetime of created allocator. */ - VkDevice VMA_NOT_NULL device; - /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional. - /** Set to 0 to use default, which is currently 256 MiB. */ - VkDeviceSize preferredLargeHeapBlockSize; - /// Custom CPU memory allocation callbacks. Optional. - /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */ - const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; - /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional. - /** Optional, can be null. */ - const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks; - /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. + /// Description of a Allocator to be created. + typedef struct VmaAllocatorCreateInfo + { + /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum. + VmaAllocatorCreateFlags flags; + /// Vulkan physical device. + /** It must be valid throughout whole lifetime of created allocator. */ + VkPhysicalDevice VMA_NOT_NULL physicalDevice; + /// Vulkan device. + /** It must be valid throughout whole lifetime of created allocator. */ + VkDevice VMA_NOT_NULL device; + /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional. + /** Set to 0 to use default, which is currently 256 MiB. */ + VkDeviceSize preferredLargeHeapBlockSize; + /// Custom CPU memory allocation callbacks. Optional. + /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */ + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; + /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional. + /** Optional, can be null. */ + const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks; + /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. - If not NULL, it must be a pointer to an array of - `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on - maximum number of bytes that can be allocated out of particular Vulkan memory - heap. + If not NULL, it must be a pointer to an array of + `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on + maximum number of bytes that can be allocated out of particular Vulkan memory + heap. - Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that - heap. This is also the default in case of `pHeapSizeLimit` = NULL. + Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that + heap. This is also the default in case of `pHeapSizeLimit` = NULL. - If there is a limit defined for a heap: + If there is a limit defined for a heap: - - If user tries to allocate more memory from that heap using this allocator, - the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. - - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the - value of this limit will be reported instead when using vmaGetMemoryProperties(). + - If user tries to allocate more memory from that heap using this allocator, + the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the + value of this limit will be reported instead when using vmaGetMemoryProperties(). - Warning! Using this feature may not be equivalent to installing a GPU with - smaller amount of memory, because graphics driver doesn't necessary fail new - allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is - exceeded. It may return success and just silently migrate some device memory - blocks to system RAM. This driver behavior can also be controlled using - VK_AMD_memory_overallocation_behavior extension. - */ - const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pHeapSizeLimit; + Warning! Using this feature may not be equivalent to installing a GPU with + smaller amount of memory, because graphics driver doesn't necessary fail new + allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is + exceeded. It may return success and just silently migrate some device memory + blocks to system RAM. This driver behavior can also be controlled using + VK_AMD_memory_overallocation_behavior extension. + */ + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pHeapSizeLimit; - /** \brief Pointers to Vulkan functions. Can be null. + /** \brief Pointers to Vulkan functions. Can be null. - For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions). - */ - const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions; - /** \brief Handle to Vulkan instance object. + For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions). + */ + const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions; + /** \brief Handle to Vulkan instance object. - Starting from version 3.0.0 this member is no longer optional, it must be set! - */ - VkInstance VMA_NOT_NULL instance; - /** \brief Optional. Vulkan version that the application uses. + Starting from version 3.0.0 this member is no longer optional, it must be set! + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Optional. Vulkan version that the application uses. - It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`. - The patch version number specified is ignored. Only the major and minor versions are considered. - Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation. - Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`. - It must match the Vulkan version used by the application and supported on the selected physical device, - so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance` - and no higher than `VkPhysicalDeviceProperties::apiVersion` found on the physical device used. - */ - uint32_t vulkanApiVersion; + It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`. + The patch version number specified is ignored. Only the major and minor versions are considered. + Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation. + Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`. + It must match the Vulkan version used by the application and supported on the selected physical device, + so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance` + and no higher than `VkPhysicalDeviceProperties::apiVersion` found on the physical device used. + */ + uint32_t vulkanApiVersion; #if VMA_EXTERNAL_MEMORY - /** \brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type. + /** \brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type. - If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount` - elements, defining external memory handle types of particular Vulkan memory type, - to be passed using `VkExportMemoryAllocateInfoKHR`. + If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount` + elements, defining external memory handle types of particular Vulkan memory type, + to be passed using `VkExportMemoryAllocateInfoKHR`. - Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type. - This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL. - */ - const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryTypeCount") pTypeExternalMemoryHandleTypes; + Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type. + This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL. + */ + const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryTypeCount") pTypeExternalMemoryHandleTypes; #endif // #if VMA_EXTERNAL_MEMORY -} VmaAllocatorCreateInfo; + } VmaAllocatorCreateInfo; -/// Information about existing #VmaAllocator object. -typedef struct VmaAllocatorInfo -{ - /** \brief Handle to Vulkan instance object. + /// Information about existing #VmaAllocator object. + typedef struct VmaAllocatorInfo + { + /** \brief Handle to Vulkan instance object. - This is the same value as has been passed through VmaAllocatorCreateInfo::instance. + This is the same value as has been passed through VmaAllocatorCreateInfo::instance. + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Handle to Vulkan physical device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice. + */ + VkPhysicalDevice VMA_NOT_NULL physicalDevice; + /** \brief Handle to Vulkan device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::device. + */ + VkDevice VMA_NOT_NULL device; + } VmaAllocatorInfo; + + /** @} */ + + /** + \addtogroup group_stats + @{ */ - VkInstance VMA_NOT_NULL instance; - /** \brief Handle to Vulkan physical device object. - This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice. + /** \brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total. + + These are fast to calculate. + See functions: vmaGetHeapBudgets(), vmaGetPoolStatistics(). */ - VkPhysicalDevice VMA_NOT_NULL physicalDevice; - /** \brief Handle to Vulkan device object. + typedef struct VmaStatistics + { + /** \brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated. + */ + uint32_t blockCount; + /** \brief Number of #VmaAllocation objects allocated. - This is the same value as has been passed through VmaAllocatorCreateInfo::device. + Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`. + */ + uint32_t allocationCount; + /** \brief Number of bytes allocated in `VkDeviceMemory` blocks. + + \note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object + (e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls + "allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image. + */ + VkDeviceSize blockBytes; + /** \brief Total number of bytes occupied by all #VmaAllocation objects. + + Always less or equal than `blockBytes`. + Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan + but unused by any #VmaAllocation. + */ + VkDeviceSize allocationBytes; + } VmaStatistics; + + /** \brief More detailed statistics than #VmaStatistics. + + These are slower to calculate. Use for debugging purposes. + See functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics(). + + Previous version of the statistics API provided averages, but they have been removed + because they can be easily calculated as: + + \code + VkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount; + VkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes; + VkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount; + \endcode */ - VkDevice VMA_NOT_NULL device; -} VmaAllocatorInfo; + typedef struct VmaDetailedStatistics + { + /// Basic statistics. + VmaStatistics statistics; + /// Number of free ranges of memory between allocations. + uint32_t unusedRangeCount; + /// Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations. + VkDeviceSize allocationSizeMin; + /// Largest allocation size. 0 if there are 0 allocations. + VkDeviceSize allocationSizeMax; + /// Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges. + VkDeviceSize unusedRangeSizeMin; + /// Largest empty range size. 0 if there are 0 empty ranges. + VkDeviceSize unusedRangeSizeMax; + } VmaDetailedStatistics; -/** @} */ + /** \brief General statistics from current state of the Allocator - + total memory usage across all memory heaps and types. -/** -\addtogroup group_stats -@{ -*/ - -/** \brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total. - -These are fast to calculate. -See functions: vmaGetHeapBudgets(), vmaGetPoolStatistics(). -*/ -typedef struct VmaStatistics -{ - /** \brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated. + These are slower to calculate. Use for debugging purposes. + See function vmaCalculateStatistics(). */ - uint32_t blockCount; - /** \brief Number of #VmaAllocation objects allocated. + typedef struct VmaTotalStatistics + { + VmaDetailedStatistics memoryType[VK_MAX_MEMORY_TYPES]; + VmaDetailedStatistics memoryHeap[VK_MAX_MEMORY_HEAPS]; + VmaDetailedStatistics total; + } VmaTotalStatistics; - Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`. + /** \brief Statistics of current memory usage and available budget for a specific memory heap. + + These are fast to calculate. + See function vmaGetHeapBudgets(). */ - uint32_t allocationCount; - /** \brief Number of bytes allocated in `VkDeviceMemory` blocks. + typedef struct VmaBudget + { + /** \brief Statistics fetched from the library. + */ + VmaStatistics statistics; + /** \brief Estimated current memory usage of the program, in bytes. - \note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object - (e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls - "allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image. + Fetched from system using VK_EXT_memory_budget extension if enabled. + + It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects + also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or + `VkDeviceMemory` blocks allocated outside of this library, if any. + */ + VkDeviceSize usage; + /** \brief Estimated amount of memory available to the program, in bytes. + + Fetched from system using VK_EXT_memory_budget extension if enabled. + + It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors + external to the program, decided by the operating system. + Difference `budget - usage` is the amount of additional memory that can probably + be allocated without problems. Exceeding the budget may result in various problems. + */ + VkDeviceSize budget; + } VmaBudget; + + /** @} */ + + /** + \addtogroup group_alloc + @{ */ - VkDeviceSize blockBytes; - /** \brief Total number of bytes occupied by all #VmaAllocation objects. - Always less or equal than `blockBytes`. - Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan - but unused by any #VmaAllocation. + /** \brief Parameters of new #VmaAllocation. + + To be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others. */ - VkDeviceSize allocationBytes; -} VmaStatistics; + typedef struct VmaAllocationCreateInfo + { + /// Use #VmaAllocationCreateFlagBits enum. + VmaAllocationCreateFlags flags; + /** \brief Intended usage of memory. -/** \brief More detailed statistics than #VmaStatistics. + You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n + If `pool` is not null, this member is ignored. + */ + VmaMemoryUsage usage; + /** \brief Flags that must be set in a Memory Type chosen for an allocation. -These are slower to calculate. Use for debugging purposes. -See functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics(). + Leave 0 if you specify memory requirements in other way. \n + If `pool` is not null, this member is ignored.*/ + VkMemoryPropertyFlags requiredFlags; + /** \brief Flags that preferably should be set in a memory type chosen for an allocation. -Previous version of the statistics API provided averages, but they have been removed -because they can be easily calculated as: + Set to 0 if no additional flags are preferred. \n + If `pool` is not null, this member is ignored. */ + VkMemoryPropertyFlags preferredFlags; + /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. -\code -VkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount; -VkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes; -VkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount; -\endcode -*/ -typedef struct VmaDetailedStatistics -{ - /// Basic statistics. - VmaStatistics statistics; - /// Number of free ranges of memory between allocations. - uint32_t unusedRangeCount; - /// Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations. - VkDeviceSize allocationSizeMin; - /// Largest allocation size. 0 if there are 0 allocations. - VkDeviceSize allocationSizeMax; - /// Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges. - VkDeviceSize unusedRangeSizeMin; - /// Largest empty range size. 0 if there are 0 empty ranges. - VkDeviceSize unusedRangeSizeMax; -} VmaDetailedStatistics; + Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if + it meets other requirements specified by this structure, with no further + restrictions on memory type index. \n + If `pool` is not null, this member is ignored. + */ + uint32_t memoryTypeBits; + /** \brief Pool that this allocation should be created in. -/** \brief General statistics from current state of the Allocator - -total memory usage across all memory heaps and types. + Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: + `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. + */ + VmaPool VMA_NULLABLE pool; + /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). -These are slower to calculate. Use for debugging purposes. -See function vmaCalculateStatistics(). -*/ -typedef struct VmaTotalStatistics -{ - VmaDetailedStatistics memoryType[VK_MAX_MEMORY_TYPES]; - VmaDetailedStatistics memoryHeap[VK_MAX_MEMORY_HEAPS]; - VmaDetailedStatistics total; -} VmaTotalStatistics; + If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either + null or pointer to a null-terminated string. The string will be then copied to + internal buffer, so it doesn't need to be valid after allocation call. + */ + void* VMA_NULLABLE pUserData; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. -/** \brief Statistics of current memory usage and available budget for a specific memory heap. + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object + and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + Otherwise, it has the priority of a memory block where it is placed and this variable is ignored. + */ + float priority; + } VmaAllocationCreateInfo; -These are fast to calculate. -See function vmaGetHeapBudgets(). -*/ -typedef struct VmaBudget -{ - /** \brief Statistics fetched from the library. + /// Describes parameter of created #VmaPool. + typedef struct VmaPoolCreateInfo + { + /** \brief Vulkan memory type index to allocate this pool from. + */ + uint32_t memoryTypeIndex; + /** \brief Use combination of #VmaPoolCreateFlagBits. + */ + VmaPoolCreateFlags flags; + /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional. + + Specify nonzero to set explicit, constant size of memory blocks used by this + pool. + + Leave 0 to use default and let the library manage block sizes automatically. + Sizes of particular blocks may vary. + In this case, the pool will also support dedicated allocations. + */ + VkDeviceSize blockSize; + /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty. + + Set to 0 to have no preallocated blocks and allow the pool be completely empty. + */ + size_t minBlockCount; + /** \brief Maximum number of blocks that can be allocated in this pool. Optional. + + Set to 0 to use default, which is `SIZE_MAX`, which means no limit. + + Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated + throughout whole lifetime of this pool. + */ + size_t maxBlockCount; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations. + + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object. + Otherwise, this variable is ignored. + */ + float priority; + /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0. + + Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two. + It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough, + e.g. when doing interop with OpenGL. + */ + VkDeviceSize minAllocationAlignment; + /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional. + + Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`. + It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`. + Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool. + + Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`, + can be attached automatically by this library when using other, more convenient of its features. + */ + void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkMemoryAllocateInfo) pMemoryAllocateNext; + } VmaPoolCreateInfo; + + /** @} */ + + /** + \addtogroup group_alloc + @{ */ - VmaStatistics statistics; - /** \brief Estimated current memory usage of the program, in bytes. - Fetched from system using VK_EXT_memory_budget extension if enabled. + /** + Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo(). - It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects - also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or - `VkDeviceMemory` blocks allocated outside of this library, if any. + There is also an extended version of this structure that carries additional parameters: #VmaAllocationInfo2. */ - VkDeviceSize usage; - /** \brief Estimated amount of memory available to the program, in bytes. + typedef struct VmaAllocationInfo + { + /** \brief Memory type index that this allocation was allocated from. - Fetched from system using VK_EXT_memory_budget extension if enabled. + It never changes. + */ + uint32_t memoryType; + /** \brief Handle to Vulkan memory object. - It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors - external to the program, decided by the operating system. - Difference `budget - usage` is the amount of additional memory that can probably - be allocated without problems. Exceeding the budget may result in various problems. + Same memory object can be shared by multiple allocations. + + It can change after the allocation is moved during \ref defragmentation. + */ + VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory; + /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation. + + 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 + vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image, + not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation + and apply this offset automatically. + + It can change after the allocation is moved during \ref defragmentation. + */ + VkDeviceSize offset; + /** \brief Size of this allocation, in bytes. + + It never changes. + + \note Allocation size returned in this variable may be greater than the size + requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the + allocation is accessible for operations on memory e.g. using a pointer after + mapping with vmaMapMemory(), but operations on the resource e.g. using + `vkCmdCopyBuffer` must be limited to the size of the resource. + */ + VkDeviceSize size; + /** \brief Pointer to the beginning of this allocation as mapped data. + + If the allocation hasn't been mapped using vmaMapMemory() and hasn't been + created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null. + + It can change after call to vmaMapMemory(), vmaUnmapMemory(). + It can also change after the allocation is moved during \ref defragmentation. + */ + void* VMA_NULLABLE pMappedData; + /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). + + It can change after call to vmaSetAllocationUserData() for this allocation. + */ + void* VMA_NULLABLE pUserData; + /** \brief Custom allocation name that was set with vmaSetAllocationName(). + + It can change after call to vmaSetAllocationName() for this allocation. + + Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with + additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. + */ + const char* VMA_NULLABLE pName; + } VmaAllocationInfo; + + /// Extended parameters of a #VmaAllocation object that can be retrieved using function vmaGetAllocationInfo2(). + typedef struct VmaAllocationInfo2 + { + /** \brief Basic parameters of the allocation. + + If you need only these, you can use function vmaGetAllocationInfo() and structure #VmaAllocationInfo instead. + */ + VmaAllocationInfo allocationInfo; + /** \brief Size of the `VkDeviceMemory` block that the allocation belongs to. + + In case of an allocation with dedicated memory, it will be equal to `allocationInfo.size`. + */ + VkDeviceSize blockSize; + /** \brief `VK_TRUE` if the allocation has dedicated memory, `VK_FALSE` if it was placed as part of a larger memory block. + + When `VK_TRUE`, it also means `VkMemoryDedicatedAllocateInfo` was used when creating the allocation + (if VK_KHR_dedicated_allocation extension or Vulkan version >= 1.1 is enabled). + */ + VkBool32 dedicatedMemory; + } VmaAllocationInfo2; + + /** Callback function called during vmaBeginDefragmentation() to check custom criterion about ending current defragmentation pass. + + Should return true if the defragmentation needs to stop current pass. */ - VkDeviceSize budget; -} VmaBudget; + typedef VkBool32(VKAPI_PTR* PFN_vmaCheckDefragmentationBreakFunction)(void* VMA_NULLABLE pUserData); -/** @} */ + /** \brief Parameters for defragmentation. -/** -\addtogroup group_alloc -@{ -*/ - -/** \brief Parameters of new #VmaAllocation. - -To be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others. -*/ -typedef struct VmaAllocationCreateInfo -{ - /// Use #VmaAllocationCreateFlagBits enum. - VmaAllocationCreateFlags flags; - /** \brief Intended usage of memory. - - You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n - If `pool` is not null, this member is ignored. + To be used with function vmaBeginDefragmentation(). */ - VmaMemoryUsage usage; - /** \brief Flags that must be set in a Memory Type chosen for an allocation. + typedef struct VmaDefragmentationInfo + { + /// \brief Use combination of #VmaDefragmentationFlagBits. + VmaDefragmentationFlags flags; + /** \brief Custom pool to be defragmented. - Leave 0 if you specify memory requirements in other way. \n - If `pool` is not null, this member is ignored.*/ - VkMemoryPropertyFlags requiredFlags; - /** \brief Flags that preferably should be set in a memory type chosen for an allocation. + If null then default pools will undergo defragmentation process. + */ + VmaPool VMA_NULLABLE pool; + /** \brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places. - Set to 0 if no additional flags are preferred. \n - If `pool` is not null, this member is ignored. */ - VkMemoryPropertyFlags preferredFlags; - /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. + `0` means no limit. + */ + VkDeviceSize maxBytesPerPass; + /** \brief Maximum number of allocations that can be moved during single pass to a different place. - Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if - it meets other requirements specified by this structure, with no further - restrictions on memory type index. \n - If `pool` is not null, this member is ignored. + `0` means no limit. + */ + uint32_t maxAllocationsPerPass; + /** \brief Optional custom callback for stopping vmaBeginDefragmentation(). + + Have to return true for breaking current defragmentation pass. + */ + PFN_vmaCheckDefragmentationBreakFunction VMA_NULLABLE pfnBreakCallback; + /// \brief Optional data to pass to custom callback for stopping pass of defragmentation. + void* VMA_NULLABLE pBreakCallbackUserData; + } VmaDefragmentationInfo; + + /// Single move of an allocation to be done for defragmentation. + typedef struct VmaDefragmentationMove + { + /// Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it. + VmaDefragmentationMoveOperation operation; + /// Allocation that should be moved. + VmaAllocation VMA_NOT_NULL srcAllocation; + /** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`. + + \warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass, + to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory(). + vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory. + */ + VmaAllocation VMA_NOT_NULL dstTmpAllocation; + } VmaDefragmentationMove; + + /** \brief Parameters for incremental defragmentation steps. + + To be used with function vmaBeginDefragmentationPass(). */ - uint32_t memoryTypeBits; - /** \brief Pool that this allocation should be created in. + typedef struct VmaDefragmentationPassMoveInfo + { + /// Number of elements in the `pMoves` array. + uint32_t moveCount; + /** \brief Array of moves to be performed by the user in the current defragmentation pass. - Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: - `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. + Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass(). + + For each element, you should: + + 1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset. + 2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`. + 3. Make sure these commands finished executing on the GPU. + 4. Destroy the old buffer/image. + + Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass(). + After this call, the allocation will point to the new place in memory. + + Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. + + Alternatively, if you decide you want to completely remove the allocation: + + 1. Destroy its buffer/image. + 2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. + + Then, after vmaEndDefragmentationPass() the allocation will be freed. + */ + VmaDefragmentationMove* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(moveCount) pMoves; + } VmaDefragmentationPassMoveInfo; + + /// Statistics returned for defragmentation process in function vmaEndDefragmentation(). + typedef struct VmaDefragmentationStats + { + /// Total number of bytes that have been copied while moving allocations to different places. + VkDeviceSize bytesMoved; + /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects. + VkDeviceSize bytesFreed; + /// Number of allocations that have been moved to different places. + uint32_t allocationsMoved; + /// Number of empty `VkDeviceMemory` objects that have been released to the system. + uint32_t deviceMemoryBlocksFreed; + } VmaDefragmentationStats; + + /** @} */ + + /** + \addtogroup group_virtual + @{ */ - VmaPool VMA_NULLABLE pool; - /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). - If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either - null or pointer to a null-terminated string. The string will be then copied to - internal buffer, so it doesn't need to be valid after allocation call. - */ - void* VMA_NULLABLE pUserData; - /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. - - It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object - and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. - Otherwise, it has the priority of a memory block where it is placed and this variable is ignored. - */ - float priority; -} VmaAllocationCreateInfo; - -/// Describes parameter of created #VmaPool. -typedef struct VmaPoolCreateInfo -{ - /** \brief Vulkan memory type index to allocate this pool from. - */ - uint32_t memoryTypeIndex; - /** \brief Use combination of #VmaPoolCreateFlagBits. - */ - VmaPoolCreateFlags flags; - /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional. - - Specify nonzero to set explicit, constant size of memory blocks used by this - pool. - - Leave 0 to use default and let the library manage block sizes automatically. - Sizes of particular blocks may vary. - In this case, the pool will also support dedicated allocations. - */ - VkDeviceSize blockSize; - /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty. - - Set to 0 to have no preallocated blocks and allow the pool be completely empty. - */ - size_t minBlockCount; - /** \brief Maximum number of blocks that can be allocated in this pool. Optional. - - Set to 0 to use default, which is `SIZE_MAX`, which means no limit. - - Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated - throughout whole lifetime of this pool. - */ - size_t maxBlockCount; - /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations. - - It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object. - Otherwise, this variable is ignored. - */ - float priority; - /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0. - - Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two. - It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough, - e.g. when doing interop with OpenGL. - */ - VkDeviceSize minAllocationAlignment; - /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional. - - Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`. - It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`. - Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool. - - Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`, - can be attached automatically by this library when using other, more convenient of its features. - */ - void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkMemoryAllocateInfo) pMemoryAllocateNext; -} VmaPoolCreateInfo; - -/** @} */ - -/** -\addtogroup group_alloc -@{ -*/ - -/** -Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo(). - -There is also an extended version of this structure that carries additional parameters: #VmaAllocationInfo2. -*/ -typedef struct VmaAllocationInfo -{ - /** \brief Memory type index that this allocation was allocated from. - - It never changes. - */ - uint32_t memoryType; - /** \brief Handle to Vulkan memory object. - - Same memory object can be shared by multiple allocations. - - It can change after the allocation is moved during \ref defragmentation. - */ - VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory; - /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation. - - 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 - vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image, - not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation - and apply this offset automatically. - - It can change after the allocation is moved during \ref defragmentation. - */ - VkDeviceSize offset; - /** \brief Size of this allocation, in bytes. - - It never changes. - - \note Allocation size returned in this variable may be greater than the size - requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the - allocation is accessible for operations on memory e.g. using a pointer after - mapping with vmaMapMemory(), but operations on the resource e.g. using - `vkCmdCopyBuffer` must be limited to the size of the resource. - */ - VkDeviceSize size; - /** \brief Pointer to the beginning of this allocation as mapped data. - - If the allocation hasn't been mapped using vmaMapMemory() and hasn't been - created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null. - - It can change after call to vmaMapMemory(), vmaUnmapMemory(). - It can also change after the allocation is moved during \ref defragmentation. - */ - void* VMA_NULLABLE pMappedData; - /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). - - It can change after call to vmaSetAllocationUserData() for this allocation. - */ - void* VMA_NULLABLE pUserData; - /** \brief Custom allocation name that was set with vmaSetAllocationName(). - - It can change after call to vmaSetAllocationName() for this allocation. - - Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with - additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. - */ - const char* VMA_NULLABLE pName; -} VmaAllocationInfo; - -/// Extended parameters of a #VmaAllocation object that can be retrieved using function vmaGetAllocationInfo2(). -typedef struct VmaAllocationInfo2 -{ - /** \brief Basic parameters of the allocation. - - If you need only these, you can use function vmaGetAllocationInfo() and structure #VmaAllocationInfo instead. - */ - VmaAllocationInfo allocationInfo; - /** \brief Size of the `VkDeviceMemory` block that the allocation belongs to. - - In case of an allocation with dedicated memory, it will be equal to `allocationInfo.size`. - */ - VkDeviceSize blockSize; - /** \brief `VK_TRUE` if the allocation has dedicated memory, `VK_FALSE` if it was placed as part of a larger memory block. - - When `VK_TRUE`, it also means `VkMemoryDedicatedAllocateInfo` was used when creating the allocation - (if VK_KHR_dedicated_allocation extension or Vulkan version >= 1.1 is enabled). - */ - VkBool32 dedicatedMemory; -} VmaAllocationInfo2; - -/** Callback function called during vmaBeginDefragmentation() to check custom criterion about ending current defragmentation pass. - -Should return true if the defragmentation needs to stop current pass. -*/ -typedef VkBool32 (VKAPI_PTR* PFN_vmaCheckDefragmentationBreakFunction)(void* VMA_NULLABLE pUserData); - -/** \brief Parameters for defragmentation. - -To be used with function vmaBeginDefragmentation(). -*/ -typedef struct VmaDefragmentationInfo -{ - /// \brief Use combination of #VmaDefragmentationFlagBits. - VmaDefragmentationFlags flags; - /** \brief Custom pool to be defragmented. - - If null then default pools will undergo defragmentation process. - */ - VmaPool VMA_NULLABLE pool; - /** \brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places. - - `0` means no limit. - */ - VkDeviceSize maxBytesPerPass; - /** \brief Maximum number of allocations that can be moved during single pass to a different place. - - `0` means no limit. - */ - uint32_t maxAllocationsPerPass; - /** \brief Optional custom callback for stopping vmaBeginDefragmentation(). - - Have to return true for breaking current defragmentation pass. - */ - PFN_vmaCheckDefragmentationBreakFunction VMA_NULLABLE pfnBreakCallback; - /// \brief Optional data to pass to custom callback for stopping pass of defragmentation. - void* VMA_NULLABLE pBreakCallbackUserData; -} VmaDefragmentationInfo; - -/// Single move of an allocation to be done for defragmentation. -typedef struct VmaDefragmentationMove -{ - /// Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it. - VmaDefragmentationMoveOperation operation; - /// Allocation that should be moved. - VmaAllocation VMA_NOT_NULL srcAllocation; - /** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`. - - \warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass, - to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory(). - vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory. - */ - VmaAllocation VMA_NOT_NULL dstTmpAllocation; -} VmaDefragmentationMove; - -/** \brief Parameters for incremental defragmentation steps. - -To be used with function vmaBeginDefragmentationPass(). -*/ -typedef struct VmaDefragmentationPassMoveInfo -{ - /// Number of elements in the `pMoves` array. - uint32_t moveCount; - /** \brief Array of moves to be performed by the user in the current defragmentation pass. - - Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass(). - - For each element, you should: - - 1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset. - 2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`. - 3. Make sure these commands finished executing on the GPU. - 4. Destroy the old buffer/image. - - Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass(). - After this call, the allocation will point to the new place in memory. - - Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. - - Alternatively, if you decide you want to completely remove the allocation: - - 1. Destroy its buffer/image. - 2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. - - Then, after vmaEndDefragmentationPass() the allocation will be freed. - */ - VmaDefragmentationMove* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(moveCount) pMoves; -} VmaDefragmentationPassMoveInfo; - -/// Statistics returned for defragmentation process in function vmaEndDefragmentation(). -typedef struct VmaDefragmentationStats -{ - /// Total number of bytes that have been copied while moving allocations to different places. - VkDeviceSize bytesMoved; - /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects. - VkDeviceSize bytesFreed; - /// Number of allocations that have been moved to different places. - uint32_t allocationsMoved; - /// Number of empty `VkDeviceMemory` objects that have been released to the system. - uint32_t deviceMemoryBlocksFreed; -} VmaDefragmentationStats; - -/** @} */ - -/** -\addtogroup group_virtual -@{ -*/ - -/// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). -typedef struct VmaVirtualBlockCreateInfo -{ - /** \brief Total size of the virtual block. - - Sizes can be expressed in bytes or any units you want as long as you are consistent in using them. - For example, if you allocate from some array of structures, 1 can mean single instance of entire structure. - */ - VkDeviceSize size; - - /** \brief Use combination of #VmaVirtualBlockCreateFlagBits. - */ - VmaVirtualBlockCreateFlags flags; - - /** \brief Custom CPU memory allocation callbacks. Optional. - - Optional, can be null. When specified, they will be used for all CPU-side memory allocations. - */ - const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; -} VmaVirtualBlockCreateInfo; - -/// Parameters of created virtual allocation to be passed to vmaVirtualAllocate(). -typedef struct VmaVirtualAllocationCreateInfo -{ - /** \brief Size of the allocation. - - Cannot be zero. - */ - VkDeviceSize size; - /** \brief Required alignment of the allocation. Optional. - - 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. - */ - VkDeviceSize alignment; - /** \brief Use combination of #VmaVirtualAllocationCreateFlagBits. - */ - VmaVirtualAllocationCreateFlags flags; - /** \brief Custom pointer to be associated with the allocation. Optional. - - It can be any value and can be used for user-defined purposes. It can be fetched or changed later. - */ - void* VMA_NULLABLE pUserData; -} VmaVirtualAllocationCreateInfo; - -/// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo(). -typedef struct VmaVirtualAllocationInfo -{ - /** \brief Offset of the allocation. - - Offset at which the allocation was made. - */ - VkDeviceSize offset; - /** \brief Size of the allocation. - - Same value as passed in VmaVirtualAllocationCreateInfo::size. - */ - VkDeviceSize size; - /** \brief Custom pointer associated with the allocation. - - Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData(). - */ - void* VMA_NULLABLE pUserData; -} VmaVirtualAllocationInfo; - -/** @} */ + /// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). + typedef struct VmaVirtualBlockCreateInfo + { + /** \brief Total size of the virtual block. + + Sizes can be expressed in bytes or any units you want as long as you are consistent in using them. + For example, if you allocate from some array of structures, 1 can mean single instance of entire structure. + */ + VkDeviceSize size; + + /** \brief Use combination of #VmaVirtualBlockCreateFlagBits. + */ + VmaVirtualBlockCreateFlags flags; + + /** \brief Custom CPU memory allocation callbacks. Optional. + + Optional, can be null. When specified, they will be used for all CPU-side memory allocations. + */ + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; + } VmaVirtualBlockCreateInfo; + + /// Parameters of created virtual allocation to be passed to vmaVirtualAllocate(). + typedef struct VmaVirtualAllocationCreateInfo + { + /** \brief Size of the allocation. + + Cannot be zero. + */ + VkDeviceSize size; + /** \brief Required alignment of the allocation. Optional. + + 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. + */ + VkDeviceSize alignment; + /** \brief Use combination of #VmaVirtualAllocationCreateFlagBits. + */ + VmaVirtualAllocationCreateFlags flags; + /** \brief Custom pointer to be associated with the allocation. Optional. + + It can be any value and can be used for user-defined purposes. It can be fetched or changed later. + */ + void* VMA_NULLABLE pUserData; + } VmaVirtualAllocationCreateInfo; + + /// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo(). + typedef struct VmaVirtualAllocationInfo + { + /** \brief Offset of the allocation. + + Offset at which the allocation was made. + */ + VkDeviceSize offset; + /** \brief Size of the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::size. + */ + VkDeviceSize size; + /** \brief Custom pointer associated with the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData(). + */ + void* VMA_NULLABLE pUserData; + } VmaVirtualAllocationInfo; + + /** @} */ #endif // _VMA_DATA_TYPES_DECLARATIONS @@ -1657,1051 +1657,1051 @@ typedef struct VmaVirtualAllocationInfo */ /// Creates #VmaAllocator object. -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( - const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator); - -/// Destroys allocator object. -VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( - VmaAllocator VMA_NULLABLE allocator); - -/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc. - -It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to -`VkPhysicalDevice`, `VkDevice` etc. every time using this function. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo); - -/** -PhysicalDeviceProperties are fetched from physicalDevice by the allocator. -You can access it here, without fetching it again on your own. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( - VmaAllocator VMA_NOT_NULL allocator, - const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties); - -/** -PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. -You can access it here, without fetching it again on your own. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( - VmaAllocator VMA_NOT_NULL allocator, - const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); - -/** -\brief Given Memory Type Index, returns Property Flags of this memory type. - -This is just a convenience function. Same information can be obtained using -vmaGetMemoryProperties(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t memoryTypeIndex, - VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); - -/** \brief Sets index of the current frame. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t frameIndex); - -/** @} */ - -/** -\addtogroup group_stats -@{ -*/ - -/** \brief Retrieves statistics from current state of the Allocator. - -This function is called "calculate" not "get" because it has to traverse all -internal data structures, so it may be quite slow. Use it for debugging purposes. -For faster but more brief statistics suitable to be called every frame or every allocation, -use vmaGetHeapBudgets(). - -Note that when using allocator from multiple threads, returned information may immediately -become outdated. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( - VmaAllocator VMA_NOT_NULL allocator, - VmaTotalStatistics* VMA_NOT_NULL pStats); - -/** \brief Retrieves information about current memory usage and budget for all memory heaps. - -\param allocator -\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used. - -This function is called "get" not "calculate" because it is very fast, suitable to be called -every frame or every allocation. For more detailed statistics use vmaCalculateStatistics(). - -Note that when using allocator from multiple threads, returned information may immediately -become outdated. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( - VmaAllocator VMA_NOT_NULL allocator, - VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pBudgets); - -/** @} */ - -/** -\addtogroup group_alloc -@{ -*/ - -/** -\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo. - -This algorithm tries to find a memory type that: - -- Is allowed by memoryTypeBits. -- Contains all the flags from pAllocationCreateInfo->requiredFlags. -- Matches intended usage. -- Has as many flags from pAllocationCreateInfo->preferredFlags as possible. - -\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result -from this function or any other allocating function probably means that your -device doesn't support any memory type with requested features for the specific -type of resource you want to use it for. Please check parameters of your -resource, like image layout (OPTIMAL versus LINEAR) or mip level count. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t memoryTypeBits, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - uint32_t* VMA_NOT_NULL pMemoryTypeIndex); - -/** -\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo. - -It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. -It internally creates a temporary, dummy buffer that never has memory bound. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( - VmaAllocator VMA_NOT_NULL allocator, - const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - uint32_t* VMA_NOT_NULL pMemoryTypeIndex); - -/** -\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo. - -It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. -It internally creates a temporary, dummy image that never has memory bound. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( - VmaAllocator VMA_NOT_NULL allocator, - const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - uint32_t* VMA_NOT_NULL pMemoryTypeIndex); - -/** \brief Allocates Vulkan device memory and creates #VmaPool object. - -\param allocator Allocator object. -\param pCreateInfo Parameters of pool to create. -\param[out] pPool Handle to created pool. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( - VmaAllocator VMA_NOT_NULL allocator, - const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool); - -/** \brief Destroys #VmaPool object and frees Vulkan device memory. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NULLABLE pool); - -/** @} */ - -/** -\addtogroup group_stats -@{ -*/ - -/** \brief Retrieves statistics of existing #VmaPool object. - -\param allocator Allocator object. -\param pool Pool object. -\param[out] pPoolStats Statistics of specified pool. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NOT_NULL pool, - VmaStatistics* VMA_NOT_NULL pPoolStats); - -/** \brief Retrieves detailed statistics of existing #VmaPool object. - -\param allocator Allocator object. -\param pool Pool object. -\param[out] pPoolStats Statistics of specified pool. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NOT_NULL pool, - VmaDetailedStatistics* VMA_NOT_NULL pPoolStats); - -/** @} */ - -/** -\addtogroup group_alloc -@{ -*/ - -/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions. - -Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, -`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is -`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). - -Possible return values: - -- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. -- `VK_SUCCESS` - corruption detection has been performed and succeeded. -- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. - `VMA_ASSERT` is also fired in that case. -- Other value: Error returned by Vulkan, e.g. memory mapping failure. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NOT_NULL pool); - -/** \brief Retrieves name of a custom pool. - -After the call `ppName` is either null or points to an internally-owned null-terminated string -containing name of the pool that was previously set. The pointer becomes invalid when the pool is -destroyed or its name is changed using vmaSetPoolName(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NOT_NULL pool, - const char* VMA_NULLABLE* VMA_NOT_NULL ppName); - -/** \brief Sets name of a custom pool. - -`pName` can be either null or pointer to a null-terminated string with new name for the pool. -Function makes internal copy of the string, so it can be changed or freed immediately after this call. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( - VmaAllocator VMA_NOT_NULL allocator, - VmaPool VMA_NOT_NULL pool, - const char* VMA_NULLABLE pName); - -/** \brief General purpose memory allocation. - -\param allocator -\param pVkMemoryRequirements -\param pCreateInfo -\param[out] pAllocation Handle to allocated memory. -\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). - -You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). - -It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(), -vmaCreateBuffer(), vmaCreateImage() instead whenever possible. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( - VmaAllocator VMA_NOT_NULL allocator, - const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, - const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/** \brief General purpose memory allocation for multiple allocation objects at once. - -\param allocator Allocator object. -\param pVkMemoryRequirements Memory requirements for each allocation. -\param pCreateInfo Creation parameters for each allocation. -\param allocationCount Number of allocations to make. -\param[out] pAllocations Pointer to array that will be filled with handles to created allocations. -\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations. - -You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). - -Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. -It is just a general purpose allocation function able to make multiple allocations at once. -It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times. - -All allocations are made using same parameters. All of them are created out of the same memory pool and type. -If any allocation fails, all allocations already made within this function call are also freed, so that when -returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( - VmaAllocator VMA_NOT_NULL allocator, - const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements, - const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo, - size_t allocationCount, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, - VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo); - -/** \brief Allocates memory suitable for given `VkBuffer`. - -\param allocator -\param buffer -\param pCreateInfo -\param[out] pAllocation Handle to allocated memory. -\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). - -It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory(). - -This is a special-purpose function. In most cases you should use vmaCreateBuffer(). - -You must free the allocation using vmaFreeMemory() when no longer needed. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( - VmaAllocator VMA_NOT_NULL allocator, - VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, - const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/** \brief Allocates memory suitable for given `VkImage`. - -\param allocator -\param image -\param pCreateInfo -\param[out] pAllocation Handle to allocated memory. -\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). - -It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory(). - -This is a special-purpose function. In most cases you should use vmaCreateImage(). - -You must free the allocation using vmaFreeMemory() when no longer needed. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( - VmaAllocator VMA_NOT_NULL allocator, - VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, - const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). - -Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( - VmaAllocator VMA_NOT_NULL allocator, - const VmaAllocation VMA_NULLABLE allocation); - -/** \brief Frees memory and destroys multiple allocations. - -Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding. -It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(), -vmaAllocateMemoryPages() and other functions. -It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times. - -Allocations in `pAllocations` array can come from any memory pools and types. -Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( - VmaAllocator VMA_NOT_NULL allocator, - size_t allocationCount, - const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations); - -/** \brief Returns current information about specified allocation. - -Current parameters of given allocation are returned in `pAllocationInfo`. - -Although this function doesn't lock any mutex, so it should be quite efficient, -you should avoid calling it too often. -You can retrieve same VmaAllocationInfo structure while creating your resource, from function -vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change -(e.g. due to defragmentation). - -There is also a new function vmaGetAllocationInfo2() that offers extended information -about the allocation, returned using new structure #VmaAllocationInfo2. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo); - -/** \brief Returns extended information about specified allocation. - -Current parameters of given allocation are returned in `pAllocationInfo`. -Extended parameters in structure #VmaAllocationInfo2 include memory block size -and a flag telling whether the allocation has dedicated memory. -It can be useful e.g. for interop with OpenGL. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VmaAllocationInfo2* VMA_NOT_NULL pAllocationInfo); - -/** \brief Sets pUserData in given allocation to new value. - -The value of pointer `pUserData` is copied to allocation's `pUserData`. -It is opaque, so you can use it however you want - e.g. -as a pointer, ordinal number or some handle to you own data. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - void* VMA_NULLABLE pUserData); - -/** \brief Sets pName in given allocation to new value. - -`pName` must be either null, or pointer to a null-terminated string. The function -makes local copy of the string and sets it as allocation's `pName`. String -passed as pName doesn't need to be valid for whole lifetime of the allocation - -you can free it after this call. String previously pointed by allocation's -`pName` is freed from memory. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - const char* VMA_NULLABLE pName); - -/** -\brief Given an allocation, returns Property Flags of its memory type. - -This is just a convenience function. Same information can be obtained using -vmaGetAllocationInfo() + vmaGetMemoryProperties(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); - -/** \brief Maps memory represented by given allocation and returns pointer to it. - -Maps memory represented by given allocation to make it accessible to CPU code. -When succeeded, `*ppData` contains pointer to first byte of this memory. - -\warning -If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is -correctly offsetted to the beginning of region assigned to this particular allocation. -Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block. -You should not add VmaAllocationInfo::offset to it! - -Mapping is internally reference-counted and synchronized, so despite raw Vulkan -function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory` -multiple times simultaneously, it is safe to call this function on allocations -assigned to the same memory block. Actual Vulkan memory will be mapped on first -mapping and unmapped on last unmapping. - -If the function succeeded, you must call vmaUnmapMemory() to unmap the -allocation when mapping is no longer needed or before freeing the allocation, at -the latest. - -It also safe to call this function multiple times on the same allocation. You -must call vmaUnmapMemory() same number of times as you called vmaMapMemory(). - -It is also safe to call this function on allocation created with -#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time. -You must still call vmaUnmapMemory() same number of times as you called -vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the -"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag. - -This function fails when used on allocation made in memory type that is not -`HOST_VISIBLE`. - -This function doesn't automatically flush or invalidate caches. -If the allocation is made from a memory types that is not `HOST_COHERENT`, -you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - void* VMA_NULLABLE* VMA_NOT_NULL ppData); - -/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). - -For details, see description of vmaMapMemory(). - -This function doesn't automatically flush or invalidate caches. -If the allocation is made from a memory types that is not `HOST_COHERENT`, -you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation); - -/** \brief Flushes memory of given allocation. - -Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation. -It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`. -Unmap operation doesn't do that automatically. - -- `offset` must be relative to the beginning of allocation. -- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. -- `offset` and `size` don't have to be aligned. - They are internally rounded down/up to multiply of `nonCoherentAtomSize`. -- If `size` is 0, this call is ignored. -- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, - this call is ignored. - -Warning! `offset` and `size` are relative to the contents of given `allocation`. -If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. -Do not pass allocation's offset as `offset`!!! - -This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is -called, otherwise `VK_SUCCESS`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize offset, - VkDeviceSize size); - -/** \brief Invalidates memory of given allocation. - -Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation. -It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`. -Map operation doesn't do that automatically. - -- `offset` must be relative to the beginning of allocation. -- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. -- `offset` and `size` don't have to be aligned. - They are internally rounded down/up to multiply of `nonCoherentAtomSize`. -- If `size` is 0, this call is ignored. -- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, - this call is ignored. - -Warning! `offset` and `size` are relative to the contents of given `allocation`. -If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. -Do not pass allocation's offset as `offset`!!! - -This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if -it is called, otherwise `VK_SUCCESS`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize offset, - VkDeviceSize size); - -/** \brief Flushes memory of given set of allocations. - -Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations. -For more information, see documentation of vmaFlushAllocation(). - -\param allocator -\param allocationCount -\param allocations -\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. -\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. - -This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is -called, otherwise `VK_SUCCESS`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t allocationCount, - const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, - const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, - const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); - -/** \brief Invalidates memory of given set of allocations. - -Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations. -For more information, see documentation of vmaInvalidateAllocation(). - -\param allocator -\param allocationCount -\param allocations -\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. -\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. - -This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is -called, otherwise `VK_SUCCESS`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t allocationCount, - const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, - const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, - const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); - -/** \brief Maps the allocation temporarily if needed, copies data from specified host pointer to it, and flushes the memory from the host caches if needed. - -\param allocator -\param pSrcHostPointer Pointer to the host data that become source of the copy. -\param dstAllocation Handle to the allocation that becomes destination of the copy. -\param dstAllocationLocalOffset Offset within `dstAllocation` where to write copied data, in bytes. -\param size Number of bytes to copy. - -This is a convenience function that allows to copy data from a host pointer to an allocation easily. -Same behavior can be achieved by calling vmaMapMemory(), `memcpy()`, vmaUnmapMemory(), vmaFlushAllocation(). - -This function can be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. -It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or -#VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. -Otherwise, the function will fail and generate a Validation Layers error. - -`dstAllocationLocalOffset` is relative to the contents of given `dstAllocation`. -If you mean whole allocation, you should pass 0. -Do not pass allocation's offset within device memory block this parameter! -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( - VmaAllocator VMA_NOT_NULL allocator, - const void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pSrcHostPointer, - VmaAllocation VMA_NOT_NULL dstAllocation, - VkDeviceSize dstAllocationLocalOffset, - VkDeviceSize size); - -/** \brief Invalidates memory in the host caches if needed, maps the allocation temporarily if needed, and copies data from it to a specified host pointer. - -\param allocator -\param srcAllocation Handle to the allocation that becomes source of the copy. -\param srcAllocationLocalOffset Offset within `srcAllocation` where to read copied data, in bytes. -\param pDstHostPointer Pointer to the host memory that become destination of the copy. -\param size Number of bytes to copy. - -This is a convenience function that allows to copy data from an allocation to a host pointer easily. -Same behavior can be achieved by calling vmaInvalidateAllocation(), vmaMapMemory(), `memcpy()`, vmaUnmapMemory(). - -This function should be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` -and `VK_MEMORY_PROPERTY_HOST_CACHED_BIT` flag. -It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. -Otherwise, the function may fail and generate a Validation Layers error. -It may also work very slowly when reading from an uncached memory. - -`srcAllocationLocalOffset` is relative to the contents of given `srcAllocation`. -If you mean whole allocation, you should pass 0. -Do not pass allocation's offset within device memory block as this parameter! -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL srcAllocation, - VkDeviceSize srcAllocationLocalOffset, - void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pDstHostPointer, - VkDeviceSize size); - -/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. - -\param allocator -\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked. - -Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, -`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are -`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). - -Possible return values: - -- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types. -- `VK_SUCCESS` - corruption detection has been performed and succeeded. -- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. - `VMA_ASSERT` is also fired in that case. -- Other value: Error returned by Vulkan, e.g. memory mapping failure. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( - VmaAllocator VMA_NOT_NULL allocator, - uint32_t memoryTypeBits); - -/** \brief Begins defragmentation process. - -\param allocator Allocator object. -\param pInfo Structure filled with parameters of defragmentation. -\param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation. -\returns -- `VK_SUCCESS` if defragmentation can begin. -- `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. - -For more information about defragmentation, see documentation chapter: -[Defragmentation](@ref defragmentation). -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( - VmaAllocator VMA_NOT_NULL allocator, - const VmaDefragmentationInfo* VMA_NOT_NULL pInfo, - VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext); - -/** \brief Ends defragmentation process. - -\param allocator Allocator object. -\param context Context object that has been created by vmaBeginDefragmentation(). -\param[out] pStats Optional stats for the defragmentation. Can be null. - -Use this function to finish defragmentation started by vmaBeginDefragmentation(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation( - VmaAllocator VMA_NOT_NULL allocator, - VmaDefragmentationContext VMA_NOT_NULL context, - VmaDefragmentationStats* VMA_NULLABLE pStats); - -/** \brief Starts single defragmentation pass. - -\param allocator Allocator object. -\param context Context object that has been created by vmaBeginDefragmentation(). -\param[out] pPassInfo Computed information for current pass. -\returns -- `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation. -- `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(), - and then preferably try another pass with vmaBeginDefragmentationPass(). -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( - VmaAllocator VMA_NOT_NULL allocator, - VmaDefragmentationContext VMA_NOT_NULL context, - VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); - -/** \brief Ends single defragmentation pass. - -\param allocator Allocator object. -\param context Context object that has been created by vmaBeginDefragmentation(). -\param pPassInfo Computed information for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you. - -Returns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible. - -Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`. -After this call: - -- Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY - (which is the default) will be pointing to the new destination place. -- Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY - will be freed. - -If no more moves are possible you can end whole defragmentation. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( - VmaAllocator VMA_NOT_NULL allocator, - VmaDefragmentationContext VMA_NOT_NULL context, - VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); - -/** \brief Binds buffer to allocation. - -Binds specified buffer to region of memory represented by specified allocation. -Gets `VkDeviceMemory` handle and offset from the allocation. -If you want to create a buffer, allocate memory for it and bind them together separately, -you should use this function for binding instead of standard `vkBindBufferMemory()`, -because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple -allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously -(which is illegal in Vulkan). - -It is recommended to use function vmaCreateBuffer() instead of this one. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer); - -/** \brief Binds buffer to allocation with additional parameters. - -\param allocator -\param allocation -\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. -\param buffer -\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null. - -This function is similar to vmaBindBufferMemory(), but it provides additional parameters. - -If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag -or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize allocationLocalOffset, - VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, - const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindBufferMemoryInfoKHR) pNext); - -/** \brief Binds image to allocation. - -Binds specified image to region of memory represented by specified allocation. -Gets `VkDeviceMemory` handle and offset from the allocation. -If you want to create an image, allocate memory for it and bind them together separately, -you should use this function for binding instead of standard `vkBindImageMemory()`, -because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple -allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously -(which is illegal in Vulkan). - -It is recommended to use function vmaCreateImage() instead of this one. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkImage VMA_NOT_NULL_NON_DISPATCHABLE image); - -/** \brief Binds image to allocation with additional parameters. - -\param allocator -\param allocation -\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. -\param image -\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. - -This function is similar to vmaBindImageMemory(), but it provides additional parameters. - -If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag -or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize allocationLocalOffset, - VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, - const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindImageMemoryInfoKHR) pNext); - -/** \brief Creates a new `VkBuffer`, allocates and binds memory for it. - -\param allocator -\param pBufferCreateInfo -\param pAllocationCreateInfo -\param[out] pBuffer Buffer that was created. -\param[out] pAllocation Allocation that was created. -\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). - -This function automatically: - --# Creates buffer. --# Allocates appropriate memory for it. --# Binds the buffer with the memory. - -If any of these operations fail, buffer and allocation are not created, -returned value is negative error code, `*pBuffer` and `*pAllocation` are null. - -If the function succeeded, you must destroy both buffer and allocation when you -no longer need them using either convenience function vmaDestroyBuffer() or -separately, using `vkDestroyBuffer()` and vmaFreeMemory(). - -If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, -VK_KHR_dedicated_allocation extension is used internally to query driver whether -it requires or prefers the new buffer to have dedicated allocation. If yes, -and if dedicated allocation is possible -(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated -allocation for this buffer, just like when using -#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. - -\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer, -although recommended as a good practice, is out of scope of this library and could be implemented -by the user as a higher-level logic on top of VMA. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( - VmaAllocator VMA_NOT_NULL allocator, - const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/** \brief Creates a buffer with additional minimum alignment. - -Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, -minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. -for interop with OpenGL. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( - VmaAllocator VMA_NOT_NULL allocator, - const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - VkDeviceSize minAlignment, - VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/** \brief Creates a new `VkBuffer`, binds already created memory for it. - -\param allocator -\param allocation Allocation that provides memory to be used for binding new buffer to it. -\param pBufferCreateInfo -\param[out] pBuffer Buffer that was created. - -This function automatically: - --# Creates buffer. --# Binds the buffer with the supplied memory. - -If any of these operations fail, buffer is not created, -returned value is negative error code and `*pBuffer` is null. - -If the function succeeded, you must destroy the buffer when you -no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding -allocation you can use convenience function vmaDestroyBuffer(). - -\note There is a new version of this function augmented with parameter `allocationLocalOffset` - see vmaCreateAliasingBuffer2(). -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, - VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); - -/** \brief Creates a new `VkBuffer`, binds already created memory for it. - -\param allocator -\param allocation Allocation that provides memory to be used for binding new buffer to it. -\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the allocation. Normally it should be 0. -\param pBufferCreateInfo -\param[out] pBuffer Buffer that was created. - -This function automatically: - --# Creates buffer. --# Binds the buffer with the supplied memory. - -If any of these operations fail, buffer is not created, -returned value is negative error code and `*pBuffer` is null. - -If the function succeeded, you must destroy the buffer when you -no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding -allocation you can use convenience function vmaDestroyBuffer(). - -\note This is a new version of the function augmented with parameter `allocationLocalOffset`. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize allocationLocalOffset, - const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, - VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); - -/** \brief Destroys Vulkan buffer and frees allocated memory. - -This is just a convenience function equivalent to: - -\code -vkDestroyBuffer(device, buffer, allocationCallbacks); -vmaFreeMemory(allocator, allocation); -\endcode - -It is safe to pass null as buffer and/or allocation. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( - VmaAllocator VMA_NOT_NULL allocator, - VkBuffer VMA_NULLABLE_NON_DISPATCHABLE buffer, - VmaAllocation VMA_NULLABLE allocation); - -/// Function similar to vmaCreateBuffer(). -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( - VmaAllocator VMA_NOT_NULL allocator, - const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, - const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, - VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage, - VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); - -/// Function similar to vmaCreateAliasingBuffer() but for images. -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, - VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); - -/// Function similar to vmaCreateAliasingBuffer2() but for images. -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2( - VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL allocation, - VkDeviceSize allocationLocalOffset, - const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, - VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); - -/** \brief Destroys Vulkan image and frees allocated memory. - -This is just a convenience function equivalent to: - -\code -vkDestroyImage(device, image, allocationCallbacks); -vmaFreeMemory(allocator, allocation); -\endcode - -It is safe to pass null as image and/or allocation. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( - VmaAllocator VMA_NOT_NULL allocator, - VkImage VMA_NULLABLE_NON_DISPATCHABLE image, - VmaAllocation VMA_NULLABLE allocation); - -/** @} */ - -/** -\addtogroup group_virtual -@{ -*/ - -/** \brief Creates new #VmaVirtualBlock object. - -\param pCreateInfo Parameters for creation. -\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( - const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock); - -/** \brief Destroys #VmaVirtualBlock object. - -Please note that you should consciously handle virtual allocations that could remain unfreed in the block. -You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock() -if you are sure this is what you want. If you do neither, an assert is called. - -If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`, -don't forget to free them. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock( - VmaVirtualBlock VMA_NULLABLE virtualBlock); - -/** \brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations. -*/ -VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty( - VmaVirtualBlock VMA_NOT_NULL virtualBlock); - -/** \brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo); - -/** \brief Allocates new virtual allocation inside given #VmaVirtualBlock. - -If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned -(despite the function doesn't ever allocate actual GPU memory). -`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`. - -\param virtualBlock Virtual block -\param pCreateInfo Parameters for the allocation -\param[out] pAllocation Returned handle of the new allocation -\param[out] pOffset Returned offset of the new allocation. Optional, can be null. -*/ -VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation, - VkDeviceSize* VMA_NULLABLE pOffset); - -/** \brief Frees virtual allocation inside given #VmaVirtualBlock. - -It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation); - -/** \brief Frees all virtual allocations inside given #VmaVirtualBlock. - -You must either call this function or free each virtual allocation individually with vmaVirtualFree() -before destroying a virtual block. Otherwise, an assert is called. - -If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`, -don't forget to free it as well. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock( - VmaVirtualBlock VMA_NOT_NULL virtualBlock); - -/** \brief Changes custom pointer associated with given virtual allocation. -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, - void* VMA_NULLABLE pUserData); - -/** \brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock. - -This function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - VmaStatistics* VMA_NOT_NULL pStats); - -/** \brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock. - -This function is slow to call. Use for debugging purposes. -For less detailed statistics, see vmaGetVirtualBlockStatistics(). -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - VmaDetailedStatistics* VMA_NOT_NULL pStats); - -/** @} */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( + const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator); + + /// Destroys allocator object. + VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( + VmaAllocator VMA_NULLABLE allocator); + + /** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc. + + It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to + `VkPhysicalDevice`, `VkDevice` etc. every time using this function. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo); + + /** + PhysicalDeviceProperties are fetched from physicalDevice by the allocator. + You can access it here, without fetching it again on your own. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties); + + /** + PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. + You can access it here, without fetching it again on your own. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); + + /** + \brief Given Memory Type Index, returns Property Flags of this memory type. + + This is just a convenience function. Same information can be obtained using + vmaGetMemoryProperties(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeIndex, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); + + /** \brief Sets index of the current frame. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t frameIndex); + + /** @} */ + + /** + \addtogroup group_stats + @{ + */ + + /** \brief Retrieves statistics from current state of the Allocator. + + This function is called "calculate" not "get" because it has to traverse all + internal data structures, so it may be quite slow. Use it for debugging purposes. + For faster but more brief statistics suitable to be called every frame or every allocation, + use vmaGetHeapBudgets(). + + Note that when using allocator from multiple threads, returned information may immediately + become outdated. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaTotalStatistics* VMA_NOT_NULL pStats); + + /** \brief Retrieves information about current memory usage and budget for all memory heaps. + + \param allocator + \param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used. + + This function is called "get" not "calculate" because it is very fast, suitable to be called + every frame or every allocation. For more detailed statistics use vmaCalculateStatistics(). + + Note that when using allocator from multiple threads, returned information may immediately + become outdated. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( + VmaAllocator VMA_NOT_NULL allocator, + VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pBudgets); + + /** @} */ + + /** + \addtogroup group_alloc + @{ + */ + + /** + \brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo. + + This algorithm tries to find a memory type that: + + - Is allowed by memoryTypeBits. + - Contains all the flags from pAllocationCreateInfo->requiredFlags. + - Matches intended usage. + - Has as many flags from pAllocationCreateInfo->preferredFlags as possible. + + \return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result + from this function or any other allocating function probably means that your + device doesn't support any memory type with requested features for the specific + type of resource you want to use it for. Please check parameters of your + resource, like image layout (OPTIMAL versus LINEAR) or mip level count. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeBits, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + + /** + \brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo. + + It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. + It internally creates a temporary, dummy buffer that never has memory bound. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + + /** + \brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo. + + It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. + It internally creates a temporary, dummy image that never has memory bound. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + + /** \brief Allocates Vulkan device memory and creates #VmaPool object. + + \param allocator Allocator object. + \param pCreateInfo Parameters of pool to create. + \param[out] pPool Handle to created pool. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( + VmaAllocator VMA_NOT_NULL allocator, + const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool); + + /** \brief Destroys #VmaPool object and frees Vulkan device memory. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NULLABLE pool); + + /** @} */ + + /** + \addtogroup group_stats + @{ + */ + + /** \brief Retrieves statistics of existing #VmaPool object. + + \param allocator Allocator object. + \param pool Pool object. + \param[out] pPoolStats Statistics of specified pool. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaStatistics* VMA_NOT_NULL pPoolStats); + + /** \brief Retrieves detailed statistics of existing #VmaPool object. + + \param allocator Allocator object. + \param pool Pool object. + \param[out] pPoolStats Statistics of specified pool. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaDetailedStatistics* VMA_NOT_NULL pPoolStats); + + /** @} */ + + /** + \addtogroup group_alloc + @{ + */ + + /** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions. + + Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, + `VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is + `HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). + + Possible return values: + + - `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. + - `VK_SUCCESS` - corruption detection has been performed and succeeded. + - `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. + - Other value: Error returned by Vulkan, e.g. memory mapping failure. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool); + + /** \brief Retrieves name of a custom pool. + + After the call `ppName` is either null or points to an internally-owned null-terminated string + containing name of the pool that was previously set. The pointer becomes invalid when the pool is + destroyed or its name is changed using vmaSetPoolName(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE* VMA_NOT_NULL ppName); + + /** \brief Sets name of a custom pool. + + `pName` can be either null or pointer to a null-terminated string with new name for the pool. + Function makes internal copy of the string, so it can be changed or freed immediately after this call. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE pName); + + /** \brief General purpose memory allocation. + + \param allocator + \param pVkMemoryRequirements + \param pCreateInfo + \param[out] pAllocation Handle to allocated memory. + \param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + + You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). + + It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(), + vmaCreateBuffer(), vmaCreateImage() instead whenever possible. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /** \brief General purpose memory allocation for multiple allocation objects at once. + + \param allocator Allocator object. + \param pVkMemoryRequirements Memory requirements for each allocation. + \param pCreateInfo Creation parameters for each allocation. + \param allocationCount Number of allocations to make. + \param[out] pAllocations Pointer to array that will be filled with handles to created allocations. + \param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations. + + You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). + + Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. + It is just a general purpose allocation function able to make multiple allocations at once. + It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times. + + All allocations are made using same parameters. All of them are created out of the same memory pool and type. + If any allocation fails, all allocations already made within this function call are also freed, so that when + returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo, + size_t allocationCount, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, + VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo); + + /** \brief Allocates memory suitable for given `VkBuffer`. + + \param allocator + \param buffer + \param pCreateInfo + \param[out] pAllocation Handle to allocated memory. + \param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + + It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory(). + + This is a special-purpose function. In most cases you should use vmaCreateBuffer(). + + You must free the allocation using vmaFreeMemory() when no longer needed. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /** \brief Allocates memory suitable for given `VkImage`. + + \param allocator + \param image + \param pCreateInfo + \param[out] pAllocation Handle to allocated memory. + \param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + + It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory(). + + This is a special-purpose function. In most cases you should use vmaCreateImage(). + + You must free the allocation using vmaFreeMemory() when no longer needed. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). + + Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( + VmaAllocator VMA_NOT_NULL allocator, + const VmaAllocation VMA_NULLABLE allocation); + + /** \brief Frees memory and destroys multiple allocations. + + Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding. + It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(), + vmaAllocateMemoryPages() and other functions. + It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times. + + Allocations in `pAllocations` array can come from any memory pools and types. + Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + size_t allocationCount, + const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations); + + /** \brief Returns current information about specified allocation. + + Current parameters of given allocation are returned in `pAllocationInfo`. + + Although this function doesn't lock any mutex, so it should be quite efficient, + you should avoid calling it too often. + You can retrieve same VmaAllocationInfo structure while creating your resource, from function + vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change + (e.g. due to defragmentation). + + There is also a new function vmaGetAllocationInfo2() that offers extended information + about the allocation, returned using new structure #VmaAllocationInfo2. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo); + + /** \brief Returns extended information about specified allocation. + + Current parameters of given allocation are returned in `pAllocationInfo`. + Extended parameters in structure #VmaAllocationInfo2 include memory block size + and a flag telling whether the allocation has dedicated memory. + It can be useful e.g. for interop with OpenGL. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo2* VMA_NOT_NULL pAllocationInfo); + + /** \brief Sets pUserData in given allocation to new value. + + The value of pointer `pUserData` is copied to allocation's `pUserData`. + It is opaque, so you can use it however you want - e.g. + as a pointer, ordinal number or some handle to you own data. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE pUserData); + + /** \brief Sets pName in given allocation to new value. + + `pName` must be either null, or pointer to a null-terminated string. The function + makes local copy of the string and sets it as allocation's `pName`. String + passed as pName doesn't need to be valid for whole lifetime of the allocation - + you can free it after this call. String previously pointed by allocation's + `pName` is freed from memory. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const char* VMA_NULLABLE pName); + + /** + \brief Given an allocation, returns Property Flags of its memory type. + + This is just a convenience function. Same information can be obtained using + vmaGetAllocationInfo() + vmaGetMemoryProperties(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); + + /** \brief Maps memory represented by given allocation and returns pointer to it. + + Maps memory represented by given allocation to make it accessible to CPU code. + When succeeded, `*ppData` contains pointer to first byte of this memory. + + \warning + If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is + correctly offsetted to the beginning of region assigned to this particular allocation. + Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block. + You should not add VmaAllocationInfo::offset to it! + + Mapping is internally reference-counted and synchronized, so despite raw Vulkan + function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory` + multiple times simultaneously, it is safe to call this function on allocations + assigned to the same memory block. Actual Vulkan memory will be mapped on first + mapping and unmapped on last unmapping. + + If the function succeeded, you must call vmaUnmapMemory() to unmap the + allocation when mapping is no longer needed or before freeing the allocation, at + the latest. + + It also safe to call this function multiple times on the same allocation. You + must call vmaUnmapMemory() same number of times as you called vmaMapMemory(). + + It is also safe to call this function on allocation created with + #VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time. + You must still call vmaUnmapMemory() same number of times as you called + vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the + "0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag. + + This function fails when used on allocation made in memory type that is not + `HOST_VISIBLE`. + + This function doesn't automatically flush or invalidate caches. + If the allocation is made from a memory types that is not `HOST_COHERENT`, + you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE* VMA_NOT_NULL ppData); + + /** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). + + For details, see description of vmaMapMemory(). + + This function doesn't automatically flush or invalidate caches. + If the allocation is made from a memory types that is not `HOST_COHERENT`, + you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation); + + /** \brief Flushes memory of given allocation. + + Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation. + It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`. + Unmap operation doesn't do that automatically. + + - `offset` must be relative to the beginning of allocation. + - `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. + - `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. + - If `size` is 0, this call is ignored. + - If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. + + Warning! `offset` and `size` are relative to the contents of given `allocation`. + If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. + Do not pass allocation's offset as `offset`!!! + + This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is + called, otherwise `VK_SUCCESS`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + + /** \brief Invalidates memory of given allocation. + + Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation. + It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`. + Map operation doesn't do that automatically. + + - `offset` must be relative to the beginning of allocation. + - `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. + - `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. + - If `size` is 0, this call is ignored. + - If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. + + Warning! `offset` and `size` are relative to the contents of given `allocation`. + If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. + Do not pass allocation's offset as `offset`!!! + + This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if + it is called, otherwise `VK_SUCCESS`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + + /** \brief Flushes memory of given set of allocations. + + Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations. + For more information, see documentation of vmaFlushAllocation(). + + \param allocator + \param allocationCount + \param allocations + \param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. + \param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + + This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is + called, otherwise `VK_SUCCESS`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + + /** \brief Invalidates memory of given set of allocations. + + Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations. + For more information, see documentation of vmaInvalidateAllocation(). + + \param allocator + \param allocationCount + \param allocations + \param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. + \param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + + This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is + called, otherwise `VK_SUCCESS`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + + /** \brief Maps the allocation temporarily if needed, copies data from specified host pointer to it, and flushes the memory from the host caches if needed. + + \param allocator + \param pSrcHostPointer Pointer to the host data that become source of the copy. + \param dstAllocation Handle to the allocation that becomes destination of the copy. + \param dstAllocationLocalOffset Offset within `dstAllocation` where to write copied data, in bytes. + \param size Number of bytes to copy. + + This is a convenience function that allows to copy data from a host pointer to an allocation easily. + Same behavior can be achieved by calling vmaMapMemory(), `memcpy()`, vmaUnmapMemory(), vmaFlushAllocation(). + + This function can be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. + It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or + #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. + Otherwise, the function will fail and generate a Validation Layers error. + + `dstAllocationLocalOffset` is relative to the contents of given `dstAllocation`. + If you mean whole allocation, you should pass 0. + Do not pass allocation's offset within device memory block this parameter! + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( + VmaAllocator VMA_NOT_NULL allocator, + const void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pSrcHostPointer, + VmaAllocation VMA_NOT_NULL dstAllocation, + VkDeviceSize dstAllocationLocalOffset, + VkDeviceSize size); + + /** \brief Invalidates memory in the host caches if needed, maps the allocation temporarily if needed, and copies data from it to a specified host pointer. + + \param allocator + \param srcAllocation Handle to the allocation that becomes source of the copy. + \param srcAllocationLocalOffset Offset within `srcAllocation` where to read copied data, in bytes. + \param pDstHostPointer Pointer to the host memory that become destination of the copy. + \param size Number of bytes to copy. + + This is a convenience function that allows to copy data from an allocation to a host pointer easily. + Same behavior can be achieved by calling vmaInvalidateAllocation(), vmaMapMemory(), `memcpy()`, vmaUnmapMemory(). + + This function should be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` + and `VK_MEMORY_PROPERTY_HOST_CACHED_BIT` flag. + It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. + Otherwise, the function may fail and generate a Validation Layers error. + It may also work very slowly when reading from an uncached memory. + + `srcAllocationLocalOffset` is relative to the contents of given `srcAllocation`. + If you mean whole allocation, you should pass 0. + Do not pass allocation's offset within device memory block as this parameter! + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL srcAllocation, + VkDeviceSize srcAllocationLocalOffset, + void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pDstHostPointer, + VkDeviceSize size); + + /** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. + + \param allocator + \param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked. + + Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, + `VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are + `HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). + + Possible return values: + + - `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types. + - `VK_SUCCESS` - corruption detection has been performed and succeeded. + - `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. + - Other value: Error returned by Vulkan, e.g. memory mapping failure. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeBits); + + /** \brief Begins defragmentation process. + + \param allocator Allocator object. + \param pInfo Structure filled with parameters of defragmentation. + \param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation. + \returns + - `VK_SUCCESS` if defragmentation can begin. + - `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. + + For more information about defragmentation, see documentation chapter: + [Defragmentation](@ref defragmentation). + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( + VmaAllocator VMA_NOT_NULL allocator, + const VmaDefragmentationInfo* VMA_NOT_NULL pInfo, + VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext); + + /** \brief Ends defragmentation process. + + \param allocator Allocator object. + \param context Context object that has been created by vmaBeginDefragmentation(). + \param[out] pStats Optional stats for the defragmentation. Can be null. + + Use this function to finish defragmentation started by vmaBeginDefragmentation(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationStats* VMA_NULLABLE pStats); + + /** \brief Starts single defragmentation pass. + + \param allocator Allocator object. + \param context Context object that has been created by vmaBeginDefragmentation(). + \param[out] pPassInfo Computed information for current pass. + \returns + - `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation. + - `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(), + and then preferably try another pass with vmaBeginDefragmentationPass(). + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); + + /** \brief Ends single defragmentation pass. + + \param allocator Allocator object. + \param context Context object that has been created by vmaBeginDefragmentation(). + \param pPassInfo Computed information for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you. + + Returns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible. + + Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`. + After this call: + + - Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY + (which is the default) will be pointing to the new destination place. + - Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY + will be freed. + + If no more moves are possible you can end whole defragmentation. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); + + /** \brief Binds buffer to allocation. + + Binds specified buffer to region of memory represented by specified allocation. + Gets `VkDeviceMemory` handle and offset from the allocation. + If you want to create a buffer, allocate memory for it and bind them together separately, + you should use this function for binding instead of standard `vkBindBufferMemory()`, + because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple + allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously + (which is illegal in Vulkan). + + It is recommended to use function vmaCreateBuffer() instead of this one. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer); + + /** \brief Binds buffer to allocation with additional parameters. + + \param allocator + \param allocation + \param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. + \param buffer + \param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null. + + This function is similar to vmaBindBufferMemory(), but it provides additional parameters. + + If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag + or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindBufferMemoryInfoKHR) pNext); + + /** \brief Binds image to allocation. + + Binds specified image to region of memory represented by specified allocation. + Gets `VkDeviceMemory` handle and offset from the allocation. + If you want to create an image, allocate memory for it and bind them together separately, + you should use this function for binding instead of standard `vkBindImageMemory()`, + because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple + allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously + (which is illegal in Vulkan). + + It is recommended to use function vmaCreateImage() instead of this one. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image); + + /** \brief Binds image to allocation with additional parameters. + + \param allocator + \param allocation + \param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. + \param image + \param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. + + This function is similar to vmaBindImageMemory(), but it provides additional parameters. + + If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag + or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindImageMemoryInfoKHR) pNext); + + /** \brief Creates a new `VkBuffer`, allocates and binds memory for it. + + \param allocator + \param pBufferCreateInfo + \param pAllocationCreateInfo + \param[out] pBuffer Buffer that was created. + \param[out] pAllocation Allocation that was created. + \param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + + This function automatically: + + -# Creates buffer. + -# Allocates appropriate memory for it. + -# Binds the buffer with the memory. + + If any of these operations fail, buffer and allocation are not created, + returned value is negative error code, `*pBuffer` and `*pAllocation` are null. + + If the function succeeded, you must destroy both buffer and allocation when you + no longer need them using either convenience function vmaDestroyBuffer() or + separately, using `vkDestroyBuffer()` and vmaFreeMemory(). + + If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, + VK_KHR_dedicated_allocation extension is used internally to query driver whether + it requires or prefers the new buffer to have dedicated allocation. If yes, + and if dedicated allocation is possible + (#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated + allocation for this buffer, just like when using + #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + + \note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer, + although recommended as a good practice, is out of scope of this library and could be implemented + by the user as a higher-level logic on top of VMA. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /** \brief Creates a buffer with additional minimum alignment. + + Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, + minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. + for interop with OpenGL. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkDeviceSize minAlignment, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /** \brief Creates a new `VkBuffer`, binds already created memory for it. + + \param allocator + \param allocation Allocation that provides memory to be used for binding new buffer to it. + \param pBufferCreateInfo + \param[out] pBuffer Buffer that was created. + + This function automatically: + + -# Creates buffer. + -# Binds the buffer with the supplied memory. + + If any of these operations fail, buffer is not created, + returned value is negative error code and `*pBuffer` is null. + + If the function succeeded, you must destroy the buffer when you + no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding + allocation you can use convenience function vmaDestroyBuffer(). + + \note There is a new version of this function augmented with parameter `allocationLocalOffset` - see vmaCreateAliasingBuffer2(). + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); + + /** \brief Creates a new `VkBuffer`, binds already created memory for it. + + \param allocator + \param allocation Allocation that provides memory to be used for binding new buffer to it. + \param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the allocation. Normally it should be 0. + \param pBufferCreateInfo + \param[out] pBuffer Buffer that was created. + + This function automatically: + + -# Creates buffer. + -# Binds the buffer with the supplied memory. + + If any of these operations fail, buffer is not created, + returned value is negative error code and `*pBuffer` is null. + + If the function succeeded, you must destroy the buffer when you + no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding + allocation you can use convenience function vmaDestroyBuffer(). + + \note This is a new version of the function augmented with parameter `allocationLocalOffset`. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); + + /** \brief Destroys Vulkan buffer and frees allocated memory. + + This is just a convenience function equivalent to: + + \code + vkDestroyBuffer(device, buffer, allocationCallbacks); + vmaFreeMemory(allocator, allocation); + \endcode + + It is safe to pass null as buffer and/or allocation. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE buffer, + VmaAllocation VMA_NULLABLE allocation); + + /// Function similar to vmaCreateBuffer(). + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + + /// Function similar to vmaCreateAliasingBuffer() but for images. + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); + + /// Function similar to vmaCreateAliasingBuffer2() but for images. + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); + + /** \brief Destroys Vulkan image and frees allocated memory. + + This is just a convenience function equivalent to: + + \code + vkDestroyImage(device, image, allocationCallbacks); + vmaFreeMemory(allocator, allocation); + \endcode + + It is safe to pass null as image and/or allocation. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NULLABLE_NON_DISPATCHABLE image, + VmaAllocation VMA_NULLABLE allocation); + + /** @} */ + + /** + \addtogroup group_virtual + @{ + */ + + /** \brief Creates new #VmaVirtualBlock object. + + \param pCreateInfo Parameters for creation. + \param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( + const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock); + + /** \brief Destroys #VmaVirtualBlock object. + + Please note that you should consciously handle virtual allocations that could remain unfreed in the block. + You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock() + if you are sure this is what you want. If you do neither, an assert is called. + + If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`, + don't forget to free them. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock( + VmaVirtualBlock VMA_NULLABLE virtualBlock); + + /** \brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations. + */ + VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + + /** \brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo); + + /** \brief Allocates new virtual allocation inside given #VmaVirtualBlock. + + If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned + (despite the function doesn't ever allocate actual GPU memory). + `pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`. + + \param virtualBlock Virtual block + \param pCreateInfo Parameters for the allocation + \param[out] pAllocation Returned handle of the new allocation + \param[out] pOffset Returned offset of the new allocation. Optional, can be null. + */ + VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation, + VkDeviceSize* VMA_NULLABLE pOffset); + + /** \brief Frees virtual allocation inside given #VmaVirtualBlock. + + It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation); + + /** \brief Frees all virtual allocations inside given #VmaVirtualBlock. + + You must either call this function or free each virtual allocation individually with vmaVirtualFree() + before destroying a virtual block. Otherwise, an assert is called. + + If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`, + don't forget to free it as well. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + + /** \brief Changes custom pointer associated with given virtual allocation. + */ + VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, + void* VMA_NULLABLE pUserData); + + /** \brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock. + + This function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaStatistics* VMA_NOT_NULL pStats); + + /** \brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock. + + This function is slow to call. Use for debugging purposes. + For less detailed statistics, see vmaGetVirtualBlockStatistics(). + */ + VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaDetailedStatistics* VMA_NOT_NULL pStats); + + /** @} */ #if VMA_STATS_STRING_ENABLED /** @@ -2716,31 +2716,31 @@ VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics( Returned string must be freed using vmaFreeVirtualBlockStatsString(). */ -VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, - VkBool32 detailedMap); + VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); -/// Frees a string returned by vmaBuildVirtualBlockStatsString(). -VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString( - VmaVirtualBlock VMA_NOT_NULL virtualBlock, - char* VMA_NULLABLE pStatsString); + /// Frees a string returned by vmaBuildVirtualBlockStatsString(). + VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE pStatsString); -/** \brief Builds and returns statistics as a null-terminated string in JSON format. -\param allocator -\param[out] ppStatsString Must be freed using vmaFreeStatsString() function. -\param detailedMap -*/ -VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( - VmaAllocator VMA_NOT_NULL allocator, - char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, - VkBool32 detailedMap); + /** \brief Builds and returns statistics as a null-terminated string in JSON format. + \param allocator + \param[out] ppStatsString Must be freed using vmaFreeStatsString() function. + \param detailedMap + */ + VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); -VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( - VmaAllocator VMA_NOT_NULL allocator, - char* VMA_NULLABLE pStatsString); + VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE pStatsString); -/** @} */ + /** @} */ #endif // VMA_STATS_STRING_ENABLED @@ -2776,22 +2776,22 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( #include #if !defined(VMA_CPP20) - #if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20 - #define VMA_CPP20 1 - #else - #define VMA_CPP20 0 - #endif +#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20 +#define VMA_CPP20 1 +#else +#define VMA_CPP20 0 +#endif #endif #ifdef _MSC_VER - #include // For functions like __popcnt, _BitScanForward etc. +#include // For functions like __popcnt, _BitScanForward etc. #endif #if VMA_CPP20 - #include +#include #endif #if VMA_STATS_STRING_ENABLED - #include // For snprintf +#include // For snprintf #endif /******************************************************************************* @@ -2809,7 +2809,7 @@ internally, like: vulkanFunctions.vkAllocateMemory = &vkAllocateMemory; */ #if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES) - #define VMA_STATIC_VULKAN_FUNCTIONS 1 +#define VMA_STATIC_VULKAN_FUNCTIONS 1 #endif /* @@ -2823,19 +2823,19 @@ VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null. */ #if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS) - #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 +#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #endif #ifndef VMA_USE_STL_SHARED_MUTEX - #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 - #define VMA_USE_STL_SHARED_MUTEX 1 - // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus - // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2. - #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L - #define VMA_USE_STL_SHARED_MUTEX 1 - #else - #define VMA_USE_STL_SHARED_MUTEX 0 - #endif +#if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 +#define VMA_USE_STL_SHARED_MUTEX 1 +// Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus +// Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2. +#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L +#define VMA_USE_STL_SHARED_MUTEX 1 +#else +#define VMA_USE_STL_SHARED_MUTEX 0 +#endif #endif /* @@ -2860,48 +2860,48 @@ The following headers are used in this CONFIGURATION section only, so feel free remove them if not needed. */ #if !defined(VMA_CONFIGURATION_USER_INCLUDES_H) - #include // for assert - #include // for min, max, swap - #include +#include // for assert +#include // for min, max, swap +#include #else - #include VMA_CONFIGURATION_USER_INCLUDES_H +#include VMA_CONFIGURATION_USER_INCLUDES_H #endif #ifndef VMA_NULL - // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. - #define VMA_NULL nullptr +// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. +#define VMA_NULL nullptr #endif #ifndef VMA_FALLTHROUGH - #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 - #define VMA_FALLTHROUGH [[fallthrough]] - #else - #define VMA_FALLTHROUGH - #endif +#if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 +#define VMA_FALLTHROUGH [[fallthrough]] +#else +#define VMA_FALLTHROUGH +#endif #endif // Normal assert to check for programmer's errors, especially in Debug configuration. #ifndef VMA_ASSERT - #ifdef NDEBUG - #define VMA_ASSERT(expr) - #else - #define VMA_ASSERT(expr) assert(expr) - #endif +#ifdef NDEBUG +#define VMA_ASSERT(expr) +#else +#define VMA_ASSERT(expr) assert(expr) +#endif #endif // Assert that will be called very often, like inside data structures e.g. operator[]. // Making it non-empty can make program slow. #ifndef VMA_HEAVY_ASSERT - #ifdef NDEBUG - #define VMA_HEAVY_ASSERT(expr) - #else - #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) - #endif +#ifdef NDEBUG +#define VMA_HEAVY_ASSERT(expr) +#else +#define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) +#endif #endif // Assert used for reporting memory leaks - unfreed allocations. #ifndef VMA_ASSERT_LEAK - #define VMA_ASSERT_LEAK(expr) VMA_ASSERT(expr) +#define VMA_ASSERT_LEAK(expr) VMA_ASSERT(expr) #endif // If your compiler is not compatible with C++17 and definition of @@ -2914,7 +2914,7 @@ remove them if not needed. static void* vma_aligned_alloc(size_t alignment, size_t size) { // alignment must be >= sizeof(void*) - if(alignment < sizeof(void*)) + if (alignment < sizeof(void*)) { alignment = sizeof(void*); } @@ -2946,13 +2946,13 @@ static void* vma_aligned_alloc(size_t alignment, size_t size) //#endif // alignment must be >= sizeof(void*) - if(alignment < sizeof(void*)) + if (alignment < sizeof(void*)) { alignment = sizeof(void*); } - void *pointer; - if(posix_memalign(&pointer, alignment, size) == 0) + void* pointer; + if (posix_memalign(&pointer, alignment, size) == 0) return pointer; return VMA_NULL; } @@ -2987,75 +2987,75 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr) #endif #ifndef VMA_ALIGN_OF - #define VMA_ALIGN_OF(type) (alignof(type)) +#define VMA_ALIGN_OF(type) (alignof(type)) #endif #ifndef VMA_SYSTEM_ALIGNED_MALLOC - #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) vma_aligned_alloc((alignment), (size)) +#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) vma_aligned_alloc((alignment), (size)) #endif #ifndef VMA_SYSTEM_ALIGNED_FREE - // VMA_SYSTEM_FREE is the old name, but might have been defined by the user - #if defined(VMA_SYSTEM_FREE) - #define VMA_SYSTEM_ALIGNED_FREE(ptr) VMA_SYSTEM_FREE(ptr) - #else - #define VMA_SYSTEM_ALIGNED_FREE(ptr) vma_aligned_free(ptr) - #endif +// VMA_SYSTEM_FREE is the old name, but might have been defined by the user +#if defined(VMA_SYSTEM_FREE) +#define VMA_SYSTEM_ALIGNED_FREE(ptr) VMA_SYSTEM_FREE(ptr) +#else +#define VMA_SYSTEM_ALIGNED_FREE(ptr) vma_aligned_free(ptr) +#endif #endif #ifndef VMA_COUNT_BITS_SET // Returns number of bits set to 1 in (v) - #define VMA_COUNT_BITS_SET(v) VmaCountBitsSet(v) +#define VMA_COUNT_BITS_SET(v) VmaCountBitsSet(v) #endif #ifndef VMA_BITSCAN_LSB // Scans integer for index of first nonzero value from the Least Significant Bit (LSB). If mask is 0 then returns UINT8_MAX - #define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask) +#define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask) #endif #ifndef VMA_BITSCAN_MSB // Scans integer for index of first nonzero value from the Most Significant Bit (MSB). If mask is 0 then returns UINT8_MAX - #define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask) +#define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask) #endif #ifndef VMA_MIN - #define VMA_MIN(v1, v2) ((std::min)((v1), (v2))) +#define VMA_MIN(v1, v2) ((std::min)((v1), (v2))) #endif #ifndef VMA_MAX - #define VMA_MAX(v1, v2) ((std::max)((v1), (v2))) +#define VMA_MAX(v1, v2) ((std::max)((v1), (v2))) #endif #ifndef VMA_SORT - #define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp) +#define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp) #endif #ifndef VMA_DEBUG_LOG_FORMAT - #define VMA_DEBUG_LOG_FORMAT(format, ...) - /* - #define VMA_DEBUG_LOG_FORMAT(format, ...) do { \ - printf((format), __VA_ARGS__); \ - printf("\n"); \ - } while(false) - */ +#define VMA_DEBUG_LOG_FORMAT(format, ...) +/* +#define VMA_DEBUG_LOG_FORMAT(format, ...) do { \ + printf((format), __VA_ARGS__); \ + printf("\n"); \ +} while(false) +*/ #endif #ifndef VMA_DEBUG_LOG - #define VMA_DEBUG_LOG(str) VMA_DEBUG_LOG_FORMAT("%s", (str)) +#define VMA_DEBUG_LOG(str) VMA_DEBUG_LOG_FORMAT("%s", (str)) #endif #ifndef VMA_LEAK_LOG_FORMAT - #define VMA_LEAK_LOG_FORMAT(format, ...) VMA_DEBUG_LOG_FORMAT(format, __VA_ARGS__) +#define VMA_LEAK_LOG_FORMAT(format, ...) VMA_DEBUG_LOG_FORMAT(format, __VA_ARGS__) #endif #ifndef VMA_CLASS_NO_COPY - #define VMA_CLASS_NO_COPY(className) \ +#define VMA_CLASS_NO_COPY(className) \ private: \ className(const className&) = delete; \ className& operator=(const className&) = delete; #endif #ifndef VMA_CLASS_NO_COPY_NO_MOVE - #define VMA_CLASS_NO_COPY_NO_MOVE(className) \ +#define VMA_CLASS_NO_COPY_NO_MOVE(className) \ private: \ className(const className&) = delete; \ className(className&&) = delete; \ @@ -3065,178 +3065,178 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr) // Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString. #if VMA_STATS_STRING_ENABLED - static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num) - { - snprintf(outStr, strLen, "%" PRIu32, num); - } - static inline void VmaUint64ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint64_t num) - { - snprintf(outStr, strLen, "%" PRIu64, num); - } - static inline void VmaPtrToStr(char* VMA_NOT_NULL outStr, size_t strLen, const void* ptr) - { - snprintf(outStr, strLen, "%p", ptr); - } +static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num) +{ + snprintf(outStr, strLen, "%" PRIu32, num); +} +static inline void VmaUint64ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint64_t num) +{ + snprintf(outStr, strLen, "%" PRIu64, num); +} +static inline void VmaPtrToStr(char* VMA_NOT_NULL outStr, size_t strLen, const void* ptr) +{ + snprintf(outStr, strLen, "%p", ptr); +} #endif #ifndef VMA_MUTEX - class VmaMutex - { +class VmaMutex +{ VMA_CLASS_NO_COPY_NO_MOVE(VmaMutex) - public: - VmaMutex() { } - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } - bool TryLock() { return m_Mutex.try_lock(); } - private: - std::mutex m_Mutex; - }; - #define VMA_MUTEX VmaMutex +public: + VmaMutex() { } + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } + bool TryLock() { return m_Mutex.try_lock(); } +private: + std::mutex m_Mutex; +}; +#define VMA_MUTEX VmaMutex #endif // Read-write mutex, where "read" is shared access, "write" is exclusive access. #ifndef VMA_RW_MUTEX - #if VMA_USE_STL_SHARED_MUTEX - // Use std::shared_mutex from C++17. - #include - class VmaRWMutex - { - public: - void LockRead() { m_Mutex.lock_shared(); } - void UnlockRead() { m_Mutex.unlock_shared(); } - bool TryLockRead() { return m_Mutex.try_lock_shared(); } - void LockWrite() { m_Mutex.lock(); } - void UnlockWrite() { m_Mutex.unlock(); } - bool TryLockWrite() { return m_Mutex.try_lock(); } - private: - std::shared_mutex m_Mutex; - }; - #define VMA_RW_MUTEX VmaRWMutex - #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600 - // Use SRWLOCK from WinAPI. - // Minimum supported client = Windows Vista, server = Windows Server 2008. - class VmaRWMutex - { - public: - VmaRWMutex() { InitializeSRWLock(&m_Lock); } - void LockRead() { AcquireSRWLockShared(&m_Lock); } - void UnlockRead() { ReleaseSRWLockShared(&m_Lock); } - bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; } - void LockWrite() { AcquireSRWLockExclusive(&m_Lock); } - void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); } - bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; } - private: - SRWLOCK m_Lock; - }; - #define VMA_RW_MUTEX VmaRWMutex - #else - // Less efficient fallback: Use normal mutex. - class VmaRWMutex - { - public: - void LockRead() { m_Mutex.Lock(); } - void UnlockRead() { m_Mutex.Unlock(); } - bool TryLockRead() { return m_Mutex.TryLock(); } - void LockWrite() { m_Mutex.Lock(); } - void UnlockWrite() { m_Mutex.Unlock(); } - bool TryLockWrite() { return m_Mutex.TryLock(); } - private: - VMA_MUTEX m_Mutex; - }; - #define VMA_RW_MUTEX VmaRWMutex - #endif // #if VMA_USE_STL_SHARED_MUTEX +#if VMA_USE_STL_SHARED_MUTEX + // Use std::shared_mutex from C++17. +#include +class VmaRWMutex +{ +public: + void LockRead() { m_Mutex.lock_shared(); } + void UnlockRead() { m_Mutex.unlock_shared(); } + bool TryLockRead() { return m_Mutex.try_lock_shared(); } + void LockWrite() { m_Mutex.lock(); } + void UnlockWrite() { m_Mutex.unlock(); } + bool TryLockWrite() { return m_Mutex.try_lock(); } +private: + std::shared_mutex m_Mutex; +}; +#define VMA_RW_MUTEX VmaRWMutex +#elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600 + // Use SRWLOCK from WinAPI. + // Minimum supported client = Windows Vista, server = Windows Server 2008. +class VmaRWMutex +{ +public: + VmaRWMutex() { InitializeSRWLock(&m_Lock); } + void LockRead() { AcquireSRWLockShared(&m_Lock); } + void UnlockRead() { ReleaseSRWLockShared(&m_Lock); } + bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; } + void LockWrite() { AcquireSRWLockExclusive(&m_Lock); } + void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); } + bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; } +private: + SRWLOCK m_Lock; +}; +#define VMA_RW_MUTEX VmaRWMutex +#else + // Less efficient fallback: Use normal mutex. +class VmaRWMutex +{ +public: + void LockRead() { m_Mutex.Lock(); } + void UnlockRead() { m_Mutex.Unlock(); } + bool TryLockRead() { return m_Mutex.TryLock(); } + void LockWrite() { m_Mutex.Lock(); } + void UnlockWrite() { m_Mutex.Unlock(); } + bool TryLockWrite() { return m_Mutex.TryLock(); } +private: + VMA_MUTEX m_Mutex; +}; +#define VMA_RW_MUTEX VmaRWMutex +#endif // #if VMA_USE_STL_SHARED_MUTEX #endif // #ifndef VMA_RW_MUTEX /* If providing your own implementation, you need to implement a subset of std::atomic. */ #ifndef VMA_ATOMIC_UINT32 - #include - #define VMA_ATOMIC_UINT32 std::atomic +#include +#define VMA_ATOMIC_UINT32 std::atomic #endif #ifndef VMA_ATOMIC_UINT64 - #include - #define VMA_ATOMIC_UINT64 std::atomic +#include +#define VMA_ATOMIC_UINT64 std::atomic #endif #ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY - /** - Every allocation will have its own memory block. - Define to 1 for debugging purposes only. - */ - #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0) +/** +Every allocation will have its own memory block. +Define to 1 for debugging purposes only. +*/ +#define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0) #endif #ifndef VMA_MIN_ALIGNMENT - /** - Minimum alignment of all allocations, in bytes. - Set to more than 1 for debugging purposes. Must be power of two. - */ - #ifdef VMA_DEBUG_ALIGNMENT // Old name - #define VMA_MIN_ALIGNMENT VMA_DEBUG_ALIGNMENT - #else - #define VMA_MIN_ALIGNMENT (1) - #endif +/** +Minimum alignment of all allocations, in bytes. +Set to more than 1 for debugging purposes. Must be power of two. +*/ +#ifdef VMA_DEBUG_ALIGNMENT // Old name +#define VMA_MIN_ALIGNMENT VMA_DEBUG_ALIGNMENT +#else +#define VMA_MIN_ALIGNMENT (1) +#endif #endif #ifndef VMA_DEBUG_MARGIN - /** - Minimum margin after every allocation, in bytes. - Set nonzero for debugging purposes only. - */ - #define VMA_DEBUG_MARGIN (0) +/** +Minimum margin after every allocation, in bytes. +Set nonzero for debugging purposes only. +*/ +#define VMA_DEBUG_MARGIN (0) #endif #ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS - /** - Define this macro to 1 to automatically fill new allocations and destroyed - allocations with some bit pattern. - */ - #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0) +/** +Define this macro to 1 to automatically fill new allocations and destroyed +allocations with some bit pattern. +*/ +#define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0) #endif #ifndef VMA_DEBUG_DETECT_CORRUPTION - /** - Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to - enable writing magic value to the margin after every allocation and - validating it, so that memory corruptions (out-of-bounds writes) are detected. - */ - #define VMA_DEBUG_DETECT_CORRUPTION (0) +/** +Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to +enable writing magic value to the margin after every allocation and +validating it, so that memory corruptions (out-of-bounds writes) are detected. +*/ +#define VMA_DEBUG_DETECT_CORRUPTION (0) #endif #ifndef VMA_DEBUG_GLOBAL_MUTEX - /** - Set this to 1 for debugging purposes only, to enable single mutex protecting all - entry calls to the library. Can be useful for debugging multithreading issues. - */ - #define VMA_DEBUG_GLOBAL_MUTEX (0) +/** +Set this to 1 for debugging purposes only, to enable single mutex protecting all +entry calls to the library. Can be useful for debugging multithreading issues. +*/ +#define VMA_DEBUG_GLOBAL_MUTEX (0) #endif #ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY - /** - Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. - Set to more than 1 for debugging purposes only. Must be power of two. - */ - #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1) +/** +Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. +Set to more than 1 for debugging purposes only. Must be power of two. +*/ +#define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1) #endif #ifndef VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT - /* - Set this to 1 to make VMA never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount - and return error instead of leaving up to Vulkan implementation what to do in such cases. - */ - #define VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT (0) +/* +Set this to 1 to make VMA never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount +and return error instead of leaving up to Vulkan implementation what to do in such cases. +*/ +#define VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT (0) #endif #ifndef VMA_SMALL_HEAP_MAX_SIZE - /// Maximum size of a memory heap in Vulkan to consider it "small". - #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024) +/// Maximum size of a memory heap in Vulkan to consider it "small". +#define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024) #endif #ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE /// Default size of a block allocated as single VkDeviceMemory from a "large" heap. - #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024) +#define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024) #endif /* @@ -3247,7 +3247,7 @@ vkMapMemory/vkUnmapMemory too many times, which may improve performance and help tools like RenderDoc. */ #ifndef VMA_MAPPING_HYSTERESIS_ENABLED - #define VMA_MAPPING_HYSTERESIS_ENABLED 1 +#define VMA_MAPPING_HYSTERESIS_ENABLED 1 #endif #define VMA_VALIDATE(cond) do { if(!(cond)) { \ @@ -3296,7 +3296,7 @@ static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = #endif static VkAllocationCallbacks VmaEmptyAllocationCallbacks = - { VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL }; +{ VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL }; #ifndef _VMA_ENUM_DECLARATIONS @@ -3436,7 +3436,7 @@ static inline uint8_t VmaBitScanLSB(uint64_t mask) return static_cast(pos); return UINT8_MAX; #elif VMA_CPP20 - if(mask) + if (mask) return static_cast(std::countr_zero(mask)); return UINT8_MAX; #elif defined __GNUC__ || defined __clang__ @@ -3462,7 +3462,7 @@ static inline uint8_t VmaBitScanLSB(uint32_t mask) return static_cast(pos); return UINT8_MAX; #elif VMA_CPP20 - if(mask) + if (mask) return static_cast(std::countr_zero(mask)); return UINT8_MAX; #elif defined __GNUC__ || defined __clang__ @@ -3487,7 +3487,7 @@ static inline uint8_t VmaBitScanMSB(uint64_t mask) if (_BitScanReverse64(&pos, mask)) return static_cast(pos); #elif VMA_CPP20 - if(mask) + if (mask) return 63 - static_cast(std::countl_zero(mask)); #elif defined __GNUC__ || defined __clang__ if (mask) @@ -3512,7 +3512,7 @@ static inline uint8_t VmaBitScanMSB(uint32_t mask) if (_BitScanReverse(&pos, mask)) return static_cast(pos); #elif VMA_CPP20 - if(mask) + if (mask) return 31 - static_cast(std::countl_zero(mask)); #elif defined __GNUC__ || defined __clang__ if (mask) @@ -3811,10 +3811,10 @@ static inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct) template static inline const FindT* VmaPnextChainFind(const MainT* mainStruct, VkStructureType sType) { - for(const VkBaseInStructure* s = (const VkBaseInStructure*)mainStruct->pNext; + for (const VkBaseInStructure* s = (const VkBaseInStructure*)mainStruct->pNext; s != VMA_NULL; s = s->pNext) { - if(s->sType == sType) + if (s->sType == sType) { return (const FindT*)s; } @@ -3837,8 +3837,8 @@ struct VmaBufferImageUsage VmaBufferImageUsage() { *this = UNKNOWN; } explicit VmaBufferImageUsage(BaseType usage) : Value(usage) { } - VmaBufferImageUsage(const VkBufferCreateInfo &createInfo, bool useKhrMaintenance5); - explicit VmaBufferImageUsage(const VkImageCreateInfo &createInfo); + VmaBufferImageUsage(const VkBufferCreateInfo& createInfo, bool useKhrMaintenance5); + explicit VmaBufferImageUsage(const VkImageCreateInfo& createInfo); bool operator==(const VmaBufferImageUsage& rhs) const { return Value == rhs.Value; } bool operator!=(const VmaBufferImageUsage& rhs) const { return Value != rhs.Value; } @@ -3853,18 +3853,18 @@ struct VmaBufferImageUsage const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0); -VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo, +VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo& createInfo, bool useKhrMaintenance5) { #if VMA_KHR_MAINTENANCE5 - if(useKhrMaintenance5) + if (useKhrMaintenance5) { // If VkBufferCreateInfo::pNext chain contains VkBufferUsageFlags2CreateInfoKHR, // take usage from it and ignore VkBufferCreateInfo::usage, per specification // of the VK_KHR_maintenance5 extension. const VkBufferUsageFlags2CreateInfoKHR* const usageFlags2 = VmaPnextChainFind(&createInfo, VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR); - if(usageFlags2) + if (usageFlags2) { this->Value = usageFlags2->usage; return; @@ -3875,7 +3875,7 @@ VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo, this->Value = (BaseType)createInfo.usage; } -VmaBufferImageUsage::VmaBufferImageUsage(const VkImageCreateInfo &createInfo) +VmaBufferImageUsage::VmaBufferImageUsage(const VkImageCreateInfo& createInfo) { // Maybe in the future there will be VK_KHR_maintenanceN extension with structure // VkImageUsageFlags2CreateInfoKHR, like the one for buffers... @@ -3897,12 +3897,12 @@ static bool FindMemoryPreferences( outPreferredFlags = allocCreateInfo.preferredFlags; outNotPreferredFlags = 0; - switch(allocCreateInfo.usage) + switch (allocCreateInfo.usage) { case VMA_MEMORY_USAGE_UNKNOWN: break; case VMA_MEMORY_USAGE_GPU_ONLY: - if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + if (!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; } @@ -3912,7 +3912,7 @@ static bool FindMemoryPreferences( break; case VMA_MEMORY_USAGE_CPU_TO_GPU: outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + if (!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; } @@ -3931,10 +3931,10 @@ static bool FindMemoryPreferences( case VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE: case VMA_MEMORY_USAGE_AUTO_PREFER_HOST: { - if(bufImgUsage == VmaBufferImageUsage::UNKNOWN) + if (bufImgUsage == VmaBufferImageUsage::UNKNOWN) { VMA_ASSERT(0 && "VMA_MEMORY_USAGE_AUTO* values can only be used with functions like vmaCreateBuffer, vmaCreateImage so that the details of the created resource are known." - " Maybe you use VkBufferUsageFlags2CreateInfoKHR but forgot to use VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT?" ); + " Maybe you use VkBufferUsageFlags2CreateInfoKHR but forgot to use VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT?"); return false; } @@ -3946,7 +3946,7 @@ static bool FindMemoryPreferences( const bool preferHost = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST; // CPU random access - e.g. a buffer written to or transferred from GPU to read back on CPU. - if(hostAccessRandom) + if (hostAccessRandom) { // Prefer cached. Cannot require it, because some platforms don't have it (e.g. Raspberry Pi - see #362)! outPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; @@ -3966,12 +3966,12 @@ static bool FindMemoryPreferences( } } // CPU sequential write - may be CPU or host-visible GPU memory, uncached and write-combined. - else if(hostAccessSequentialWrite) + else if (hostAccessSequentialWrite) { // Want uncached and write-combined. outNotPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost) + if (!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost) { outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; } @@ -3979,10 +3979,10 @@ static bool FindMemoryPreferences( { outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; // Direct GPU access, CPU sequential write (e.g. a dynamic uniform buffer updated every frame) - if(deviceAccess) + if (deviceAccess) { // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose GPU memory. - if(preferHost) + if (preferHost) outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; else outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; @@ -3991,7 +3991,7 @@ static bool FindMemoryPreferences( else { // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose CPU memory. - if(preferDevice) + if (preferDevice) outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; else outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; @@ -4013,7 +4013,7 @@ static bool FindMemoryPreferences( // a "swap file" copy to free some GPU memory (then better CPU memory). // Up to the user to decide. If no preferece, assume the former and choose GPU memory. - if(preferHost) + if (preferHost) outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; else outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; @@ -4025,7 +4025,7 @@ static bool FindMemoryPreferences( } // Avoid DEVICE_COHERENT unless explicitly requested. - if(((allocCreateInfo.requiredFlags | allocCreateInfo.preferredFlags) & + if (((allocCreateInfo.requiredFlags | allocCreateInfo.preferredFlags) & (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0) { outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY; @@ -4238,7 +4238,7 @@ public: { if (m_pMutex) { m_pMutex->Lock(); } } - ~VmaMutexLock() { if (m_pMutex) { m_pMutex->Unlock(); } } + ~VmaMutexLock() { if (m_pMutex) { m_pMutex->Unlock(); } } private: VMA_MUTEX* m_pMutex; @@ -4277,10 +4277,10 @@ private: }; #if VMA_DEBUG_GLOBAL_MUTEX - static VMA_MUTEX gDebugGlobalMutex; - #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true); +static VMA_MUTEX gDebugGlobalMutex; +#define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true); #else - #define VMA_DEBUG_GLOBAL_MUTEX_LOCK +#define VMA_DEBUG_GLOBAL_MUTEX_LOCK #endif #endif // _VMA_MUTEX_LOCK @@ -4294,7 +4294,7 @@ public: ~AtomicTransactionalIncrement() { - if(m_Atomic) + if (m_Atomic) --(*m_Atomic); } @@ -4929,7 +4929,7 @@ VmaListItem* VmaRawList::PushBack() { ItemType* const pNewItem = m_ItemAllocator.Alloc(); pNewItem->pNext = VMA_NULL; - if(IsEmpty()) + if (IsEmpty()) { pNewItem->pPrev = VMA_NULL; m_pFront = pNewItem; @@ -4983,7 +4983,7 @@ void VmaRawList::PopBack() VMA_HEAVY_ASSERT(m_Count > 0); ItemType* const pBackItem = m_pBack; ItemType* const pPrevItem = pBackItem->pPrev; - if(pPrevItem != VMA_NULL) + if (pPrevItem != VMA_NULL) { pPrevItem->pNext = VMA_NULL; } @@ -5016,7 +5016,7 @@ void VmaRawList::Remove(ItemType* pItem) VMA_HEAVY_ASSERT(pItem != VMA_NULL); VMA_HEAVY_ASSERT(m_Count > 0); - if(pItem->pPrev != VMA_NULL) + if (pItem->pPrev != VMA_NULL) { pItem->pPrev->pNext = pItem->pNext; } @@ -5026,7 +5026,7 @@ void VmaRawList::Remove(ItemType* pItem) m_pFront = pItem->pNext; } - if(pItem->pNext != VMA_NULL) + if (pItem->pNext != VMA_NULL) { pItem->pNext->pPrev = pItem->pPrev; } @@ -5043,14 +5043,14 @@ void VmaRawList::Remove(ItemType* pItem) template VmaListItem* VmaRawList::InsertBefore(ItemType* pItem) { - if(pItem != VMA_NULL) + if (pItem != VMA_NULL) { ItemType* const prevItem = pItem->pPrev; ItemType* const newItem = m_ItemAllocator.Alloc(); newItem->pPrev = prevItem; newItem->pNext = pItem; pItem->pPrev = newItem; - if(prevItem != VMA_NULL) + if (prevItem != VMA_NULL) { prevItem->pNext = newItem; } @@ -5069,14 +5069,14 @@ VmaListItem* VmaRawList::InsertBefore(ItemType* pItem) template VmaListItem* VmaRawList::InsertAfter(ItemType* pItem) { - if(pItem != VMA_NULL) + if (pItem != VMA_NULL) { ItemType* const nextItem = pItem->pNext; ItemType* const newItem = m_ItemAllocator.Alloc(); newItem->pNext = nextItem; newItem->pPrev = pItem; pItem->pNext = newItem; - if(nextItem != VMA_NULL) + if (nextItem != VMA_NULL) { nextItem->pPrev = newItem; } @@ -5125,7 +5125,7 @@ public: friend class const_iterator; friend class VmaList; public: - iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } @@ -5144,7 +5144,7 @@ public: VmaRawList* m_pList; VmaListItem* m_pItem; - iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} }; class reverse_iterator { @@ -5160,8 +5160,8 @@ public: bool operator==(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } bool operator!=(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } - reverse_iterator operator++(int) { reverse_iterator result = *this; ++* this; return result; } - reverse_iterator operator--(int) { reverse_iterator result = *this; --* this; return result; } + reverse_iterator operator++(int) { reverse_iterator result = *this; ++*this; return result; } + reverse_iterator operator--(int) { reverse_iterator result = *this; --*this; return result; } reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } reverse_iterator& operator--(); @@ -5170,7 +5170,7 @@ public: VmaRawList* m_pList; VmaListItem* m_pItem; - reverse_iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + reverse_iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} }; class const_iterator { @@ -5188,8 +5188,8 @@ public: bool operator==(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } bool operator!=(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } - const_iterator operator++(int) { const_iterator result = *this; ++* this; return result; } - const_iterator operator--(int) { const_iterator result = *this; --* this; return result; } + const_iterator operator++(int) { const_iterator result = *this; ++*this; return result; } + const_iterator operator--(int) { const_iterator result = *this; --*this; return result; } const_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; } const_iterator& operator--(); @@ -5216,8 +5216,8 @@ public: bool operator==(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } bool operator!=(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } - const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++* this; return result; } - const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --* this; return result; } + const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++*this; return result; } + const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --*this; return result; } const_reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } const_reverse_iterator& operator--(); @@ -5347,7 +5347,7 @@ public: // Movable, not copyable. VmaIntrusiveLinkedList() = default; - VmaIntrusiveLinkedList(VmaIntrusiveLinkedList && src); + VmaIntrusiveLinkedList(VmaIntrusiveLinkedList&& src); VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList&) = delete; VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src); VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete; @@ -5997,10 +5997,10 @@ public: bool PostMap() { #if VMA_MAPPING_HYSTERESIS_ENABLED - if(m_ExtraMapping == 0) + if (m_ExtraMapping == 0) { ++m_MajorCounter; - if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING) + if (m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING) { m_ExtraMapping = 1; m_MajorCounter = 0; @@ -6018,7 +6018,7 @@ public: void PostUnmap() { #if VMA_MAPPING_HYSTERESIS_ENABLED - if(m_ExtraMapping == 0) + if (m_ExtraMapping == 0) ++m_MajorCounter; else // m_ExtraMapping == 1 PostMinorCounter(); @@ -6029,7 +6029,7 @@ public: void PostAlloc() { #if VMA_MAPPING_HYSTERESIS_ENABLED - if(m_ExtraMapping == 1) + if (m_ExtraMapping == 1) ++m_MajorCounter; else // m_ExtraMapping == 0 PostMinorCounter(); @@ -6041,10 +6041,10 @@ public: bool PostFree() { #if VMA_MAPPING_HYSTERESIS_ENABLED - if(m_ExtraMapping == 1) + if (m_ExtraMapping == 1) { ++m_MajorCounter; - if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING && + if (m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING && m_MajorCounter > m_MinorCounter + 1) { m_ExtraMapping = 0; @@ -6068,11 +6068,11 @@ private: void PostMinorCounter() { - if(m_MinorCounter < m_MajorCounter) + if (m_MinorCounter < m_MajorCounter) { ++m_MinorCounter; } - else if(m_MajorCounter > 0) + else if (m_MajorCounter > 0) { --m_MajorCounter; --m_MinorCounter; @@ -6093,7 +6093,7 @@ public: public: // Strengthened - VkResult GetHandle(VkDevice device, VkDeviceMemory memory, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept + VkResult GetHandle(VkDevice device, VkDeviceMemory memory, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, bool useMutex, HANDLE* pHandle) noexcept { *pHandle = VMA_NULL; // We only care about atomicity of handle retrieval, not about memory order. @@ -6108,29 +6108,19 @@ public: HANDLE hCreatedHandle = VMA_NULL; + VkResult res = VK_SUCCESS; // If failed, try to create it. - VkResult res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &hCreatedHandle); - if (res == VK_SUCCESS) { - // Successfully created handle, try to set it. - if (!m_hHandle.compare_exchange_strong(handle, hCreatedHandle, std::memory_order_relaxed)) + VmaMutexLockWrite lock(m_Mutex, useMutex); + if (m_hHandle.load(std::memory_order_relaxed) == VMA_NULL) { - // AMD workaround - if (hCreatedHandle != m_hHandle.load(std::memory_order_relaxed)) - { - ::CloseHandle(hCreatedHandle); - } + res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &hCreatedHandle); + m_hHandle.store(hCreatedHandle, std::memory_order_relaxed); } } - - // If somehow it was set in the meantime, return it. - if (m_hHandle.load(std::memory_order_relaxed)) - { - *pHandle = Duplicate(hTargetProcess); - return VK_SUCCESS; - } + *pHandle = Duplicate(hTargetProcess); return res; -} + } operator bool() const noexcept { return m_hHandle != VMA_NULL; } private: @@ -6164,6 +6154,7 @@ private: } private: std::atomic m_hHandle; + VMA_RW_MUTEX m_Mutex; // Protects access m_Handle }; #else class VmaWin32Handle @@ -6274,8 +6265,8 @@ struct VmaAllocation_T enum FLAGS { - FLAG_PERSISTENT_MAP = 0x01, - FLAG_MAPPING_ALLOWED = 0x02, + FLAG_PERSISTENT_MAP = 0x01, + FLAG_MAPPING_ALLOWED = 0x02, }; public: @@ -6336,12 +6327,12 @@ public: #if VMA_STATS_STRING_ENABLED VmaBufferImageUsage GetBufferImageUsage() const { return m_BufferImageUsage; } - void InitBufferUsage(const VkBufferCreateInfo &createInfo, bool useKhrMaintenance5) + void InitBufferUsage(const VkBufferCreateInfo& createInfo, bool useKhrMaintenance5) { VMA_ASSERT(m_BufferImageUsage == VmaBufferImageUsage::UNKNOWN); m_BufferImageUsage = VmaBufferImageUsage(createInfo, useKhrMaintenance5); } - void InitImageUsage(const VkImageCreateInfo &createInfo) + void InitImageUsage(const VkImageCreateInfo& createInfo) { VMA_ASSERT(m_BufferImageUsage == VmaBufferImageUsage::UNKNOWN); m_BufferImageUsage = VmaBufferImageUsage(createInfo); @@ -6485,7 +6476,7 @@ bool VmaDedicatedAllocationList::Validate() void VmaDedicatedAllocationList::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) { - for(auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) + for (auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) { const VkDeviceSize size = item->GetSize(); inoutStats.statistics.blockCount++; @@ -6502,7 +6493,7 @@ void VmaDedicatedAllocationList::AddStatistics(VmaStatistics& inoutStats) inoutStats.blockCount += allocCount; inoutStats.allocationCount += allocCount; - for(auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) + for (auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) { const VkDeviceSize size = item->GetSize(); inoutStats.blockBytes += size; @@ -8027,7 +8018,7 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest( VMA_ASSERT(pAllocationRequest != VMA_NULL); VMA_HEAVY_ASSERT(Validate()); - if(allocSize > GetSize()) + if (allocSize > GetSize()) return false; pAllocationRequest->size = allocSize; @@ -9169,7 +9160,7 @@ bool VmaBlockMetadata_TLSF::CreateAllocationRequest( nextListBlock = nextListBlock->NextFree(); } } - else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT ) + else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT) { // Perform search from the start VmaStlAllocator allocator(GetAllocationCallbacks()); @@ -9716,7 +9707,7 @@ public: size_t GetBlockCount() const { return m_Blocks.size(); } // To be used only while the m_Mutex is locked. Used during defragmentation. VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; } - VMA_RW_MUTEX &GetMutex() { return m_Mutex; } + VMA_RW_MUTEX& GetMutex() { return m_Mutex; } VkResult CreateMinBlocks(); void AddStatistics(VmaStatistics& inoutStats); @@ -10125,7 +10116,7 @@ VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& creat VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant createInfo.pUserData); outAllocation = (VmaVirtualAllocation)request.allocHandle; - if(outOffset) + if (outOffset) *outOffset = m_Metadata->GetAllocationOffset(request.allocHandle); return VK_SUCCESS; } @@ -10527,7 +10518,7 @@ static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count) template static void vma_delete(VmaAllocator hAllocator, T* ptr) { - if(ptr != VMA_NULL) + if (ptr != VMA_NULL) { ptr->~T(); VmaFree(hAllocator, ptr); @@ -10537,9 +10528,9 @@ static void vma_delete(VmaAllocator hAllocator, T* ptr) template static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count) { - if(ptr != VMA_NULL) + if (ptr != VMA_NULL) { - for(size_t i = count; i--; ) + for (size_t i = count; i--; ) ptr[i].~T(); VmaFree(hAllocator, ptr); } @@ -10624,7 +10615,7 @@ void VmaDeviceMemoryBlock::PostAlloc(VmaAllocator hAllocator) void VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator) { VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); - if(m_MappingHysteresis.PostFree()) + if (m_MappingHysteresis.PostFree()) { VMA_ASSERT(m_MappingHysteresis.GetExtraMapping() == 0); if (m_MapCount == 0) @@ -10802,7 +10793,7 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory( VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, decltype(&vkGetMemoryWin32HandleKHR) pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept { VMA_ASSERT(pHandle); - return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, &vkGetMemoryWin32HandleKHR, hTargetProcess, pHandle); + return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, &vkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle); } #endif // VK_USE_PLATFORM_WIN32_KHR #endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS @@ -10819,7 +10810,7 @@ VmaAllocation_T::VmaAllocation_T(bool mappingAllowed) m_MapCount{ 0 }, m_Flags{ 0 } { - if(mappingAllowed) + if (mappingAllowed) m_Flags |= (uint8_t)FLAG_MAPPING_ALLOWED; } @@ -10846,7 +10837,7 @@ void VmaAllocation_T::InitBlockAllocation( m_Alignment = alignment; m_Size = size; m_MemoryTypeIndex = memoryTypeIndex; - if(mapped) + if (mapped) { VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP; @@ -10871,7 +10862,7 @@ void VmaAllocation_T::InitDedicatedAllocation( m_Size = size; m_MemoryTypeIndex = memoryTypeIndex; m_SuballocationType = (uint8_t)suballocationType; - if(pMappedData != VMA_NULL) + if (pMappedData != VMA_NULL) { VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP; @@ -11115,7 +11106,7 @@ VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTarget case ALLOCATION_TYPE_BLOCK: return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle); case ALLOCATION_TYPE_DEDICATED: - return m_DedicatedAllocation.m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle); + return m_DedicatedAllocation.m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle); default: VMA_ASSERT(0); return VK_ERROR_FEATURE_NOT_PRESENT; @@ -11126,7 +11117,7 @@ VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTarget void VmaAllocation_T::FreeName(VmaAllocator hAllocator) { - if(m_pName) + if (m_pName) { VmaFreeString(hAllocator->GetAllocationCallbacks(), m_pName); m_pName = VMA_NULL; @@ -11337,7 +11328,7 @@ VkResult VmaBlockVector::AllocatePage( { const bool isHostVisible = (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; - if(isHostVisible) + if (isHostVisible) { const bool isMappingAllowed = (createInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0; @@ -11347,7 +11338,7 @@ VkResult VmaBlockVector::AllocatePage( This way, having many blocks, we will separate mappable and non-mappable allocations, hopefully limiting the number of blocks that are mapped, which will help tools like RenderDoc. */ - for(size_t mappingI = 0; mappingI < 2; ++mappingI) + for (size_t mappingI = 0; mappingI < 2; ++mappingI) { // Forward order in m_Blocks - prefer blocks with smallest amount of free space. for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) @@ -11355,7 +11346,7 @@ VkResult VmaBlockVector::AllocatePage( VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VMA_ASSERT(pCurrBlock); const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL; - if((mappingI == 0) == (isMappingAllowed == isBlockMapped)) + if ((mappingI == 0) == (isMappingAllowed == isBlockMapped)) { VkResult res = AllocateFromBlock( pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); @@ -12077,7 +12068,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo m_PassStats.bytesFreed += freedBlockSize; } - if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT && + if (m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT && m_AlgorithmState != VMA_NULL) { // Avoid unnecessary tries to allocate when new free block is available @@ -12112,7 +12103,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo { do { - if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT) + if (m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT) { if (m_AlgorithmState != VMA_NULL) { @@ -12750,7 +12741,7 @@ bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType curr bool& texturePresent, bool& bufferPresent, bool& otherPresent) { const size_t prevMoveCount = m_Moves.size(); - for (size_t i = firstFreeBlock ; i;) + for (size_t i = firstFreeBlock; i;) { VmaDeviceMemoryBlock* block = vector.GetBlock(--i); VmaBlockMetadata* metadata = block->m_pMetadata; @@ -12809,7 +12800,7 @@ VmaPool_T::VmaPool_T( createInfo.maxBlockCount, (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), createInfo.blockSize != 0, // explicitBlockSize - createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm + createInfo.flags& VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm createInfo.priority, VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment), createInfo.pMemoryAllocateNext), @@ -12842,17 +12833,17 @@ void VmaPool_T::SetName(const char* pName) #ifndef _VMA_ALLOCATOR_T_FUNCTIONS VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : - m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0), + m_UseMutex((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0), m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0), - m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0), - m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0), - m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0), - m_UseAmdDeviceCoherentMemory((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0), - m_UseKhrBufferDeviceAddress((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0), - m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0), - m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0), - m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0), - m_UseKhrExternalMemoryWin32((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32) != 0), + m_UseKhrDedicatedAllocation((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0), + m_UseKhrBindMemory2((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0), + m_UseExtMemoryBudget((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0), + m_UseAmdDeviceCoherentMemory((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0), + m_UseKhrBufferDeviceAddress((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0), + m_UseExtMemoryPriority((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0), + m_UseKhrMaintenance4((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0), + m_UseKhrMaintenance5((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0), + m_UseKhrExternalMemoryWin32((pCreateInfo->flags& VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32) != 0), m_hDevice(pCreateInfo->device), m_hInstance(pCreateInfo->instance), m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL), @@ -12867,13 +12858,13 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : m_NextPoolId(0), m_GlobalMemoryTypeBits(UINT32_MAX) { - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { m_UseKhrDedicatedAllocation = false; m_UseKhrBindMemory2 = false; } - if(VMA_DEBUG_DETECT_CORRUPTION) + if (VMA_DEBUG_DETECT_CORRUPTION) { // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it. VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0); @@ -12881,84 +12872,84 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device && pCreateInfo->instance); - if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0)) { #if !(VMA_DEDICATED_ALLOCATION) - if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0) + if ((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros."); } #endif #if !(VMA_BIND_MEMORY2) - if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0) + if ((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros."); } #endif } #if !(VMA_MEMORY_BUDGET) - if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) + if ((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros."); } #endif #if !(VMA_BUFFER_DEVICE_ADDRESS) - if(m_UseKhrBufferDeviceAddress) + if (m_UseKhrBufferDeviceAddress) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif #if VMA_VULKAN_VERSION < 1003000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) { VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_3 but required Vulkan version is disabled by preprocessor macros."); } #endif #if VMA_VULKAN_VERSION < 1002000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0)) { VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros."); } #endif #if VMA_VULKAN_VERSION < 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros."); } #endif #if !(VMA_MEMORY_PRIORITY) - if(m_UseExtMemoryPriority) + if (m_UseExtMemoryPriority) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif #if !(VMA_KHR_MAINTENANCE4) - if(m_UseKhrMaintenance4) + if (m_UseKhrMaintenance4) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif #if !(VMA_KHR_MAINTENANCE5) - if(m_UseKhrMaintenance5) + if (m_UseKhrMaintenance5) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif #if !(VMA_KHR_MAINTENANCE5) - if(m_UseKhrMaintenance5) + if (m_UseKhrMaintenance5) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif #if !defined(VK_USE_PLATFORM_WIN32_KHR) - if(m_UseKhrExternalMemoryWin32) + if (m_UseKhrExternalMemoryWin32) { VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); } #endif - memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks)); + memset(&m_DeviceMemoryCallbacks, 0, sizeof(m_DeviceMemoryCallbacks)); memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties)); memset(&m_MemProps, 0, sizeof(m_MemProps)); @@ -12969,7 +12960,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : memset(&m_TypeExternalMemoryHandleTypes, 0, sizeof(m_TypeExternalMemoryHandleTypes)); #endif // #if VMA_EXTERNAL_MEMORY - if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL) + if (pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL) { m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData; m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate; @@ -12992,22 +12983,22 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits(); #if VMA_EXTERNAL_MEMORY - if(pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL) + if (pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL) { memcpy(m_TypeExternalMemoryHandleTypes, pCreateInfo->pTypeExternalMemoryHandleTypes, sizeof(VkExternalMemoryHandleTypeFlagsKHR) * GetMemoryTypeCount()); } #endif // #if VMA_EXTERNAL_MEMORY - if(pCreateInfo->pHeapSizeLimit != VMA_NULL) + if (pCreateInfo->pHeapSizeLimit != VMA_NULL) { - for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) + for (uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) { const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex]; - if(limit != VK_WHOLE_SIZE) + if (limit != VK_WHOLE_SIZE) { m_HeapSizeLimitMask |= 1u << heapIndex; - if(limit < m_MemProps.memoryHeaps[heapIndex].size) + if (limit < m_MemProps.memoryHeaps[heapIndex].size) { m_MemProps.memoryHeaps[heapIndex].size = limit; } @@ -13015,10 +13006,10 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : } } - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { // Create only supported types - if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) + if ((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) { const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex); m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)( @@ -13038,14 +13029,14 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : // because minBlockCount is 0. } } -} + } VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo) { VkResult res = VK_SUCCESS; #if VMA_MEMORY_BUDGET - if(m_UseExtMemoryBudget) + if (m_UseExtMemoryBudget) { UpdateVulkanBudget(); } @@ -13058,7 +13049,7 @@ VmaAllocator_T::~VmaAllocator_T() { VMA_ASSERT(m_Pools.IsEmpty()); - for(size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; ) + for (size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; ) { vma_delete(this, m_pBlockVectors[memTypeIndex]); } @@ -13070,7 +13061,7 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc ImportVulkanFunctions_Static(); #endif - if(pVulkanFunctions != VMA_NULL) + if (pVulkanFunctions != VMA_NULL) { ImportVulkanFunctions_Custom(pVulkanFunctions); } @@ -13109,7 +13100,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Static() // Vulkan 1.1 #if VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2; m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2; @@ -13119,14 +13110,14 @@ void VmaAllocator_T::ImportVulkanFunctions_Static() #endif #if VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; } #endif #if VMA_VULKAN_VERSION >= 1003000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) { m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)vkGetDeviceBufferMemoryRequirements; m_VulkanFunctions.vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)vkGetDeviceImageMemoryRequirements; @@ -13229,7 +13220,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, "vkCmdCopyBuffer"); #if VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2, "vkGetBufferMemoryRequirements2"); VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, "vkGetImageMemoryRequirements2"); @@ -13239,18 +13230,18 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() #endif #if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); } - else if(m_UseExtMemoryBudget) + else if (m_UseExtMemoryBudget) { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); } #endif #if VMA_DEDICATED_ALLOCATION - if(m_UseKhrDedicatedAllocation) + if (m_UseKhrDedicatedAllocation) { VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, "vkGetBufferMemoryRequirements2KHR"); VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, "vkGetImageMemoryRequirements2KHR"); @@ -13258,7 +13249,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() #endif #if VMA_BIND_MEMORY2 - if(m_UseKhrBindMemory2) + if (m_UseKhrBindMemory2) { VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, "vkBindBufferMemory2KHR"); VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, "vkBindImageMemory2KHR"); @@ -13266,25 +13257,25 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() #endif // #if VMA_BIND_MEMORY2 #if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); } - else if(m_UseExtMemoryBudget) + else if (m_UseExtMemoryBudget) { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); } #endif // #if VMA_MEMORY_BUDGET #if VMA_VULKAN_VERSION >= 1003000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) { VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirements, "vkGetDeviceBufferMemoryRequirements"); VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirements, "vkGetDeviceImageMemoryRequirements"); } #endif #if VMA_KHR_MAINTENANCE4 - if(m_UseKhrMaintenance4) + if (m_UseKhrMaintenance4) { VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirementsKHR, "vkGetDeviceBufferMemoryRequirementsKHR"); VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR"); @@ -13323,7 +13314,7 @@ void VmaAllocator_T::ValidateVulkanFunctions() VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL); #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation) { VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL); @@ -13331,7 +13322,7 @@ void VmaAllocator_T::ValidateVulkanFunctions() #endif #if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 - if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2) + if (m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2) { VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL); @@ -13339,7 +13330,7 @@ void VmaAllocator_T::ValidateVulkanFunctions() #endif #if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 - if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL); } @@ -13392,10 +13383,10 @@ VkResult VmaAllocator_T::AllocateMemoryOfType( memTypeIndex, size, allocationCount); - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) return res; - if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + if ((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) { return AllocateDedicatedMemory( pool, @@ -13423,23 +13414,23 @@ VkResult VmaAllocator_T::AllocateMemoryOfType( (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 && (pool == VK_NULL_HANDLE || !blockVector.HasExplicitBlockSize()); - if(canAllocateDedicated) + if (canAllocateDedicated) { // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size. - if(size > blockVector.GetPreferredBlockSize() / 2) + if (size > blockVector.GetPreferredBlockSize() / 2) { dedicatedPreferred = true; } // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget, // which can quickly deplete maxMemoryAllocationCount: Don't prefer dedicated allocations when above // 3/4 of the maximum allocation count. - if(m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount < UINT32_MAX / 4 && + if (m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount < UINT32_MAX / 4 && m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4) { dedicatedPreferred = false; } - if(dedicatedPreferred) + if (dedicatedPreferred) { res = AllocateDedicatedMemory( pool, @@ -13460,7 +13451,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType( allocationCount, pAllocations, blockVector.GetAllocationNextPtr()); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here. VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); @@ -13476,11 +13467,11 @@ VkResult VmaAllocator_T::AllocateMemoryOfType( suballocType, allocationCount, pAllocations); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) return VK_SUCCESS; // Try dedicated memory. - if(canAllocateDedicated && !dedicatedPreferred) + if (canAllocateDedicated && !dedicatedPreferred) { res = AllocateDedicatedMemory( pool, @@ -13501,7 +13492,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType( allocationCount, pAllocations, blockVector.GetAllocationNextPtr()); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here. VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); @@ -13542,17 +13533,17 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR }; - if(!canAliasMemory) + if (!canAliasMemory) { - if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { - if(dedicatedBuffer != VK_NULL_HANDLE) + if (dedicatedBuffer != VK_NULL_HANDLE) { VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE); dedicatedAllocInfo.buffer = dedicatedBuffer; VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); } - else if(dedicatedImage != VK_NULL_HANDLE) + else if (dedicatedImage != VK_NULL_HANDLE) { dedicatedAllocInfo.image = dedicatedImage; VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); @@ -13563,19 +13554,19 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( #if VMA_BUFFER_DEVICE_ADDRESS VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR }; - if(m_UseKhrBufferDeviceAddress) + if (m_UseKhrBufferDeviceAddress) { bool canContainBufferWithDeviceAddress = true; - if(dedicatedBuffer != VK_NULL_HANDLE) + if (dedicatedBuffer != VK_NULL_HANDLE) { canContainBufferWithDeviceAddress = dedicatedBufferImageUsage == VmaBufferImageUsage::UNKNOWN || dedicatedBufferImageUsage.Contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT); } - else if(dedicatedImage != VK_NULL_HANDLE) + else if (dedicatedImage != VK_NULL_HANDLE) { canContainBufferWithDeviceAddress = false; } - if(canContainBufferWithDeviceAddress) + if (canContainBufferWithDeviceAddress) { allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo); @@ -13585,7 +13576,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( #if VMA_MEMORY_PRIORITY VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; - if(m_UseExtMemoryPriority) + if (m_UseExtMemoryPriority) { VMA_ASSERT(priority >= 0.f && priority <= 1.f); priorityInfo.priority = priority; @@ -13597,7 +13588,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( // Attach VkExportMemoryAllocateInfoKHR if necessary. VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; exportMemoryAllocInfo.handleTypes = GetExternalMemoryHandleTypeFlags(memTypeIndex); - if(exportMemoryAllocInfo.handleTypes != 0) + if (exportMemoryAllocInfo.handleTypes != 0) { VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo); } @@ -13605,7 +13596,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( size_t allocIndex; VkResult res = VK_SUCCESS; - for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex) { res = AllocateDedicatedMemoryPage( pool, @@ -13618,13 +13609,13 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( isMappingAllowed, pUserData, pAllocations + allocIndex); - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) { break; } } - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex) { @@ -13635,7 +13626,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( else { // Free all already created allocations. - while(allocIndex--) + while (allocIndex--) { VmaAllocation currAlloc = pAllocations[allocIndex]; VkDeviceMemory hMemory = currAlloc->GetMemory(); @@ -13675,14 +13666,14 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage( { VkDeviceMemory hMemory = VK_NULL_HANDLE; VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory); - if(res < 0) + if (res < 0) { VMA_DEBUG_LOG(" vkAllocateMemory FAILED"); return res; } void* pMappedData = VMA_NULL; - if(map) + if (map) { res = (*m_VulkanFunctions.vkMapMemory)( m_hDevice, @@ -13691,7 +13682,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage( VK_WHOLE_SIZE, 0, &pMappedData); - if(res < 0) + if (res < 0) { VMA_DEBUG_LOG(" vkMapMemory FAILED"); FreeVulkanMemory(memTypeIndex, size, hMemory); @@ -13706,7 +13697,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage( else (*pAllocation)->SetUserData(this, pUserData); m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size); - if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) + if (VMA_DEBUG_INITIALIZE_ALLOCATIONS) { FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED); } @@ -13721,7 +13712,7 @@ void VmaAllocator_T::GetBufferMemoryRequirements( bool& prefersDedicatedAllocation) const { #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 - if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR }; memReqInfo.buffer = hBuffer; @@ -13735,14 +13726,14 @@ void VmaAllocator_T::GetBufferMemoryRequirements( memReq = memReq2.memoryRequirements; requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE); - prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); } else #endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 { (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq); requiresDedicatedAllocation = false; - prefersDedicatedAllocation = false; + prefersDedicatedAllocation = false; } } @@ -13753,7 +13744,7 @@ void VmaAllocator_T::GetImageMemoryRequirements( bool& prefersDedicatedAllocation) const { #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 - if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + if (m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR }; memReqInfo.image = hImage; @@ -13767,14 +13758,14 @@ void VmaAllocator_T::GetImageMemoryRequirements( memReq = memReq2.memoryRequirements; requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE); - prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); } else #endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 { (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq); requiresDedicatedAllocation = false; - prefersDedicatedAllocation = false; + prefersDedicatedAllocation = false; } } @@ -13786,13 +13777,13 @@ VkResult VmaAllocator_T::FindMemoryTypeIndex( { memoryTypeBits &= GetGlobalMemoryTypeBits(); - if(pAllocationCreateInfo->memoryTypeBits != 0) + if (pAllocationCreateInfo->memoryTypeBits != 0) { memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits; } VkMemoryPropertyFlags requiredFlags = 0, preferredFlags = 0, notPreferredFlags = 0; - if(!FindMemoryPreferences( + if (!FindMemoryPreferences( IsIntegratedGpu(), *pAllocationCreateInfo, bufImgUsage, @@ -13803,26 +13794,26 @@ VkResult VmaAllocator_T::FindMemoryTypeIndex( *pMemoryTypeIndex = UINT32_MAX; uint32_t minCost = UINT32_MAX; - for(uint32_t memTypeIndex = 0, memTypeBit = 1; + for (uint32_t memTypeIndex = 0, memTypeBit = 1; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex, memTypeBit <<= 1) { // This memory type is acceptable according to memoryTypeBits bitmask. - if((memTypeBit & memoryTypeBits) != 0) + if ((memTypeBit & memoryTypeBits) != 0) { const VkMemoryPropertyFlags currFlags = m_MemProps.memoryTypes[memTypeIndex].propertyFlags; // This memory type contains requiredFlags. - if((requiredFlags & ~currFlags) == 0) + if ((requiredFlags & ~currFlags) == 0) { // Calculate cost as number of bits from preferredFlags not present in this memory type. uint32_t currCost = VMA_COUNT_BITS_SET(preferredFlags & ~currFlags) + VMA_COUNT_BITS_SET(currFlags & notPreferredFlags); // Remember memory type with lowest cost. - if(currCost < minCost) + if (currCost < minCost) { *pMemoryTypeIndex = memTypeIndex; - if(currCost == 0) + if (currCost == 0) { return VK_SUCCESS; } @@ -13841,19 +13832,19 @@ VkResult VmaAllocator_T::CalcMemTypeParams( size_t allocationCount) { // If memory type is not HOST_VISIBLE, disable MAPPED. - if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && + if ((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { inoutCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT; } - if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + if ((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0) { const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); VmaBudget heapBudget = {}; GetHeapBudgets(&heapBudget, heapIndex, 1); - if(heapBudget.usage + size * allocationCount > heapBudget.budget) + if (heapBudget.usage + size * allocationCount > heapBudget.budget) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; } @@ -13873,9 +13864,9 @@ VkResult VmaAllocator_T::CalcAllocationParams( VMA_ASSERT((((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) == 0 || (inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0)) && "Specifying VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT requires also VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT."); - if(inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST) + if (inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST) { - if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0) + if ((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0) { VMA_ASSERT((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0 && "When using VMA_ALLOCATION_CREATE_MAPPED_BIT and usage = VMA_MEMORY_USAGE_AUTO*, you must also specify VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT."); @@ -13883,15 +13874,15 @@ VkResult VmaAllocator_T::CalcAllocationParams( } // If memory is lazily allocated, it should be always dedicated. - if(dedicatedRequired || + if (dedicatedRequired || inoutCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED) { inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - if(inoutCreateInfo.pool != VK_NULL_HANDLE) + if (inoutCreateInfo.pool != VK_NULL_HANDLE) { - if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && + if (inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) { VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); @@ -13900,14 +13891,14 @@ VkResult VmaAllocator_T::CalcAllocationParams( inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority(); } - if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + if ((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) { VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense."); return VK_ERROR_FEATURE_NOT_PRESENT; } - if(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY && + if (VMA_DEBUG_ALWAYS_DEDICATED_MEMORY && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) { inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; @@ -13917,11 +13908,11 @@ VkResult VmaAllocator_T::CalcAllocationParams( // And so does VMA_MEMORY_USAGE_UNKNOWN because it is used with custom pools. // Which specific flag is used doesn't matter. They change things only when used with VMA_MEMORY_USAGE_AUTO*. // Otherwise they just protect from assert on mapping. - if(inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO && + if (inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO && inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE && inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_HOST) { - if((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) == 0) + if ((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) == 0) { inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; } @@ -13946,17 +13937,17 @@ VkResult VmaAllocator_T::AllocateMemory( VMA_ASSERT(VmaIsPow2(vkMemReq.alignment)); - if(vkMemReq.size == 0) + if (vkMemReq.size == 0) { return VK_ERROR_INITIALIZATION_FAILED; } VmaAllocationCreateInfo createInfoFinal = createInfo; VkResult res = CalcAllocationParams(createInfoFinal, requiresDedicatedAllocation, prefersDedicatedAllocation); - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) return res; - if(createInfoFinal.pool != VK_NULL_HANDLE) + if (createInfoFinal.pool != VK_NULL_HANDLE) { VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector; return AllocateMemoryOfType( @@ -13982,7 +13973,7 @@ VkResult VmaAllocator_T::AllocateMemory( uint32_t memTypeIndex = UINT32_MAX; res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex); // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) return res; do { @@ -14004,14 +13995,14 @@ VkResult VmaAllocator_T::AllocateMemory( allocationCount, pAllocations); // Allocation succeeded - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) return VK_SUCCESS; // Remove old memTypeIndex from list of possibilities. memoryTypeBits &= ~(1u << memTypeIndex); // Find alternative memTypeIndex. res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex); - } while(res == VK_SUCCESS); + } while (res == VK_SUCCESS); // No other matching memory type index could be found. // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. @@ -14025,38 +14016,38 @@ void VmaAllocator_T::FreeMemory( { VMA_ASSERT(pAllocations); - for(size_t allocIndex = allocationCount; allocIndex--; ) + for (size_t allocIndex = allocationCount; allocIndex--; ) { VmaAllocation allocation = pAllocations[allocIndex]; - if(allocation != VK_NULL_HANDLE) + if (allocation != VK_NULL_HANDLE) { - if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) + if (VMA_DEBUG_INITIALIZE_ALLOCATIONS) { FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED); } allocation->FreeName(this); - switch(allocation->GetType()) + switch (allocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaBlockVector* pBlockVector = VMA_NULL; + VmaPool hPool = allocation->GetParentPool(); + if (hPool != VK_NULL_HANDLE) { - VmaBlockVector* pBlockVector = VMA_NULL; - VmaPool hPool = allocation->GetParentPool(); - if(hPool != VK_NULL_HANDLE) - { - pBlockVector = &hPool->m_BlockVector; - } - else - { - const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); - pBlockVector = m_pBlockVectors[memTypeIndex]; - VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); - } - pBlockVector->Free(allocation); + pBlockVector = &hPool->m_BlockVector; } - break; + else + { + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + pBlockVector = m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); + } + pBlockVector->Free(allocation); + } + break; case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: FreeDedicatedMemory(allocation); break; @@ -14071,13 +14062,13 @@ void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats) { // Initialize. VmaClearDetailedStatistics(pStats->total); - for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) + for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) VmaClearDetailedStatistics(pStats->memoryType[i]); - for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) + for (uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) VmaClearDetailedStatistics(pStats->memoryHeap[i]); // Process default pools. - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; if (pBlockVector != VMA_NULL) @@ -14087,7 +14078,7 @@ void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats) // Process custom pools. { VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); - for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + for (VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { VmaBlockVector& blockVector = pool->m_BlockVector; const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); @@ -14097,20 +14088,20 @@ void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats) } // Process dedicated allocations. - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { m_DedicatedAllocations[memTypeIndex].AddDetailedStatistics(pStats->memoryType[memTypeIndex]); } // Sum from memory types to memory heaps. - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { const uint32_t memHeapIndex = m_MemProps.memoryTypes[memTypeIndex].heapIndex; VmaAddDetailedStatistics(pStats->memoryHeap[memHeapIndex], pStats->memoryType[memTypeIndex]); } // Sum from memory heaps to total. - for(uint32_t memHeapIndex = 0; memHeapIndex < GetMemoryHeapCount(); ++memHeapIndex) + for (uint32_t memHeapIndex = 0; memHeapIndex < GetMemoryHeapCount(); ++memHeapIndex) VmaAddDetailedStatistics(pStats->total, pStats->memoryHeap[memHeapIndex]); VMA_ASSERT(pStats->total.statistics.allocationCount == 0 || @@ -14122,12 +14113,12 @@ void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats) void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount) { #if VMA_MEMORY_BUDGET - if(m_UseExtMemoryBudget) + if (m_UseExtMemoryBudget) { - if(m_Budget.m_OperationsSinceBudgetFetch < 30) + if (m_Budget.m_OperationsSinceBudgetFetch < 30) { VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex); - for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) + for (uint32_t i = 0; i < heapCount; ++i, ++outBudgets) { const uint32_t heapIndex = firstHeap + i; @@ -14136,7 +14127,7 @@ void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, u outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex]; outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex]; - if(m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]) + if (m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]) { outBudgets->usage = m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; @@ -14160,7 +14151,7 @@ void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, u else #endif { - for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) + for (uint32_t i = 0; i < heapCount; ++i, ++outBudgets) { const uint32_t heapIndex = firstHeap + i; @@ -14212,26 +14203,26 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo VmaPoolCreateInfo newCreateInfo = *pCreateInfo; // Protection against uninitialized new structure member. If garbage data are left there, this pointer dereference would crash. - if(pCreateInfo->pMemoryAllocateNext) + if (pCreateInfo->pMemoryAllocateNext) { VMA_ASSERT(((const VkBaseInStructure*)pCreateInfo->pMemoryAllocateNext)->sType != 0); } - if(newCreateInfo.maxBlockCount == 0) + if (newCreateInfo.maxBlockCount == 0) { newCreateInfo.maxBlockCount = SIZE_MAX; } - if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount) + if (newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount) { return VK_ERROR_INITIALIZATION_FAILED; } // Memory type index out of range or forbidden. - if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || + if (pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0) { return VK_ERROR_FEATURE_NOT_PRESENT; } - if(newCreateInfo.minAllocationAlignment > 0) + if (newCreateInfo.minAllocationAlignment > 0) { VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment)); } @@ -14241,7 +14232,7 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize); VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks(); - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) { vma_delete(this, *pPool); *pPool = VMA_NULL; @@ -14288,7 +14279,7 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) m_CurrentFrameIndex.store(frameIndex); #if VMA_MEMORY_BUDGET - if(m_UseExtMemoryBudget) + if (m_UseExtMemoryBudget) { UpdateVulkanBudget(); } @@ -14305,13 +14296,13 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT; // Process default pools. - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; - if(pBlockVector != VMA_NULL) + if (pBlockVector != VMA_NULL) { VkResult localRes = pBlockVector->CheckCorruption(); - switch(localRes) + switch (localRes) { case VK_ERROR_FEATURE_NOT_PRESENT: break; @@ -14327,12 +14318,12 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) // Process custom pools. { VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); - for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + for (VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { - if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) + if (((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) { VkResult localRes = pool->m_BlockVector.CheckCorruption(); - switch(localRes) + switch (localRes) { case VK_ERROR_FEATURE_NOT_PRESENT: break; @@ -14354,7 +14345,7 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc AtomicTransactionalIncrement deviceMemoryCountIncrement; const uint64_t prevDeviceMemoryCount = deviceMemoryCountIncrement.Increment(&m_DeviceMemoryCount); #if VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT - if(prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount) + if (prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount) { return VK_ERROR_TOO_MANY_OBJECTS; } @@ -14363,22 +14354,22 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex); // HeapSizeLimit is in effect for this heap. - if((m_HeapSizeLimitMask & (1u << heapIndex)) != 0) + if ((m_HeapSizeLimitMask & (1u << heapIndex)) != 0) { const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size; VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex]; - for(;;) + for (;;) { const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize; - if(blockBytesAfterAllocation > heapSize) + if (blockBytesAfterAllocation > heapSize) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation)) + } + if (m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation)) { break; } - } +} } else { @@ -14389,14 +14380,14 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc // VULKAN CALL vkAllocateMemory. VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { #if VMA_MEMORY_BUDGET ++m_Budget.m_OperationsSinceBudgetFetch; #endif // Informative callback. - if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL) + if (m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL) { (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize, m_DeviceMemoryCallbacks.pUserData); } @@ -14410,12 +14401,12 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc } return res; -} + } void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory) { // Informative callback. - if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL) + if (m_DeviceMemoryCallbacks.pfnFree != VMA_NULL) { (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size, m_DeviceMemoryCallbacks.pUserData); } @@ -14436,10 +14427,10 @@ VkResult VmaAllocator_T::BindVulkanBuffer( VkBuffer buffer, const void* pNext) { - if(pNext != VMA_NULL) + if (pNext != VMA_NULL) { #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 - if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + if ((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL) { VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR }; @@ -14467,10 +14458,10 @@ VkResult VmaAllocator_T::BindVulkanImage( VkImage image, const void* pNext) { - if(pNext != VMA_NULL) + if (pNext != VMA_NULL) { #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 - if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + if ((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL) { VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR }; @@ -14494,20 +14485,20 @@ VkResult VmaAllocator_T::BindVulkanImage( VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData) { - switch(hAllocation->GetType()) + switch (hAllocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + char* pBytes = VMA_NULL; + VkResult res = pBlock->Map(this, 1, (void**)&pBytes); + if (res == VK_SUCCESS) { - VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); - char *pBytes = VMA_NULL; - VkResult res = pBlock->Map(this, 1, (void**)&pBytes); - if(res == VK_SUCCESS) - { - *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset(); - hAllocation->BlockAllocMap(); - } - return res; + *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset(); + hAllocation->BlockAllocMap(); } + return res; + } case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: return hAllocation->DedicatedAllocMap(this, ppData); default: @@ -14518,15 +14509,15 @@ VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData) void VmaAllocator_T::Unmap(VmaAllocation hAllocation) { - switch(hAllocation->GetType()) + switch (hAllocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: - { - VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); - hAllocation->BlockAllocUnmap(); - pBlock->Unmap(this, 1); - } - break; + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + hAllocation->BlockAllocUnmap(); + pBlock->Unmap(this, 1); + } + break; case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: hAllocation->DedicatedAllocUnmap(this); break; @@ -14542,7 +14533,7 @@ VkResult VmaAllocator_T::BindBufferMemory( const void* pNext) { VkResult res = VK_ERROR_UNKNOWN_COPY; - switch(hAllocation->GetType()) + switch (hAllocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext); @@ -14567,7 +14558,7 @@ VkResult VmaAllocator_T::BindImageMemory( const void* pNext) { VkResult res = VK_ERROR_UNKNOWN_COPY; - switch(hAllocation->GetType()) + switch (hAllocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext); @@ -14593,9 +14584,9 @@ VkResult VmaAllocator_T::FlushOrInvalidateAllocation( VkResult res = VK_SUCCESS; VkMappedMemoryRange memRange = {}; - if(GetFlushOrInvalidateRange(hAllocation, offset, size, memRange)) + if (GetFlushOrInvalidateRange(hAllocation, offset, size, memRange)) { - switch(op) + switch (op) { case VMA_CACHE_FLUSH: res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange); @@ -14621,22 +14612,22 @@ VkResult VmaAllocator_T::FlushOrInvalidateAllocations( typedef VmaSmallVector RangeVector; RangeVector ranges = RangeVector(RangeAllocator(GetAllocationCallbacks())); - for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + for (uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) { const VmaAllocation alloc = allocations[allocIndex]; const VkDeviceSize offset = offsets != VMA_NULL ? offsets[allocIndex] : 0; const VkDeviceSize size = sizes != VMA_NULL ? sizes[allocIndex] : VK_WHOLE_SIZE; VkMappedMemoryRange newRange; - if(GetFlushOrInvalidateRange(alloc, offset, size, newRange)) + if (GetFlushOrInvalidateRange(alloc, offset, size, newRange)) { ranges.push_back(newRange); } } VkResult res = VK_SUCCESS; - if(!ranges.empty()) + if (!ranges.empty()) { - switch(op) + switch (op) { case VMA_CACHE_FLUSH: res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data()); @@ -14660,7 +14651,7 @@ VkResult VmaAllocator_T::CopyMemoryToAllocation( { void* dstMappedData = VMA_NULL; VkResult res = Map(dstAllocation, &dstMappedData); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { memcpy((char*)dstMappedData + dstAllocationLocalOffset, pSrcHostPointer, (size_t)size); Unmap(dstAllocation); @@ -14677,10 +14668,10 @@ VkResult VmaAllocator_T::CopyAllocationToMemory( { void* srcMappedData = VMA_NULL; VkResult res = Map(srcAllocation, &srcMappedData); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { res = FlushOrInvalidateAllocation(srcAllocation, srcAllocationLocalOffset, size, VMA_CACHE_INVALIDATE); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { memcpy(pDstHostPointer, (const char*)srcMappedData + srcAllocationLocalOffset, (size_t)size); Unmap(srcAllocation); @@ -14695,7 +14686,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation) const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); VmaPool parentPool = allocation->GetParentPool(); - if(parentPool == VK_NULL_HANDLE) + if (parentPool == VK_NULL_HANDLE) { // Default pool m_DedicatedAllocations[memTypeIndex].Unregister(allocation); @@ -14737,7 +14728,7 @@ uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const VkBuffer buf = VK_NULL_HANDLE; VkResult res = (*GetVulkanFunctions().vkCreateBuffer)( m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { // Query for supported memory types. VkMemoryRequirements memReq; @@ -14758,12 +14749,12 @@ uint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits() const uint32_t memoryTypeBits = UINT32_MAX; - if(!m_UseAmdDeviceCoherentMemory) + if (!m_UseAmdDeviceCoherentMemory) { // Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD. - for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0) + if ((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0) { memoryTypeBits &= ~(1u << memTypeIndex); } @@ -14779,7 +14770,7 @@ bool VmaAllocator_T::GetFlushOrInvalidateRange( VkMappedMemoryRange& outRange) const { const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); - if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex)) + if (size > 0 && IsMemoryTypeNonCoherent(memTypeIndex)) { const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize; const VkDeviceSize allocationSize = allocation->GetSize(); @@ -14789,11 +14780,11 @@ bool VmaAllocator_T::GetFlushOrInvalidateRange( outRange.pNext = VMA_NULL; outRange.memory = allocation->GetMemory(); - switch(allocation->GetType()) + switch (allocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); - if(size == VK_WHOLE_SIZE) + if (size == VK_WHOLE_SIZE) { outRange.size = allocationSize - outRange.offset; } @@ -14809,7 +14800,7 @@ bool VmaAllocator_T::GetFlushOrInvalidateRange( { // 1. Still within this allocation. outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); - if(size == VK_WHOLE_SIZE) + if (size == VK_WHOLE_SIZE) { size = allocationSize - offset; } @@ -14851,22 +14842,22 @@ void VmaAllocator_T::UpdateVulkanBudget() { VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex); - for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) + for (uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) { m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex]; m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex]; m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load(); // Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size. - if(m_Budget.m_VulkanBudget[heapIndex] == 0) + if (m_Budget.m_VulkanBudget[heapIndex] == 0) { m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics. } - else if(m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size) + else if (m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size) { m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size; } - if(m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0) + if (m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0) { m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; } @@ -14878,13 +14869,13 @@ void VmaAllocator_T::UpdateVulkanBudget() void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern) { - if(VMA_DEBUG_INITIALIZE_ALLOCATIONS && + if (VMA_DEBUG_INITIALIZE_ALLOCATIONS && hAllocation->IsMappingAllowed() && (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) { void* pData = VMA_NULL; VkResult res = Map(hAllocation, &pData); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { memset(pData, (int)pattern, (size_t)hAllocation->GetSize()); FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH); @@ -14900,7 +14891,7 @@ void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pat uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits() { uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load(); - if(memoryTypeBits == UINT32_MAX) + if (memoryTypeBits == UINT32_MAX) { memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits(); m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits); @@ -15011,7 +15002,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( VMA_DEBUG_LOG("vmaCreateAllocator"); *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo); VkResult result = (*pAllocator)->Init(pCreateInfo); - if(result < 0) + if (result < 0) { vma_delete(pCreateInfo->pAllocationCallbacks, *pAllocator); *pAllocator = VK_NULL_HANDLE; @@ -15022,7 +15013,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( VmaAllocator allocator) { - if(allocator != VK_NULL_HANDLE) + if (allocator != VK_NULL_HANDLE) { VMA_DEBUG_LOG("vmaDestroyAllocator"); VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; // Have to copy the callbacks when destroying. @@ -15040,7 +15031,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaA VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( VmaAllocator allocator, - const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties) + const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties) { VMA_ASSERT(allocator && ppPhysicalDeviceProperties); *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties; @@ -15072,7 +15063,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->SetCurrentFrameIndex(frameIndex); + allocator->SetCurrentFrameIndex(frameIndex); } VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( @@ -15081,7 +15072,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( { VMA_ASSERT(allocator && pStats); VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->CalculateStatistics(pStats); + allocator->CalculateStatistics(pStats); } VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( @@ -15090,7 +15081,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( { VMA_ASSERT(allocator && pBudgets); VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount()); + allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount()); } #if VMA_STATS_STRING_ENABLED @@ -15103,7 +15094,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( VMA_ASSERT(allocator && ppStatsString); VMA_DEBUG_GLOBAL_MUTEX_LOCK - VmaStringBuilder sb(allocator->GetAllocationCallbacks()); + VmaStringBuilder sb(allocator->GetAllocationCallbacks()); { VmaBudget budgets[VK_MAX_MEMORY_HEAPS]; allocator->GetHeapBudgets(budgets, 0, allocator->GetMemoryHeapCount()); @@ -15172,16 +15163,16 @@ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( { if (heapInfo.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) json.WriteString("DEVICE_LOCAL"); - #if VMA_VULKAN_VERSION >= 1001000 +#if VMA_VULKAN_VERSION >= 1001000 if (heapInfo.flags & VK_MEMORY_HEAP_MULTI_INSTANCE_BIT) json.WriteString("MULTI_INSTANCE"); - #endif +#endif VkMemoryHeapFlags flags = heapInfo.flags & ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT - #if VMA_VULKAN_VERSION >= 1001000 +#if VMA_VULKAN_VERSION >= 1001000 | VK_MEMORY_HEAP_MULTI_INSTANCE_BIT - #endif +#endif ); if (flags != 0) json.WriteNumber(flags); @@ -15230,25 +15221,25 @@ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( json.WriteString("HOST_CACHED"); if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) json.WriteString("LAZILY_ALLOCATED"); - #if VMA_VULKAN_VERSION >= 1001000 +#if VMA_VULKAN_VERSION >= 1001000 if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) json.WriteString("PROTECTED"); - #endif - #if VK_AMD_device_coherent_memory +#endif +#if VK_AMD_device_coherent_memory if (flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) json.WriteString("DEVICE_COHERENT_AMD"); if (flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) json.WriteString("DEVICE_UNCACHED_AMD"); - #endif +#endif flags &= ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - #if VMA_VULKAN_VERSION >= 1001000 +#if VMA_VULKAN_VERSION >= 1001000 | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT - #endif - #if VK_AMD_device_coherent_memory +#endif +#if VK_AMD_device_coherent_memory | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY - #endif +#endif | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); @@ -15286,7 +15277,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( VmaAllocator allocator, char* pStatsString) { - if(pStatsString != VMA_NULL) + if (pStatsString != VMA_NULL) { VMA_ASSERT(allocator); VmaFreeString(allocator->GetAllocationCallbacks(), pStatsString); @@ -15327,13 +15318,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( VkResult res; #if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 - if(funcs->vkGetDeviceBufferMemoryRequirements) + if (funcs->vkGetDeviceBufferMemoryRequirements) { // Can query straight from VkBufferCreateInfo :) - VkDeviceBufferMemoryRequirementsKHR devBufMemReq = {VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR}; + VkDeviceBufferMemoryRequirementsKHR devBufMemReq = { VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR }; devBufMemReq.pCreateInfo = pBufferCreateInfo; - VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2}; + VkMemoryRequirements2 memReq = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; (*funcs->vkGetDeviceBufferMemoryRequirements)(hDev, &devBufMemReq, &memReq); res = allocator->FindMemoryTypeIndex( @@ -15347,7 +15338,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( VkBuffer hBuffer = VK_NULL_HANDLE; res = funcs->vkCreateBuffer( hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { VkMemoryRequirements memReq = {}; funcs->vkGetBufferMemoryRequirements(hDev, hBuffer, &memReq); @@ -15379,15 +15370,15 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( VkResult res; #if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 - if(funcs->vkGetDeviceImageMemoryRequirements) + if (funcs->vkGetDeviceImageMemoryRequirements) { // Can query straight from VkImageCreateInfo :) - VkDeviceImageMemoryRequirementsKHR devImgMemReq = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR}; + VkDeviceImageMemoryRequirementsKHR devImgMemReq = { VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR }; devImgMemReq.pCreateInfo = pImageCreateInfo; VMA_ASSERT(pImageCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY && (pImageCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_COPY) == 0 && "Cannot use this VkImageCreateInfo with vmaFindMemoryTypeIndexForImageInfo as I don't know what to pass as VkDeviceImageMemoryRequirements::planeAspect."); - VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2}; + VkMemoryRequirements2 memReq = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; (*funcs->vkGetDeviceImageMemoryRequirements)(hDev, &devImgMemReq, &memReq); res = allocator->FindMemoryTypeIndex( @@ -15401,7 +15392,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( VkImage hImage = VK_NULL_HANDLE; res = funcs->vkCreateImage( hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage); - if(res == VK_SUCCESS) + if (res == VK_SUCCESS) { VkMemoryRequirements memReq = {}; funcs->vkGetImageMemoryRequirements(hDev, hImage, &memReq); @@ -15428,7 +15419,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->CreatePool(pCreateInfo, pPool); + return allocator->CreatePool(pCreateInfo, pPool); } VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( @@ -15437,7 +15428,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( { VMA_ASSERT(allocator); - if(pool == VK_NULL_HANDLE) + if (pool == VK_NULL_HANDLE) { return; } @@ -15446,7 +15437,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->DestroyPool(pool); + allocator->DestroyPool(pool); } VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( @@ -15458,7 +15449,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->GetPoolStatistics(pool, pPoolStats); + allocator->GetPoolStatistics(pool, pPoolStats); } VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( @@ -15470,7 +15461,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->CalculatePoolStatistics(pool, pPoolStats); + allocator->CalculatePoolStatistics(pool, pPoolStats); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool) @@ -15479,7 +15470,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocato VMA_DEBUG_GLOBAL_MUTEX_LOCK - VMA_DEBUG_LOG("vmaCheckPoolCorruption"); + VMA_DEBUG_LOG("vmaCheckPoolCorruption"); return allocator->CheckPoolCorruption(pool); } @@ -15495,7 +15486,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( VMA_DEBUG_GLOBAL_MUTEX_LOCK - *ppName = pool->GetName(); + * ppName = pool->GetName(); } VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( @@ -15509,7 +15500,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( VMA_DEBUG_GLOBAL_MUTEX_LOCK - pool->SetName(pName); + pool->SetName(pName); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( @@ -15525,19 +15516,19 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkResult result = allocator->AllocateMemory( - *pVkMemoryRequirements, - false, // requiresDedicatedAllocation - false, // prefersDedicatedAllocation - VK_NULL_HANDLE, // dedicatedBuffer - VK_NULL_HANDLE, // dedicatedImage - VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage - *pCreateInfo, - VMA_SUBALLOCATION_TYPE_UNKNOWN, - 1, // allocationCount - pAllocation); + VkResult result = allocator->AllocateMemory( + *pVkMemoryRequirements, + false, // requiresDedicatedAllocation + false, // prefersDedicatedAllocation + VK_NULL_HANDLE, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_UNKNOWN, + 1, // allocationCount + pAllocation); - if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) + if (pAllocationInfo != VMA_NULL && result == VK_SUCCESS) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -15553,7 +15544,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( VmaAllocation* pAllocations, VmaAllocationInfo* pAllocationInfo) { - if(allocationCount == 0) + if (allocationCount == 0) { return VK_SUCCESS; } @@ -15564,21 +15555,21 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkResult result = allocator->AllocateMemory( - *pVkMemoryRequirements, - false, // requiresDedicatedAllocation - false, // prefersDedicatedAllocation - VK_NULL_HANDLE, // dedicatedBuffer - VK_NULL_HANDLE, // dedicatedImage - VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage - *pCreateInfo, - VMA_SUBALLOCATION_TYPE_UNKNOWN, - allocationCount, - pAllocations); + VkResult result = allocator->AllocateMemory( + *pVkMemoryRequirements, + false, // requiresDedicatedAllocation + false, // prefersDedicatedAllocation + VK_NULL_HANDLE, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_UNKNOWN, + allocationCount, + pAllocations); - if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) + if (pAllocationInfo != VMA_NULL && result == VK_SUCCESS) { - for(size_t i = 0; i < allocationCount; ++i) + for (size_t i = 0; i < allocationCount; ++i) { allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i); } @@ -15600,7 +15591,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkMemoryRequirements vkMemReq = {}; + VkMemoryRequirements vkMemReq = {}; bool requiresDedicatedAllocation = false; bool prefersDedicatedAllocation = false; allocator->GetBufferMemoryRequirements(buffer, vkMemReq, @@ -15619,7 +15610,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( 1, // allocationCount pAllocation); - if(pAllocationInfo && result == VK_SUCCESS) + if (pAllocationInfo && result == VK_SUCCESS) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -15640,9 +15631,9 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkMemoryRequirements vkMemReq = {}; + VkMemoryRequirements vkMemReq = {}; bool requiresDedicatedAllocation = false; - bool prefersDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; allocator->GetImageMemoryRequirements(image, vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation); @@ -15658,7 +15649,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( 1, // allocationCount pAllocation); - if(pAllocationInfo && result == VK_SUCCESS) + if (pAllocationInfo && result == VK_SUCCESS) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -15672,7 +15663,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( { VMA_ASSERT(allocator); - if(allocation == VK_NULL_HANDLE) + if (allocation == VK_NULL_HANDLE) { return; } @@ -15681,9 +15672,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->FreeMemory( - 1, // allocationCount - &allocation); + allocator->FreeMemory( + 1, // allocationCount + &allocation); } VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( @@ -15691,7 +15682,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( size_t allocationCount, const VmaAllocation* pAllocations) { - if(allocationCount == 0) + if (allocationCount == 0) { return; } @@ -15702,7 +15693,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->FreeMemory(allocationCount, pAllocations); + allocator->FreeMemory(allocationCount, pAllocations); } VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( @@ -15714,7 +15705,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->GetAllocationInfo(allocation, pAllocationInfo); + allocator->GetAllocationInfo(allocation, pAllocationInfo); } VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( @@ -15726,7 +15717,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->GetAllocationInfo2(allocation, pAllocationInfo); + allocator->GetAllocationInfo2(allocation, pAllocationInfo); } VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( @@ -15738,7 +15729,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocation->SetUserData(allocator, pUserData); + allocation->SetUserData(allocator, pUserData); } VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName( @@ -15768,7 +15759,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->Map(allocation, ppData); + return allocator->Map(allocation, ppData); } VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( @@ -15779,7 +15770,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->Unmap(allocation); + allocator->Unmap(allocation); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( @@ -15794,7 +15785,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH); + return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( @@ -15809,7 +15800,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE); + return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( @@ -15821,7 +15812,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( { VMA_ASSERT(allocator); - if(allocationCount == 0) + if (allocationCount == 0) { return VK_SUCCESS; } @@ -15832,7 +15823,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH); + return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( @@ -15844,7 +15835,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( { VMA_ASSERT(allocator); - if(allocationCount == 0) + if (allocationCount == 0) { return VK_SUCCESS; } @@ -15855,7 +15846,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE); + return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( @@ -15867,7 +15858,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( { VMA_ASSERT(allocator && pSrcHostPointer && dstAllocation); - if(size == 0) + if (size == 0) { return VK_SUCCESS; } @@ -15876,7 +15867,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->CopyMemoryToAllocation(pSrcHostPointer, dstAllocation, dstAllocationLocalOffset, size); + return allocator->CopyMemoryToAllocation(pSrcHostPointer, dstAllocation, dstAllocationLocalOffset, size); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( @@ -15888,7 +15879,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( { VMA_ASSERT(allocator && srcAllocation && pDstHostPointer); - if(size == 0) + if (size == 0) { return VK_SUCCESS; } @@ -15897,7 +15888,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->CopyAllocationToMemory(srcAllocation, srcAllocationLocalOffset, pDstHostPointer, size); + return allocator->CopyAllocationToMemory(srcAllocation, srcAllocationLocalOffset, pDstHostPointer, size); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( @@ -15910,7 +15901,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->CheckCorruption(memoryTypeBits); + return allocator->CheckCorruption(memoryTypeBits); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( @@ -15931,7 +15922,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( VMA_DEBUG_GLOBAL_MUTEX_LOCK - *pContext = vma_new(allocator, VmaDefragmentationContext_T)(allocator, *pInfo); + * pContext = vma_new(allocator, VmaDefragmentationContext_T)(allocator, *pInfo); return VK_SUCCESS; } @@ -15946,8 +15937,8 @@ VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation( VMA_DEBUG_GLOBAL_MUTEX_LOCK - if (pStats) - context->GetStats(*pStats); + if (pStats) + context->GetStats(*pStats); vma_delete(allocator, context); } @@ -15962,7 +15953,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return context->DefragmentPassBegin(*pPassInfo); + return context->DefragmentPassBegin(*pPassInfo); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( @@ -15976,7 +15967,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return context->DefragmentPassEnd(*pPassInfo); + return context->DefragmentPassEnd(*pPassInfo); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( @@ -15990,7 +15981,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL); + return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( @@ -16006,7 +15997,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext); + return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( @@ -16020,7 +16011,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->BindImageMemory(allocation, 0, image, VMA_NULL); + return allocator->BindImageMemory(allocation, 0, image, VMA_NULL); } VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( @@ -16049,11 +16040,11 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( { VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation); - if(pBufferCreateInfo->size == 0) + if (pBufferCreateInfo->size == 0) { return VK_ERROR_INITIALIZATION_FAILED; } - if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + if ((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && !allocator->m_UseKhrBufferDeviceAddress) { VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); @@ -16064,7 +16055,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( VMA_DEBUG_GLOBAL_MUTEX_LOCK - *pBuffer = VK_NULL_HANDLE; + * pBuffer = VK_NULL_HANDLE; *pAllocation = VK_NULL_HANDLE; // 1. Create VkBuffer. @@ -16073,12 +16064,12 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( pBufferCreateInfo, allocator->GetAllocationCallbacks(), pBuffer); - if(res >= 0) + if (res >= 0) { // 2. vkGetBufferMemoryRequirements. VkMemoryRequirements vkMemReq = {}; bool requiresDedicatedAllocation = false; - bool prefersDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation); @@ -16095,20 +16086,20 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( 1, // allocationCount pAllocation); - if(res >= 0) + if (res >= 0) { // 3. Bind buffer with memory. - if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + if ((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) { res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); } - if(res >= 0) + if (res >= 0) { // All steps succeeded. - #if VMA_STATS_STRING_ENABLED - (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); - #endif - if(pAllocationInfo != VMA_NULL) +#if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); +#endif + if (pAllocationInfo != VMA_NULL) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -16141,11 +16132,11 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( { VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && VmaIsPow2(minAlignment) && pBuffer && pAllocation); - if(pBufferCreateInfo->size == 0) + if (pBufferCreateInfo->size == 0) { return VK_ERROR_INITIALIZATION_FAILED; } - if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + if ((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && !allocator->m_UseKhrBufferDeviceAddress) { VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); @@ -16156,7 +16147,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( VMA_DEBUG_GLOBAL_MUTEX_LOCK - *pBuffer = VK_NULL_HANDLE; + * pBuffer = VK_NULL_HANDLE; *pAllocation = VK_NULL_HANDLE; // 1. Create VkBuffer. @@ -16165,12 +16156,12 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( pBufferCreateInfo, allocator->GetAllocationCallbacks(), pBuffer); - if(res >= 0) + if (res >= 0) { // 2. vkGetBufferMemoryRequirements. VkMemoryRequirements vkMemReq = {}; bool requiresDedicatedAllocation = false; - bool prefersDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation); @@ -16190,20 +16181,20 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( 1, // allocationCount pAllocation); - if(res >= 0) + if (res >= 0) { // 3. Bind buffer with memory. - if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + if ((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) { res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); } - if(res >= 0) + if (res >= 0) { // All steps succeeded. - #if VMA_STATS_STRING_ENABLED - (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); - #endif - if(pAllocationInfo != VMA_NULL) +#if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); +#endif + if (pAllocationInfo != VMA_NULL) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -16261,12 +16252,12 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2( VMA_DEBUG_GLOBAL_MUTEX_LOCK - // 1. Create VkBuffer. - VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( - allocator->m_hDevice, - pBufferCreateInfo, - allocator->GetAllocationCallbacks(), - pBuffer); + // 1. Create VkBuffer. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( + allocator->m_hDevice, + pBufferCreateInfo, + allocator->GetAllocationCallbacks(), + pBuffer); if (res >= 0) { // 2. Bind buffer with memory. @@ -16287,7 +16278,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( { VMA_ASSERT(allocator); - if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + if (buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) { return; } @@ -16296,12 +16287,12 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( VMA_DEBUG_GLOBAL_MUTEX_LOCK - if(buffer != VK_NULL_HANDLE) - { - (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks()); - } + if (buffer != VK_NULL_HANDLE) + { + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks()); + } - if(allocation != VK_NULL_HANDLE) + if (allocation != VK_NULL_HANDLE) { allocator->FreeMemory( 1, // allocationCount @@ -16319,7 +16310,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( { VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation); - if(pImageCreateInfo->extent.width == 0 || + if (pImageCreateInfo->extent.width == 0 || pImageCreateInfo->extent.height == 0 || pImageCreateInfo->extent.depth == 0 || pImageCreateInfo->mipLevels == 0 || @@ -16332,7 +16323,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( VMA_DEBUG_GLOBAL_MUTEX_LOCK - *pImage = VK_NULL_HANDLE; + * pImage = VK_NULL_HANDLE; *pAllocation = VK_NULL_HANDLE; // 1. Create VkImage. @@ -16341,7 +16332,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( pImageCreateInfo, allocator->GetAllocationCallbacks(), pImage); - if(res >= 0) + if (res >= 0) { VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ? VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL : @@ -16350,7 +16341,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( // 2. Allocate memory using allocator. VkMemoryRequirements vkMemReq = {}; bool requiresDedicatedAllocation = false; - bool prefersDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; allocator->GetImageMemoryRequirements(*pImage, vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation); @@ -16366,20 +16357,20 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( 1, // allocationCount pAllocation); - if(res >= 0) + if (res >= 0) { // 3. Bind image with memory. - if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + if ((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) { res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL); } - if(res >= 0) + if (res >= 0) { // All steps succeeded. - #if VMA_STATS_STRING_ENABLED - (*pAllocation)->InitImageUsage(*pImageCreateInfo); - #endif - if(pAllocationInfo != VMA_NULL) +#if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitImageUsage(*pImageCreateInfo); +#endif + if (pAllocationInfo != VMA_NULL) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } @@ -16434,12 +16425,12 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2( VMA_DEBUG_GLOBAL_MUTEX_LOCK - // 1. Create VkImage. - VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)( - allocator->m_hDevice, - pImageCreateInfo, - allocator->GetAllocationCallbacks(), - pImage); + // 1. Create VkImage. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)( + allocator->m_hDevice, + pImageCreateInfo, + allocator->GetAllocationCallbacks(), + pImage); if (res >= 0) { // 2. Bind image with memory. @@ -16460,7 +16451,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( { VMA_ASSERT(allocator); - if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + if (image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) { return; } @@ -16469,11 +16460,11 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( VMA_DEBUG_GLOBAL_MUTEX_LOCK - if(image != VK_NULL_HANDLE) - { - (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks()); - } - if(allocation != VK_NULL_HANDLE) + if (image != VK_NULL_HANDLE) + { + (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks()); + } + if (allocation != VK_NULL_HANDLE) { allocator->FreeMemory( 1, // allocationCount @@ -16483,7 +16474,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaVirtualBlock VMA_NULLABLE * VMA_NOT_NULL pVirtualBlock) + VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock) { VMA_ASSERT(pCreateInfo && pVirtualBlock); VMA_ASSERT(pCreateInfo->size > 0); @@ -16491,7 +16482,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( VMA_DEBUG_GLOBAL_MUTEX_LOCK; *pVirtualBlock = vma_new(pCreateInfo->pAllocationCallbacks, VmaVirtualBlock_T)(*pCreateInfo); VkResult res = (*pVirtualBlock)->Init(); - if(res < 0) + if (res < 0) { vma_delete(pCreateInfo->pAllocationCallbacks, *pVirtualBlock); *pVirtualBlock = VK_NULL_HANDLE; @@ -16501,7 +16492,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(VmaVirtualBlock VMA_NULLABLE virtualBlock) { - if(virtualBlock != VK_NULL_HANDLE) + if (virtualBlock != VK_NULL_HANDLE) { VMA_DEBUG_LOG("vmaDestroyVirtualBlock"); VMA_DEBUG_GLOBAL_MUTEX_LOCK; @@ -16539,7 +16530,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(VmaVirtualBlock VMA_NOT_N VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(VmaVirtualBlock VMA_NOT_NULL virtualBlock, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation) { - if(allocation != VK_NULL_HANDLE) + if (allocation != VK_NULL_HANDLE) { VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); VMA_DEBUG_LOG("vmaVirtualFree"); @@ -16586,7 +16577,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(VmaVirtualBlo #if VMA_STATS_STRING_ENABLED VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, - char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap) + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, VkBool32 detailedMap) { VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && ppStatsString != VMA_NULL); VMA_DEBUG_GLOBAL_MUTEX_LOCK; @@ -16599,7 +16590,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, char* VMA_NULLABLE pStatsString) { - if(pStatsString != VMA_NULL) + if (pStatsString != VMA_NULL) { VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); VMA_DEBUG_GLOBAL_MUTEX_LOCK;