Next small step: moved split logic from VmaBlockMetadata_Buddy::CreateAllocationRequest to VmaBlockMetadata_Buddy::Alloc.

This commit is contained in:
Adam Sawicki 2018-09-06 17:04:32 +02:00
parent a83793a63e
commit bf1a931a2d

View File

@ -4927,6 +4927,9 @@ private:
void CleanupAfterFree(); void CleanupAfterFree();
}; };
/*
Level 0 has block size = GetSize(). Level 1 has block size = GetSize() / 2 and so on...
*/
class VmaBlockMetadata_Buddy : public VmaBlockMetadata class VmaBlockMetadata_Buddy : public VmaBlockMetadata
{ {
VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy) VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
@ -9380,72 +9383,20 @@ bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
} }
const uint32_t targetLevel = AllocSizeToLevel(allocSize); const uint32_t targetLevel = AllocSizeToLevel(allocSize);
for(uint32_t level = targetLevel + 1; level--; )
// No free node with intended size.
if(m_FreeList[targetLevel] == VMA_NULL)
{ {
// Go up until we find free node with larget size. if(m_FreeList[level] != VMA_NULL)
uint32_t level = targetLevel;
while(m_FreeList[level] == VMA_NULL)
{ {
if(level == 0) pAllocationRequest->offset = m_FreeList[level]->offset;
{ pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
return false; pAllocationRequest->sumItemSize = 0;
} pAllocationRequest->itemsToMakeLostCount = 0;
--level; pAllocationRequest->customData = (void*)(uintptr_t)level;
} return true;
// Go down, splitting free nodes.
while(level < targetLevel)
{
// Get first free node at current level.
Node* node = m_FreeList[level];
// Remove it from list of free nodes at this level.
m_FreeList[level] = node->free.nextFree;
const uint32_t childrenLevel = level + 1;
// Create two free sub-nodes.
Node* leftChild = new Node();
Node* rightChild = new Node();
leftChild->offset = node->offset;
leftChild->type = Node::TYPE_FREE;
leftChild->parent = node;
leftChild->buddy = rightChild;
leftChild->free.nextFree = VMA_NULL;
rightChild->offset = node->offset + LevelToNodeSize(childrenLevel);
rightChild->type = Node::TYPE_FREE;
rightChild->parent = node;
rightChild->buddy = leftChild;
rightChild->free.nextFree = VMA_NULL;
// Convert current node to split type.
node->type = Node::TYPE_SPLIT;
node->split.leftChild = leftChild;
// Add child nodes to free list.
leftChild->free.nextFree = m_FreeList[childrenLevel];
m_FreeList[childrenLevel] = leftChild;
rightChild->free.nextFree = m_FreeList[childrenLevel];
m_FreeList[childrenLevel] = rightChild;
++level;
} }
} }
Node* freeNode = m_FreeList[targetLevel]; return false;
VMA_ASSERT(freeNode != VMA_NULL);
pAllocationRequest->offset = freeNode->offset;
// TODO
pAllocationRequest->sumFreeSize = 0;
pAllocationRequest->sumItemSize = 0;
pAllocationRequest->itemsToMakeLostCount = 0;
pAllocationRequest->customData = (void*)(uintptr_t)targetLevel;
return true;
} }
bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost( bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
@ -9473,17 +9424,60 @@ void VmaBlockMetadata_Buddy::Alloc(
bool upperAddress, bool upperAddress,
VmaAllocation hAllocation) VmaAllocation hAllocation)
{ {
const uint32_t targetLevel = (uint32_t)(uintptr_t)request.customData; const uint32_t targetLevel = AllocSizeToLevel(allocSize);
VMA_ASSERT(m_FreeList[targetLevel] != VMA_NULL); uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
Node* node = m_FreeList[targetLevel]; VMA_ASSERT(m_FreeList[currLevel] != VMA_NULL);
VMA_ASSERT(node->type == Node::TYPE_FREE); Node* currNode = m_FreeList[currLevel];
VMA_ASSERT(currNode->type == Node::TYPE_FREE);
VMA_ASSERT(currNode->offset == request.offset);
// Go down, splitting free nodes.
while(currLevel < targetLevel)
{
// currNode is already first free node at currLevel.
// Remove it from list of free nodes at this currLevel.
m_FreeList[currLevel] = currNode->free.nextFree;
const uint32_t childrenLevel = currLevel + 1;
// Create two free sub-nodes.
Node* leftChild = new Node();
Node* rightChild = new Node();
leftChild->offset = currNode->offset;
leftChild->type = Node::TYPE_FREE;
leftChild->parent = currNode;
leftChild->buddy = rightChild;
leftChild->free.nextFree = VMA_NULL;
rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel);
rightChild->type = Node::TYPE_FREE;
rightChild->parent = currNode;
rightChild->buddy = leftChild;
rightChild->free.nextFree = VMA_NULL;
// Convert current currNode to split type.
currNode->type = Node::TYPE_SPLIT;
currNode->split.leftChild = leftChild;
// Add child nodes to free list.
rightChild->free.nextFree = m_FreeList[childrenLevel];
m_FreeList[childrenLevel] = rightChild;
leftChild->free.nextFree = m_FreeList[childrenLevel];
m_FreeList[childrenLevel] = leftChild;
++currLevel;
currNode = m_FreeList[currLevel];
}
// Remove from free list. // Remove from free list.
m_FreeList[targetLevel] = node->free.nextFree; VMA_ASSERT(currLevel == targetLevel && currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
m_FreeList[targetLevel] = currNode->free.nextFree;
// Convert to allocation node. // Convert to allocation node.
node->type = Node::TYPE_ALLOCATION; currNode->type = Node::TYPE_ALLOCATION;
node->allocation.alloc = hAllocation; currNode->allocation.alloc = hAllocation;
} }
void VmaBlockMetadata_Buddy::Free(const VmaAllocation allocation) void VmaBlockMetadata_Buddy::Free(const VmaAllocation allocation)