@@ -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