VmaBlockMetadata_Buddy: Added respecting of allocation alignment.
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 9286c5c..9f9a6da 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -4168,6 +4168,23 @@
assert(res == VK_SUCCESS);
bufInfo.push_back(newBufInfo);
+ // Test some small allocation with alignment requirement.
+ {
+ VkMemoryRequirements memReq;
+ memReq.alignment = 256;
+ memReq.memoryTypeBits = UINT32_MAX;
+ memReq.size = 32;
+
+ newBufInfo.Buffer = VK_NULL_HANDLE;
+ res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo,
+ &newBufInfo.Allocation, &allocInfo);
+ assert(res == VK_SUCCESS);
+ assert(allocInfo.offset % memReq.alignment == 0);
+ bufInfo.push_back(newBufInfo);
+ }
+
+ //SaveAllocatorStatsToFile(L"TEST.json");
+
VmaPoolStats stats = {};
vmaGetPoolStats(g_hAllocator, pool, &stats);
int DBG = 0; // Set breakpoint here to inspect `stats`.
diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h
index 41a5a92..a11e654 100644
--- a/src/vk_mem_alloc.h
+++ b/src/vk_mem_alloc.h
@@ -9400,14 +9400,19 @@
const uint32_t targetLevel = AllocSizeToLevel(allocSize);
for(uint32_t level = targetLevel + 1; level--; )
{
- if(m_FreeList[level].front != VMA_NULL)
+ for(Node* freeNode = m_FreeList[level].front;
+ freeNode != VMA_NULL;
+ freeNode = freeNode->free.next)
{
- pAllocationRequest->offset = m_FreeList[level].front->offset;
- pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
- pAllocationRequest->sumItemSize = 0;
- pAllocationRequest->itemsToMakeLostCount = 0;
- pAllocationRequest->customData = (void*)(uintptr_t)level;
- return true;
+ if(freeNode->offset % allocAlignment == 0)
+ {
+ pAllocationRequest->offset = freeNode->offset;
+ pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
+ pAllocationRequest->sumItemSize = 0;
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->customData = (void*)(uintptr_t)level;
+ return true;
+ }
}
}
@@ -9444,10 +9449,14 @@
{
const uint32_t targetLevel = AllocSizeToLevel(allocSize);
uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
- VMA_ASSERT(m_FreeList[currLevel].front != VMA_NULL);
+
Node* currNode = m_FreeList[currLevel].front;
- VMA_ASSERT(currNode->type == Node::TYPE_FREE);
- VMA_ASSERT(currNode->offset == request.offset);
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ while(currNode->offset != request.offset)
+ {
+ currNode = currNode->free.next;
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ }
// Go down, splitting free nodes.
while(currLevel < targetLevel)
@@ -9484,10 +9493,17 @@
//m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
++currLevel;
currNode = m_FreeList[currLevel].front;
+
+ /*
+ We can be sure that currNode, as left child of node previously split,
+ also fullfills the alignment requirement.
+ */
}
// Remove from free list.
- VMA_ASSERT(currLevel == targetLevel && currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ VMA_ASSERT(currLevel == targetLevel &&
+ currNode != VMA_NULL &&
+ currNode->type == Node::TYPE_FREE);
RemoveFromFreeList(currLevel, currNode);
// Convert to allocation node.