mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
synced 2024-11-21 20:00:11 +00:00
Added support for functions vmaDefragmentationBegin, vmaDefragmentationEnd to recording file format and VmaReplay.
This commit is contained in:
parent
920bfbe6f3
commit
a12a7fe43e
@ -209,6 +209,22 @@ No parameters.
|
||||
- allocation : pointer
|
||||
- newSize : uint64
|
||||
|
||||
**vmaDefragmentationBegin** (min format version: 1.5)
|
||||
|
||||
- defragmentationInfo2.flags : uint32
|
||||
- defragmentationInfo2.pAllocations : list of pointers
|
||||
- defragmentationInfo2.pPools : list of pointers
|
||||
- defragmentationInfo2.maxCpuBytesToMove : uint64
|
||||
- defragmentationInfo2.maxCpuAllocationsToMove : uint32
|
||||
- defragmentationInfo2.maxGpuBytesToMove : uint64
|
||||
- defragmentationInfo2.maxGpuAllocationsToMove : uint32
|
||||
- defragmentationInfo2.commandBuffer : pointer
|
||||
- context (output) : pointer
|
||||
|
||||
**vmaDefragmentationEnd** (min format version: 1.5)
|
||||
|
||||
- context : pointer
|
||||
|
||||
# Data types
|
||||
|
||||
**bool**
|
||||
|
@ -85,6 +85,8 @@ enum class VMA_FUNCTION
|
||||
GetAllocationInfo,
|
||||
MakePoolAllocationsLost,
|
||||
ResizeAllocation,
|
||||
DefragmentationBegin,
|
||||
DefragmentationEnd,
|
||||
Count
|
||||
};
|
||||
static const char* VMA_FUNCTION_NAMES[] = {
|
||||
@ -108,6 +110,8 @@ static const char* VMA_FUNCTION_NAMES[] = {
|
||||
"vmaGetAllocationInfo",
|
||||
"vmaMakePoolAllocationsLost",
|
||||
"vmaResizeAllocation",
|
||||
"vmaDefragmentationBegin",
|
||||
"vmaDefragmentationEnd",
|
||||
};
|
||||
static_assert(
|
||||
_countof(VMA_FUNCTION_NAMES) == (size_t)VMA_FUNCTION::Count,
|
||||
@ -839,7 +843,7 @@ void ConfigurationParser::CompareMemProps(
|
||||
|
||||
static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
|
||||
|
||||
static bool g_MemoryAliasingWarningEnabled = true;
|
||||
static const bool g_MemoryAliasingWarningEnabled = false;
|
||||
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
|
||||
VkDebugReportFlagsEXT flags,
|
||||
@ -973,6 +977,7 @@ private:
|
||||
};
|
||||
std::unordered_map<uint64_t, Pool> m_Pools;
|
||||
std::unordered_map<uint64_t, Allocation> m_Allocations;
|
||||
std::unordered_map<uint64_t, VmaDefragmentationContext> m_DefragmentationContexts;
|
||||
|
||||
struct Thread
|
||||
{
|
||||
@ -1029,6 +1034,8 @@ private:
|
||||
void ExecuteGetAllocationInfo(size_t lineNumber, const CsvSplit& csvSplit);
|
||||
void ExecuteMakePoolAllocationsLost(size_t lineNumber, const CsvSplit& csvSplit);
|
||||
void ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit);
|
||||
void ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit);
|
||||
void ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit);
|
||||
|
||||
void DestroyAllocation(size_t lineNumber, const CsvSplit& csvSplit, const char* functionName);
|
||||
|
||||
@ -1175,6 +1182,10 @@ void Player::ExecuteLine(size_t lineNumber, const StrRange& line)
|
||||
ExecuteMakePoolAllocationsLost(lineNumber, csvSplit);
|
||||
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::ResizeAllocation]))
|
||||
ExecuteResizeAllocation(lineNumber, csvSplit);
|
||||
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationBegin]))
|
||||
ExecuteDefragmentationBegin(lineNumber, csvSplit);
|
||||
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationEnd]))
|
||||
ExecuteDefragmentationEnd(lineNumber, csvSplit);
|
||||
else
|
||||
{
|
||||
if(IssueWarning())
|
||||
@ -1611,6 +1622,21 @@ int Player::InitVulkan()
|
||||
|
||||
void Player::FinalizeVulkan()
|
||||
{
|
||||
if(!m_DefragmentationContexts.empty())
|
||||
{
|
||||
printf("WARNING: Defragmentation contexts not destroyed: %zu.\n", m_DefragmentationContexts.size());
|
||||
|
||||
if(CLEANUP_LEAKED_OBJECTS)
|
||||
{
|
||||
for(const auto& it : m_DefragmentationContexts)
|
||||
{
|
||||
vmaDefragmentationEnd(m_Allocator, it.second);
|
||||
}
|
||||
}
|
||||
|
||||
m_DefragmentationContexts.clear();
|
||||
}
|
||||
|
||||
if(!m_Allocations.empty())
|
||||
{
|
||||
printf("WARNING: Allocations not destroyed: %zu.\n", m_Allocations.size());
|
||||
@ -1744,8 +1770,6 @@ void Player::Defragment()
|
||||
return;
|
||||
}
|
||||
|
||||
g_MemoryAliasingWarningEnabled = false;
|
||||
|
||||
const time_point timeBeg = std::chrono::high_resolution_clock::now();
|
||||
|
||||
VmaDefragmentationInfo2 defragInfo = {};
|
||||
@ -1835,8 +1859,6 @@ void Player::Defragment()
|
||||
}
|
||||
|
||||
vkResetCommandPool(m_Device, m_CommandPool, 0);
|
||||
|
||||
g_MemoryAliasingWarningEnabled = true;
|
||||
}
|
||||
|
||||
void Player::PrintStats()
|
||||
@ -2894,6 +2916,198 @@ void Player::ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit)
|
||||
{
|
||||
m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationBegin);
|
||||
|
||||
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 9, false))
|
||||
{
|
||||
VmaDefragmentationInfo2 defragInfo = {};
|
||||
std::vector<uint64_t> allocationOrigPtrs;
|
||||
std::vector<uint64_t> poolOrigPtrs;
|
||||
uint64_t cmdBufOrigPtr = 0;
|
||||
uint64_t defragCtxOrigPtr = 0;
|
||||
|
||||
if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), defragInfo.flags) &&
|
||||
StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), allocationOrigPtrs) &&
|
||||
StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), poolOrigPtrs) &&
|
||||
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), defragInfo.maxCpuBytesToMove) &&
|
||||
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), defragInfo.maxCpuAllocationsToMove) &&
|
||||
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), defragInfo.maxGpuBytesToMove) &&
|
||||
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), defragInfo.maxGpuAllocationsToMove) &&
|
||||
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), cmdBufOrigPtr) &&
|
||||
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), defragCtxOrigPtr))
|
||||
{
|
||||
const size_t allocationOrigPtrCount = allocationOrigPtrs.size();
|
||||
std::vector<VmaAllocation> allocations;
|
||||
allocations.reserve(allocationOrigPtrCount);
|
||||
for(size_t i = 0; i < allocationOrigPtrCount; ++i)
|
||||
{
|
||||
const auto it = m_Allocations.find(allocationOrigPtrs[i]);
|
||||
if(it != m_Allocations.end() && it->second.allocation)
|
||||
{
|
||||
allocations.push_back(it->second.allocation);
|
||||
}
|
||||
}
|
||||
if(!allocations.empty())
|
||||
{
|
||||
defragInfo.allocationCount = (uint32_t)allocations.size();
|
||||
defragInfo.pAllocations = allocations.data();
|
||||
}
|
||||
|
||||
const size_t poolOrigPtrCount = poolOrigPtrs.size();
|
||||
std::vector<VmaPool> pools;
|
||||
pools.reserve(poolOrigPtrCount);
|
||||
for(size_t i = 0; i < poolOrigPtrCount; ++i)
|
||||
{
|
||||
const auto it = m_Pools.find(poolOrigPtrs[i]);
|
||||
if(it != m_Pools.end() && it->second.pool)
|
||||
{
|
||||
pools.push_back(it->second.pool);
|
||||
}
|
||||
}
|
||||
if(!pools.empty())
|
||||
{
|
||||
defragInfo.poolCount = (uint32_t)pools.size();
|
||||
defragInfo.pPools = pools.data();
|
||||
}
|
||||
|
||||
if(allocations.size() != allocationOrigPtrCount ||
|
||||
pools.size() != poolOrigPtrCount)
|
||||
{
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: Passing %zu allocations and %zu pools to vmaDefragmentationBegin, while originally %zu allocations and %zu pools were passed.\n",
|
||||
lineNumber,
|
||||
allocations.size(), pools.size(),
|
||||
allocationOrigPtrCount, poolOrigPtrCount);
|
||||
}
|
||||
}
|
||||
|
||||
if(cmdBufOrigPtr)
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
VkResult res = vkBeginCommandBuffer(m_CommandBuffer, &cmdBufBeginInfo);
|
||||
if(res == VK_SUCCESS)
|
||||
{
|
||||
defragInfo.commandBuffer = m_CommandBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Line %zu: vkBeginCommandBuffer failed (%d)\n", lineNumber, res);
|
||||
}
|
||||
}
|
||||
|
||||
VmaDefragmentationContext defragCtx = nullptr;
|
||||
VkResult res = vmaDefragmentationBegin(m_Allocator, &defragInfo, nullptr, &defragCtx);
|
||||
|
||||
if(defragInfo.commandBuffer)
|
||||
{
|
||||
vkEndCommandBuffer(m_CommandBuffer);
|
||||
|
||||
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &m_CommandBuffer;
|
||||
vkQueueSubmit(m_TransferQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(m_TransferQueue);
|
||||
}
|
||||
|
||||
if(res >= VK_SUCCESS)
|
||||
{
|
||||
if(defragCtx)
|
||||
{
|
||||
if(defragCtxOrigPtr)
|
||||
{
|
||||
// We have defragmentation context, originally had defragmentation context: Store it.
|
||||
m_DefragmentationContexts[defragCtxOrigPtr] = defragCtx;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have defragmentation context, originally it was null: End immediately.
|
||||
vmaDefragmentationEnd(m_Allocator, defragCtx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(defragCtxOrigPtr)
|
||||
{
|
||||
// We have no defragmentation context, originally there was one: Store null.
|
||||
m_DefragmentationContexts[defragCtxOrigPtr] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have no defragmentation context, originally there wasn't as well - nothing to do.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(defragCtxOrigPtr)
|
||||
{
|
||||
// Currently failed, originally succeeded.
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: vmaDefragmentationBegin failed (%d), while originally succeeded.\n", lineNumber, res);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Currently failed, originally don't know.
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: vmaDefragmentationBegin failed (%d).\n", lineNumber, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: Invalid parameters for vmaDefragmentationBegin.\n", lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit)
|
||||
{
|
||||
m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationEnd);
|
||||
|
||||
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
|
||||
{
|
||||
uint64_t origPtr = 0;
|
||||
|
||||
if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
|
||||
{
|
||||
if(origPtr != 0)
|
||||
{
|
||||
const auto it = m_DefragmentationContexts.find(origPtr);
|
||||
if(it != m_DefragmentationContexts.end())
|
||||
{
|
||||
vmaDefragmentationEnd(m_Allocator, it->second);
|
||||
m_DefragmentationContexts.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: Defragmentation context %llX not found.\n", lineNumber, origPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IssueWarning())
|
||||
{
|
||||
printf("Line %zu: Invalid parameters for vmaDefragmentationEnd.\n", lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Main functions
|
||||
|
||||
|
@ -6370,6 +6370,11 @@ public:
|
||||
VmaAllocation allocation);
|
||||
void RecordMakePoolAllocationsLost(uint32_t frameIndex,
|
||||
VmaPool pool);
|
||||
void RecordDefragmentationBegin(uint32_t frameIndex,
|
||||
const VmaDefragmentationInfo2& info,
|
||||
VmaDefragmentationContext ctx);
|
||||
void RecordDefragmentationEnd(uint32_t frameIndex,
|
||||
VmaDefragmentationContext ctx);
|
||||
|
||||
private:
|
||||
struct CallParams
|
||||
@ -6397,7 +6402,21 @@ private:
|
||||
int64_t m_StartCounter;
|
||||
|
||||
void GetBasicParams(CallParams& outParams);
|
||||
void PrintPointerList(uint64_t count, const VmaAllocation* pItems);
|
||||
|
||||
// T must be a pointer type, e.g. VmaAllocation, VmaPool.
|
||||
template<typename T>
|
||||
void PrintPointerList(uint64_t count, const T* pItems)
|
||||
{
|
||||
if(count)
|
||||
{
|
||||
fprintf(m_File, "%p", pItems[0]);
|
||||
for(uint64_t i = 1; i < count; ++i)
|
||||
{
|
||||
fprintf(m_File, " %p", pItems[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Flush();
|
||||
};
|
||||
|
||||
@ -13608,6 +13627,41 @@ void VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,
|
||||
Flush();
|
||||
}
|
||||
|
||||
void VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,
|
||||
const VmaDefragmentationInfo2& info,
|
||||
VmaDefragmentationContext ctx)
|
||||
{
|
||||
CallParams callParams;
|
||||
GetBasicParams(callParams);
|
||||
|
||||
VmaMutexLock lock(m_FileMutex, m_UseMutex);
|
||||
fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationBegin,%u,", callParams.threadId, callParams.time, frameIndex,
|
||||
info.flags);
|
||||
PrintPointerList(info.allocationCount, info.pAllocations);
|
||||
fprintf(m_File, ",");
|
||||
PrintPointerList(info.poolCount, info.pPools);
|
||||
fprintf(m_File, ",%llu,%u,%llu,%u,%p,%p\n",
|
||||
info.maxCpuBytesToMove,
|
||||
info.maxCpuAllocationsToMove,
|
||||
info.maxGpuBytesToMove,
|
||||
info.maxGpuAllocationsToMove,
|
||||
info.commandBuffer,
|
||||
ctx);
|
||||
Flush();
|
||||
}
|
||||
|
||||
void VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,
|
||||
VmaDefragmentationContext ctx)
|
||||
{
|
||||
CallParams callParams;
|
||||
GetBasicParams(callParams);
|
||||
|
||||
VmaMutexLock lock(m_FileMutex, m_UseMutex);
|
||||
fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationEnd,%p\n", callParams.threadId, callParams.time, frameIndex,
|
||||
ctx);
|
||||
Flush();
|
||||
}
|
||||
|
||||
VmaRecorder::UserDataString::UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData)
|
||||
{
|
||||
if(pUserData != VMA_NULL)
|
||||
@ -13683,18 +13737,6 @@ void VmaRecorder::GetBasicParams(CallParams& outParams)
|
||||
outParams.time = (double)(counter.QuadPart - m_StartCounter) / (double)m_Freq;
|
||||
}
|
||||
|
||||
void VmaRecorder::PrintPointerList(uint64_t count, const VmaAllocation* pItems)
|
||||
{
|
||||
if(count)
|
||||
{
|
||||
fprintf(m_File, "%p", pItems[0]);
|
||||
for(uint64_t i = 1; i < count; ++i)
|
||||
{
|
||||
fprintf(m_File, " %p", pItems[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VmaRecorder::Flush()
|
||||
{
|
||||
if((m_Flags & VMA_RECORD_FLUSH_AFTER_CALL_BIT) != 0)
|
||||
@ -15987,7 +16029,17 @@ VkResult vmaDefragmentationBegin(
|
||||
|
||||
VMA_DEBUG_GLOBAL_MUTEX_LOCK
|
||||
|
||||
return allocator->DefragmentationBegin(*pInfo, pStats, pContext);
|
||||
VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext);
|
||||
|
||||
#if VMA_RECORDING_ENABLED
|
||||
if(allocator->GetRecorder() != VMA_NULL)
|
||||
{
|
||||
allocator->GetRecorder()->RecordDefragmentationBegin(
|
||||
allocator->GetCurrentFrameIndex(), *pInfo, *pContext);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
VkResult vmaDefragmentationEnd(
|
||||
@ -16002,6 +16054,14 @@ VkResult vmaDefragmentationEnd(
|
||||
{
|
||||
VMA_DEBUG_GLOBAL_MUTEX_LOCK
|
||||
|
||||
#if VMA_RECORDING_ENABLED
|
||||
if(allocator->GetRecorder() != VMA_NULL)
|
||||
{
|
||||
allocator->GetRecorder()->RecordDefragmentationEnd(
|
||||
allocator->GetCurrentFrameIndex(), context);
|
||||
}
|
||||
#endif
|
||||
|
||||
return allocator->DefragmentationEnd(context);
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user