mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
synced 2024-11-26 00:24:35 +00:00
Changed behavior of debug margin to create distinct blocks instead of identifying them by size and free status.
Code by @medranSolus
This commit is contained in:
parent
51c8b56011
commit
4b01ef07ef
@ -9988,8 +9988,11 @@ private:
|
|||||||
|
|
||||||
void MarkFree() { prevFree = VMA_NULL; }
|
void MarkFree() { prevFree = VMA_NULL; }
|
||||||
void MarkTaken() { prevFree = this; }
|
void MarkTaken() { prevFree = this; }
|
||||||
bool IsFree() const { return prevFree != this; }
|
void MarkMargin() { prevFree = reinterpret_cast<Block*>(UINTPTR_MAX); }
|
||||||
void*& UserData() { VMA_HEAVY_ASSERT(!IsFree()); return userData; }
|
bool IsFree() const { return !IsTaken() && !IsMargin(); }
|
||||||
|
bool IsTaken() const { return prevFree == this; }
|
||||||
|
bool IsMargin() const { return prevFree == reinterpret_cast<Block*>(UINTPTR_MAX); }
|
||||||
|
void*& UserData() { VMA_HEAVY_ASSERT(IsTaken()); return userData; }
|
||||||
Block*& PrevFree() { return prevFree; }
|
Block*& PrevFree() { return prevFree; }
|
||||||
Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; }
|
Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; }
|
||||||
|
|
||||||
@ -10154,8 +10157,7 @@ bool VmaBlockMetadata_TLSF::Validate() const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++allocCount;
|
// Check if taken or margin block is not on a free list
|
||||||
// Check if taken block is not on a free list
|
|
||||||
Block* freeBlock = m_FreeList[listIndex];
|
Block* freeBlock = m_FreeList[listIndex];
|
||||||
while (freeBlock)
|
while (freeBlock)
|
||||||
{
|
{
|
||||||
@ -10163,9 +10165,22 @@ bool VmaBlockMetadata_TLSF::Validate() const
|
|||||||
freeBlock = freeBlock->NextFree();
|
freeBlock = freeBlock->NextFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsVirtual())
|
if (prev->IsMargin())
|
||||||
{
|
{
|
||||||
VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size));
|
// Margin block belongs to free block category,
|
||||||
|
// but is not granted seat on the free list
|
||||||
|
++freeCount;
|
||||||
|
calculatedFreeSize += prev->size;
|
||||||
|
VMA_VALIDATE(prev->prevPhysical != VMA_NULL);
|
||||||
|
VMA_VALIDATE(prev->prevPhysical->IsTaken());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++allocCount;
|
||||||
|
if (!IsVirtual())
|
||||||
|
{
|
||||||
|
VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10198,10 +10213,10 @@ void VmaBlockMetadata_TLSF::AddDetailedStatistics(VmaDetailedStatistics& inoutSt
|
|||||||
|
|
||||||
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
||||||
{
|
{
|
||||||
if (block->IsFree())
|
if (block->IsTaken())
|
||||||
VmaAddDetailedStatisticsUnusedRange(inoutStats, block->size);
|
|
||||||
else
|
|
||||||
VmaAddDetailedStatisticsAllocation(inoutStats, block->size);
|
VmaAddDetailedStatisticsAllocation(inoutStats, block->size);
|
||||||
|
else
|
||||||
|
VmaAddDetailedStatisticsUnusedRange(inoutStats, block->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10239,10 +10254,10 @@ void VmaBlockMetadata_TLSF::PrintDetailedMap(class VmaJsonWriter& json) const
|
|||||||
for (; i < blockCount; ++i)
|
for (; i < blockCount; ++i)
|
||||||
{
|
{
|
||||||
Block* block = blockList[i];
|
Block* block = blockList[i];
|
||||||
if (block->IsFree())
|
if (block->IsTaken())
|
||||||
PrintDetailedMap_UnusedRange(json, block->offset, block->size);
|
|
||||||
else
|
|
||||||
PrintDetailedMap_Allocation(json, block->offset, block->size, block->UserData());
|
PrintDetailedMap_Allocation(json, block->offset, block->size, block->UserData());
|
||||||
|
else
|
||||||
|
PrintDetailedMap_UnusedRange(json, block->offset, block->size);
|
||||||
}
|
}
|
||||||
if (m_NullBlock->size > 0)
|
if (m_NullBlock->size > 0)
|
||||||
PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size);
|
PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size);
|
||||||
@ -10417,7 +10432,7 @@ VkResult VmaBlockMetadata_TLSF::CheckCorruption(const void* pBlockData)
|
|||||||
{
|
{
|
||||||
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
||||||
{
|
{
|
||||||
if (!block->IsFree())
|
if (block->IsTaken())
|
||||||
{
|
{
|
||||||
if (!VmaValidateMagicValue(pBlockData, block->offset + block->size))
|
if (!VmaValidateMagicValue(pBlockData, block->offset + block->size))
|
||||||
{
|
{
|
||||||
@ -10446,7 +10461,6 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
if (currentBlock != m_NullBlock)
|
if (currentBlock != m_NullBlock)
|
||||||
RemoveFreeBlock(currentBlock);
|
RemoveFreeBlock(currentBlock);
|
||||||
|
|
||||||
VkDeviceSize debugMargin = GetDebugMargin();
|
|
||||||
VkDeviceSize misssingAlignment = offset - currentBlock->offset;
|
VkDeviceSize misssingAlignment = offset - currentBlock->offset;
|
||||||
|
|
||||||
// Append missing alignment to prev block or create new one
|
// Append missing alignment to prev block or create new one
|
||||||
@ -10455,7 +10469,7 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
Block* prevBlock = currentBlock->prevPhysical;
|
Block* prevBlock = currentBlock->prevPhysical;
|
||||||
VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!");
|
VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!");
|
||||||
|
|
||||||
if (prevBlock->IsFree() && prevBlock->size != debugMargin)
|
if (prevBlock->IsFree())
|
||||||
{
|
{
|
||||||
uint32_t oldList = GetListIndex(prevBlock->size);
|
uint32_t oldList = GetListIndex(prevBlock->size);
|
||||||
prevBlock->size += misssingAlignment;
|
prevBlock->size += misssingAlignment;
|
||||||
@ -10488,6 +10502,7 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
currentBlock->offset += misssingAlignment;
|
currentBlock->offset += misssingAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkDeviceSize debugMargin = GetDebugMargin();
|
||||||
VkDeviceSize size = request.size + debugMargin;
|
VkDeviceSize size = request.size + debugMargin;
|
||||||
if (currentBlock->size == size)
|
if (currentBlock->size == size)
|
||||||
{
|
{
|
||||||
@ -10544,10 +10559,13 @@ void VmaBlockMetadata_TLSF::Alloc(
|
|||||||
newBlock->offset = currentBlock->offset + currentBlock->size;
|
newBlock->offset = currentBlock->offset + currentBlock->size;
|
||||||
newBlock->prevPhysical = currentBlock;
|
newBlock->prevPhysical = currentBlock;
|
||||||
newBlock->nextPhysical = currentBlock->nextPhysical;
|
newBlock->nextPhysical = currentBlock->nextPhysical;
|
||||||
newBlock->MarkTaken();
|
newBlock->MarkMargin();
|
||||||
currentBlock->nextPhysical->prevPhysical = newBlock;
|
currentBlock->nextPhysical->prevPhysical = newBlock;
|
||||||
currentBlock->nextPhysical = newBlock;
|
currentBlock->nextPhysical = newBlock;
|
||||||
InsertFreeBlock(newBlock);
|
// Count margin block into stats, but don't place it on free list
|
||||||
|
// as it will never be selected for allocation
|
||||||
|
++m_BlocksFreeCount;
|
||||||
|
m_BlocksFreeSize += debugMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsVirtual())
|
if (!IsVirtual())
|
||||||
@ -10560,7 +10578,7 @@ void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle)
|
|||||||
{
|
{
|
||||||
Block* block = (Block*)allocHandle;
|
Block* block = (Block*)allocHandle;
|
||||||
Block* next = block->nextPhysical;
|
Block* next = block->nextPhysical;
|
||||||
VMA_ASSERT(!block->IsFree() && "Block is already free!");
|
VMA_ASSERT(block->IsTaken() && "Block is already free or margin!");
|
||||||
|
|
||||||
if (!IsVirtual())
|
if (!IsVirtual())
|
||||||
m_GranularityHandler.FreePages(block->offset, block->size);
|
m_GranularityHandler.FreePages(block->offset, block->size);
|
||||||
@ -10569,7 +10587,9 @@ void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle)
|
|||||||
VkDeviceSize debugMargin = GetDebugMargin();
|
VkDeviceSize debugMargin = GetDebugMargin();
|
||||||
if (debugMargin > 0)
|
if (debugMargin > 0)
|
||||||
{
|
{
|
||||||
RemoveFreeBlock(next);
|
// Adjust stats for one less block
|
||||||
|
--m_BlocksFreeCount;
|
||||||
|
m_BlocksFreeSize -= block->size;
|
||||||
MergeBlock(next, block);
|
MergeBlock(next, block);
|
||||||
block = next;
|
block = next;
|
||||||
next = next->nextPhysical;
|
next = next->nextPhysical;
|
||||||
@ -10598,7 +10618,7 @@ void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle)
|
|||||||
void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
|
void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
|
||||||
{
|
{
|
||||||
Block* block = (Block*)allocHandle;
|
Block* block = (Block*)allocHandle;
|
||||||
VMA_ASSERT(!block->IsFree() && "Cannot get allocation info for free block!");
|
VMA_ASSERT(block->IsTaken() && "Cannot get allocation info for not taken block!");
|
||||||
outInfo.offset = block->offset;
|
outInfo.offset = block->offset;
|
||||||
outInfo.size = block->size;
|
outInfo.size = block->size;
|
||||||
outInfo.pUserData = block->UserData();
|
outInfo.pUserData = block->UserData();
|
||||||
@ -10607,7 +10627,7 @@ void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVir
|
|||||||
void* VmaBlockMetadata_TLSF::GetAllocationUserData(VmaAllocHandle allocHandle) const
|
void* VmaBlockMetadata_TLSF::GetAllocationUserData(VmaAllocHandle allocHandle) const
|
||||||
{
|
{
|
||||||
Block* block = (Block*)allocHandle;
|
Block* block = (Block*)allocHandle;
|
||||||
VMA_ASSERT(!block->IsFree() && "Cannot get user data for free block!");
|
VMA_ASSERT(block->IsTaken() && "Cannot get user data for not taken block!");
|
||||||
return block->UserData();
|
return block->UserData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10618,7 +10638,7 @@ VmaAllocHandle VmaBlockMetadata_TLSF::GetAllocationListBegin() const
|
|||||||
|
|
||||||
for (Block* block = m_NullBlock->prevPhysical; block; block = block->prevPhysical)
|
for (Block* block = m_NullBlock->prevPhysical; block; block = block->prevPhysical)
|
||||||
{
|
{
|
||||||
if (!block->IsFree())
|
if (block->IsTaken())
|
||||||
return (VmaAllocHandle)block;
|
return (VmaAllocHandle)block;
|
||||||
}
|
}
|
||||||
VMA_ASSERT(false && "If m_AllocCount > 0 then should find any allocation!");
|
VMA_ASSERT(false && "If m_AllocCount > 0 then should find any allocation!");
|
||||||
@ -10628,11 +10648,11 @@ VmaAllocHandle VmaBlockMetadata_TLSF::GetAllocationListBegin() const
|
|||||||
VmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc) const
|
VmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc) const
|
||||||
{
|
{
|
||||||
Block* startBlock = (Block*)prevAlloc;
|
Block* startBlock = (Block*)prevAlloc;
|
||||||
VMA_ASSERT(!startBlock->IsFree() && "Incorrect block!");
|
VMA_ASSERT(startBlock->IsTaken() && "Incorrect block!");
|
||||||
|
|
||||||
for (Block* block = startBlock->prevPhysical; block; block = block->prevPhysical)
|
for (Block* block = startBlock->prevPhysical; block; block = block->prevPhysical)
|
||||||
{
|
{
|
||||||
if (!block->IsFree())
|
if (block->IsTaken())
|
||||||
return (VmaAllocHandle)block;
|
return (VmaAllocHandle)block;
|
||||||
}
|
}
|
||||||
return VK_NULL_HANDLE;
|
return VK_NULL_HANDLE;
|
||||||
@ -10641,7 +10661,7 @@ VmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc
|
|||||||
VkDeviceSize VmaBlockMetadata_TLSF::GetNextFreeRegionSize(VmaAllocHandle alloc) const
|
VkDeviceSize VmaBlockMetadata_TLSF::GetNextFreeRegionSize(VmaAllocHandle alloc) const
|
||||||
{
|
{
|
||||||
Block* block = (Block*)alloc;
|
Block* block = (Block*)alloc;
|
||||||
VMA_ASSERT(!block->IsFree() && "Incorrect block!");
|
VMA_ASSERT(block->IsTaken() && "Incorrect block!");
|
||||||
|
|
||||||
if (block->prevPhysical)
|
if (block->prevPhysical)
|
||||||
return block->prevPhysical->IsFree() ? block->prevPhysical->size : 0;
|
return block->prevPhysical->IsFree() ? block->prevPhysical->size : 0;
|
||||||
@ -10672,14 +10692,14 @@ void VmaBlockMetadata_TLSF::Clear()
|
|||||||
void VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
|
void VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
|
||||||
{
|
{
|
||||||
Block* block = (Block*)allocHandle;
|
Block* block = (Block*)allocHandle;
|
||||||
VMA_ASSERT(!block->IsFree() && "Trying to set user data for not allocated block!");
|
VMA_ASSERT(block->IsTaken() && "Trying to set user data for not allocated block!");
|
||||||
block->UserData() = userData;
|
block->UserData() = userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaBlockMetadata_TLSF::DebugLogAllAllocations() const
|
void VmaBlockMetadata_TLSF::DebugLogAllAllocations() const
|
||||||
{
|
{
|
||||||
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
|
||||||
if (!block->IsFree())
|
if (block->IsTaken())
|
||||||
DebugLogAllocation(block->offset, block->size, block->UserData());
|
DebugLogAllocation(block->offset, block->size, block->UserData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3943,10 +3943,6 @@ void TestHeapSizeLimit()
|
|||||||
vmaDestroyAllocator(hAllocator);
|
vmaDestroyAllocator(hAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef VMA_DEBUG_MARGIN
|
|
||||||
#define VMA_DEBUG_MARGIN (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void TestDebugMargin()
|
static void TestDebugMargin()
|
||||||
{
|
{
|
||||||
if(VMA_DEBUG_MARGIN == 0)
|
if(VMA_DEBUG_MARGIN == 0)
|
||||||
@ -3990,7 +3986,7 @@ static void TestDebugMargin()
|
|||||||
const bool isLast = allocIndex == BUF_COUNT - 1;
|
const bool isLast = allocIndex == BUF_COUNT - 1;
|
||||||
bufInfo.size = (VkDeviceSize)(allocIndex + 1) * 256;
|
bufInfo.size = (VkDeviceSize)(allocIndex + 1) * 256;
|
||||||
// Last one will be mapped.
|
// Last one will be mapped.
|
||||||
allocCreateInfo.flags = isLast ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
|
allocCreateInfo.flags = isLast ? VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT : 0;
|
||||||
|
|
||||||
VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buffers[allocIndex].Buffer, &buffers[allocIndex].Allocation, &allocInfo[allocIndex]);
|
VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buffers[allocIndex].Buffer, &buffers[allocIndex].Allocation, &allocInfo[allocIndex]);
|
||||||
TEST(res == VK_SUCCESS);
|
TEST(res == VK_SUCCESS);
|
||||||
|
Loading…
Reference in New Issue
Block a user