VulkanMemoryAllocator 0.10.5.1 → 0.11
raw patch · 5 files changed
+210/−95 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- VulkanMemoryAllocator: instance GHC.Classes.Eq VulkanMemoryAllocator.DefragmentationInfo
+ VulkanMemoryAllocator: [$sel:breakCallbackUserData:DefragmentationInfo] :: DefragmentationInfo -> Ptr ()
+ VulkanMemoryAllocator: [$sel:pfnBreakCallback:DefragmentationInfo] :: DefragmentationInfo -> PFN_vmaCheckDefragmentationBreakFunction
+ VulkanMemoryAllocator: type FN_vmaCheckDefragmentationBreakFunction = ("pUserData" ::: Ptr ()) -> IO Bool32
+ VulkanMemoryAllocator: type PFN_vmaCheckDefragmentationBreakFunction = FunPtr FN_vmaCheckDefragmentationBreakFunction
- VulkanMemoryAllocator: DefragmentationInfo :: DefragmentationFlags -> Pool -> DeviceSize -> Word32 -> DefragmentationInfo
+ VulkanMemoryAllocator: DefragmentationInfo :: DefragmentationFlags -> Pool -> DeviceSize -> Word32 -> PFN_vmaCheckDefragmentationBreakFunction -> Ptr () -> DefragmentationInfo
Files
- VulkanMemoryAllocator.cabal +1/−1
- VulkanMemoryAllocator/include/vk_mem_alloc.h +175/−88
- changelog.md +3/−0
- package.yaml +1/−1
- src/VulkanMemoryAllocator.hs +30/−5
VulkanMemoryAllocator.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: VulkanMemoryAllocator-version: 0.10.5.1+version: 0.11 synopsis: Bindings to the VulkanMemoryAllocator library category: Graphics homepage: https://github.com/expipiplus1/vulkan#readme
VulkanMemoryAllocator/include/vk_mem_alloc.h view
@@ -126,9 +126,7 @@ extern "C" { #endif -#ifndef VULKAN_H_- #include <vulkan/vulkan.h>-#endif+#include <vulkan/vulkan.h> #if !defined(VMA_VULKAN_VERSION) #if defined(VK_VERSION_1_3)@@ -234,6 +232,12 @@ #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)+#endif+ // Define this macro to decorate pointers with an attribute specifying the // length of the array they point to if they are not null. //@@ -1319,7 +1323,7 @@ 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 pMemoryAllocateNext;+ void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkMemoryAllocateInfo) pMemoryAllocateNext; } VmaPoolCreateInfo; /** @} */@@ -1389,6 +1393,12 @@ const char* VMA_NULLABLE pName; } VmaAllocationInfo; +/** 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().@@ -1412,6 +1422,13 @@ `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.@@ -2227,7 +2244,7 @@ VmaAllocation VMA_NOT_NULL allocation, VkDeviceSize allocationLocalOffset, VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer,- const void* VMA_NULLABLE pNext);+ const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindBufferMemoryInfoKHR) pNext); /** \brief Binds image to allocation. @@ -2264,7 +2281,7 @@ VmaAllocation VMA_NOT_NULL allocation, VkDeviceSize allocationLocalOffset, VkImage VMA_NOT_NULL_NON_DISPATCHABLE image,- const void* VMA_NULLABLE pNext);+ const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindImageMemoryInfoKHR) pNext); /** \brief Creates a new `VkBuffer`, allocates and binds memory for it. @@ -2607,13 +2624,25 @@ #include <utility> #include <type_traits> +#if !defined(VMA_CPP20)+ #if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20+ #define VMA_CPP20 1+ #else+ #define VMA_CPP20 0+ #endif+#endif+ #ifdef _MSC_VER #include <intrin.h> // For functions like __popcnt, _BitScanForward etc. #endif-#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20+#if VMA_CPP20 #include <bit> // For std::popcount #endif +#if VMA_STATS_STRING_ENABLED+ #include <cstdio> // For snprintf+#endif+ /******************************************************************************* CONFIGURATION SECTION @@ -2647,8 +2676,7 @@ #endif #ifndef VMA_USE_STL_SHARED_MUTEX- // Compiler conforms to C++17.- #if __cplusplus >= 201703L+ #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.@@ -2693,6 +2721,14 @@ #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+#endif+ // Normal assert to check for programmer's errors, especially in Debug configuration. #ifndef VMA_ASSERT #ifdef NDEBUG@@ -2769,7 +2805,7 @@ { return _aligned_malloc(size, alignment); }-#elif __cplusplus >= 201703L // Compiler conforms to C++17.+#elif __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 static void* vma_aligned_alloc(size_t alignment, size_t size) { return aligned_alloc(alignment, size);@@ -2795,7 +2831,7 @@ #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@@ -2856,6 +2892,21 @@ #define VMA_DEBUG_LOG(str) VMA_DEBUG_LOG_FORMAT("%s", (str)) #endif +#ifndef VMA_CLASS_NO_COPY+ #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) \+ private: \+ className(const className&) = delete; \+ className(className&&) = delete; \+ className& operator=(const className&) = delete; \+ className& operator=(className&&) = delete;+#endif+ // 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)@@ -2875,7 +2926,9 @@ #ifndef VMA_MUTEX 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(); }@@ -3041,13 +3094,6 @@ #define VMA_MAPPING_HYSTERESIS_ENABLED 1 #endif -#ifndef VMA_CLASS_NO_COPY- #define VMA_CLASS_NO_COPY(className) \- private: \- className(const className&) = delete; \- className& operator=(const className&) = delete;-#endif- #define VMA_VALIDATE(cond) do { if(!(cond)) { \ VMA_ASSERT(0 && "Validation failed: " #cond); \ return false; \@@ -3225,7 +3271,7 @@ */ static inline uint32_t VmaCountBitsSet(uint32_t v) {-#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20+#if VMA_CPP20 return std::popcount(v); #else uint32_t c = v - ((v >> 1) & 0x55555555);@@ -3540,7 +3586,7 @@ template <typename CmpLess, typename IterT, typename KeyT> static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp) {- size_t down = 0, up = (end - beg);+ size_t down = 0, up = size_t(end - beg); while (down < up) { const size_t mid = down + (up - down) / 2; // Overflow-safe midpoint calculation@@ -3656,7 +3702,7 @@ return false; } // This relies on values of VK_IMAGE_USAGE_TRANSFER* being the same VK_BUFFER_IMAGE_TRANSFER*.- const bool deviceAccess = (bufImgUsage & ~(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) != 0;+ const bool deviceAccess = (bufImgUsage & ~static_cast<VkFlags>(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) != 0; const bool hostAccessSequentialWrite = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT) != 0; const bool hostAccessRandom = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) != 0; const bool hostAccessAllowTransferInstead = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) != 0;@@ -3666,18 +3712,21 @@ // CPU random access - e.g. a buffer written to or transferred from GPU to read back on CPU. if(hostAccessRandom) {- if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost)+ // 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;++ if (!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost) { // Nice if it will end up in HOST_VISIBLE, but more importantly prefer DEVICE_LOCAL. // Omitting HOST_VISIBLE here is intentional. // In case there is DEVICE_LOCAL | HOST_VISIBLE | HOST_CACHED, it will pick that one. // Otherwise, this will give same weight to DEVICE_LOCAL as HOST_VISIBLE | HOST_CACHED and select the former if occurs first on the list.- outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; } else {- // Always CPU memory, cached.- outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;+ // Always CPU memory.+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; } } // CPU sequential write - may be CPU or host-visible GPU memory, uncached and write-combined.@@ -3716,19 +3765,18 @@ // No CPU access else {- // GPU access, no CPU access (e.g. a color attachment image) - prefer GPU memory- if(deviceAccess)- {- // ...unless there is a clear preference from the user not to do so.- if(preferHost)- outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;- else- outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;- }+ // if(deviceAccess)+ //+ // GPU access, no CPU access (e.g. a color attachment image) - prefer GPU memory,+ // unless there is a clear preference from the user not to do so.+ //+ // else:+ // // No direct GPU access, no CPU access, just transfers. // It may be staging copy intended for e.g. preserving image for next frame (then better GPU memory) or // 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) outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; else@@ -3947,7 +3995,7 @@ // Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope). struct VmaMutexLock {- VMA_CLASS_NO_COPY(VmaMutexLock)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLock) public: VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) : m_pMutex(useMutex ? &mutex : VMA_NULL)@@ -3963,7 +4011,7 @@ // Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading. struct VmaMutexLockRead {- VMA_CLASS_NO_COPY(VmaMutexLockRead)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockRead) public: VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) : m_pMutex(useMutex ? &mutex : VMA_NULL)@@ -3979,7 +4027,7 @@ // Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing. struct VmaMutexLockWrite {- VMA_CLASS_NO_COPY(VmaMutexLockWrite)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockWrite) public: VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) : m_pMutex(useMutex ? &mutex : VMA_NULL)@@ -4002,11 +4050,11 @@ #ifndef _VMA_ATOMIC_TRANSACTIONAL_INCREMENT // An object that increments given atomic but decrements it back in the destructor unless Commit() is called.-template<typename T>+template<typename AtomicT> struct AtomicTransactionalIncrement { public:- typedef std::atomic<T> AtomicT;+ using T = decltype(AtomicT().load()); ~AtomicTransactionalIncrement() {@@ -4434,7 +4482,7 @@ template<typename T> class VmaPoolAllocator {- VMA_CLASS_NO_COPY(VmaPoolAllocator)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaPoolAllocator) public: VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity); ~VmaPoolAllocator();@@ -4567,7 +4615,7 @@ template<typename T> class VmaRawList {- VMA_CLASS_NO_COPY(VmaRawList)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaRawList) public: typedef VmaListItem<T> ItemType; @@ -4830,7 +4878,7 @@ template<typename T, typename AllocatorT> class VmaList {- VMA_CLASS_NO_COPY(VmaList)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaList) public: class reverse_iterator; class const_iterator;@@ -5422,7 +5470,7 @@ char* p = &buf[10]; do {- *--p = '0' + (num % 10);+ *--p = '0' + (char)(num % 10); num /= 10; } while (num); Add(p);@@ -5435,7 +5483,7 @@ char* p = &buf[20]; do {- *--p = '0' + (num % 10);+ *--p = '0' + (char)(num % 10); num /= 10; } while (num); Add(p);@@ -5457,7 +5505,7 @@ */ class VmaJsonWriter {- VMA_CLASS_NO_COPY(VmaJsonWriter)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaJsonWriter) public: // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object. VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);@@ -5649,7 +5697,6 @@ break; default: VMA_ASSERT(0 && "Character not currently supported.");- break; } } }@@ -5796,7 +5843,7 @@ class VmaMappingHysteresis {- VMA_CLASS_NO_COPY(VmaMappingHysteresis)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaMappingHysteresis) public: VmaMappingHysteresis() = default; @@ -5903,7 +5950,7 @@ */ class VmaDeviceMemoryBlock {- VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaDeviceMemoryBlock) public: VmaBlockMetadata* m_pMetadata; @@ -6126,6 +6173,7 @@ */ class VmaDedicatedAllocationList {+ VMA_CLASS_NO_COPY_NO_MOVE(VmaDedicatedAllocationList) public: VmaDedicatedAllocationList() {} ~VmaDedicatedAllocationList();@@ -6311,6 +6359,7 @@ */ class VmaBlockMetadata {+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata) public: // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object. VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks,@@ -6377,7 +6426,7 @@ protected: const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; } VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }- VkDeviceSize GetDebugMargin() const { return IsVirtual() ? 0 : VMA_DEBUG_MARGIN; }+ VkDeviceSize GetDebugMargin() const { return VkDeviceSize(IsVirtual() ? 0 : VMA_DEBUG_MARGIN); } void DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const; #if VMA_STATS_STRING_ENABLED@@ -6751,7 +6800,7 @@ { friend class VmaDefragmentationAlgorithm_Generic; friend class VmaDefragmentationAlgorithm_Fast;- VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Generic) public: VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual);@@ -7590,7 +7639,7 @@ */ class VmaBlockMetadata_Linear : public VmaBlockMetadata {- VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Linear) public: VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual);@@ -9209,7 +9258,7 @@ */ class VmaBlockMetadata_Buddy : public VmaBlockMetadata {- VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Buddy) public: VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual);@@ -9908,7 +9957,7 @@ // VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT for fastest alloc time possible. class VmaBlockMetadata_TLSF : public VmaBlockMetadata {- VMA_CLASS_NO_COPY(VmaBlockMetadata_TLSF)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_TLSF) public: VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual);@@ -10070,7 +10119,7 @@ else m_ListsCount += 4; - m_MemoryClasses = memoryClass + 2;+ m_MemoryClasses = memoryClass + uint8_t(2); memset(m_InnerIsFreeBitmap, 0, MAX_MEMORY_CLASSES * sizeof(uint32_t)); m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount);@@ -10263,7 +10312,7 @@ // Round up to the next block VkDeviceSize sizeForNextList = allocSize;- VkDeviceSize smallSizeStep = SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4);+ VkDeviceSize smallSizeStep = VkDeviceSize(SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4)); if (allocSize > SMALL_BUFFER_SIZE) { sizeForNextList += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX));@@ -10273,8 +10322,8 @@ else sizeForNextList += smallSizeStep; - uint32_t nextListIndex = 0;- uint32_t prevListIndex = 0;+ uint32_t nextListIndex = m_ListsCount;+ uint32_t prevListIndex = m_ListsCount; Block* nextListBlock = VMA_NULL; Block* prevListBlock = VMA_NULL; @@ -10672,7 +10721,7 @@ uint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) const { if (size > SMALL_BUFFER_SIZE)- return VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT;+ return uint8_t(VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT); return 0; } @@ -10847,7 +10896,7 @@ class VmaBlockVector { friend struct VmaDefragmentationContext_T;- VMA_CLASS_NO_COPY(VmaBlockVector)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockVector) public: VmaBlockVector( VmaAllocator hAllocator,@@ -10966,7 +11015,7 @@ #ifndef _VMA_DEFRAGMENTATION_CONTEXT struct VmaDefragmentationContext_T {- VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaDefragmentationContext_T) public: VmaDefragmentationContext_T( VmaAllocator hAllocator,@@ -11016,6 +11065,8 @@ const VkDeviceSize m_MaxPassBytes; const uint32_t m_MaxPassAllocations;+ const PFN_vmaCheckDefragmentationBreakFunction m_BreakCallback;+ void* m_BreakCallbackUserData; VmaStlAllocator<VmaDefragmentationMove> m_MoveAllocator; VmaVector<VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove>> m_Moves;@@ -11053,7 +11104,7 @@ struct VmaPool_T { friend struct VmaPoolListItemTraits;- VMA_CLASS_NO_COPY(VmaPool_T)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaPool_T) public: VmaBlockVector m_BlockVector; VmaDedicatedAllocationList m_DedicatedAllocations;@@ -11095,6 +11146,9 @@ #ifndef _VMA_CURRENT_BUDGET_DATA struct VmaCurrentBudgetData {+ VMA_CLASS_NO_COPY_NO_MOVE(VmaCurrentBudgetData)+public:+ VMA_ATOMIC_UINT32 m_BlockCount[VK_MAX_MEMORY_HEAPS]; VMA_ATOMIC_UINT32 m_AllocationCount[VK_MAX_MEMORY_HEAPS]; VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];@@ -11163,7 +11217,7 @@ */ class VmaAllocationObjectAllocator {- VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocationObjectAllocator) public: VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) : m_Allocator(pAllocationCallbacks, 1024) {}@@ -11193,7 +11247,7 @@ #ifndef _VMA_VIRTUAL_BLOCK_T struct VmaVirtualBlock_T {- VMA_CLASS_NO_COPY(VmaVirtualBlock_T)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaVirtualBlock_T) public: const bool m_AllocationCallbacksSpecified; const VkAllocationCallbacks m_AllocationCallbacks;@@ -11333,7 +11387,7 @@ // Main allocator object. struct VmaAllocator_T {- VMA_CLASS_NO_COPY(VmaAllocator_T)+ VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocator_T) public: bool m_UseMutex; uint32_t m_VulkanApiVersion;@@ -12943,6 +12997,8 @@ const VmaDefragmentationInfo& info) : m_MaxPassBytes(info.maxBytesPerPass == 0 ? VK_WHOLE_SIZE : info.maxBytesPerPass), m_MaxPassAllocations(info.maxAllocationsPerPass == 0 ? UINT32_MAX : info.maxAllocationsPerPass),+ m_BreakCallback(info.pfnBreakCallback),+ m_BreakCallbackUserData(info.pBreakCallbackUserData), m_MoveAllocator(hAllocator->GetAllocationCallbacks()), m_Moves(m_MoveAllocator) {@@ -13197,29 +13253,24 @@ m_PassStats.bytesFreed += freedBlockSize; } - switch (m_Algorithm)- {- case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:+ if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT &&+ m_AlgorithmState != VMA_NULL) {- if (m_AlgorithmState != VMA_NULL)+ // Avoid unnecessary tries to allocate when new free block is available+ StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[vectorIndex];+ if (state.firstFreeBlock != SIZE_MAX) {- // Avoid unnecessary tries to allocate when new free block is available- StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[vectorIndex];- if (state.firstFreeBlock != SIZE_MAX)+ const size_t diff = prevCount - currentCount;+ if (state.firstFreeBlock >= diff) {- const size_t diff = prevCount - currentCount;- if (state.firstFreeBlock >= diff)- {- state.firstFreeBlock -= diff;- if (state.firstFreeBlock != 0)- state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty();- }- else- state.firstFreeBlock = 0;+ state.firstFreeBlock -= diff;+ if (state.firstFreeBlock != 0)+ state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty(); }+ else+ state.firstFreeBlock = 0; } }- } } moveInfo.moveCount = 0; moveInfo.pMoves = VMA_NULL;@@ -13343,6 +13394,10 @@ VmaDefragmentationContext_T::CounterStatus VmaDefragmentationContext_T::CheckCounters(VkDeviceSize bytes) {+ // Check custom criteria if exists+ if (m_BreakCallback && m_BreakCallback(m_BreakCallbackUserData))+ return CounterStatus::End;+ // Ignore allocation if will exceed max size for copy if (m_PassStats.bytesMoved + bytes > m_MaxPassBytes) {@@ -13351,6 +13406,8 @@ else return CounterStatus::End; }+ else+ m_IgnoredAllocs = 0; return CounterStatus::Pass; } @@ -13360,8 +13417,8 @@ // Early return when max found if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes) {- VMA_ASSERT(m_PassStats.allocationsMoved == m_MaxPassAllocations ||- m_PassStats.bytesMoved == m_MaxPassBytes && "Exceeded maximal pass threshold!");+ VMA_ASSERT((m_PassStats.allocationsMoved == m_MaxPassAllocations ||+ m_PassStats.bytesMoved == m_MaxPassBytes) && "Exceeded maximal pass threshold!"); return true; } return false;@@ -13710,7 +13767,7 @@ { // Full clear performed already if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE)- reinterpret_cast<size_t*>(m_AlgorithmState)[index] = last;+ vectorState.firstFreeBlock = last; return true; } }@@ -13780,6 +13837,7 @@ } else break;+ VMA_FALLTHROUGH; // Fallthrough } case StateExtensive::Operation::MoveBuffers: {@@ -13804,6 +13862,7 @@ } else break;+ VMA_FALLTHROUGH; // Fallthrough } case StateExtensive::Operation::MoveAll: {@@ -14201,6 +14260,12 @@ m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2; m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2; m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2;+ }+#endif++#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))+ { m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; } #endif@@ -14253,7 +14318,7 @@ VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); #endif -#if VMA_MEMORY_BUDGET+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); #endif @@ -14308,8 +14373,18 @@ VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, "vkGetImageMemoryRequirements2"); VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2, "vkBindBufferMemory2"); VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2, "vkBindImageMemory2");+ }+#endif++#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))+ { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2"); }+ else if(m_UseExtMemoryBudget)+ {+ VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2KHR");+ } #endif #if VMA_DEDICATED_ALLOCATION@@ -14328,9 +14403,13 @@ } #endif // #if VMA_BIND_MEMORY2 -#if VMA_MEMORY_BUDGET- if(m_UseExtMemoryBudget)+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) {+ VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2");+ }+ else if(m_UseExtMemoryBudget)+ { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); } #endif // #if VMA_MEMORY_BUDGET@@ -15374,7 +15453,7 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory) {- AtomicTransactionalIncrement<uint32_t> deviceMemoryCountIncrement;+ AtomicTransactionalIncrement<VMA_ATOMIC_UINT32> deviceMemoryCountIncrement; const uint64_t prevDeviceMemoryCount = deviceMemoryCountIncrement.Increment(&m_DeviceMemoryCount); #if VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT if(prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount)@@ -15531,6 +15610,7 @@ } return res; }+ VMA_FALLTHROUGH; // Fallthrough case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: return hAllocation->DedicatedAllocMap(this, ppData); default:@@ -18165,6 +18245,12 @@ vkDestroyImage(allocator, img1, nullptr); \endcode +VMA also provides convenience functions that create a buffer or image and bind it to memory+represented by an existing #VmaAllocation:+vmaCreateAliasingBuffer(), vmaCreateAliasingBuffer2(),+vmaCreateAliasingImage(), vmaCreateAliasingImage2().+Versions with "2" offer additional parameter `allocationLocalOffset`.+ Remember that using resources that alias in memory requires proper synchronization. You need to issue a memory barrier to make sure commands that use `img1` and `img2` don't overlap on GPU timeline.@@ -19162,6 +19248,7 @@ // [Executed in runtime]: memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);+ vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE); //vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT VkBufferCopy bufCopy = { 0, // srcOffset
changelog.md view
@@ -2,6 +2,9 @@ ## WIP +## [0.11] - 2023-10-17+- Bump VMA+ ## [0.10.5.1] - 2023-10-17 - Raise upper bound on `vulkan`
package.yaml view
@@ -1,5 +1,5 @@ name: VulkanMemoryAllocator-version: "0.10.5.1"+version: "0.11" synopsis: Bindings to the VulkanMemoryAllocator library category: Graphics maintainer: Ellie Hermaszewska <live.long.and.prosper@monoid.al>
src/VulkanMemoryAllocator.hs view
@@ -175,6 +175,8 @@ , AllocationCreateInfo(..) , PoolCreateInfo(..) , AllocationInfo(..)+ , PFN_vmaCheckDefragmentationBreakFunction+ , FN_vmaCheckDefragmentationBreakFunction , DefragmentationInfo(..) , DefragmentationMove(..) , DefragmentationPassMoveInfo(..)@@ -5545,6 +5547,11 @@ Nothing +type FN_vmaCheckDefragmentationBreakFunction = ("pUserData" ::: Ptr ()) -> IO Bool32+-- No documentation found for TopLevel "PFN_vmaCheckDefragmentationBreakFunction"+type PFN_vmaCheckDefragmentationBreakFunction = FunPtr FN_vmaCheckDefragmentationBreakFunction++ -- | VmaDefragmentationInfo -- -- Parameters for defragmentation.@@ -5567,22 +5574,31 @@ -- -- @0@ means no limit. maxAllocationsPerPass :: Word32+ , -- | Optional custom callback for stopping 'beginDefragmentation'.+ --+ -- Have to return true for breaking current defragmentation pass.+ pfnBreakCallback :: PFN_vmaCheckDefragmentationBreakFunction+ , -- | Optional data to pass to custom callback for stopping pass of+ -- defragmentation.+ breakCallbackUserData :: Ptr () }- deriving (Typeable, Eq)+ deriving (Typeable) #if defined(GENERIC_INSTANCES) deriving instance Generic (DefragmentationInfo) #endif deriving instance Show DefragmentationInfo instance ToCStruct DefragmentationInfo where- withCStruct x f = allocaBytes 32 $ \p -> pokeCStruct p x (f p)+ withCStruct x f = allocaBytes 48 $ \p -> pokeCStruct p x (f p) pokeCStruct p DefragmentationInfo{..} f = do poke ((p `plusPtr` 0 :: Ptr DefragmentationFlags)) (flags) poke ((p `plusPtr` 8 :: Ptr Pool)) (pool) poke ((p `plusPtr` 16 :: Ptr DeviceSize)) (maxBytesPerPass) poke ((p `plusPtr` 24 :: Ptr Word32)) (maxAllocationsPerPass)+ poke ((p `plusPtr` 32 :: Ptr PFN_vmaCheckDefragmentationBreakFunction)) (pfnBreakCallback)+ poke ((p `plusPtr` 40 :: Ptr (Ptr ()))) (breakCallbackUserData) f- cStructSize = 32+ cStructSize = 48 cStructAlignment = 8 pokeZeroCStruct p f = do poke ((p `plusPtr` 0 :: Ptr DefragmentationFlags)) (zero)@@ -5596,17 +5612,26 @@ pool <- peek @Pool ((p `plusPtr` 8 :: Ptr Pool)) maxBytesPerPass <- peek @DeviceSize ((p `plusPtr` 16 :: Ptr DeviceSize)) maxAllocationsPerPass <- peek @Word32 ((p `plusPtr` 24 :: Ptr Word32))+ pfnBreakCallback <- peek @PFN_vmaCheckDefragmentationBreakFunction ((p `plusPtr` 32 :: Ptr PFN_vmaCheckDefragmentationBreakFunction))+ pBreakCallbackUserData <- peek @(Ptr ()) ((p `plusPtr` 40 :: Ptr (Ptr ()))) pure $ DefragmentationInfo- flags pool maxBytesPerPass maxAllocationsPerPass+ flags+ pool+ maxBytesPerPass+ maxAllocationsPerPass+ pfnBreakCallback+ pBreakCallbackUserData instance Storable DefragmentationInfo where- sizeOf ~_ = 32+ sizeOf ~_ = 48 alignment ~_ = 8 peek = peekCStruct poke ptr poked = pokeCStruct ptr poked (pure ()) instance Zero DefragmentationInfo where zero = DefragmentationInfo+ zero+ zero zero zero zero