From c6f8c86085bd3b9e06f6eabcc4af9c1f3f332c86 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 6 Apr 2020 17:17:38 +0800 Subject: [PATCH 1/7] Add annotations for nullability and length These are only present on the declarations in the C API. New macros - `VMA_NULLABLE` - `VMA_NOT_NULL` - `VMA_NULLABLE_NON_DISPATCHABLE` - `VMA_NOT_NULL_NON_DISPATCHABLE` - `VMA_LEN_IF_NOT_NULL` On clang `VMA_NOT_NULL` and `VMA_NULLABLE` are defined as `_Nonnull` and `_Nullable`. Clang will use these annotations to generate diagnostics when these functions or structs are incorrectly used. `VMA_NULLABLE_NON_DISPATCHABLE` and `VMA_NOT_NULL_NON_DISPATCHABLE` are not defined on platforms where Vulkan's non-dispatchable handles are not pointers; on platforms where they are, these macros are defined to be `VMA_NULLABLE` and `VMA_NOT_NULL` respectively. `LEN_IF_NOT_NULL` is not defined for any compiler. It is included to mirror the `len` attribute in the Vulkan XML spec in order to aid in development of other language bindings for this library. It was tempting to use C's array syntax (`foo(int len, int arr[len])`)to specify lengths, however this is not possible to use with optional pointers, nor is it possible to use inside structs. For the sake of consistency only `VMA_LEN_IF_NOT_NULL` is used (additionally neither clang not gcc generate warnings for function misuse when the array length specifier is anything but an integer literal). - Also correct a couple of typos - Also add assert on ppName in vmaGetPoolName Closes #114 --- src/vk_mem_alloc.h | 459 +++++++++++++++++++++++++-------------------- 1 file changed, 258 insertions(+), 201 deletions(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 7e70a9e..bc782e1 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -1993,6 +1993,54 @@ available through VmaAllocatorCreateInfo::pRecordSettings. #define VMA_CALL_POST #endif +// Define this macro to decorate pointers with an attribute specifying the +// length of the array they point to if they are not null. +// +// The length may be one of +// - The name of another parameter in the argument list where the pointer is declared +// - The name of another member in the struct where the pointer is declared +#ifndef VMA_LEN_IF_NOT_NULL + #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 +#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 +#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 +#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 +#endif + /** \struct VmaAllocator \brief Represents main object of this library initialized. @@ -2006,18 +2054,18 @@ VK_DEFINE_HANDLE(VmaAllocator) /// Callback function called after successful vkAllocateMemory. typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)( - VmaAllocator allocator, - uint32_t memoryType, - VkDeviceMemory memory, - VkDeviceSize size, - void* pUserData); + 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 allocator, - uint32_t memoryType, - VkDeviceMemory memory, - VkDeviceSize size, - void* pUserData); + 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`. @@ -2028,11 +2076,11 @@ Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. */ typedef struct VmaDeviceMemoryCallbacks { /// Optional, can be null. - PFN_vmaAllocateDeviceMemoryFunction pfnAllocate; + PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate; /// Optional, can be null. - PFN_vmaFreeDeviceMemoryFunction pfnFree; + PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree; /// Optional, can be null. - void* pUserData; + void* VMA_NULLABLE pUserData; } VmaDeviceMemoryCallbacks; /// Flags for created #VmaAllocator. @@ -2140,33 +2188,33 @@ typedef VkFlags VmaAllocatorCreateFlags; Used in VmaAllocatorCreateInfo::pVulkanFunctions. */ typedef struct VmaVulkanFunctions { - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; - PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; - PFN_vkAllocateMemory vkAllocateMemory; - PFN_vkFreeMemory vkFreeMemory; - PFN_vkMapMemory vkMapMemory; - PFN_vkUnmapMemory vkUnmapMemory; - PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; - PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; - PFN_vkBindBufferMemory vkBindBufferMemory; - PFN_vkBindImageMemory vkBindImageMemory; - PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; - PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; - PFN_vkCreateBuffer vkCreateBuffer; - PFN_vkDestroyBuffer vkDestroyBuffer; - PFN_vkCreateImage vkCreateImage; - PFN_vkDestroyImage vkDestroyImage; - PFN_vkCmdCopyBuffer vkCmdCopyBuffer; + PFN_vkGetPhysicalDeviceProperties VMA_NOT_NULL vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceMemoryProperties VMA_NOT_NULL vkGetPhysicalDeviceMemoryProperties; + PFN_vkAllocateMemory VMA_NOT_NULL vkAllocateMemory; + PFN_vkFreeMemory VMA_NOT_NULL vkFreeMemory; + PFN_vkMapMemory VMA_NOT_NULL vkMapMemory; + PFN_vkUnmapMemory VMA_NOT_NULL vkUnmapMemory; + PFN_vkFlushMappedMemoryRanges VMA_NOT_NULL vkFlushMappedMemoryRanges; + PFN_vkInvalidateMappedMemoryRanges VMA_NOT_NULL vkInvalidateMappedMemoryRanges; + PFN_vkBindBufferMemory VMA_NOT_NULL vkBindBufferMemory; + PFN_vkBindImageMemory VMA_NOT_NULL vkBindImageMemory; + PFN_vkGetBufferMemoryRequirements VMA_NOT_NULL vkGetBufferMemoryRequirements; + PFN_vkGetImageMemoryRequirements VMA_NOT_NULL vkGetImageMemoryRequirements; + PFN_vkCreateBuffer VMA_NOT_NULL vkCreateBuffer; + PFN_vkDestroyBuffer VMA_NOT_NULL vkDestroyBuffer; + PFN_vkCreateImage VMA_NOT_NULL vkCreateImage; + PFN_vkDestroyImage VMA_NOT_NULL vkDestroyImage; + PFN_vkCmdCopyBuffer VMA_NOT_NULL vkCmdCopyBuffer; #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 - PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; - PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; + PFN_vkGetBufferMemoryRequirements2KHR VMA_NOT_NULL vkGetBufferMemoryRequirements2KHR; + PFN_vkGetImageMemoryRequirements2KHR VMA_NOT_NULL vkGetImageMemoryRequirements2KHR; #endif #if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 - PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; - PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; + PFN_vkBindBufferMemory2KHR VMA_NOT_NULL vkBindBufferMemory2KHR; + PFN_vkBindImageMemory2KHR VMA_NOT_NULL vkBindImageMemory2KHR; #endif #if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 - PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; + PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NOT_NULL vkGetPhysicalDeviceMemoryProperties2KHR; #endif } VmaVulkanFunctions; @@ -2195,7 +2243,7 @@ typedef struct VmaRecordSettings It will be opened for the whole time #VmaAllocator object is alive. If opening this file fails, creation of the whole allocator object fails. */ - const char* pFilePath; + const char* VMA_NOT_NULL pFilePath; } VmaRecordSettings; /// Description of a Allocator to be created. @@ -2205,19 +2253,19 @@ typedef struct VmaAllocatorCreateInfo VmaAllocatorCreateFlags flags; /// Vulkan physical device. /** It must be valid throughout whole lifetime of created allocator. */ - VkPhysicalDevice physicalDevice; + VkPhysicalDevice VMA_NOT_NULL physicalDevice; /// Vulkan device. /** It must be valid throughout whole lifetime of created allocator. */ - VkDevice device; + 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* pAllocationCallbacks; + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional. /** Optional, can be null. */ - const VmaDeviceMemoryCallbacks* pDeviceMemoryCallbacks; + const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks; /** \brief Maximum number of additional frames that are in use at the same time as current frame. This value is used only when you make allocations with @@ -2256,24 +2304,25 @@ typedef struct VmaAllocatorCreateInfo blocks to system RAM. This driver behavior can also be controlled using VK_AMD_memory_overallocation_behavior extension. */ - const VkDeviceSize* pHeapSizeLimit; + const VkDeviceSize* VMA_NULLABLE pHeapSizeLimit; + /** \brief Pointers to Vulkan functions. Can be null. For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions). */ - const VmaVulkanFunctions* pVulkanFunctions; + const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions; /** \brief Parameters for recording of VMA calls. Can be null. If not null, it enables recording of calls to VMA functions to a file. If support for recording is not enabled using `VMA_RECORDING_ENABLED` macro, creation of the allocator object fails with `VK_ERROR_FEATURE_NOT_PRESENT`. */ - const VmaRecordSettings* pRecordSettings; + const VmaRecordSettings* VMA_NULLABLE pRecordSettings; /** \brief Handle to Vulkan instance object. Starting from version 3.0.0 this member is no longer optional, it must be set! */ - VkInstance instance; + VkInstance VMA_NOT_NULL instance; /** \brief Optional. The highest version of Vulkan that the application is designed to use. 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`. @@ -2287,12 +2336,12 @@ typedef struct VmaAllocatorCreateInfo /// Creates Allocator object. VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( - const VmaAllocatorCreateInfo* pCreateInfo, - VmaAllocator* pAllocator); + const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocator* VMA_NOT_NULL pAllocator); /// Destroys allocator object. VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( - VmaAllocator allocator); + VmaAllocator VMA_NULLABLE allocator); /** \brief Information about existing #VmaAllocator object. */ @@ -2302,17 +2351,17 @@ typedef struct VmaAllocatorInfo This is the same value as has been passed through VmaAllocatorCreateInfo::instance. */ - VkInstance 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 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 device; + VkDevice VMA_NOT_NULL device; } VmaAllocatorInfo; /** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc. @@ -2320,23 +2369,23 @@ typedef struct VmaAllocatorInfo 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 allocator, VmaAllocatorInfo* pAllocatorInfo); +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 allocator, - const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties); + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceProperties** 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 allocator, - const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties); + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceMemoryProperties** VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); /** \brief Given Memory Type Index, returns Property Flags of this memory type. @@ -2345,9 +2394,9 @@ This is just a convenience function. Same information can be obtained using vmaGetMemoryProperties(). */ VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( - VmaAllocator allocator, + VmaAllocator VMA_NOT_NULL allocator, uint32_t memoryTypeIndex, - VkMemoryPropertyFlags* pFlags); + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); /** \brief Sets index of the current frame. @@ -2358,7 +2407,7 @@ when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot become lost in the current frame. */ VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( - VmaAllocator allocator, + VmaAllocator VMA_NOT_NULL allocator, uint32_t frameIndex); /** \brief Calculated statistics of memory usage in entire allocator. @@ -2397,8 +2446,8 @@ Note that when using allocator from multiple threads, returned information may i become outdated. */ VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats( - VmaAllocator allocator, - VmaStats* pStats); + VmaAllocator VMA_NOT_NULL allocator, + VmaStats* VMA_NOT_NULL pStats); /** \brief Statistics of current memory usage and available budget, in bytes, for specific memory heap. */ @@ -2452,8 +2501,8 @@ Note that when using allocator from multiple threads, returned information may i become outdated. */ VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget( - VmaAllocator allocator, - VmaBudget* pBudget); + VmaAllocator VMA_NOT_NULL allocator, + VmaBudget* VMA_NOT_NULL pBudget); #ifndef VMA_STATS_STRING_ENABLED #define VMA_STATS_STRING_ENABLED 1 @@ -2465,13 +2514,13 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget( /** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function. */ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( - VmaAllocator allocator, - char** ppStatsString, + VmaAllocator VMA_NOT_NULL allocator, + char** VMA_NOT_NULL ppStatsString, VkBool32 detailedMap); VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( - VmaAllocator allocator, - char* pStatsString); + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE pStatsString); #endif // #if VMA_STATS_STRING_ENABLED @@ -2697,14 +2746,14 @@ typedef struct VmaAllocationCreateInfo Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. */ - VmaPool pool; + 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* pUserData; + void* VMA_NULLABLE pUserData; } VmaAllocationCreateInfo; /** @@ -2724,10 +2773,10 @@ 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 allocator, + VmaAllocator VMA_NOT_NULL allocator, uint32_t memoryTypeBits, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - uint32_t* pMemoryTypeIndex); + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); /** \brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo. @@ -2742,10 +2791,10 @@ It is just a convenience function, equivalent to calling: - `vkDestroyBuffer` */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( - VmaAllocator allocator, - const VkBufferCreateInfo* pBufferCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - uint32_t* pMemoryTypeIndex); + 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. @@ -2760,10 +2809,10 @@ It is just a convenience function, equivalent to calling: - `vkDestroyImage` */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( - VmaAllocator allocator, - const VkImageCreateInfo* pImageCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - uint32_t* pMemoryTypeIndex); + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); /// Flags to be passed as VmaPoolCreateInfo::flags. typedef enum VmaPoolCreateFlagBits { @@ -2905,15 +2954,15 @@ typedef struct VmaPoolStats { @param[out] pPool Handle to created pool. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( - VmaAllocator allocator, - const VmaPoolCreateInfo* pCreateInfo, - VmaPool* pPool); + VmaAllocator VMA_NOT_NULL allocator, + const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaPool* VMA_NOT_NULL pPool); /** \brief Destroys #VmaPool object and frees Vulkan device memory. */ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( - VmaAllocator allocator, - VmaPool pool); + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NULLABLE pool); /** \brief Retrieves statistics of existing #VmaPool object. @@ -2922,9 +2971,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( @param[out] pPoolStats Statistics of specified pool. */ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats( - VmaAllocator allocator, - VmaPool pool, - VmaPoolStats* pPoolStats); + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaPoolStats* VMA_NOT_NULL pPoolStats); /** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now. @@ -2933,9 +2982,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats( @param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information. */ VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost( - VmaAllocator allocator, - VmaPool pool, - size_t* pLostAllocationCount); + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + size_t* VMA_NULLABLE pLostAllocationCount); /** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions. @@ -2951,7 +3000,7 @@ Possible return values: `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 allocator, VmaPool pool); +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. @@ -2960,9 +3009,9 @@ containing name of the pool that was previously set. The pointer becomes invalid destroyed or its name is changed using vmaSetPoolName(). */ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( - VmaAllocator allocator, - VmaPool pool, - const char** ppName); + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char** VMA_NOT_NULL ppName); /** \brief Sets name of a custom pool. @@ -2970,9 +3019,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( 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 allocator, - VmaPool pool, - const char* pName); + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE pName); /** \struct VmaAllocation \brief Represents single memory allocation. @@ -3016,7 +3065,7 @@ typedef struct VmaAllocationInfo { If the allocation is lost, it is equal to `VK_NULL_HANDLE`. */ - VkDeviceMemory deviceMemory; + VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory; /** \brief Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation. It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost. @@ -3030,17 +3079,17 @@ typedef struct VmaAllocationInfo { /** \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 null. + 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 call to vmaDefragment() if this allocation is passed to the function. */ - void* pMappedData; + 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* pUserData; + void* VMA_NULLABLE pUserData; } VmaAllocationInfo; /** \brief General purpose memory allocation. @@ -3054,11 +3103,11 @@ It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage vmaCreateBuffer(), vmaCreateImage() instead whenever possible. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( - VmaAllocator allocator, - const VkMemoryRequirements* pVkMemoryRequirements, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief General purpose memory allocation for multiple allocation objects at once. @@ -3080,12 +3129,12 @@ If any allocation fails, all allocations already made within this function call 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 allocator, - const VkMemoryRequirements* pVkMemoryRequirements, - const VmaAllocationCreateInfo* pCreateInfo, + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, size_t allocationCount, - VmaAllocation* pAllocations, - VmaAllocationInfo* pAllocationInfo); + VmaAllocation* VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo VMA_LEN_IF_NOT_NULL(allocationCount)); /** @param[out] pAllocation Handle to allocated memory. @@ -3094,27 +3143,27 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( You should free the memory using vmaFreeMemory(). */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( - VmaAllocator allocator, - VkBuffer buffer, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /// Function similar to vmaAllocateMemoryForBuffer(). VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( - VmaAllocator allocator, - VkImage image, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation* 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 allocator, - VmaAllocation allocation); + VmaAllocator VMA_NOT_NULL allocator, + const VmaAllocation VMA_NULLABLE allocation); /** \brief Frees memory and destroys multiple allocations. @@ -3127,9 +3176,9 @@ 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 allocator, + VmaAllocator VMA_NOT_NULL allocator, size_t allocationCount, - VmaAllocation* pAllocations); + const VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount)); /** \brief Deprecated. @@ -3139,8 +3188,8 @@ In current version it returns `VK_SUCCESS` only if `newSize` equals current allo Otherwise returns `VK_ERROR_OUT_OF_POOL_MEMORY`, indicating that allocation's size could not be changed. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaResizeAllocation( - VmaAllocator allocator, - VmaAllocation allocation, + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, VkDeviceSize newSize); /** \brief Returns current information about specified allocation and atomically marks it as used in current frame. @@ -3160,9 +3209,9 @@ you can avoid calling it too often. - If you just want to check if allocation is not lost, vmaTouchAllocation() will work faster. */ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( - VmaAllocator allocator, - VmaAllocation allocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo); /** \brief Returns `VK_TRUE` if allocation is not lost and atomically marks it as used in current frame. @@ -3179,8 +3228,8 @@ If the allocation has been created without #VMA_ALLOCATION_CREATE_CAN_BECOME_LOS this function always returns `VK_TRUE`. */ VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation( - VmaAllocator allocator, - VmaAllocation allocation); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation); /** \brief Sets pUserData in given allocation to new value. @@ -3196,9 +3245,9 @@ 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 allocator, - VmaAllocation allocation, - void* pUserData); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE pUserData); /** \brief Creates new allocation that is in lost state from the beginning. @@ -3211,8 +3260,8 @@ not bound to any image or buffer. It has size = 0. It cannot be turned into a real, non-empty allocation. */ VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation( - VmaAllocator allocator, - VmaAllocation* pAllocation); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation* VMA_NOT_NULL pAllocation); /** \brief Maps memory represented by given allocation and returns pointer to it. @@ -3253,9 +3302,9 @@ 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 allocator, - VmaAllocation allocation, - void** ppData); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void** VMA_NOT_NULL ppData); /** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). @@ -3266,8 +3315,8 @@ 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 allocator, - VmaAllocation allocation); + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation); /** \brief Flushes memory of given allocation. @@ -3287,7 +3336,11 @@ 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`!!! */ -VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size); +VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); /** \brief Invalidates memory of given allocation. @@ -3307,7 +3360,11 @@ 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`!!! */ -VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size); +VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + 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. @@ -3325,7 +3382,7 @@ Possible return values: `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 allocator, uint32_t memoryTypeBits); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator VMA_NOT_NULL allocator, uint32_t memoryTypeBits); /** \struct VmaDefragmentationContext \brief Represents Opaque object that represents started defragmentation process. @@ -3361,13 +3418,13 @@ typedef struct VmaDefragmentationInfo2 { It is safe to pass allocations that are in the lost state - they are ignored. All allocations not present in this array are considered non-moveable during this defragmentation. */ - VmaAllocation* pAllocations; + VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount); /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation. The array should have `allocationCount` elements. You can pass null if you are not interested in this information. */ - VkBool32* pAllocationsChanged; + VkBool32* VMA_NULLABLE pAllocationsChanged VMA_LEN_IF_NOT_NULL(allocationCount); /** \brief Numer of pools in `pPools` array. */ uint32_t poolCount; @@ -3386,7 +3443,7 @@ typedef struct VmaDefragmentationInfo2 { Using this array is equivalent to specifying all allocations from the pools in `pAllocations`. It might be more efficient. */ - VmaPool* pPools; + VmaPool VMA_NOT_NULL * VMA_NULLABLE pPools VMA_LEN_IF_NOT_NULL(poolCount); /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`. `VK_WHOLE_SIZE` means no limit. @@ -3415,12 +3472,12 @@ typedef struct VmaDefragmentationInfo2 { Passing null means that only CPU defragmentation will be performed. */ - VkCommandBuffer commandBuffer; + VkCommandBuffer VMA_NULLABLE commandBuffer; } VmaDefragmentationInfo2; typedef struct VmaDefragmentationPassMoveInfo { - VmaAllocation allocation; - VkDeviceMemory memory; + VmaAllocation VMA_NOT_NULL allocation; + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory; VkDeviceSize offset; } VmaDefragmentationPassMoveInfo; @@ -3430,7 +3487,7 @@ To be used with function vmaBeginDefragmentationPass(). */ typedef struct VmaDefragmentationPassInfo { uint32_t moveCount; - VmaDefragmentationPassMoveInfo* pMoves; + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pMoves VMA_LEN_IF_NOT_NULL(moveCount); } VmaDefragmentationPassInfo; /** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment(). @@ -3492,10 +3549,10 @@ For more information and important limitations regarding defragmentation, see do [Defragmentation](@ref defragmentation). */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin( - VmaAllocator allocator, - const VmaDefragmentationInfo2* pInfo, - VmaDefragmentationStats* pStats, - VmaDefragmentationContext *pContext); + VmaAllocator VMA_NOT_NULL allocator, + const VmaDefragmentationInfo2* VMA_NOT_NULL pInfo, + VmaDefragmentationStats* VMA_NULLABLE pStats, + VmaDefragmentationContext* VMA_NOT_NULL pContext); /** \brief Ends defragmentation process. @@ -3503,17 +3560,17 @@ Use this function to finish defragmentation started by vmaDefragmentationBegin() It is safe to pass `context == null`. The function then does nothing. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd( - VmaAllocator allocator, - VmaDefragmentationContext context); + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context); VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( - VmaAllocator allocator, - VmaDefragmentationContext context, - VmaDefragmentationPassInfo* pInfo + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context, + VmaDefragmentationPassInfo* VMA_NOT_NULL pInfo ); VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( - VmaAllocator allocator, - VmaDefragmentationContext context + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context ); /** \brief Deprecated. Compacts memory by moving allocations. @@ -3557,12 +3614,12 @@ you should measure that on your platform. For more information, see [Defragmentation](@ref defragmentation) chapter. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( - VmaAllocator allocator, - VmaAllocation* pAllocations, + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), size_t allocationCount, - VkBool32* pAllocationsChanged, - const VmaDefragmentationInfo *pDefragmentationInfo, - VmaDefragmentationStats* pDefragmentationStats); + VkBool32* VMA_NULLABLE pAllocationsChanged VMA_LEN_IF_NOT_NULL(allocationCount), + const VmaDefragmentationInfo* VMA_NULLABLE pDefragmentationInfo, + VmaDefragmentationStats* VMA_NULLABLE pDefragmentationStats); /** \brief Binds buffer to allocation. @@ -3577,9 +3634,9 @@ allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from mul It is recommended to use function vmaCreateBuffer() instead of this one. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( - VmaAllocator allocator, - VmaAllocation allocation, - VkBuffer buffer); + 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. @@ -3592,11 +3649,11 @@ If `pNext` is not null, #VmaAllocator object must have been created with #VMA_AL or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( - VmaAllocator allocator, - VmaAllocation allocation, + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, VkDeviceSize allocationLocalOffset, - VkBuffer buffer, - const void* pNext); + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const void* VMA_NULLABLE pNext); /** \brief Binds image to allocation. @@ -3611,9 +3668,9 @@ allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from mul It is recommended to use function vmaCreateImage() instead of this one. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( - VmaAllocator allocator, - VmaAllocation allocation, - VkImage image); + 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. @@ -3626,11 +3683,11 @@ If `pNext` is not null, #VmaAllocator object must have been created with #VMA_AL or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( - VmaAllocator allocator, - VmaAllocation allocation, + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, VkDeviceSize allocationLocalOffset, - VkImage image, - const void* pNext); + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const void* VMA_NULLABLE pNext); /** @param[out] pBuffer Buffer that was created. @@ -3659,12 +3716,12 @@ allocation for this buffer, just like when using VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( - VmaAllocator allocator, - const VkBufferCreateInfo* pBufferCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - VkBuffer* pBuffer, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkBuffer* VMA_NOT_NULL pBuffer, + VmaAllocation* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan buffer and frees allocated memory. @@ -3678,18 +3735,18 @@ vmaFreeMemory(allocator, allocation); It it safe to pass null as buffer and/or allocation. */ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( - VmaAllocator allocator, - VkBuffer buffer, - VmaAllocation allocation); + 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 allocator, - const VkImageCreateInfo* pImageCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - VkImage* pImage, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkImage* VMA_NOT_NULL pImage, + VmaAllocation* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan image and frees allocated memory. @@ -3703,9 +3760,9 @@ vmaFreeMemory(allocator, allocation); It it safe to pass null as image and/or allocation. */ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( - VmaAllocator allocator, - VkImage image, - VmaAllocation allocation); + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NULLABLE_NON_DISPATCHABLE image, + VmaAllocation VMA_NULLABLE allocation); #ifdef __cplusplus } @@ -17614,7 +17671,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( VmaPool pool, const char** ppName) { - VMA_ASSERT(allocator && pool); + VMA_ASSERT(allocator && pool && ppName); VMA_DEBUG_LOG("vmaGetPoolName"); From 35939a0fd16882967d227f0709c8276a6820aede Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 6 Apr 2020 18:28:46 +0800 Subject: [PATCH 2/7] Add VMA_NULLABLE to pointed to out values --- src/vk_mem_alloc.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index bc782e1..63f223c 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -2337,7 +2337,7 @@ typedef struct VmaAllocatorCreateInfo /// Creates Allocator object. VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaAllocator* VMA_NOT_NULL pAllocator); + VmaAllocator VMA_NULLABLE * VMA_NOT_NULL pAllocator); /// Destroys allocator object. VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( @@ -2377,7 +2377,7 @@ 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_NOT_NULL ppPhysicalDeviceProperties); + const VkPhysicalDeviceProperties* VMA_NULLABLE * VMA_NOT_NULL ppPhysicalDeviceProperties); /** PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. @@ -2385,7 +2385,7 @@ 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_NOT_NULL ppPhysicalDeviceMemoryProperties); + const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE * VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); /** \brief Given Memory Type Index, returns Property Flags of this memory type. @@ -2515,7 +2515,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget( */ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( VmaAllocator VMA_NOT_NULL allocator, - char** VMA_NOT_NULL ppStatsString, + char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap); VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( @@ -2956,7 +2956,7 @@ typedef struct VmaPoolStats { VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( VmaAllocator VMA_NOT_NULL allocator, const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, - VmaPool* VMA_NOT_NULL pPool); + VmaPool VMA_NULLABLE * VMA_NOT_NULL pPool); /** \brief Destroys #VmaPool object and frees Vulkan device memory. */ @@ -3011,7 +3011,7 @@ 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_NOT_NULL ppName); + const char* VMA_NULLABLE * VMA_NOT_NULL ppName); /** \brief Sets name of a custom pool. @@ -3106,7 +3106,7 @@ 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_NOT_NULL pAllocation, + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation, VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief General purpose memory allocation for multiple allocation objects at once. @@ -3133,7 +3133,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, size_t allocationCount, - VmaAllocation* VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), VmaAllocationInfo* VMA_NULLABLE pAllocationInfo VMA_LEN_IF_NOT_NULL(allocationCount)); /** @@ -3146,7 +3146,7 @@ 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_NOT_NULL pAllocation, + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation, VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /// Function similar to vmaAllocateMemoryForBuffer(). @@ -3154,7 +3154,7 @@ 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_NOT_NULL pAllocation, + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation, VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). @@ -3261,7 +3261,7 @@ a real, non-empty allocation. */ VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation( VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation* VMA_NOT_NULL pAllocation); + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation); /** \brief Maps memory represented by given allocation and returns pointer to it. @@ -3304,7 +3304,7 @@ you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as requir VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( VmaAllocator VMA_NOT_NULL allocator, VmaAllocation VMA_NOT_NULL allocation, - void** VMA_NOT_NULL ppData); + void* VMA_NULLABLE * VMA_NOT_NULL ppData); /** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). @@ -3552,7 +3552,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin( VmaAllocator VMA_NOT_NULL allocator, const VmaDefragmentationInfo2* VMA_NOT_NULL pInfo, VmaDefragmentationStats* VMA_NULLABLE pStats, - VmaDefragmentationContext* VMA_NOT_NULL pContext); + VmaDefragmentationContext VMA_NULLABLE * VMA_NOT_NULL pContext); /** \brief Ends defragmentation process. @@ -3719,8 +3719,8 @@ 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_NOT_NULL pBuffer, - VmaAllocation* VMA_NOT_NULL pAllocation, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE * VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation, VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan buffer and frees allocated memory. @@ -3744,8 +3744,8 @@ 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_NOT_NULL pImage, - VmaAllocation* VMA_NOT_NULL pAllocation, + VkImage VMA_NULLABLE_NON_DISPATCHABLE * VMA_NOT_NULL pImage, + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation, VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan image and frees allocated memory. From 3a756282ab6f708347329d0001dca3568bbfc7dd Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 6 Apr 2020 18:30:13 +0800 Subject: [PATCH 3/7] Disable -Wnullability-completeness for the implementation --- src/vk_mem_alloc.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 63f223c..b09d718 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -3778,6 +3778,12 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( #ifdef VMA_IMPLEMENTATION #undef VMA_IMPLEMENTATION +// Only the public API has nullability annotations, not the implementation +#ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wnullability-completeness" +#endif + #include #include #include @@ -18629,4 +18635,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( } } +#ifdef __clang__ + // -Wnullability-completeness + #pragma clang diagnostic pop +#endif + #endif // #ifdef VMA_IMPLEMENTATION From b9725fc20379a66f5eec1cc0253bc659002e8a01 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 6 Apr 2020 19:38:02 +0800 Subject: [PATCH 4/7] Annotate types with lengths instead of parameters/members --- src/vk_mem_alloc.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index b09d718..6f3a1b0 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -3133,8 +3133,8 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, size_t allocationCount, - VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), - VmaAllocationInfo* VMA_NULLABLE pAllocationInfo VMA_LEN_IF_NOT_NULL(allocationCount)); + VmaAllocation VMA_NULLABLE * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, + VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo); /** @param[out] pAllocation Handle to allocated memory. @@ -3178,7 +3178,7 @@ Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entr VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( VmaAllocator VMA_NOT_NULL allocator, size_t allocationCount, - const VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount)); + const VmaAllocation VMA_NULLABLE * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations); /** \brief Deprecated. @@ -3418,13 +3418,13 @@ typedef struct VmaDefragmentationInfo2 { It is safe to pass allocations that are in the lost state - they are ignored. All allocations not present in this array are considered non-moveable during this defragmentation. */ - VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount); + VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations; /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation. The array should have `allocationCount` elements. You can pass null if you are not interested in this information. */ - VkBool32* VMA_NULLABLE pAllocationsChanged VMA_LEN_IF_NOT_NULL(allocationCount); + VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged; /** \brief Numer of pools in `pPools` array. */ uint32_t poolCount; @@ -3443,7 +3443,7 @@ typedef struct VmaDefragmentationInfo2 { Using this array is equivalent to specifying all allocations from the pools in `pAllocations`. It might be more efficient. */ - VmaPool VMA_NOT_NULL * VMA_NULLABLE pPools VMA_LEN_IF_NOT_NULL(poolCount); + VmaPool VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(poolCount) pPools; /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`. `VK_WHOLE_SIZE` means no limit. @@ -3487,7 +3487,7 @@ To be used with function vmaBeginDefragmentationPass(). */ typedef struct VmaDefragmentationPassInfo { uint32_t moveCount; - VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pMoves VMA_LEN_IF_NOT_NULL(moveCount); + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(moveCount) pMoves; } VmaDefragmentationPassInfo; /** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment(). @@ -3615,9 +3615,9 @@ For more information, see [Defragmentation](@ref defragmentation) chapter. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL pAllocations VMA_LEN_IF_NOT_NULL(allocationCount), + VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, size_t allocationCount, - VkBool32* VMA_NULLABLE pAllocationsChanged VMA_LEN_IF_NOT_NULL(allocationCount), + VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged, const VmaDefragmentationInfo* VMA_NULLABLE pDefragmentationInfo, VmaDefragmentationStats* VMA_NULLABLE pDefragmentationStats); From 08bc59bee51b3cc8eb11a43595ec17e66f1346b2 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 6 Apr 2020 19:42:13 +0800 Subject: [PATCH 5/7] Add length annotation for VmaAllocatorCreateInfo::pHeapSizeLimit --- src/vk_mem_alloc.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 6f3a1b0..86e297c 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -1999,6 +1999,11 @@ available through VmaAllocatorCreateInfo::pRecordSettings. // The length may be one of // - The name of another parameter in the argument list where the pointer is declared // - The name of another member in the struct where the pointer is declared +// - The name of a member of a struct type, meaning the value of that member in +// the context of the call. For example +// VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount"), +// 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) #endif @@ -2304,7 +2309,7 @@ typedef struct VmaAllocatorCreateInfo blocks to system RAM. This driver behavior can also be controlled using VK_AMD_memory_overallocation_behavior extension. */ - const VkDeviceSize* VMA_NULLABLE pHeapSizeLimit; + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pHeapSizeLimit; /** \brief Pointers to Vulkan functions. Can be null. From f22cd7b3c6d346997afebd33237b27cfa68f2ae2 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 7 Apr 2020 17:39:07 +0800 Subject: [PATCH 6/7] Add const qualifier to handles where possible This mirrors the Vulkan specification where handles are often passed with a const qualifier --- src/vk_mem_alloc.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 86e297c..7c160b7 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -3423,7 +3423,7 @@ typedef struct VmaDefragmentationInfo2 { It is safe to pass allocations that are in the lost state - they are ignored. All allocations not present in this array are considered non-moveable during this defragmentation. */ - VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations; + const VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations; /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation. The array should have `allocationCount` elements. @@ -3448,7 +3448,7 @@ typedef struct VmaDefragmentationInfo2 { Using this array is equivalent to specifying all allocations from the pools in `pAllocations`. It might be more efficient. */ - VmaPool VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(poolCount) pPools; + const VmaPool VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(poolCount) pPools; /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`. `VK_WHOLE_SIZE` means no limit. @@ -3620,7 +3620,7 @@ For more information, see [Defragmentation](@ref defragmentation) chapter. */ VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( VmaAllocator VMA_NOT_NULL allocator, - VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, + const VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, size_t allocationCount, VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged, const VmaDefragmentationInfo* VMA_NULLABLE pDefragmentationInfo, @@ -7191,10 +7191,10 @@ public: VmaDefragmentationStats* pStats); ~VmaDefragmentationContext_T(); - void AddPools(uint32_t poolCount, VmaPool* pPools); + void AddPools(uint32_t poolCount, const VmaPool* pPools); void AddAllocations( uint32_t allocationCount, - VmaAllocation* pAllocations, + const VmaAllocation* pAllocations, VkBool32* pAllocationsChanged); /* @@ -14293,7 +14293,7 @@ VmaDefragmentationContext_T::~VmaDefragmentationContext_T() } } -void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, VmaPool* pPools) +void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pPools) { for(uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex) { @@ -14330,7 +14330,7 @@ void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, VmaPool* pPools) void VmaDefragmentationContext_T::AddAllocations( uint32_t allocationCount, - VmaAllocation* pAllocations, + const VmaAllocation* pAllocations, VkBool32* pAllocationsChanged) { // Dispatch pAllocations among defragmentators. Create them when necessary. @@ -17947,7 +17947,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( VmaAllocator allocator, size_t allocationCount, - VmaAllocation* pAllocations) + const VmaAllocation* pAllocations) { if(allocationCount == 0) { @@ -18166,7 +18166,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, u VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( VmaAllocator allocator, - VmaAllocation* pAllocations, + const VmaAllocation* pAllocations, size_t allocationCount, VkBool32* pAllocationsChanged, const VmaDefragmentationInfo *pDefragmentationInfo, From 48104608949c11227f36e29c48a04f1ab5f8b2fe Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 7 Apr 2020 22:40:27 +0800 Subject: [PATCH 7/7] Do not include nullability and length annotations in documentation --- src/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Doxyfile b/src/Doxyfile index 3efbdb9..b880bb2 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -2188,7 +2188,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = VMA_CALL_PRE= VMA_CALL_POST= +PREDEFINED = VMA_CALL_PRE= VMA_CALL_POST= VMA_NOT_NULL= VMA_NULLABLE= VMA_LEN_IF_NOT_NULL(len)= VMA_NOT_NULL_NON_DISPATCHABLE= VMA_NULLABLE_NON_DISPATCHABLE= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The