summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2022-02-12 12:47:08 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2022-02-12 12:47:08 +0100
commit4e6c9d3ae979f2eb0151cf581fe61d2f3194ea72 (patch)
tree91a5316d207c8fcad76d24864f9ddef5c0ecfe50 /thirdparty
parent648a10514bfd574eebcd332ff5b672659ead5850 (diff)
Add a separate pool for small allocations in Vulkan RD
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/vulkan/patches/03-VMA-universal-pools.patch567
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.h346
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();
}