Merge branch 'master' into feature-small-buffers
diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h
index 47f79db..71f8990 100644
--- a/include/vk_mem_alloc.h
+++ b/include/vk_mem_alloc.h
@@ -7262,6 +7262,8 @@
#endif
};
+struct VmaBlockVector;
+
/*
Represents a single block of device memory (`VkDeviceMemory`) with all the
data about its regions (aka suballocations, #VmaAllocation), assigned and free.
@@ -7285,6 +7287,7 @@
// Always call after construction.
void Init(
VmaAllocator hAllocator,
+ VmaBlockVector* parentBlockVector,
VmaPool hParentPool,
uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory,
@@ -7294,6 +7297,7 @@
// Always call before destruction.
void Destroy(VmaAllocator allocator);
+ VmaBlockVector* GetParentBlockVector() const { return m_ParentBlockVector; }
VmaPool GetParentPool() const { return m_hParentPool; }
VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
@@ -7326,10 +7330,11 @@
const void* pNext);
private:
- VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
- uint32_t m_MemoryTypeIndex;
- uint32_t m_Id;
- VkDeviceMemory m_hMemory;
+ VmaBlockVector* m_ParentBlockVector = VMA_NULL;
+ VmaPool m_hParentPool = VK_NULL_HANDLE; // VK_NULL_HANDLE if not belongs to custom pool.
+ uint32_t m_MemoryTypeIndex = UINT32_MAX;
+ uint32_t m_Id = 0;
+ VkDeviceMemory m_hMemory = VK_NULL_HANDLE;
/*
Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
@@ -7337,8 +7342,8 @@
Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
*/
VMA_MUTEX m_Mutex;
- uint32_t m_MapCount;
- void* m_pMappedData;
+ uint32_t m_MapCount = 0;
+ void* m_pMappedData = VMA_NULL;
};
struct VmaDefragmentationMove
@@ -8235,6 +8240,7 @@
// Default pools.
VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
+ VmaBlockVector* m_pSmallBufferBlockVectors[VK_MAX_MEMORY_TYPES];
typedef VmaIntrusiveLinkedList<VmaDedicatedAllocationListItemTraits> DedicatedAllocationLinkedList;
DedicatedAllocationLinkedList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];
@@ -12656,18 +12662,13 @@
////////////////////////////////////////////////////////////////////////////////
// class VmaDeviceMemoryBlock
-VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
- m_pMetadata(VMA_NULL),
- m_MemoryTypeIndex(UINT32_MAX),
- m_Id(0),
- m_hMemory(VK_NULL_HANDLE),
- m_MapCount(0),
- m_pMappedData(VMA_NULL)
+VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)
{
}
void VmaDeviceMemoryBlock::Init(
VmaAllocator hAllocator,
+ VmaBlockVector* parentBlockVector,
VmaPool hParentPool,
uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory,
@@ -12675,8 +12676,10 @@
uint32_t id,
uint32_t algorithm)
{
+ VMA_ASSERT(parentBlockVector != VMA_NULL);
VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+ m_ParentBlockVector = parentBlockVector;
m_hParentPool = hParentPool;
m_MemoryTypeIndex = newMemoryTypeIndex;
m_Id = id;
@@ -13485,6 +13488,8 @@
void VmaBlockVector::Free(
const VmaAllocation hAllocation)
{
+ VMA_ASSERT(hAllocation->GetBlock()->GetParentBlockVector() == this);
+
VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
bool budgetExceeded = false;
@@ -13717,6 +13722,7 @@
VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
pBlock->Init(
m_hAllocator,
+ this, // parentBlockVector
m_hParentPool,
m_MemoryTypeIndex,
mem,
@@ -16146,6 +16152,7 @@
memset(&m_MemProps, 0, sizeof(m_MemProps));
memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
+ memset(&m_pSmallBufferBlockVectors, 0, sizeof(m_pSmallBufferBlockVectors));
memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));
#if VMA_EXTERNAL_MEMORY
@@ -16216,6 +16223,20 @@
0.5f, // priority (0.5 is the default per Vulkan spec)
GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment
VMA_NULL); // // pMemoryAllocateNext
+ m_pSmallBufferBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
+ this,
+ VK_NULL_HANDLE, // hParentPool
+ memTypeIndex,
+ preferredBlockSize,
+ 0,
+ SIZE_MAX,
+ 1, // bufferImageGranularity forced to 1 !!!
+ pCreateInfo->frameInUseCount,
+ false, // explicitBlockSize
+ false, // linearAlgorithm
+ 0.5f, // priority (0.5 is the default per Vulkan spec)
+ GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment
+ VMA_NULL); // // pMemoryAllocateNext
// No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
// becase minBlockCount is 0.
}
@@ -16279,6 +16300,7 @@
VMA_ASSERT(0 && "Unfreed dedicated allocations found.");
}
+ vma_delete(this, m_pSmallBufferBlockVectors[memTypeIndex]);
vma_delete(this, m_pBlockVectors[memTypeIndex]);
}
}
@@ -16534,7 +16556,8 @@
finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
}
- VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex];
+ bool isSmallBuffer = dedicatedBuffer != VK_NULL_HANDLE && size <= 4096; // TODO
+ VmaBlockVector* const blockVector = isSmallBuffer ? m_pSmallBufferBlockVectors[memTypeIndex] : m_pBlockVectors[memTypeIndex];
VMA_ASSERT(blockVector);
const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
@@ -17071,8 +17094,7 @@
}
else
{
- const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
- pBlockVector = m_pBlockVectors[memTypeIndex];
+ pBlockVector = allocation->GetBlock()->GetParentBlockVector();
}
pBlockVector->Free(allocation);
}
@@ -17108,6 +17130,10 @@
VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
VMA_ASSERT(pBlockVector);
pBlockVector->AddStats(pStats);
+
+ VmaBlockVector* const pSmallBufferBlockVector = m_pSmallBufferBlockVectors[memTypeIndex];
+ VMA_ASSERT(pSmallBufferBlockVector);
+ pSmallBufferBlockVector->AddStats(pStats);
}
// Process custom pools.
@@ -18105,6 +18131,7 @@
json.EndObject();
}
+ // Default pools
{
bool allocationsStarted = false;
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
@@ -18131,6 +18158,33 @@
}
}
+ // Small buffer pools
+ {
+ bool allocationsStarted = false;
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ if(m_pSmallBufferBlockVectors[memTypeIndex]->IsEmpty() == false)
+ {
+ if(allocationsStarted == false)
+ {
+ allocationsStarted = true;
+ json.WriteString("SmallBufferPools");
+ json.BeginObject();
+ }
+
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+
+ m_pSmallBufferBlockVectors[memTypeIndex]->PrintDetailedMap(json);
+ }
+ }
+ if(allocationsStarted)
+ {
+ json.EndObject();
+ }
+ }
+
// Custom pools
{
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);