mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
synced 2024-11-05 12:20:07 +00:00
fix GPU memory defragmentation to restrict supported memory types
Defragmentation of GPU memory is restricted to those memory types that support creating buffer used for transfers. #59
This commit is contained in:
parent
672f7c8e94
commit
bb18b299dc
@ -3206,7 +3206,6 @@ remove them if not needed.
|
|||||||
#include <cassert> // for assert
|
#include <cassert> // for assert
|
||||||
#include <algorithm> // for min, max
|
#include <algorithm> // for min, max
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <atomic> // for std::atomic
|
|
||||||
|
|
||||||
#ifndef VMA_NULL
|
#ifndef VMA_NULL
|
||||||
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
|
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
|
||||||
@ -3396,7 +3395,8 @@ If providing your own implementation, you need to implement a subset of std::ato
|
|||||||
- bool compare_exchange_weak(uint32_t& expected, uint32_t desired)
|
- bool compare_exchange_weak(uint32_t& expected, uint32_t desired)
|
||||||
*/
|
*/
|
||||||
#ifndef VMA_ATOMIC_UINT32
|
#ifndef VMA_ATOMIC_UINT32
|
||||||
#define VMA_ATOMIC_UINT32 std::atomic<uint32_t>
|
#include <atomic>
|
||||||
|
#define VMA_ATOMIC_UINT32 std::atomic<uint32_t>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
|
#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
|
||||||
@ -3744,6 +3744,18 @@ static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fills structure with parameters of an example buffer to be used for transfers
|
||||||
|
during GPU memory defragmentation.
|
||||||
|
*/
|
||||||
|
static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo)
|
||||||
|
{
|
||||||
|
memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo));
|
||||||
|
outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size.
|
||||||
|
}
|
||||||
|
|
||||||
// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
|
// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
|
||||||
struct VmaMutexLock
|
struct VmaMutexLock
|
||||||
{
|
{
|
||||||
@ -6779,11 +6791,18 @@ public:
|
|||||||
|
|
||||||
void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
|
void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns bit mask of memory types that can support defragmentation on GPU as
|
||||||
|
they support creation of required buffer for copy operations.
|
||||||
|
*/
|
||||||
|
uint32_t GetGpuDefragmentationMemoryTypeBits();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDeviceSize m_PreferredLargeHeapBlockSize;
|
VkDeviceSize m_PreferredLargeHeapBlockSize;
|
||||||
|
|
||||||
VkPhysicalDevice m_PhysicalDevice;
|
VkPhysicalDevice m_PhysicalDevice;
|
||||||
VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
|
VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
|
||||||
|
VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.
|
||||||
|
|
||||||
VMA_RW_MUTEX m_PoolsMutex;
|
VMA_RW_MUTEX m_PoolsMutex;
|
||||||
// Protected by m_PoolsMutex. Sorted by pointer value.
|
// Protected by m_PoolsMutex. Sorted by pointer value.
|
||||||
@ -6838,6 +6857,12 @@ private:
|
|||||||
|
|
||||||
// Tries to free pMemory as Dedicated Memory. Returns true if found and freed.
|
// Tries to free pMemory as Dedicated Memory. Returns true if found and freed.
|
||||||
void FreeDedicatedMemory(VmaAllocation allocation);
|
void FreeDedicatedMemory(VmaAllocation allocation);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculates and returns bit mask of memory types that can support defragmentation
|
||||||
|
on GPU as they support creation of required buffer for copy operations.
|
||||||
|
*/
|
||||||
|
uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -12266,9 +12291,8 @@ void VmaBlockVector::ApplyDefragmentationMovesGpu(
|
|||||||
|
|
||||||
// Go over all blocks. Create and bind buffer for whole block if necessary.
|
// Go over all blocks. Create and bind buffer for whole block if necessary.
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo bufCreateInfo;
|
||||||
bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
|
VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo);
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
||||||
|
|
||||||
for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
|
for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
|
||||||
{
|
{
|
||||||
@ -12428,7 +12452,8 @@ void VmaBlockVector::Defragment(
|
|||||||
const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
|
const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
|
||||||
isHostVisible;
|
isHostVisible;
|
||||||
const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
|
const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
|
||||||
!IsCorruptionDetectionEnabled();
|
!IsCorruptionDetectionEnabled() &&
|
||||||
|
((1u << m_MemoryTypeIndex) & m_hAllocator->GetGpuDefragmentationMemoryTypeBits()) != 0;
|
||||||
|
|
||||||
// There are options to defragment this memory type.
|
// There are options to defragment this memory type.
|
||||||
if(canDefragmentOnCpu || canDefragmentOnGpu)
|
if(canDefragmentOnCpu || canDefragmentOnGpu)
|
||||||
@ -14164,6 +14189,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
|
|||||||
m_PreferredLargeHeapBlockSize(0),
|
m_PreferredLargeHeapBlockSize(0),
|
||||||
m_PhysicalDevice(pCreateInfo->physicalDevice),
|
m_PhysicalDevice(pCreateInfo->physicalDevice),
|
||||||
m_CurrentFrameIndex(0),
|
m_CurrentFrameIndex(0),
|
||||||
|
m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),
|
||||||
m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
|
m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
|
||||||
m_NextPoolId(0)
|
m_NextPoolId(0)
|
||||||
#if VMA_RECORDING_ENABLED
|
#if VMA_RECORDING_ENABLED
|
||||||
@ -15555,6 +15581,31 @@ void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation)
|
|||||||
VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
|
VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const
|
||||||
|
{
|
||||||
|
VkBufferCreateInfo dummyBufCreateInfo;
|
||||||
|
VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo);
|
||||||
|
|
||||||
|
uint32_t memoryTypeBits = 0;
|
||||||
|
|
||||||
|
// Create buffer.
|
||||||
|
VkBuffer buf = VMA_NULL;
|
||||||
|
VkResult res = (*GetVulkanFunctions().vkCreateBuffer)(
|
||||||
|
m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
// Query for supported memory types.
|
||||||
|
VkMemoryRequirements memReq;
|
||||||
|
(*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq);
|
||||||
|
memoryTypeBits = memReq.memoryTypeBits;
|
||||||
|
|
||||||
|
// Destroy buffer.
|
||||||
|
(*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks());
|
||||||
|
}
|
||||||
|
|
||||||
|
return memoryTypeBits;
|
||||||
|
}
|
||||||
|
|
||||||
void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
|
void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
|
||||||
{
|
{
|
||||||
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
|
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
|
||||||
@ -15576,6 +15627,17 @@ void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()
|
||||||
|
{
|
||||||
|
uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load();
|
||||||
|
if(memoryTypeBits == UINT32_MAX)
|
||||||
|
{
|
||||||
|
memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits();
|
||||||
|
m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits);
|
||||||
|
}
|
||||||
|
return memoryTypeBits;
|
||||||
|
}
|
||||||
|
|
||||||
#if VMA_STATS_STRING_ENABLED
|
#if VMA_STATS_STRING_ENABLED
|
||||||
|
|
||||||
void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
|
void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
|
||||||
|
Loading…
Reference in New Issue
Block a user