diff options
author | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2022-02-12 12:47:08 +0100 |
---|---|---|
committer | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2022-02-12 12:47:08 +0100 |
commit | 4e6c9d3ae979f2eb0151cf581fe61d2f3194ea72 (patch) | |
tree | 91a5316d207c8fcad76d24864f9ddef5c0ecfe50 /thirdparty/vulkan | |
parent | 648a10514bfd574eebcd332ff5b672659ead5850 (diff) |
Add a separate pool for small allocations in Vulkan RD
Diffstat (limited to 'thirdparty/vulkan')
-rw-r--r-- | thirdparty/vulkan/patches/03-VMA-universal-pools.patch | 567 | ||||
-rw-r--r-- | thirdparty/vulkan/vk_mem_alloc.h | 346 |
2 files changed, 756 insertions, 157 deletions
diff --git a/thirdparty/vulkan/patches/03-VMA-universal-pools.patch b/thirdparty/vulkan/patches/03-VMA-universal-pools.patch new file mode 100644 index 0000000000..a5de3aaace --- /dev/null +++ b/thirdparty/vulkan/patches/03-VMA-universal-pools.patch @@ -0,0 +1,567 @@ +diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h +index 74c66b9789..89e00e6326 100644 +--- a/thirdparty/vulkan/vk_mem_alloc.h ++++ b/thirdparty/vulkan/vk_mem_alloc.h +@@ -1127,31 +1127,26 @@ typedef struct VmaAllocationCreateInfo + /** \brief Intended usage of memory. + + You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n +- If `pool` is not null, this member is ignored. + */ + VmaMemoryUsage usage; + /** \brief Flags that must be set in a Memory Type chosen for an allocation. + +- Leave 0 if you specify memory requirements in other way. \n +- If `pool` is not null, this member is ignored.*/ ++ Leave 0 if you specify memory requirements in other way.*/ + VkMemoryPropertyFlags requiredFlags; + /** \brief Flags that preferably should be set in a memory type chosen for an allocation. + +- Set to 0 if no additional flags are preferred. \n +- If `pool` is not null, this member is ignored. */ ++ Set to 0 if no additional flags are preferred.*/ + VkMemoryPropertyFlags preferredFlags; + /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. + + Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if + it meets other requirements specified by this structure, with no further + restrictions on memory type index. \n +- If `pool` is not null, this member is ignored. + */ + uint32_t memoryTypeBits; + /** \brief Pool that this allocation should be created in. + +- Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: +- `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. ++ Leave `VK_NULL_HANDLE` to allocate from default 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(). +@@ -1173,9 +1168,6 @@ typedef struct VmaAllocationCreateInfo + /// Describes parameter of created #VmaPool. + typedef struct VmaPoolCreateInfo + { +- /** \brief Vulkan memory type index to allocate this pool from. +- */ +- uint32_t memoryTypeIndex; + /** \brief Use combination of #VmaPoolCreateFlagBits. + */ + VmaPoolCreateFlags flags; +@@ -10904,13 +10896,12 @@ struct VmaPool_T + friend struct VmaPoolListItemTraits; + VMA_CLASS_NO_COPY(VmaPool_T) + public: +- VmaBlockVector m_BlockVector; +- VmaDedicatedAllocationList m_DedicatedAllocations; ++ VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES]; ++ VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES]; + + VmaPool_T( + VmaAllocator hAllocator, +- const VmaPoolCreateInfo& createInfo, +- VkDeviceSize preferredBlockSize); ++ const VmaPoolCreateInfo& createInfo); + ~VmaPool_T(); + + uint32_t GetId() const { return m_Id; } +@@ -10924,6 +10915,7 @@ public: + #endif + + private: ++ const VmaAllocator m_hAllocator; + uint32_t m_Id; + char* m_Name; + VmaPool_T* m_PrevPool = VMA_NULL; +@@ -11405,8 +11397,10 @@ private: + + void ValidateVulkanFunctions(); + ++public: // I'm sorry + VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex); + ++private: + VkResult AllocateMemoryOfType( + VmaPool pool, + VkDeviceSize size, +@@ -14176,30 +14170,36 @@ void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pP + { + VmaPool pool = pPools[poolIndex]; + VMA_ASSERT(pool); +- // Pools with algorithm other than default are not defragmented. +- if (pool->m_BlockVector.GetAlgorithm() == 0) ++ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) + { +- VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; +- +- for (size_t i = m_CustomPoolContexts.size(); i--; ) ++ if(pool->m_pBlockVectors[memTypeIndex]) + { +- if (m_CustomPoolContexts[i]->GetCustomPool() == pool) ++ // Pools with algorithm other than default are not defragmented. ++ if (pool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0) + { +- pBlockVectorDefragCtx = m_CustomPoolContexts[i]; +- break; +- } +- } ++ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; + +- if (!pBlockVectorDefragCtx) +- { +- pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( +- m_hAllocator, +- pool, +- &pool->m_BlockVector); +- m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); +- } ++ for (size_t i = m_CustomPoolContexts.size(); i--; ) ++ { ++ if (m_CustomPoolContexts[i]->GetCustomPool() == pool) ++ { ++ pBlockVectorDefragCtx = m_CustomPoolContexts[i]; ++ break; ++ } ++ } ++ ++ if (!pBlockVectorDefragCtx) ++ { ++ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( ++ m_hAllocator, ++ pool, ++ pool->m_pBlockVectors[memTypeIndex]); ++ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); ++ } + +- pBlockVectorDefragCtx->AddAll(); ++ pBlockVectorDefragCtx->AddAll(); ++ } ++ } + } + } + } +@@ -14214,6 +14214,7 @@ void VmaDefragmentationContext_T::AddAllocations( + { + const VmaAllocation hAlloc = pAllocations[allocIndex]; + VMA_ASSERT(hAlloc); ++ const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); + // DedicatedAlloc cannot be defragmented. + if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) + { +@@ -14224,7 +14225,7 @@ void VmaDefragmentationContext_T::AddAllocations( + if (hAllocPool != VK_NULL_HANDLE) + { + // Pools with algorithm other than default are not defragmented. +- if (hAllocPool->m_BlockVector.GetAlgorithm() == 0) ++ if (hAllocPool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0) + { + for (size_t i = m_CustomPoolContexts.size(); i--; ) + { +@@ -14239,7 +14240,7 @@ void VmaDefragmentationContext_T::AddAllocations( + pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( + m_hAllocator, + hAllocPool, +- &hAllocPool->m_BlockVector); ++ hAllocPool->m_pBlockVectors[memTypeIndex]); + m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); + } + } +@@ -14247,7 +14248,6 @@ void VmaDefragmentationContext_T::AddAllocations( + // This allocation belongs to default pool. + else + { +- const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); + pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex]; + if (!pBlockVectorDefragCtx) + { +@@ -14481,41 +14481,61 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd() + #ifndef _VMA_POOL_T_FUNCTIONS + VmaPool_T::VmaPool_T( + VmaAllocator hAllocator, +- const VmaPoolCreateInfo& createInfo, +- VkDeviceSize preferredBlockSize) +- : m_BlockVector( +- hAllocator, +- this, // hParentPool +- createInfo.memoryTypeIndex, +- createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize, +- createInfo.minBlockCount, +- createInfo.maxBlockCount, +- (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), +- createInfo.blockSize != 0, // explicitBlockSize +- createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm +- createInfo.priority, +- VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment), +- createInfo.pMemoryAllocateNext), ++ const VmaPoolCreateInfo& createInfo) : ++ m_hAllocator(hAllocator), ++ m_pBlockVectors{}, + m_Id(0), +- m_Name(VMA_NULL) {} ++ m_Name(VMA_NULL) ++{ ++ for(uint32_t memTypeIndex = 0; memTypeIndex < hAllocator->GetMemoryTypeCount(); ++memTypeIndex) ++ { ++ // Create only supported types ++ if((hAllocator->GetGlobalMemoryTypeBits() & (1u << memTypeIndex)) != 0) ++ { ++ m_pBlockVectors[memTypeIndex] = vma_new(hAllocator, VmaBlockVector)( ++ hAllocator, ++ this, // hParentPool ++ memTypeIndex, ++ createInfo.blockSize != 0 ? createInfo.blockSize : hAllocator->CalcPreferredBlockSize(memTypeIndex), ++ createInfo.minBlockCount, ++ createInfo.maxBlockCount, ++ (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), ++ false, // explicitBlockSize ++ createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm ++ createInfo.priority, ++ VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(memTypeIndex), createInfo.minAllocationAlignment), ++ createInfo.pMemoryAllocateNext); ++ } ++ } ++} + + VmaPool_T::~VmaPool_T() + { + VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL); ++ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) ++ { ++ vma_delete(m_hAllocator, m_pBlockVectors[memTypeIndex]); ++ } + } + + void VmaPool_T::SetName(const char* pName) + { +- const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks(); +- VmaFreeString(allocs, m_Name); +- +- if (pName != VMA_NULL) +- { +- m_Name = VmaCreateStringCopy(allocs, pName); +- } +- else ++ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) + { +- m_Name = VMA_NULL; ++ if(m_pBlockVectors[memTypeIndex]) ++ { ++ const VkAllocationCallbacks* allocs = m_pBlockVectors[memTypeIndex]->GetAllocator()->GetAllocationCallbacks(); ++ VmaFreeString(allocs, m_Name); ++ ++ if (pName != VMA_NULL) ++ { ++ m_Name = VmaCreateStringCopy(allocs, pName); ++ } ++ else ++ { ++ m_Name = VMA_NULL; ++ } ++ } + } + } + #endif // _VMA_POOL_T_FUNCTIONS +@@ -15377,15 +15397,22 @@ VkResult VmaAllocator_T::CalcAllocationParams( + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + } + +- if(inoutCreateInfo.pool != VK_NULL_HANDLE) ++ if(inoutCreateInfo.pool != VK_NULL_HANDLE && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + { +- if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && +- (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) ++ // Assuming here every block has the same block size and priority. ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { +- VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); +- return VK_ERROR_FEATURE_NOT_PRESENT; ++ if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]) ++ { ++ if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->HasExplicitBlockSize()) ++ { ++ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); ++ return VK_ERROR_FEATURE_NOT_PRESENT; ++ } ++ inoutCreateInfo.priority = inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->GetPriority(); ++ break; ++ } + } +- inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority(); + } + + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && +@@ -15429,67 +15456,46 @@ VkResult VmaAllocator_T::AllocateMemory( + if(res != VK_SUCCESS) + return res; + +- if(createInfoFinal.pool != VK_NULL_HANDLE) ++ // Bit mask of memory Vulkan types acceptable for this allocation. ++ uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; ++ uint32_t memTypeIndex = UINT32_MAX; ++ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); ++ // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. ++ if(res != VK_SUCCESS) ++ return res; ++ do + { +- VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector; +- return AllocateMemoryOfType( ++ VmaBlockVector* blockVector = createInfoFinal.pool == VK_NULL_HANDLE ? m_pBlockVectors[memTypeIndex] : createInfoFinal.pool->m_pBlockVectors[memTypeIndex]; ++ VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); ++ VmaDedicatedAllocationList& dedicatedAllocations = createInfoFinal.pool == VK_NULL_HANDLE ? m_DedicatedAllocations[memTypeIndex] : createInfoFinal.pool->m_DedicatedAllocations[memTypeIndex]; ++ res = AllocateMemoryOfType( + createInfoFinal.pool, + vkMemReq.size, + vkMemReq.alignment, +- prefersDedicatedAllocation, ++ requiresDedicatedAllocation || prefersDedicatedAllocation, + dedicatedBuffer, + dedicatedBufferUsage, + dedicatedImage, + createInfoFinal, +- blockVector.GetMemoryTypeIndex(), ++ memTypeIndex, + suballocType, +- createInfoFinal.pool->m_DedicatedAllocations, +- blockVector, ++ dedicatedAllocations, ++ *blockVector, + allocationCount, + pAllocations); +- } +- else +- { +- // Bit mask of memory Vulkan types acceptable for this allocation. +- uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; +- uint32_t memTypeIndex = UINT32_MAX; +- res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); +- // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. +- if(res != VK_SUCCESS) +- return res; +- do +- { +- VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex]; +- VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); +- res = AllocateMemoryOfType( +- VK_NULL_HANDLE, +- vkMemReq.size, +- vkMemReq.alignment, +- requiresDedicatedAllocation || prefersDedicatedAllocation, +- dedicatedBuffer, +- dedicatedBufferUsage, +- dedicatedImage, +- createInfoFinal, +- memTypeIndex, +- suballocType, +- m_DedicatedAllocations[memTypeIndex], +- *blockVector, +- allocationCount, +- pAllocations); +- // Allocation succeeded +- if(res == VK_SUCCESS) +- return VK_SUCCESS; ++ // Allocation succeeded ++ if(res == VK_SUCCESS) ++ return VK_SUCCESS; + +- // Remove old memTypeIndex from list of possibilities. +- memoryTypeBits &= ~(1u << memTypeIndex); +- // Find alternative memTypeIndex. +- res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); +- } while(res == VK_SUCCESS); ++ // Remove old memTypeIndex from list of possibilities. ++ memoryTypeBits &= ~(1u << memTypeIndex); ++ // Find alternative memTypeIndex. ++ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); ++ } while(res == VK_SUCCESS); + +- // No other matching memory type index could be found. +- // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. +- return VK_ERROR_OUT_OF_DEVICE_MEMORY; +- } ++ // No other matching memory type index could be found. ++ // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. ++ return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + + void VmaAllocator_T::FreeMemory( +@@ -15515,16 +15521,16 @@ void VmaAllocator_T::FreeMemory( + { + VmaBlockVector* pBlockVector = VMA_NULL; + VmaPool hPool = allocation->GetParentPool(); ++ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + if(hPool != VK_NULL_HANDLE) + { +- pBlockVector = &hPool->m_BlockVector; ++ pBlockVector = hPool->m_pBlockVectors[memTypeIndex]; + } + else + { +- const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + pBlockVector = m_pBlockVectors[memTypeIndex]; +- VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); + } ++ VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); + pBlockVector->Free(allocation); + } + break; +@@ -15564,11 +15570,17 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats) + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { +- VmaBlockVector& blockVector = pool->m_BlockVector; +- blockVector.AddStats(pStats); +- const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); +- const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); +- pool->m_DedicatedAllocations.AddStats(pStats, memTypeIndex, memHeapIndex); ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) ++ { ++ if (pool->m_pBlockVectors[memTypeIndex]) ++ { ++ VmaBlockVector& blockVector = *pool->m_pBlockVectors[memTypeIndex]; ++ blockVector.AddStats(pStats); ++ const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); ++ const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); ++ pool->m_DedicatedAllocations[memTypeIndex].AddStats(pStats, memTypeIndex, memHeapIndex); ++ } ++ } + } + } + +@@ -15720,27 +15732,26 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo + { + return VK_ERROR_INITIALIZATION_FAILED; + } +- // Memory type index out of range or forbidden. +- if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || +- ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0) +- { +- return VK_ERROR_FEATURE_NOT_PRESENT; +- } + if(newCreateInfo.minAllocationAlignment > 0) + { + VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment)); + } + +- const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex); +- +- *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize); ++ *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo); + +- VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks(); +- if(res != VK_SUCCESS) ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { +- vma_delete(this, *pPool); +- *pPool = VMA_NULL; +- return res; ++ // Create only supported types ++ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) ++ { ++ VkResult res = (*pPool)->m_pBlockVectors[memTypeIndex]->CreateMinBlocks(); ++ if(res != VK_SUCCESS) ++ { ++ vma_delete(this, *pPool); ++ *pPool = VMA_NULL; ++ return res; ++ } ++ } + } + + // Add to m_Pools. +@@ -15772,8 +15783,14 @@ void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats) + pPoolStats->unusedRangeCount = 0; + pPoolStats->blockCount = 0; + +- pool->m_BlockVector.AddPoolStats(pPoolStats); +- pool->m_DedicatedAllocations.AddPoolStats(pPoolStats); ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) ++ { ++ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) ++ { ++ pool->m_pBlockVectors[memTypeIndex]->AddPoolStats(pPoolStats); ++ pool->m_DedicatedAllocations[memTypeIndex].AddPoolStats(pPoolStats); ++ } ++ } + } + + void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) +@@ -15790,7 +15807,13 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) + + VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool) + { +- return hPool->m_BlockVector.CheckCorruption(); ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) ++ { ++ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) ++ { ++ return hPool->m_pBlockVectors[memTypeIndex]->CheckCorruption(); ++ } ++ } + } + + VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) +@@ -15822,18 +15845,21 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { +- if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { +- VkResult localRes = pool->m_BlockVector.CheckCorruption(); +- switch(localRes) ++ if(pool->m_pBlockVectors[memTypeIndex] && ((1u << memTypeIndex) & memoryTypeBits) != 0) + { +- case VK_ERROR_FEATURE_NOT_PRESENT: +- break; +- case VK_SUCCESS: +- finalRes = VK_SUCCESS; +- break; +- default: +- return localRes; ++ VkResult localRes = pool->m_pBlockVectors[memTypeIndex]->CheckCorruption(); ++ switch(localRes) ++ { ++ case VK_ERROR_FEATURE_NOT_PRESENT: ++ break; ++ case VK_SUCCESS: ++ finalRes = VK_SUCCESS; ++ break; ++ default: ++ return localRes; ++ } + } + } + } +@@ -16155,7 +16181,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation) + else + { + // Custom pool +- parentPool->m_DedicatedAllocations.Unregister(allocation); ++ parentPool->m_DedicatedAllocations[memTypeIndex].Unregister(allocation); + } + + VkDeviceMemory hMemory = allocation->GetMemory(); +@@ -16430,12 +16456,18 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) + json.EndString(); + + json.BeginObject(); +- pool->m_BlockVector.PrintDetailedMap(json); +- +- if (!pool->m_DedicatedAllocations.IsEmpty()) ++ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { +- json.WriteString("DedicatedAllocations"); +- pool->m_DedicatedAllocations.BuildStatsString(json); ++ if (pool->m_pBlockVectors[memTypeIndex]) ++ { ++ pool->m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json); ++ } ++ ++ if (!pool->m_DedicatedAllocations[memTypeIndex].IsEmpty()) ++ { ++ json.WriteString("DedicatedAllocations"); ++ pool->m_DedicatedAllocations->BuildStatsString(json); ++ } + } + json.EndObject(); + } diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h index 74c66b9789..89e00e6326 100644 --- a/thirdparty/vulkan/vk_mem_alloc.h +++ b/thirdparty/vulkan/vk_mem_alloc.h @@ -1127,31 +1127,26 @@ typedef struct VmaAllocationCreateInfo /** \brief Intended usage of memory. You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n - If `pool` is not null, this member is ignored. */ VmaMemoryUsage usage; /** \brief Flags that must be set in a Memory Type chosen for an allocation. - Leave 0 if you specify memory requirements in other way. \n - If `pool` is not null, this member is ignored.*/ + Leave 0 if you specify memory requirements in other way.*/ VkMemoryPropertyFlags requiredFlags; /** \brief Flags that preferably should be set in a memory type chosen for an allocation. - Set to 0 if no additional flags are preferred. \n - If `pool` is not null, this member is ignored. */ + Set to 0 if no additional flags are preferred.*/ VkMemoryPropertyFlags preferredFlags; /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if it meets other requirements specified by this structure, with no further restrictions on memory type index. \n - If `pool` is not null, this member is ignored. */ uint32_t memoryTypeBits; /** \brief Pool that this allocation should be created in. - Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: - `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. + Leave `VK_NULL_HANDLE` to allocate from default 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(). @@ -1173,9 +1168,6 @@ typedef struct VmaAllocationCreateInfo /// Describes parameter of created #VmaPool. typedef struct VmaPoolCreateInfo { - /** \brief Vulkan memory type index to allocate this pool from. - */ - uint32_t memoryTypeIndex; /** \brief Use combination of #VmaPoolCreateFlagBits. */ VmaPoolCreateFlags flags; @@ -10904,13 +10896,12 @@ struct VmaPool_T friend struct VmaPoolListItemTraits; VMA_CLASS_NO_COPY(VmaPool_T) public: - VmaBlockVector m_BlockVector; - VmaDedicatedAllocationList m_DedicatedAllocations; + VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES]; + VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES]; VmaPool_T( VmaAllocator hAllocator, - const VmaPoolCreateInfo& createInfo, - VkDeviceSize preferredBlockSize); + const VmaPoolCreateInfo& createInfo); ~VmaPool_T(); uint32_t GetId() const { return m_Id; } @@ -10924,6 +10915,7 @@ public: #endif private: + const VmaAllocator m_hAllocator; uint32_t m_Id; char* m_Name; VmaPool_T* m_PrevPool = VMA_NULL; @@ -11405,8 +11397,10 @@ private: void ValidateVulkanFunctions(); +public: // I'm sorry VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex); +private: VkResult AllocateMemoryOfType( VmaPool pool, VkDeviceSize size, @@ -14176,30 +14170,36 @@ void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pP { VmaPool pool = pPools[poolIndex]; VMA_ASSERT(pool); - // Pools with algorithm other than default are not defragmented. - if (pool->m_BlockVector.GetAlgorithm() == 0) + for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) { - VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; - - for (size_t i = m_CustomPoolContexts.size(); i--; ) + if(pool->m_pBlockVectors[memTypeIndex]) { - if (m_CustomPoolContexts[i]->GetCustomPool() == pool) + // Pools with algorithm other than default are not defragmented. + if (pool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0) { - pBlockVectorDefragCtx = m_CustomPoolContexts[i]; - break; - } - } + VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; - if (!pBlockVectorDefragCtx) - { - pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( - m_hAllocator, - pool, - &pool->m_BlockVector); - m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); - } + for (size_t i = m_CustomPoolContexts.size(); i--; ) + { + if (m_CustomPoolContexts[i]->GetCustomPool() == pool) + { + pBlockVectorDefragCtx = m_CustomPoolContexts[i]; + break; + } + } + + if (!pBlockVectorDefragCtx) + { + pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( + m_hAllocator, + pool, + pool->m_pBlockVectors[memTypeIndex]); + m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); + } - pBlockVectorDefragCtx->AddAll(); + pBlockVectorDefragCtx->AddAll(); + } + } } } } @@ -14214,6 +14214,7 @@ void VmaDefragmentationContext_T::AddAllocations( { const VmaAllocation hAlloc = pAllocations[allocIndex]; VMA_ASSERT(hAlloc); + const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); // DedicatedAlloc cannot be defragmented. if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) { @@ -14224,7 +14225,7 @@ void VmaDefragmentationContext_T::AddAllocations( if (hAllocPool != VK_NULL_HANDLE) { // Pools with algorithm other than default are not defragmented. - if (hAllocPool->m_BlockVector.GetAlgorithm() == 0) + if (hAllocPool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0) { for (size_t i = m_CustomPoolContexts.size(); i--; ) { @@ -14239,7 +14240,7 @@ void VmaDefragmentationContext_T::AddAllocations( pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( m_hAllocator, hAllocPool, - &hAllocPool->m_BlockVector); + hAllocPool->m_pBlockVectors[memTypeIndex]); m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); } } @@ -14247,7 +14248,6 @@ void VmaDefragmentationContext_T::AddAllocations( // This allocation belongs to default pool. else { - const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex]; if (!pBlockVectorDefragCtx) { @@ -14481,41 +14481,61 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd() #ifndef _VMA_POOL_T_FUNCTIONS VmaPool_T::VmaPool_T( VmaAllocator hAllocator, - const VmaPoolCreateInfo& createInfo, - VkDeviceSize preferredBlockSize) - : m_BlockVector( - hAllocator, - this, // hParentPool - createInfo.memoryTypeIndex, - createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize, - createInfo.minBlockCount, - createInfo.maxBlockCount, - (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), - createInfo.blockSize != 0, // explicitBlockSize - createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm - createInfo.priority, - VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment), - createInfo.pMemoryAllocateNext), + const VmaPoolCreateInfo& createInfo) : + m_hAllocator(hAllocator), + m_pBlockVectors{}, m_Id(0), - m_Name(VMA_NULL) {} + m_Name(VMA_NULL) +{ + for(uint32_t memTypeIndex = 0; memTypeIndex < hAllocator->GetMemoryTypeCount(); ++memTypeIndex) + { + // Create only supported types + if((hAllocator->GetGlobalMemoryTypeBits() & (1u << memTypeIndex)) != 0) + { + m_pBlockVectors[memTypeIndex] = vma_new(hAllocator, VmaBlockVector)( + hAllocator, + this, // hParentPool + memTypeIndex, + createInfo.blockSize != 0 ? createInfo.blockSize : hAllocator->CalcPreferredBlockSize(memTypeIndex), + createInfo.minBlockCount, + createInfo.maxBlockCount, + (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), + false, // explicitBlockSize + createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm + createInfo.priority, + VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(memTypeIndex), createInfo.minAllocationAlignment), + createInfo.pMemoryAllocateNext); + } + } +} VmaPool_T::~VmaPool_T() { VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL); + for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) + { + vma_delete(m_hAllocator, m_pBlockVectors[memTypeIndex]); + } } void VmaPool_T::SetName(const char* pName) { - const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks(); - VmaFreeString(allocs, m_Name); - - if (pName != VMA_NULL) - { - m_Name = VmaCreateStringCopy(allocs, pName); - } - else + for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex) { - m_Name = VMA_NULL; + if(m_pBlockVectors[memTypeIndex]) + { + const VkAllocationCallbacks* allocs = m_pBlockVectors[memTypeIndex]->GetAllocator()->GetAllocationCallbacks(); + VmaFreeString(allocs, m_Name); + + if (pName != VMA_NULL) + { + m_Name = VmaCreateStringCopy(allocs, pName); + } + else + { + m_Name = VMA_NULL; + } + } } } #endif // _VMA_POOL_T_FUNCTIONS @@ -15377,15 +15397,22 @@ VkResult VmaAllocator_T::CalcAllocationParams( inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } - if(inoutCreateInfo.pool != VK_NULL_HANDLE) + if(inoutCreateInfo.pool != VK_NULL_HANDLE && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) { - if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && - (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + // Assuming here every block has the same block size and priority. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); - return VK_ERROR_FEATURE_NOT_PRESENT; + if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]) + { + if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->HasExplicitBlockSize()) + { + VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); + return VK_ERROR_FEATURE_NOT_PRESENT; + } + inoutCreateInfo.priority = inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->GetPriority(); + break; + } } - inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority(); } if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && @@ -15429,67 +15456,46 @@ VkResult VmaAllocator_T::AllocateMemory( if(res != VK_SUCCESS) return res; - if(createInfoFinal.pool != VK_NULL_HANDLE) + // Bit mask of memory Vulkan types acceptable for this allocation. + uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; + uint32_t memTypeIndex = UINT32_MAX; + res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); + // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. + if(res != VK_SUCCESS) + return res; + do { - VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector; - return AllocateMemoryOfType( + VmaBlockVector* blockVector = createInfoFinal.pool == VK_NULL_HANDLE ? m_pBlockVectors[memTypeIndex] : createInfoFinal.pool->m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); + VmaDedicatedAllocationList& dedicatedAllocations = createInfoFinal.pool == VK_NULL_HANDLE ? m_DedicatedAllocations[memTypeIndex] : createInfoFinal.pool->m_DedicatedAllocations[memTypeIndex]; + res = AllocateMemoryOfType( createInfoFinal.pool, vkMemReq.size, vkMemReq.alignment, - prefersDedicatedAllocation, + requiresDedicatedAllocation || prefersDedicatedAllocation, dedicatedBuffer, dedicatedBufferUsage, dedicatedImage, createInfoFinal, - blockVector.GetMemoryTypeIndex(), + memTypeIndex, suballocType, - createInfoFinal.pool->m_DedicatedAllocations, - blockVector, + dedicatedAllocations, + *blockVector, allocationCount, pAllocations); - } - else - { - // Bit mask of memory Vulkan types acceptable for this allocation. - uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; - uint32_t memTypeIndex = UINT32_MAX; - res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); - // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. - if(res != VK_SUCCESS) - return res; - do - { - VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex]; - VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); - res = AllocateMemoryOfType( - VK_NULL_HANDLE, - vkMemReq.size, - vkMemReq.alignment, - requiresDedicatedAllocation || prefersDedicatedAllocation, - dedicatedBuffer, - dedicatedBufferUsage, - dedicatedImage, - createInfoFinal, - memTypeIndex, - suballocType, - m_DedicatedAllocations[memTypeIndex], - *blockVector, - allocationCount, - pAllocations); - // Allocation succeeded - if(res == VK_SUCCESS) - return VK_SUCCESS; + // Allocation succeeded + if(res == VK_SUCCESS) + return VK_SUCCESS; - // Remove old memTypeIndex from list of possibilities. - memoryTypeBits &= ~(1u << memTypeIndex); - // Find alternative memTypeIndex. - res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); - } while(res == VK_SUCCESS); + // Remove old memTypeIndex from list of possibilities. + memoryTypeBits &= ~(1u << memTypeIndex); + // Find alternative memTypeIndex. + res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); + } while(res == VK_SUCCESS); - // No other matching memory type index could be found. - // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } + // No other matching memory type index could be found. + // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. + return VK_ERROR_OUT_OF_DEVICE_MEMORY; } void VmaAllocator_T::FreeMemory( @@ -15515,16 +15521,16 @@ void VmaAllocator_T::FreeMemory( { VmaBlockVector* pBlockVector = VMA_NULL; VmaPool hPool = allocation->GetParentPool(); + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); if(hPool != VK_NULL_HANDLE) { - pBlockVector = &hPool->m_BlockVector; + pBlockVector = hPool->m_pBlockVectors[memTypeIndex]; } else { - const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); pBlockVector = m_pBlockVectors[memTypeIndex]; - VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); } + VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); pBlockVector->Free(allocation); } break; @@ -15564,11 +15570,17 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats) VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { - VmaBlockVector& blockVector = pool->m_BlockVector; - blockVector.AddStats(pStats); - const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); - const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); - pool->m_DedicatedAllocations.AddStats(pStats, memTypeIndex, memHeapIndex); + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + if (pool->m_pBlockVectors[memTypeIndex]) + { + VmaBlockVector& blockVector = *pool->m_pBlockVectors[memTypeIndex]; + blockVector.AddStats(pStats); + const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); + const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + pool->m_DedicatedAllocations[memTypeIndex].AddStats(pStats, memTypeIndex, memHeapIndex); + } + } } } @@ -15720,27 +15732,26 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo { return VK_ERROR_INITIALIZATION_FAILED; } - // Memory type index out of range or forbidden. - if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || - ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0) - { - return VK_ERROR_FEATURE_NOT_PRESENT; - } if(newCreateInfo.minAllocationAlignment > 0) { VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment)); } - const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex); - - *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize); + *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo); - VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks(); - if(res != VK_SUCCESS) + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - vma_delete(this, *pPool); - *pPool = VMA_NULL; - return res; + // Create only supported types + if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) + { + VkResult res = (*pPool)->m_pBlockVectors[memTypeIndex]->CreateMinBlocks(); + if(res != VK_SUCCESS) + { + vma_delete(this, *pPool); + *pPool = VMA_NULL; + return res; + } + } } // Add to m_Pools. @@ -15772,8 +15783,14 @@ void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats) pPoolStats->unusedRangeCount = 0; pPoolStats->blockCount = 0; - pool->m_BlockVector.AddPoolStats(pPoolStats); - pool->m_DedicatedAllocations.AddPoolStats(pPoolStats); + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) + { + pool->m_pBlockVectors[memTypeIndex]->AddPoolStats(pPoolStats); + pool->m_DedicatedAllocations[memTypeIndex].AddPoolStats(pPoolStats); + } + } } void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) @@ -15790,7 +15807,13 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool) { - return hPool->m_BlockVector.CheckCorruption(); + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) + { + return hPool->m_pBlockVectors[memTypeIndex]->CheckCorruption(); + } + } } VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) @@ -15822,18 +15845,21 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { - if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - VkResult localRes = pool->m_BlockVector.CheckCorruption(); - switch(localRes) + if(pool->m_pBlockVectors[memTypeIndex] && ((1u << memTypeIndex) & memoryTypeBits) != 0) { - case VK_ERROR_FEATURE_NOT_PRESENT: - break; - case VK_SUCCESS: - finalRes = VK_SUCCESS; - break; - default: - return localRes; + VkResult localRes = pool->m_pBlockVectors[memTypeIndex]->CheckCorruption(); + switch(localRes) + { + case VK_ERROR_FEATURE_NOT_PRESENT: + break; + case VK_SUCCESS: + finalRes = VK_SUCCESS; + break; + default: + return localRes; + } } } } @@ -16155,7 +16181,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation) else { // Custom pool - parentPool->m_DedicatedAllocations.Unregister(allocation); + parentPool->m_DedicatedAllocations[memTypeIndex].Unregister(allocation); } VkDeviceMemory hMemory = allocation->GetMemory(); @@ -16430,12 +16456,18 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) json.EndString(); json.BeginObject(); - pool->m_BlockVector.PrintDetailedMap(json); - - if (!pool->m_DedicatedAllocations.IsEmpty()) + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - json.WriteString("DedicatedAllocations"); - pool->m_DedicatedAllocations.BuildStatsString(json); + if (pool->m_pBlockVectors[memTypeIndex]) + { + pool->m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json); + } + + if (!pool->m_DedicatedAllocations[memTypeIndex].IsEmpty()) + { + json.WriteString("DedicatedAllocations"); + pool->m_DedicatedAllocations->BuildStatsString(json); + } } json.EndObject(); } |