VmaBlockMetadata_Buddy: Added respecting of allocation alignment.

This commit is contained in:
Adam Sawicki 2018-09-21 14:57:24 +02:00
parent a01d4587df
commit 9933c5cadf
2 changed files with 44 additions and 11 deletions

View File

@ -4168,6 +4168,23 @@ static void BasicTestBuddyAllocator()
assert(res == VK_SUCCESS); assert(res == VK_SUCCESS);
bufInfo.push_back(newBufInfo); 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 = {}; VmaPoolStats stats = {};
vmaGetPoolStats(g_hAllocator, pool, &stats); vmaGetPoolStats(g_hAllocator, pool, &stats);
int DBG = 0; // Set breakpoint here to inspect `stats`. int DBG = 0; // Set breakpoint here to inspect `stats`.

View File

@ -9400,14 +9400,19 @@ bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
const uint32_t targetLevel = AllocSizeToLevel(allocSize); const uint32_t targetLevel = AllocSizeToLevel(allocSize);
for(uint32_t level = targetLevel + 1; level--; ) 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; if(freeNode->offset % allocAlignment == 0)
pAllocationRequest->sumFreeSize = LevelToNodeSize(level); {
pAllocationRequest->sumItemSize = 0; pAllocationRequest->offset = freeNode->offset;
pAllocationRequest->itemsToMakeLostCount = 0; pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
pAllocationRequest->customData = (void*)(uintptr_t)level; pAllocationRequest->sumItemSize = 0;
return true; pAllocationRequest->itemsToMakeLostCount = 0;
pAllocationRequest->customData = (void*)(uintptr_t)level;
return true;
}
} }
} }
@ -9444,10 +9449,14 @@ void VmaBlockMetadata_Buddy::Alloc(
{ {
const uint32_t targetLevel = AllocSizeToLevel(allocSize); const uint32_t targetLevel = AllocSizeToLevel(allocSize);
uint32_t currLevel = (uint32_t)(uintptr_t)request.customData; uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
VMA_ASSERT(m_FreeList[currLevel].front != VMA_NULL);
Node* currNode = m_FreeList[currLevel].front; Node* currNode = m_FreeList[currLevel].front;
VMA_ASSERT(currNode->type == Node::TYPE_FREE); VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
VMA_ASSERT(currNode->offset == request.offset); while(currNode->offset != request.offset)
{
currNode = currNode->free.next;
VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
}
// Go down, splitting free nodes. // Go down, splitting free nodes.
while(currLevel < targetLevel) while(currLevel < targetLevel)
@ -9484,10 +9493,17 @@ void VmaBlockMetadata_Buddy::Alloc(
//m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2. //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
++currLevel; ++currLevel;
currNode = m_FreeList[currLevel].front; 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. // 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); RemoveFromFreeList(currLevel, currNode);
// Convert to allocation node. // Convert to allocation node.