Fix for out-of-bound accessing last free block in EXTENSIVE defragmentation algorithm.

Code by @medranSolus
See #232
This commit is contained in:
Adam Sawicki 2022-03-28 13:19:34 +02:00
parent 228a1b68ae
commit 35e1539161

View File

@ -13289,7 +13289,7 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo
VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]); VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]);
if (state.firstFreeBlock != SIZE_MAX) if (state.firstFreeBlock != SIZE_MAX)
{ {
if (i < state.firstFreeBlock - 1) if (i + 1 < state.firstFreeBlock)
{ {
if (state.firstFreeBlock > 1) if (state.firstFreeBlock > 1)
VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[--state.firstFreeBlock]); 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::FindFreeBlockTexture:
case StateExtensive::Operation::FindFreeBlockAll: 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 // No free blocks, have to clear last one
size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1; size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1;
VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata; VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata;
@ -13777,8 +13784,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto
} }
vectorState.firstFreeBlock = last; vectorState.firstFreeBlock = last;
// Nothing done, block found without reallocations, can perform another reallocs in same pass // Nothing done, block found without reallocations, can perform another reallocs in same pass
if (prevMoveCount == m_Moves.size()) return ComputeDefragmentation_Extensive(vector, index);
return ComputeDefragmentation_Extensive(vector, index);
} }
break; break;
} }