From 3216bf6dc78d1b9f67151b11dc33d8871eab0815 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Wed, 27 Oct 2021 16:45:08 +0200 Subject: [PATCH] Necessary refactoring to prepare for virtual allocator --- include/vk_mem_alloc.h | 430 +++++++++++++++++++++++++++-------------- 1 file changed, 285 insertions(+), 145 deletions(-) diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h index 11b7840..4f25bb6 100644 --- a/include/vk_mem_alloc.h +++ b/include/vk_mem_alloc.h @@ -2147,6 +2147,21 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( VkImage VMA_NULLABLE_NON_DISPATCHABLE image, VmaAllocation VMA_NULLABLE allocation); +/// Parameters of an existing virtual allocation, returned by TODO(). +struct VmaVirtualAllocationInfo +{ + /** \brief Size of the allocation. + + Same value as passed in TODO::size. + */ + VkDeviceSize size; + /** \brief Custom pointer associated with the allocation. + + Same value as passed in TODO::pUserData or TODO::SetAllocationUserData(). + */ + void* VMA_NULLABLE pUserData; +}; + #ifdef __cplusplus } #endif @@ -4783,7 +4798,7 @@ struct VmaSuballocation { VkDeviceSize offset; VkDeviceSize size; - VmaAllocation hAllocation; + void* userData; VmaSuballocationType type; }; @@ -4853,18 +4868,20 @@ in a single VkDeviceMemory block. class VmaBlockMetadata { public: - VmaBlockMetadata(VmaAllocator hAllocator); + VmaBlockMetadata(VmaAllocator hAllocator, bool isVirtual); virtual ~VmaBlockMetadata() { } virtual void Init(VkDeviceSize size) { m_Size = size; } // Validates all data structures inside this object. If not valid, returns false. virtual bool Validate() const = 0; + bool IsVirtual() const { return m_IsVirtual; } VkDeviceSize GetSize() const { return m_Size; } virtual size_t GetAllocationCount() const = 0; virtual VkDeviceSize GetSumFreeSize() const = 0; virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0; // Returns true if this block is empty - contains only single free suballocation. virtual bool IsEmpty() const = 0; + virtual void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const = 0; virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0; // Shouldn't modify blockCount. @@ -4904,12 +4921,17 @@ public: const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation) = 0; + void* userData) = 0; // Frees suballocation assigned to given memory region. - virtual void Free(const VmaAllocation allocation) = 0; virtual void FreeAtOffset(VkDeviceSize offset) = 0; + // Frees all allocations. + // Careful! Don't call it if there are VmaAllocation objects owned by userData of cleared allocations! + virtual void Clear() = 0; + + virtual void SetAllocationUserData(VkDeviceSize offset, void* userData) = 0; + protected: const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; } @@ -4930,6 +4952,7 @@ protected: private: VkDeviceSize m_Size; const VkAllocationCallbacks* m_pAllocationCallbacks; + const bool m_IsVirtual; }; #define VMA_VALIDATE(cond) do { if(!(cond)) { \ @@ -4941,7 +4964,7 @@ class VmaBlockMetadata_Generic : public VmaBlockMetadata { VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic) public: - VmaBlockMetadata_Generic(VmaAllocator hAllocator); + VmaBlockMetadata_Generic(VmaAllocator hAllocator, bool isVirtual); virtual ~VmaBlockMetadata_Generic(); virtual void Init(VkDeviceSize size); @@ -4983,10 +5006,12 @@ public: const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation); + void* userData); - virtual void Free(const VmaAllocation allocation); virtual void FreeAtOffset(VkDeviceSize offset); + virtual void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const; + virtual void Clear(); + virtual void SetAllocationUserData(VkDeviceSize offset, void* userData); //////////////////////////////////////////////////////////////////////////////// // For defragmentation @@ -5119,7 +5144,7 @@ class VmaBlockMetadata_Linear : public VmaBlockMetadata { VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear) public: - VmaBlockMetadata_Linear(VmaAllocator hAllocator); + VmaBlockMetadata_Linear(VmaAllocator hAllocator, bool isVirtual); virtual ~VmaBlockMetadata_Linear(); virtual void Init(VkDeviceSize size); @@ -5161,10 +5186,12 @@ public: const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation); + void* userData); - virtual void Free(const VmaAllocation allocation); virtual void FreeAtOffset(VkDeviceSize offset); + virtual void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const; + virtual void Clear(); + virtual void SetAllocationUserData(VkDeviceSize offset, void* userData); private: /* @@ -5249,7 +5276,7 @@ class VmaBlockMetadata_Buddy : public VmaBlockMetadata { VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy) public: - VmaBlockMetadata_Buddy(VmaAllocator hAllocator); + VmaBlockMetadata_Buddy(VmaAllocator hAllocator, bool isVirtual); virtual ~VmaBlockMetadata_Buddy(); virtual void Init(VkDeviceSize size); @@ -5291,10 +5318,12 @@ public: const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation); + void* userData); - virtual void Free(const VmaAllocation allocation) { FreeAtOffset(allocation, allocation->GetOffset()); } - virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); } + virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VK_NULL_HANDLE, offset); } + virtual void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const; + virtual void Clear(); + virtual void SetAllocationUserData(VkDeviceSize offset, void* userData); private: static const VkDeviceSize MIN_NODE_SIZE = 32; @@ -5334,7 +5363,7 @@ private: } free; struct { - VmaAllocation alloc; + void* userData; } allocation; struct { @@ -5365,7 +5394,7 @@ private: uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const; inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; } // Alloc passed just for validation. Can be null. - void FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset); + void FreeAtOffset(VmaAllocation allocForValidation, VkDeviceSize offset); void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const; // Adds node to the front of FreeList at given level. // node->type must be FREE. @@ -7411,9 +7440,10 @@ struct VmaSuballocationItemSizeLess //////////////////////////////////////////////////////////////////////////////// // class VmaBlockMetadata -VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) : +VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator, bool isVirtual) : m_Size(0), - m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks()) + m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks()), + m_IsVirtual(isVirtual) { } @@ -7485,8 +7515,8 @@ void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const //////////////////////////////////////////////////////////////////////////////// // class VmaBlockMetadata_Generic -VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) : - VmaBlockMetadata(hAllocator), +VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator, bool isVirtual) : + VmaBlockMetadata(hAllocator, isVirtual), m_FreeCount(0), m_SumFreeSize(0), m_Suballocations(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), @@ -7509,7 +7539,7 @@ void VmaBlockMetadata_Generic::Init(VkDeviceSize size) suballoc.offset = 0; suballoc.size = size; suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; + suballoc.userData = VMA_NULL; VMA_ASSERT(size > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER); m_Suballocations.push_back(suballoc); @@ -7543,7 +7573,11 @@ bool VmaBlockMetadata_Generic::Validate() const // Two adjacent free suballocations are invalid. They should be merged. VMA_VALIDATE(!prevFree || !currFree); - VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE)); + VmaAllocation alloc = (VmaAllocation)subAlloc.userData; + if(!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } if(currFree) { @@ -7559,8 +7593,11 @@ bool VmaBlockMetadata_Generic::Validate() const } else { - VMA_VALIDATE(subAlloc.hAllocation->GetOffset() == subAlloc.offset); - VMA_VALIDATE(subAlloc.hAllocation->GetSize() == subAlloc.size); + if(!IsVirtual()) + { + VMA_VALIDATE(alloc->GetOffset() == subAlloc.offset); + VMA_VALIDATE(alloc->GetSize() == subAlloc.size); + } // Margin required between allocations - previous allocation must be free. VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree); @@ -7672,7 +7709,8 @@ void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const } else { - PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation); + VMA_ASSERT(!IsVirtual()); // TODO? + PrintDetailedMap_Allocation(json, suballoc.offset, (VmaAllocation)suballoc.userData); } } @@ -7795,6 +7833,7 @@ bool VmaBlockMetadata_Generic::CreateAllocationRequest( if(canMakeOtherLost) { + VMA_ASSERT(!IsVirtual()); // Brute-force algorithm. TODO: Come up with something better. bool found = false; @@ -7804,8 +7843,9 @@ bool VmaBlockMetadata_Generic::CreateAllocationRequest( suballocIt != m_Suballocations.end(); ++suballocIt) { + VmaAllocation const alloc = (VmaAllocation)suballocIt->userData; if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE || - suballocIt->hAllocation->CanBecomeLost()) + alloc->CanBecomeLost()) { if(CheckAllocation( currentFrameIndex, @@ -7848,6 +7888,7 @@ bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost( uint32_t frameInUseCount, VmaAllocationRequest* pAllocationRequest) { + VMA_ASSERT(!IsVirtual()); VMA_ASSERT(pAllocationRequest && pAllocationRequest->type == VmaAllocationRequestType::Normal); while(pAllocationRequest->itemsToMakeLostCount > 0) @@ -7857,9 +7898,9 @@ bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost( ++pAllocationRequest->item; } VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end()); - VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE); - VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost()); - if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) + VmaAllocation const alloc = (VmaAllocation)pAllocationRequest->item->userData; + VMA_ASSERT(alloc != VK_NULL_HANDLE && alloc->CanBecomeLost()); + if(alloc->MakeLost(currentFrameIndex, frameInUseCount)) { pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item); --pAllocationRequest->itemsToMakeLostCount; @@ -7879,14 +7920,16 @@ bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost( uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) { + VMA_ASSERT(!IsVirtual()); uint32_t lostAllocationCount = 0; for(VmaSuballocationList::iterator it = m_Suballocations.begin(); it != m_Suballocations.end(); ++it) { + VmaAllocation const alloc = (VmaAllocation)it->userData; if(it->type != VMA_SUBALLOCATION_TYPE_FREE && - it->hAllocation->CanBecomeLost() && - it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) + alloc->CanBecomeLost() && + alloc->MakeLost(currentFrameIndex, frameInUseCount)) { it = FreeSuballocation(it); ++lostAllocationCount; @@ -7921,7 +7964,7 @@ void VmaBlockMetadata_Generic::Alloc( const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation) + void* userData) { VMA_ASSERT(request.type == VmaAllocationRequestType::Normal); VMA_ASSERT(request.item != m_Suballocations.end()); @@ -7941,7 +7984,7 @@ void VmaBlockMetadata_Generic::Alloc( suballoc.offset = request.offset; suballoc.size = allocSize; suballoc.type = type; - suballoc.hAllocation = hAllocation; + suballoc.userData = userData; // If there are any free bytes remaining at the end, insert new free suballocation after current one. if(paddingEnd) @@ -7982,23 +8025,6 @@ void VmaBlockMetadata_Generic::Alloc( m_SumFreeSize -= allocSize; } -void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation) -{ - for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); - suballocItem != m_Suballocations.end(); - ++suballocItem) - { - VmaSuballocation& suballoc = *suballocItem; - if(suballoc.hAllocation == allocation) - { - FreeSuballocation(suballocItem); - VMA_HEAVY_ASSERT(Validate()); - return; - } - } - VMA_ASSERT(0 && "Not found!"); -} - void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset) { for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); @@ -8015,6 +8041,44 @@ void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset) VMA_ASSERT(0 && "Not found!"); } +void VmaBlockMetadata_Generic::GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const +{ + for (VmaSuballocationList::const_iterator suballocItem = m_Suballocations.begin(); + suballocItem != m_Suballocations.end(); + ++suballocItem) + { + const VmaSuballocation& suballoc = *suballocItem; + if (suballoc.offset == offset) + { + outInfo.size = suballoc.size; + outInfo.pUserData = suballoc.userData; + return; + } + } + VMA_ASSERT(0 && "Not found!"); +} + +void VmaBlockMetadata_Generic::Clear() +{ + VMA_ASSERT(0 && "TODO implement"); +} + +void VmaBlockMetadata_Generic::SetAllocationUserData(VkDeviceSize offset, void* userData) +{ + for (VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); + suballocItem != m_Suballocations.end(); + ++suballocItem) + { + VmaSuballocation& suballoc = *suballocItem; + if (suballoc.offset == offset) + { + suballoc.userData = userData; + return; + } + } + VMA_ASSERT(0 && "Not found!"); +} + bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const { VkDeviceSize lastSize = 0; @@ -8055,14 +8119,16 @@ bool VmaBlockMetadata_Generic::CheckAllocation( if(canMakeOtherLost) { + VMA_ASSERT(!IsVirtual()); if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE) { *pSumFreeSize = suballocItem->size; } else { - if(suballocItem->hAllocation->CanBecomeLost() && - suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) + VmaAllocation const alloc = (VmaAllocation)suballocItem->userData; + if(alloc->CanBecomeLost() && + alloc->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) { ++*itemsToMakeLostCount; *pSumItemSize = suballocItem->size; @@ -8158,9 +8224,10 @@ bool VmaBlockMetadata_Generic::CheckAllocation( } else { - VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE); - if(lastSuballocItem->hAllocation->CanBecomeLost() && - lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) + VmaAllocation const lastSuballocAlloc = (VmaAllocation)lastSuballocItem->userData; + VMA_ASSERT(lastSuballocAlloc != VK_NULL_HANDLE); + if(lastSuballocAlloc->CanBecomeLost() && + lastSuballocAlloc->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) { ++*itemsToMakeLostCount; *pSumItemSize += lastSuballocItem->size; @@ -8188,9 +8255,10 @@ bool VmaBlockMetadata_Generic::CheckAllocation( { if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) { - VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE); - if(nextSuballoc.hAllocation->CanBecomeLost() && - nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) + VmaAllocation const nextSuballocAlloc = (VmaAllocation)nextSuballoc.userData; + VMA_ASSERT(nextSuballocAlloc != VK_NULL_HANDLE); + if(nextSuballocAlloc->CanBecomeLost() && + nextSuballocAlloc->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) { ++*itemsToMakeLostCount; } @@ -8324,7 +8392,7 @@ VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSu // Change this suballocation to be marked as free. VmaSuballocation& suballoc = *suballocItem; suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; + suballoc.userData = VMA_NULL; // Update totals. ++m_FreeCount; @@ -8433,7 +8501,7 @@ bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible( VkDeviceSize bufferImageGranularity, VmaSuballocationType& inOutPrevSuballocType) const { - if(bufferImageGranularity == 1 || IsEmpty()) + if(bufferImageGranularity == 1 || IsEmpty() || IsVirtual()) { return false; } @@ -8445,7 +8513,8 @@ bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible( const VmaSuballocationType suballocType = suballoc.type; if(suballocType != VMA_SUBALLOCATION_TYPE_FREE) { - minAlignment = VMA_MIN(minAlignment, suballoc.hAllocation->GetAlignment()); + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + minAlignment = VMA_MIN(minAlignment, alloc->GetAlignment()); if(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType)) { typeConflictFound = true; @@ -8460,8 +8529,8 @@ bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible( //////////////////////////////////////////////////////////////////////////////// // class VmaBlockMetadata_Linear -VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator) : - VmaBlockMetadata(hAllocator), +VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator, bool isVirtual) : + VmaBlockMetadata(hAllocator, isVirtual), m_SumFreeSize(0), m_Suballocations0(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), m_Suballocations1(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), @@ -8496,14 +8565,14 @@ bool VmaBlockMetadata_Linear::Validate() const if(!suballocations1st.empty()) { // Null item at the beginning should be accounted into m_1stNullItemsBeginCount. - VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE); + VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].userData != VMA_NULL); // Null item at the end should be just pop_back(). - VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE); + VMA_VALIDATE(suballocations1st.back().userData != VMA_NULL); } if(!suballocations2nd.empty()) { // Null item at the end should be just pop_back(). - VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE); + VMA_VALIDATE(suballocations2nd.back().userData != VMA_NULL); } VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size()); @@ -8522,13 +8591,20 @@ bool VmaBlockMetadata_Linear::Validate() const const VmaSuballocation& suballoc = suballocations2nd[i]; const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); - VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE)); + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if(!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } VMA_VALIDATE(suballoc.offset >= offset); if(!currFree) { - VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset); - VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size); + if(!IsVirtual()) + { + VMA_VALIDATE(alloc->GetOffset() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } sumUsedSize += suballoc.size; } else @@ -8546,7 +8622,7 @@ bool VmaBlockMetadata_Linear::Validate() const { const VmaSuballocation& suballoc = suballocations1st[i]; VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE && - suballoc.hAllocation == VK_NULL_HANDLE); + suballoc.userData == VMA_NULL); } size_t nullItem1stCount = m_1stNullItemsBeginCount; @@ -8556,14 +8632,21 @@ bool VmaBlockMetadata_Linear::Validate() const const VmaSuballocation& suballoc = suballocations1st[i]; const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); - VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE)); + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if(!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } VMA_VALIDATE(suballoc.offset >= offset); VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree); if(!currFree) { - VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset); - VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size); + if(!IsVirtual()) + { + VMA_VALIDATE(alloc->GetOffset() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } sumUsedSize += suballoc.size; } else @@ -8584,13 +8667,20 @@ bool VmaBlockMetadata_Linear::Validate() const const VmaSuballocation& suballoc = suballocations2nd[i]; const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); - VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE)); + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if(!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } VMA_VALIDATE(suballoc.offset >= offset); if(!currFree) { - VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset); - VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size); + if(!IsVirtual()) + { + VMA_VALIDATE(alloc->GetOffset() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } sumUsedSize += suballoc.size; } else @@ -8682,6 +8772,8 @@ VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax() const void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const { + VMA_ASSERT(!IsVirtual()); // TODO + const VkDeviceSize size = GetSize(); const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); @@ -8707,7 +8799,7 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc2ndIndex < suballoc2ndCount && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { ++nextAlloc2ndIndex; } @@ -8764,7 +8856,7 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc1stIndex < suballoc1stCount && - suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE) + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) { ++nextAlloc1stIndex; } @@ -8820,7 +8912,7 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc2ndIndex != SIZE_MAX && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { --nextAlloc2ndIndex; } @@ -8875,6 +8967,8 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const { + VMA_ASSERT(!IsVirtual()); // TODO + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); const VkDeviceSize size = GetSize(); @@ -8893,7 +8987,7 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex < suballoc2ndCount && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { ++nextAlloc2ndIndex; } @@ -8946,7 +9040,7 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc1stIndex < suballoc1stCount && - suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE) + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) { ++nextAlloc1stIndex; } @@ -8998,7 +9092,7 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex != SIZE_MAX && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { --nextAlloc2ndIndex; } @@ -9070,7 +9164,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex < suballoc2ndCount && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { ++nextAlloc2ndIndex; } @@ -9119,7 +9213,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc1stIndex < suballoc1stCount && - suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE) + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) { ++nextAlloc1stIndex; } @@ -9166,7 +9260,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex != SIZE_MAX && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { --nextAlloc2ndIndex; } @@ -9221,7 +9315,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex < suballoc2ndCount && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { ++nextAlloc2ndIndex; } @@ -9241,7 +9335,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const // 2. Process this allocation. // There is allocation with suballoc.offset, suballoc.size. - PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation); + PrintDetailedMap_Allocation(json, suballoc.offset, (VmaAllocation)suballoc.userData); // 3. Prepare for next iteration. lastOffset = suballoc.offset + suballoc.size; @@ -9268,7 +9362,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAllocIndex to the end. while(nextAlloc1stIndex < suballoc1stCount && - suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE) + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) { ++nextAlloc1stIndex; } @@ -9288,7 +9382,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const // 2. Process this allocation. // There is allocation with suballoc.offset, suballoc.size. - PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation); + PrintDetailedMap_Allocation(json, suballoc.offset, (VmaAllocation)suballoc.userData); // 3. Prepare for next iteration. lastOffset = suballoc.offset + suballoc.size; @@ -9316,7 +9410,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const { // Find next non-null allocation or move nextAlloc2ndIndex to the end. while(nextAlloc2ndIndex != SIZE_MAX && - suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE) + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) { --nextAlloc2ndIndex; } @@ -9336,7 +9430,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const // 2. Process this allocation. // There is allocation with suballoc.offset, suballoc.size. - PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation); + PrintDetailedMap_Allocation(json, suballoc.offset, (VmaAllocation)suballoc.userData); // 3. Prepare for next iteration. lastOffset = suballoc.offset + suballoc.size; @@ -9667,6 +9761,7 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress( if(canMakeOtherLost) { + VMA_ASSERT(!IsVirtual()); while(index1st < suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN > suballocations1st[index1st].offset) { @@ -9678,9 +9773,10 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress( } else { - VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE); - if(suballoc.hAllocation->CanBecomeLost() && - suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + VMA_ASSERT(alloc != VK_NULL_HANDLE); + if(alloc->CanBecomeLost() && + alloc->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) { ++pAllocationRequest->itemsToMakeLostCount; pAllocationRequest->sumItemSize += suballoc.size; @@ -9702,11 +9798,12 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress( const VmaSuballocation& suballoc = suballocations1st[index1st]; if(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity)) { - if(suballoc.hAllocation != VK_NULL_HANDLE) + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (alloc != VK_NULL_HANDLE) { // Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type). - if(suballoc.hAllocation->CanBecomeLost() && - suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) + if(alloc->CanBecomeLost() && + alloc->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) { ++pAllocationRequest->itemsToMakeLostCount; pAllocationRequest->sumItemSize += suballoc.size; @@ -9783,6 +9880,8 @@ bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost( uint32_t frameInUseCount, VmaAllocationRequest* pAllocationRequest) { + VMA_ASSERT(!IsVirtual()); + if(pAllocationRequest->itemsToMakeLostCount == 0) { return true; @@ -9811,12 +9910,12 @@ bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost( VmaSuballocation& suballoc = (*suballocations)[index]; if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) { - VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE); - VMA_ASSERT(suballoc.hAllocation->CanBecomeLost()); - if(suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + VMA_ASSERT(alloc != VK_NULL_HANDLE && alloc->CanBecomeLost()); + if(alloc->MakeLost(currentFrameIndex, frameInUseCount)) { suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; + suballoc.userData = VMA_NULL; m_SumFreeSize += suballoc.size; if(suballocations == &AccessSuballocations1st()) { @@ -9844,18 +9943,21 @@ bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost( uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) { + VMA_ASSERT(!IsVirtual()); + uint32_t lostAllocationCount = 0; SuballocationVectorType& suballocations1st = AccessSuballocations1st(); for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i) { VmaSuballocation& suballoc = suballocations1st[i]; + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE && - suballoc.hAllocation->CanBecomeLost() && - suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) + alloc->CanBecomeLost() && + alloc->MakeLost(currentFrameIndex, frameInUseCount)) { suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; + suballoc.userData = VMA_NULL; ++m_1stNullItemsMiddleCount; m_SumFreeSize += suballoc.size; ++lostAllocationCount; @@ -9866,12 +9968,13 @@ uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i) { VmaSuballocation& suballoc = suballocations2nd[i]; + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE && - suballoc.hAllocation->CanBecomeLost() && - suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) + alloc->CanBecomeLost() && + alloc->MakeLost(currentFrameIndex, frameInUseCount)) { suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; + suballoc.userData = VMA_NULL; ++m_2ndNullItemsCount; m_SumFreeSize += suballoc.size; ++lostAllocationCount; @@ -9933,9 +10036,9 @@ void VmaBlockMetadata_Linear::Alloc( const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation) + void* userData) { - const VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type }; + const VmaSuballocation newSuballoc = { request.offset, allocSize, userData, type }; switch(request.type) { @@ -9996,11 +10099,6 @@ void VmaBlockMetadata_Linear::Alloc( m_SumFreeSize -= newSuballoc.size; } -void VmaBlockMetadata_Linear::Free(const VmaAllocation allocation) -{ - FreeAtOffset(allocation->GetOffset()); -} - void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) { SuballocationVectorType& suballocations1st = AccessSuballocations1st(); @@ -10013,7 +10111,7 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) if(firstSuballoc.offset == offset) { firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - firstSuballoc.hAllocation = VK_NULL_HANDLE; + firstSuballoc.userData = VMA_NULL; m_SumFreeSize += firstSuballoc.size; ++m_1stNullItemsBeginCount; CleanupAfterFree(); @@ -10060,7 +10158,7 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) if(it != suballocations1st.end()) { it->type = VMA_SUBALLOCATION_TYPE_FREE; - it->hAllocation = VK_NULL_HANDLE; + it->userData = VMA_NULL; ++m_1stNullItemsMiddleCount; m_SumFreeSize += it->size; CleanupAfterFree(); @@ -10080,7 +10178,7 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) if(it != suballocations2nd.end()) { it->type = VMA_SUBALLOCATION_TYPE_FREE; - it->hAllocation = VK_NULL_HANDLE; + it->userData = VMA_NULL; ++m_2ndNullItemsCount; m_SumFreeSize += it->size; CleanupAfterFree(); @@ -10091,6 +10189,21 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) VMA_ASSERT(0 && "Allocation to free not found in linear allocator!"); } +void VmaBlockMetadata_Linear::GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const +{ + VMA_ASSERT(0 && "TODO implement"); +} + +void VmaBlockMetadata_Linear::Clear() +{ + VMA_ASSERT(0 && "TODO implement"); +} + +void VmaBlockMetadata_Linear::SetAllocationUserData(VkDeviceSize offset, void* userData) +{ + VMA_ASSERT(0 && "TODO implement"); +} + bool VmaBlockMetadata_Linear::ShouldCompact1st() const { const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount; @@ -10120,7 +10233,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() // Find more null items at the beginning of 1st vector. while(m_1stNullItemsBeginCount < suballoc1stCount && - suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE) + suballocations1st[m_1stNullItemsBeginCount].userData == VMA_NULL) { ++m_1stNullItemsBeginCount; --m_1stNullItemsMiddleCount; @@ -10128,7 +10241,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() // Find more null items at the end of 1st vector. while(m_1stNullItemsMiddleCount > 0 && - suballocations1st.back().hAllocation == VK_NULL_HANDLE) + suballocations1st.back().userData == VMA_NULL) { --m_1stNullItemsMiddleCount; suballocations1st.pop_back(); @@ -10136,7 +10249,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() // Find more null items at the end of 2nd vector. while(m_2ndNullItemsCount > 0 && - suballocations2nd.back().hAllocation == VK_NULL_HANDLE) + suballocations2nd.back().userData == VMA_NULL) { --m_2ndNullItemsCount; suballocations2nd.pop_back(); @@ -10144,7 +10257,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() // Find more null items at the beginning of 2nd vector. while(m_2ndNullItemsCount > 0 && - suballocations2nd[0].hAllocation == VK_NULL_HANDLE) + suballocations2nd[0].userData == VMA_NULL) { --m_2ndNullItemsCount; VmaVectorRemove(suballocations2nd, 0); @@ -10156,7 +10269,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() size_t srcIndex = m_1stNullItemsBeginCount; for(size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex) { - while(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE) + while(suballocations1st[srcIndex].userData == VMA_NULL) { ++srcIndex; } @@ -10189,7 +10302,7 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() m_2ndVectorMode = SECOND_VECTOR_EMPTY; m_1stNullItemsMiddleCount = m_2ndNullItemsCount; while(m_1stNullItemsBeginCount < suballocations2nd.size() && - suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE) + suballocations2nd[m_1stNullItemsBeginCount].userData == VMA_NULL) { ++m_1stNullItemsBeginCount; --m_1stNullItemsMiddleCount; @@ -10207,8 +10320,8 @@ void VmaBlockMetadata_Linear::CleanupAfterFree() //////////////////////////////////////////////////////////////////////////////// // class VmaBlockMetadata_Buddy -VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) : - VmaBlockMetadata(hAllocator), +VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator, bool isVirtual) : + VmaBlockMetadata(hAllocator, isVirtual), m_Root(VMA_NULL), m_AllocationCount(0), m_FreeCount(1), @@ -10449,7 +10562,7 @@ void VmaBlockMetadata_Buddy::Alloc( const VmaAllocationRequest& request, VmaSuballocationType type, VkDeviceSize allocSize, - VmaAllocation hAllocation) + void* userData) { VMA_ASSERT(request.type == VmaAllocationRequestType::Normal); @@ -10514,13 +10627,28 @@ void VmaBlockMetadata_Buddy::Alloc( // Convert to allocation node. currNode->type = Node::TYPE_ALLOCATION; - currNode->allocation.alloc = hAllocation; + currNode->allocation.userData = userData; ++m_AllocationCount; --m_FreeCount; m_SumFreeSize -= allocSize; } +void VmaBlockMetadata_Buddy::GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const +{ + VMA_ASSERT(0 && "TODO implement"); +} + +void VmaBlockMetadata_Buddy::Clear() +{ + VMA_ASSERT(0 && "TODO implement"); +} + +void VmaBlockMetadata_Buddy::SetAllocationUserData(VkDeviceSize offset, void* userData) +{ + VMA_ASSERT(0 && "TODO implement"); +} + void VmaBlockMetadata_Buddy::DeleteNode(Node* node) { if(node->type == Node::TYPE_SPLIT) @@ -10534,6 +10662,7 @@ void VmaBlockMetadata_Buddy::DeleteNode(Node* node) bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const { + VMA_ASSERT(!IsVirtual()); // TODO VMA_VALIDATE(level < m_LevelCount); VMA_VALIDATE(curr->parent == parent); VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL)); @@ -10547,8 +10676,8 @@ bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* pa break; case Node::TYPE_ALLOCATION: ++ctx.calculatedAllocationCount; - ctx.calculatedSumFreeSize += levelNodeSize - curr->allocation.alloc->GetSize(); - VMA_VALIDATE(curr->allocation.alloc != VK_NULL_HANDLE); + VMA_VALIDATE(curr->allocation.userData != VMA_NULL); + ctx.calculatedSumFreeSize += levelNodeSize - ((VmaAllocation)(curr->allocation.userData))->GetSize(); break; case Node::TYPE_SPLIT: { @@ -10591,7 +10720,7 @@ uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const return level; } -void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset) +void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation allocForValidation, VkDeviceSize offset) { // Find node and level. Node* node = m_Root; @@ -10615,7 +10744,11 @@ void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offs } VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION); - VMA_ASSERT(alloc == VK_NULL_HANDLE || node->allocation.alloc == alloc); + VmaAllocation const alloc = (VmaAllocation)node->allocation.userData; + if(!IsVirtual() && allocForValidation) + { + VMA_ASSERT(alloc == allocForValidation); + } ++m_FreeCount; --m_AllocationCount; @@ -10644,6 +10777,7 @@ void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offs void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const { + VMA_ASSERT(!IsVirtual()); // TODO switch(node->type) { case Node::TYPE_FREE: @@ -10654,7 +10788,7 @@ void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, co break; case Node::TYPE_ALLOCATION: { - const VkDeviceSize allocSize = node->allocation.alloc->GetSize(); + const VkDeviceSize allocSize = ((VmaAllocation)(node->allocation.userData))->GetSize(); ++outInfo.allocationCount; outInfo.usedBytes += allocSize; outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, allocSize); @@ -10740,6 +10874,7 @@ void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node) #if VMA_STATS_STRING_ENABLED void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const { + VMA_ASSERT(!IsVirtual()); // TODO switch(node->type) { case Node::TYPE_FREE: @@ -10747,8 +10882,9 @@ void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, con break; case Node::TYPE_ALLOCATION: { - PrintDetailedMap_Allocation(json, node->offset, node->allocation.alloc); - const VkDeviceSize allocSize = node->allocation.alloc->GetSize(); + VmaAllocation const alloc = (VmaAllocation)node->allocation.userData; + PrintDetailedMap_Allocation(json, node->offset, alloc); + const VkDeviceSize allocSize = alloc->GetSize(); if(allocSize < levelNodeSize) { PrintDetailedMap_UnusedRange(json, node->offset + allocSize, levelNodeSize - allocSize); @@ -10803,16 +10939,19 @@ void VmaDeviceMemoryBlock::Init( switch(algorithm) { case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT: - m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator); + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator, + false); // isVirtual break; case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT: - m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator); + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator, + false); // isVirtual break; default: VMA_ASSERT(0); // Fall-through. case 0: - m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator); + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator, + false); // isVirtual } m_pMetadata->Init(newSize); } @@ -11630,7 +11769,7 @@ void VmaBlockVector::Free( pBlock->Unmap(m_hAllocator, 1); } - pBlock->m_pMetadata->Free(hAllocation); + pBlock->m_pMetadata->FreeAtOffset(hAllocation->GetOffset()); VMA_HEAVY_ASSERT(pBlock->Validate()); VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex); @@ -12689,13 +12828,14 @@ VkResult VmaDefragmentationAlgorithm_Generic::Defragment( if(m_AllAllocations) { VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata; - for(VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin(); + VMA_ASSERT(!pMetadata->IsVirtual()); + for (VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin(); it != pMetadata->m_Suballocations.end(); ++it) { if(it->type != VMA_SUBALLOCATION_TYPE_FREE) { - AllocationInfo allocInfo = AllocationInfo(it->hAllocation, VMA_NULL); + AllocationInfo allocInfo = AllocationInfo((VmaAllocation)it->userData, VMA_NULL); pBlockInfo->m_Allocations.push_back(allocInfo); } } @@ -12818,7 +12958,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment( for(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin(); !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); ) { - VmaAllocation_T* const pAlloc = srcSuballocIt->hAllocation; + VmaAllocation const pAlloc = (VmaAllocation)srcSuballocIt->userData; const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment(); const VkDeviceSize srcAllocSize = srcSuballocIt->size; if(m_AllocationsMoved == maxAllocationsToMove || @@ -12849,7 +12989,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment( VmaSuballocation suballoc = *srcSuballocIt; suballoc.offset = dstAllocOffset; - suballoc.hAllocation->ChangeOffset(dstAllocOffset); + ((VmaAllocation)(suballoc.userData))->ChangeOffset(dstAllocOffset); m_BytesMoved += srcAllocSize; ++m_AllocationsMoved; @@ -12877,7 +13017,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment( VmaSuballocation suballoc = *srcSuballocIt; suballoc.offset = dstAllocOffset; - suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset); + ((VmaAllocation)(suballoc.userData))->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset); m_BytesMoved += srcAllocSize; ++m_AllocationsMoved; @@ -12943,7 +13083,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment( else { srcSuballocIt->offset = dstAllocOffset; - srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset); + ((VmaAllocation)(srcSuballocIt->userData))->ChangeOffset(dstAllocOffset); dstOffset = dstAllocOffset + srcAllocSize; m_BytesMoved += srcAllocSize; ++m_AllocationsMoved; @@ -12968,7 +13108,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment( VmaSuballocation suballoc = *srcSuballocIt; suballoc.offset = dstAllocOffset; - suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset); + ((VmaAllocation)(suballoc.userData))->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset); dstOffset = dstAllocOffset + srcAllocSize; m_BytesMoved += srcAllocSize; ++m_AllocationsMoved;