Skip to content

Commit 4f900cd

Browse files
Delete empty block unconditionally if budget is exceeded.
Also fixed crash when freeing lost allocation.
1 parent e6e3329 commit 4f900cd

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

src/vk_mem_alloc.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12149,6 +12149,14 @@ void VmaBlockVector::Free(
1214912149
{
1215012150
VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
1215112151

12152+
bool budgetExceeded = false;
12153+
{
12154+
const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
12155+
VmaBudget heapBudget = {};
12156+
m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
12157+
budgetExceeded = heapBudget.usage >= heapBudget.budget;
12158+
}
12159+
1215212160
// Scope for lock.
1215312161
{
1215412162
VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
@@ -12171,11 +12179,12 @@ void VmaBlockVector::Free(
1217112179

1217212180
VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex);
1217312181

12182+
const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount;
1217412183
// pBlock became empty after this deallocation.
1217512184
if(pBlock->m_pMetadata->IsEmpty())
1217612185
{
12177-
// Already has empty Allocation. We don't want to have two, so delete this one.
12178-
if(m_HasEmptyBlock && m_Blocks.size() > m_MinBlockCount)
12186+
// Already has empty block. We don't want to have two, so delete this one.
12187+
if((m_HasEmptyBlock || budgetExceeded) && canDeleteBlock)
1217912188
{
1218012189
pBlockToDelete = pBlock;
1218112190
Remove(pBlock);
@@ -12188,10 +12197,10 @@ void VmaBlockVector::Free(
1218812197
}
1218912198
// pBlock didn't become empty, but we have another empty block - find and free that one.
1219012199
// (This is optional, heuristics.)
12191-
else if(m_HasEmptyBlock)
12200+
else if(m_HasEmptyBlock && canDeleteBlock)
1219212201
{
1219312202
VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
12194-
if(pLastBlock->m_pMetadata->IsEmpty() && m_Blocks.size() > m_MinBlockCount)
12203+
if(pLastBlock->m_pMetadata->IsEmpty())
1219512204
{
1219612205
pBlockToDelete = pLastBlock;
1219712206
m_Blocks.pop_back();
@@ -12202,11 +12211,11 @@ void VmaBlockVector::Free(
1220212211
IncrementallySortBlocks();
1220312212
}
1220412213

12205-
// Destruction of a free Allocation. Deferred until this point, outside of mutex
12214+
// Destruction of a free block. Deferred until this point, outside of mutex
1220612215
// lock, for performance reason.
1220712216
if(pBlockToDelete != VMA_NULL)
1220812217
{
12209-
VMA_DEBUG_LOG(" Deleted empty allocation");
12218+
VMA_DEBUG_LOG(" Deleted empty block");
1221012219
pBlockToDelete->Destroy(m_hAllocator);
1221112220
vma_delete(m_hAllocator, pBlockToDelete);
1221212221
}
@@ -15223,8 +15232,11 @@ void VmaAllocator_T::FreeMemory(
1522315232
}
1522415233
}
1522515234

15226-
m_Budget.m_AllocationBytes[MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex())] -= allocation->GetSize();
15227-
++m_Budget.m_OperationsSinceBudgetFetch;
15235+
if(allocation->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)
15236+
{
15237+
m_Budget.m_AllocationBytes[MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex())] -= allocation->GetSize();
15238+
++m_Budget.m_OperationsSinceBudgetFetch;
15239+
}
1522815240
allocation->SetUserData(this, VMA_NULL);
1522915241
allocation->Dtor();
1523015242
m_AllocationObjectAllocator.Free(allocation);

0 commit comments

Comments
 (0)