Fix for out-of-bound accessing last free block in EXTENSIVE defragmentation algorithm.
Code by
See
@@ -13289,7 +13289,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]);
if (state.firstFreeBlock != SIZE_MAX)
{
- if (i < state.firstFreeBlock - 1)
+ if (i + 1 < state.firstFreeBlock)
{
if (state.firstFreeBlock > 1)
VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[--state.firstFreeBlock]);
@@ -13709,6 +13709,13 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto
case StateExtensive::Operation::FindFreeBlockTexture:
case StateExtensive::Operation::FindFreeBlockAll:
{
+ // No more blocks to free, just perform fast realloc and move to cleanup
+ if (vectorState.firstFreeBlock == 0)
+ {
+ vectorState.operation = StateExtensive::Operation::Cleanup;
+ return ComputeDefragmentation_Fast(vector);
+ }
+
// No free blocks, have to clear last one
size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1;
VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata;
@@ -13777,7 +13784,6 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto
}
vectorState.firstFreeBlock = last;
// Nothing done, block found without reallocations, can perform another reallocs in same pass
- if (prevMoveCount == m_Moves.size())
return ComputeDefragmentation_Extensive(vector, index);
}
break;
