| 12663 | } |
| 12664 | |
| 12665 | bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index) |
| 12666 | { |
| 12667 | // First free single block, then populate it to the brim, then free another block, and so on |
| 12668 | |
| 12669 | // Fallback to previous algorithm since without granularity conflicts it can achieve max packing |
| 12670 | if (vector.m_BufferImageGranularity == 1) |
| 12671 | return ComputeDefragmentation_Full(vector); |
| 12672 | |
| 12673 | VMA_ASSERT(m_AlgorithmState != VMA_NULL); |
| 12674 | |
| 12675 | StateExtensive& vectorState = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[index]; |
| 12676 | |
| 12677 | bool texturePresent = false; |
| 12678 | bool bufferPresent = false; |
| 12679 | bool otherPresent = false; |
| 12680 | switch (vectorState.operation) |
| 12681 | { |
| 12682 | case StateExtensive::Operation::Done: // Vector defragmented |
| 12683 | return false; |
| 12684 | case StateExtensive::Operation::FindFreeBlockBuffer: |
| 12685 | case StateExtensive::Operation::FindFreeBlockTexture: |
| 12686 | case StateExtensive::Operation::FindFreeBlockAll: |
| 12687 | { |
| 12688 | // No more blocks to free, just perform fast realloc and move to cleanup |
| 12689 | if (vectorState.firstFreeBlock == 0) |
| 12690 | { |
| 12691 | vectorState.operation = StateExtensive::Operation::Cleanup; |
| 12692 | return ComputeDefragmentation_Fast(vector); |
| 12693 | } |
| 12694 | |
| 12695 | // No free blocks, have to clear last one |
| 12696 | size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1; |
| 12697 | VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata; |
| 12698 | |
| 12699 | const size_t prevMoveCount = m_Moves.size(); |
| 12700 | for (VmaAllocHandle handle = freeMetadata->GetAllocationListBegin(); |
| 12701 | handle != VK_NULL_HANDLE; |
| 12702 | handle = freeMetadata->GetNextAllocation(handle)) |
| 12703 | { |
| 12704 | MoveAllocationData moveData = GetMoveData(handle, freeMetadata); |
| 12705 | switch (CheckCounters(moveData.move.srcAllocation->GetSize())) |
| 12706 | { |
| 12707 | case CounterStatus::Ignore: |
| 12708 | continue; |
| 12709 | case CounterStatus::End: |
| 12710 | return true; |
| 12711 | case CounterStatus::Pass: |
| 12712 | break; |
| 12713 | default: |
| 12714 | VMA_ASSERT(0); |
| 12715 | } |
| 12716 | |
| 12717 | // Check all previous blocks for free space |
| 12718 | if (AllocInOtherBlock(0, last, moveData, vector)) |
| 12719 | { |
| 12720 | // Full clear performed already |
| 12721 | if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE) |
| 12722 | vectorState.firstFreeBlock = last; |
nothing calls this directly
no test coverage detected