mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
synced 2024-11-05 12:20:07 +00:00
VmaDefragmentationAlgorithm_Fast: Added support for memmove() of overlapping memory regions when defragmenting on CPU.
This commit is contained in:
parent
e168191f3d
commit
647cf24b7f
@ -1375,6 +1375,30 @@ void TestDefragmentationSimple()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Allocation that must be move to an overlapping place using memmove().
|
||||||
|
Create 2 buffers, second slightly bigger than the first. Delete first. Then defragment.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
AllocInfo allocInfo[2];
|
||||||
|
|
||||||
|
bufCreateInfo.size = BUF_SIZE;
|
||||||
|
CreateBuffer(pool, bufCreateInfo, false, allocInfo[0]);
|
||||||
|
const VkDeviceSize biggerBufSize = BUF_SIZE + BUF_SIZE / 256;
|
||||||
|
bufCreateInfo.size = biggerBufSize;
|
||||||
|
CreateBuffer(pool, bufCreateInfo, false, allocInfo[1]);
|
||||||
|
|
||||||
|
DestroyAllocation(allocInfo[0]);
|
||||||
|
|
||||||
|
VmaDefragmentationStats defragStats;
|
||||||
|
Defragment(&allocInfo[1], 1, nullptr, &defragStats);
|
||||||
|
// If this fails, it means we couldn't do memmove with overlapping regions.
|
||||||
|
TEST(defragStats.allocationsMoved == 1 && defragStats.bytesMoved > 0);
|
||||||
|
|
||||||
|
ValidateAllocationsData(&allocInfo[1], 1);
|
||||||
|
DestroyAllocation(allocInfo[1]);
|
||||||
|
}
|
||||||
|
|
||||||
vmaDestroyPool(g_hAllocator, pool);
|
vmaDestroyPool(g_hAllocator, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5784,7 +5784,8 @@ public:
|
|||||||
VmaDefragmentationAlgorithm_Generic(
|
VmaDefragmentationAlgorithm_Generic(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
VmaBlockVector* pBlockVector,
|
VmaBlockVector* pBlockVector,
|
||||||
uint32_t currentFrameIndex);
|
uint32_t currentFrameIndex,
|
||||||
|
bool overlappingMoveSupported);
|
||||||
virtual ~VmaDefragmentationAlgorithm_Generic();
|
virtual ~VmaDefragmentationAlgorithm_Generic();
|
||||||
|
|
||||||
virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
|
virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
|
||||||
@ -5910,7 +5911,8 @@ public:
|
|||||||
VmaDefragmentationAlgorithm_Fast(
|
VmaDefragmentationAlgorithm_Fast(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
VmaBlockVector* pBlockVector,
|
VmaBlockVector* pBlockVector,
|
||||||
uint32_t currentFrameIndex);
|
uint32_t currentFrameIndex,
|
||||||
|
bool overlappingMoveSupported);
|
||||||
virtual ~VmaDefragmentationAlgorithm_Fast();
|
virtual ~VmaDefragmentationAlgorithm_Fast();
|
||||||
|
|
||||||
virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
|
virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
|
||||||
@ -5930,6 +5932,8 @@ private:
|
|||||||
size_t origBlockIndex;
|
size_t origBlockIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bool m_OverlappingMoveSupported;
|
||||||
|
|
||||||
uint32_t m_AllocationCount;
|
uint32_t m_AllocationCount;
|
||||||
bool m_AllAllocations;
|
bool m_AllAllocations;
|
||||||
|
|
||||||
@ -5984,7 +5988,7 @@ public:
|
|||||||
void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
|
void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
|
||||||
void AddAll() { m_AllAllocations = true; }
|
void AddAll() { m_AllAllocations = true; }
|
||||||
|
|
||||||
void Begin();
|
void Begin(bool overlappingMoveSupported);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const VmaAllocator m_hAllocator;
|
const VmaAllocator m_hAllocator;
|
||||||
@ -11602,7 +11606,7 @@ void VmaBlockVector::ApplyDefragmentationMovesCpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
|
// THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
|
||||||
memcpy(
|
memmove(
|
||||||
reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
|
reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
|
||||||
reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
|
reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
|
||||||
static_cast<size_t>(move.size));
|
static_cast<size_t>(move.size));
|
||||||
@ -11842,13 +11846,15 @@ void VmaBlockVector::Defragment(
|
|||||||
m_hAllocator->IsIntegratedGpu();
|
m_hAllocator->IsIntegratedGpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overlappingMoveSupported = !defragmentOnGpu;
|
||||||
|
|
||||||
if(m_hAllocator->m_UseMutex)
|
if(m_hAllocator->m_UseMutex)
|
||||||
{
|
{
|
||||||
m_Mutex.LockWrite();
|
m_Mutex.LockWrite();
|
||||||
pCtx->mutexLocked = true;
|
pCtx->mutexLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCtx->Begin();
|
pCtx->Begin(overlappingMoveSupported);
|
||||||
|
|
||||||
// Defragment.
|
// Defragment.
|
||||||
|
|
||||||
@ -12015,7 +12021,8 @@ void VmaBlockVector::AddStats(VmaStats* pStats)
|
|||||||
VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
|
VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
VmaBlockVector* pBlockVector,
|
VmaBlockVector* pBlockVector,
|
||||||
uint32_t currentFrameIndex) :
|
uint32_t currentFrameIndex,
|
||||||
|
bool overlappingMoveSupported) :
|
||||||
VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
|
VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
|
||||||
m_AllAllocations(false),
|
m_AllAllocations(false),
|
||||||
m_AllocationCount(0),
|
m_AllocationCount(0),
|
||||||
@ -12307,8 +12314,10 @@ bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
|
|||||||
VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
|
VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
VmaBlockVector* pBlockVector,
|
VmaBlockVector* pBlockVector,
|
||||||
uint32_t currentFrameIndex) :
|
uint32_t currentFrameIndex,
|
||||||
|
bool overlappingMoveSupported) :
|
||||||
VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
|
VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
|
||||||
|
m_OverlappingMoveSupported(overlappingMoveSupported),
|
||||||
m_AllocationCount(0),
|
m_AllocationCount(0),
|
||||||
m_AllAllocations(false),
|
m_AllAllocations(false),
|
||||||
m_BytesMoved(0),
|
m_BytesMoved(0),
|
||||||
@ -12396,18 +12405,26 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
|
|||||||
// Same block
|
// Same block
|
||||||
if(dstBlockInfoIndex == srcBlockInfoIndex)
|
if(dstBlockInfoIndex == srcBlockInfoIndex)
|
||||||
{
|
{
|
||||||
// Destination and source place overlap.
|
VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
|
||||||
if(dstAllocOffset + srcAllocSize > srcAllocOffset)
|
|
||||||
|
const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
|
||||||
|
|
||||||
|
bool skipOver = overlap;
|
||||||
|
if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
|
||||||
|
{
|
||||||
|
// If destination and source place overlap, skip if it would move it
|
||||||
|
// by only < 1/64 of its size.
|
||||||
|
skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(skipOver)
|
||||||
{
|
{
|
||||||
// Just step over this allocation.
|
|
||||||
// TODO: Support memmove() here.
|
|
||||||
dstOffset = srcAllocOffset + srcAllocSize;
|
dstOffset = srcAllocOffset + srcAllocSize;
|
||||||
++srcSuballocIt;
|
++srcSuballocIt;
|
||||||
}
|
}
|
||||||
// MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
|
// MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VMA_ASSERT(dstAllocOffset < srcAllocOffset);
|
|
||||||
srcSuballocIt->offset = dstAllocOffset;
|
srcSuballocIt->offset = dstAllocOffset;
|
||||||
srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
|
srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
|
||||||
dstOffset = dstAllocOffset + srcAllocSize;
|
dstOffset = dstAllocOffset + srcAllocSize;
|
||||||
@ -12604,7 +12621,7 @@ void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, V
|
|||||||
m_Allocations.push_back(info);
|
m_Allocations.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaBlockVectorDefragmentationContext::Begin()
|
void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported)
|
||||||
{
|
{
|
||||||
const bool allAllocations = m_AllAllocations ||
|
const bool allAllocations = m_AllAllocations ||
|
||||||
m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
|
m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
|
||||||
@ -12624,12 +12641,12 @@ void VmaBlockVectorDefragmentationContext::Begin()
|
|||||||
!m_pBlockVector->IsBufferImageGranularityConflictPossible())
|
!m_pBlockVector->IsBufferImageGranularityConflictPossible())
|
||||||
{
|
{
|
||||||
m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
|
m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
|
||||||
m_hAllocator, m_pBlockVector, m_CurrFrameIndex);
|
m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
|
m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
|
||||||
m_hAllocator, m_pBlockVector, m_CurrFrameIndex);
|
m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allAllocations)
|
if(allAllocations)
|
||||||
|
Loading…
Reference in New Issue
Block a user