@@ -5784,7 +5784,8 @@ class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm
57845784 VmaDefragmentationAlgorithm_Generic(
57855785 VmaAllocator hAllocator,
57865786 VmaBlockVector* pBlockVector,
5787- uint32_t currentFrameIndex);
5787+ uint32_t currentFrameIndex,
5788+ bool overlappingMoveSupported);
57885789 virtual ~VmaDefragmentationAlgorithm_Generic();
57895790
57905791 virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
@@ -5910,7 +5911,8 @@ class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
59105911 VmaDefragmentationAlgorithm_Fast(
59115912 VmaAllocator hAllocator,
59125913 VmaBlockVector* pBlockVector,
5913- uint32_t currentFrameIndex);
5914+ uint32_t currentFrameIndex,
5915+ bool overlappingMoveSupported);
59145916 virtual ~VmaDefragmentationAlgorithm_Fast();
59155917
59165918 virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
@@ -5930,6 +5932,8 @@ class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
59305932 size_t origBlockIndex;
59315933 };
59325934
5935+ const bool m_OverlappingMoveSupported;
5936+
59335937 uint32_t m_AllocationCount;
59345938 bool m_AllAllocations;
59355939
@@ -5984,7 +5988,7 @@ class VmaBlockVectorDefragmentationContext
59845988 void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
59855989 void AddAll() { m_AllAllocations = true; }
59865990
5987- void Begin();
5991+ void Begin(bool overlappingMoveSupported );
59885992
59895993private:
59905994 const VmaAllocator m_hAllocator;
@@ -11602,7 +11606,7 @@ void VmaBlockVector::ApplyDefragmentationMovesCpu(
1160211606 }
1160311607
1160411608 // THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
11605- memcpy (
11609+ memmove (
1160611610 reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
1160711611 reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
1160811612 static_cast<size_t>(move.size));
@@ -11842,13 +11846,15 @@ void VmaBlockVector::Defragment(
1184211846 m_hAllocator->IsIntegratedGpu();
1184311847 }
1184411848
11849+ bool overlappingMoveSupported = !defragmentOnGpu;
11850+
1184511851 if(m_hAllocator->m_UseMutex)
1184611852 {
1184711853 m_Mutex.LockWrite();
1184811854 pCtx->mutexLocked = true;
1184911855 }
1185011856
11851- pCtx->Begin();
11857+ pCtx->Begin(overlappingMoveSupported );
1185211858
1185311859 // Defragment.
1185411860
@@ -12015,7 +12021,8 @@ void VmaBlockVector::AddStats(VmaStats* pStats)
1201512021VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
1201612022 VmaAllocator hAllocator,
1201712023 VmaBlockVector* pBlockVector,
12018- uint32_t currentFrameIndex) :
12024+ uint32_t currentFrameIndex,
12025+ bool overlappingMoveSupported) :
1201912026 VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
1202012027 m_AllAllocations(false),
1202112028 m_AllocationCount(0),
@@ -12307,8 +12314,10 @@ bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
1230712314VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
1230812315 VmaAllocator hAllocator,
1230912316 VmaBlockVector* pBlockVector,
12310- uint32_t currentFrameIndex) :
12317+ uint32_t currentFrameIndex,
12318+ bool overlappingMoveSupported) :
1231112319 VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
12320+ m_OverlappingMoveSupported(overlappingMoveSupported),
1231212321 m_AllocationCount(0),
1231312322 m_AllAllocations(false),
1231412323 m_BytesMoved(0),
@@ -12396,18 +12405,26 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
1239612405 // Same block
1239712406 if(dstBlockInfoIndex == srcBlockInfoIndex)
1239812407 {
12399- // Destination and source place overlap.
12400- if(dstAllocOffset + srcAllocSize > srcAllocOffset)
12408+ VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
12409+
12410+ const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
12411+
12412+ bool skipOver = overlap;
12413+ if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
12414+ {
12415+ // If destination and source place overlap, skip if it would move it
12416+ // by only < 1/64 of its size.
12417+ skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
12418+ }
12419+
12420+ if(skipOver)
1240112421 {
12402- // Just step over this allocation.
12403- // TODO: Support memmove() here.
1240412422 dstOffset = srcAllocOffset + srcAllocSize;
1240512423 ++srcSuballocIt;
1240612424 }
1240712425 // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
1240812426 else
1240912427 {
12410- VMA_ASSERT(dstAllocOffset < srcAllocOffset);
1241112428 srcSuballocIt->offset = dstAllocOffset;
1241212429 srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
1241312430 dstOffset = dstAllocOffset + srcAllocSize;
@@ -12604,7 +12621,7 @@ void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, V
1260412621 m_Allocations.push_back(info);
1260512622}
1260612623
12607- void VmaBlockVectorDefragmentationContext::Begin()
12624+ void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported )
1260812625{
1260912626 const bool allAllocations = m_AllAllocations ||
1261012627 m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
@@ -12624,12 +12641,12 @@ void VmaBlockVectorDefragmentationContext::Begin()
1262412641 !m_pBlockVector->IsBufferImageGranularityConflictPossible())
1262512642 {
1262612643 m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
12627- m_hAllocator, m_pBlockVector, m_CurrFrameIndex);
12644+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported );
1262812645 }
1262912646 else
1263012647 {
1263112648 m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
12632- m_hAllocator, m_pBlockVector, m_CurrFrameIndex);
12649+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported );
1263312650 }
1263412651
1263512652 if(allAllocations)
0 commit comments