Skip to content

Commit a12a7fe

Browse files
Added support for functions vmaDefragmentationBegin, vmaDefragmentationEnd to recording file format and VmaReplay.
1 parent 920bfbe commit a12a7fe

3 files changed

Lines changed: 309 additions & 19 deletions

File tree

docs/Recording file format.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,22 @@ No parameters.
209209
- allocation : pointer
210210
- newSize : uint64
211211

212+
**vmaDefragmentationBegin** (min format version: 1.5)
213+
214+
- defragmentationInfo2.flags : uint32
215+
- defragmentationInfo2.pAllocations : list of pointers
216+
- defragmentationInfo2.pPools : list of pointers
217+
- defragmentationInfo2.maxCpuBytesToMove : uint64
218+
- defragmentationInfo2.maxCpuAllocationsToMove : uint32
219+
- defragmentationInfo2.maxGpuBytesToMove : uint64
220+
- defragmentationInfo2.maxGpuAllocationsToMove : uint32
221+
- defragmentationInfo2.commandBuffer : pointer
222+
- context (output) : pointer
223+
224+
**vmaDefragmentationEnd** (min format version: 1.5)
225+
226+
- context : pointer
227+
212228
# Data types
213229

214230
**bool**

src/VmaReplay/VmaReplay.cpp

Lines changed: 219 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ enum class VMA_FUNCTION
8585
GetAllocationInfo,
8686
MakePoolAllocationsLost,
8787
ResizeAllocation,
88+
DefragmentationBegin,
89+
DefragmentationEnd,
8890
Count
8991
};
9092
static const char* VMA_FUNCTION_NAMES[] = {
@@ -108,6 +110,8 @@ static const char* VMA_FUNCTION_NAMES[] = {
108110
"vmaGetAllocationInfo",
109111
"vmaMakePoolAllocationsLost",
110112
"vmaResizeAllocation",
113+
"vmaDefragmentationBegin",
114+
"vmaDefragmentationEnd",
111115
};
112116
static_assert(
113117
_countof(VMA_FUNCTION_NAMES) == (size_t)VMA_FUNCTION::Count,
@@ -839,7 +843,7 @@ void ConfigurationParser::CompareMemProps(
839843

840844
static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
841845

842-
static bool g_MemoryAliasingWarningEnabled = true;
846+
static const bool g_MemoryAliasingWarningEnabled = false;
843847

844848
static VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
845849
VkDebugReportFlagsEXT flags,
@@ -973,6 +977,7 @@ class Player
973977
};
974978
std::unordered_map<uint64_t, Pool> m_Pools;
975979
std::unordered_map<uint64_t, Allocation> m_Allocations;
980+
std::unordered_map<uint64_t, VmaDefragmentationContext> m_DefragmentationContexts;
976981

977982
struct Thread
978983
{
@@ -1029,6 +1034,8 @@ class Player
10291034
void ExecuteGetAllocationInfo(size_t lineNumber, const CsvSplit& csvSplit);
10301035
void ExecuteMakePoolAllocationsLost(size_t lineNumber, const CsvSplit& csvSplit);
10311036
void ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit);
1037+
void ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit);
1038+
void ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit);
10321039

10331040
void DestroyAllocation(size_t lineNumber, const CsvSplit& csvSplit, const char* functionName);
10341041

@@ -1175,6 +1182,10 @@ void Player::ExecuteLine(size_t lineNumber, const StrRange& line)
11751182
ExecuteMakePoolAllocationsLost(lineNumber, csvSplit);
11761183
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::ResizeAllocation]))
11771184
ExecuteResizeAllocation(lineNumber, csvSplit);
1185+
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationBegin]))
1186+
ExecuteDefragmentationBegin(lineNumber, csvSplit);
1187+
else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationEnd]))
1188+
ExecuteDefragmentationEnd(lineNumber, csvSplit);
11781189
else
11791190
{
11801191
if(IssueWarning())
@@ -1611,6 +1622,21 @@ int Player::InitVulkan()
16111622

16121623
void Player::FinalizeVulkan()
16131624
{
1625+
if(!m_DefragmentationContexts.empty())
1626+
{
1627+
printf("WARNING: Defragmentation contexts not destroyed: %zu.\n", m_DefragmentationContexts.size());
1628+
1629+
if(CLEANUP_LEAKED_OBJECTS)
1630+
{
1631+
for(const auto& it : m_DefragmentationContexts)
1632+
{
1633+
vmaDefragmentationEnd(m_Allocator, it.second);
1634+
}
1635+
}
1636+
1637+
m_DefragmentationContexts.clear();
1638+
}
1639+
16141640
if(!m_Allocations.empty())
16151641
{
16161642
printf("WARNING: Allocations not destroyed: %zu.\n", m_Allocations.size());
@@ -1744,8 +1770,6 @@ void Player::Defragment()
17441770
return;
17451771
}
17461772

1747-
g_MemoryAliasingWarningEnabled = false;
1748-
17491773
const time_point timeBeg = std::chrono::high_resolution_clock::now();
17501774

17511775
VmaDefragmentationInfo2 defragInfo = {};
@@ -1835,8 +1859,6 @@ void Player::Defragment()
18351859
}
18361860

18371861
vkResetCommandPool(m_Device, m_CommandPool, 0);
1838-
1839-
g_MemoryAliasingWarningEnabled = true;
18401862
}
18411863

18421864
void Player::PrintStats()
@@ -2894,6 +2916,198 @@ void Player::ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit
28942916
}
28952917
}
28962918

2919+
void Player::ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit)
2920+
{
2921+
m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationBegin);
2922+
2923+
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 9, false))
2924+
{
2925+
VmaDefragmentationInfo2 defragInfo = {};
2926+
std::vector<uint64_t> allocationOrigPtrs;
2927+
std::vector<uint64_t> poolOrigPtrs;
2928+
uint64_t cmdBufOrigPtr = 0;
2929+
uint64_t defragCtxOrigPtr = 0;
2930+
2931+
if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), defragInfo.flags) &&
2932+
StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), allocationOrigPtrs) &&
2933+
StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), poolOrigPtrs) &&
2934+
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), defragInfo.maxCpuBytesToMove) &&
2935+
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), defragInfo.maxCpuAllocationsToMove) &&
2936+
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), defragInfo.maxGpuBytesToMove) &&
2937+
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), defragInfo.maxGpuAllocationsToMove) &&
2938+
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), cmdBufOrigPtr) &&
2939+
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), defragCtxOrigPtr))
2940+
{
2941+
const size_t allocationOrigPtrCount = allocationOrigPtrs.size();
2942+
std::vector<VmaAllocation> allocations;
2943+
allocations.reserve(allocationOrigPtrCount);
2944+
for(size_t i = 0; i < allocationOrigPtrCount; ++i)
2945+
{
2946+
const auto it = m_Allocations.find(allocationOrigPtrs[i]);
2947+
if(it != m_Allocations.end() && it->second.allocation)
2948+
{
2949+
allocations.push_back(it->second.allocation);
2950+
}
2951+
}
2952+
if(!allocations.empty())
2953+
{
2954+
defragInfo.allocationCount = (uint32_t)allocations.size();
2955+
defragInfo.pAllocations = allocations.data();
2956+
}
2957+
2958+
const size_t poolOrigPtrCount = poolOrigPtrs.size();
2959+
std::vector<VmaPool> pools;
2960+
pools.reserve(poolOrigPtrCount);
2961+
for(size_t i = 0; i < poolOrigPtrCount; ++i)
2962+
{
2963+
const auto it = m_Pools.find(poolOrigPtrs[i]);
2964+
if(it != m_Pools.end() && it->second.pool)
2965+
{
2966+
pools.push_back(it->second.pool);
2967+
}
2968+
}
2969+
if(!pools.empty())
2970+
{
2971+
defragInfo.poolCount = (uint32_t)pools.size();
2972+
defragInfo.pPools = pools.data();
2973+
}
2974+
2975+
if(allocations.size() != allocationOrigPtrCount ||
2976+
pools.size() != poolOrigPtrCount)
2977+
{
2978+
if(IssueWarning())
2979+
{
2980+
printf("Line %zu: Passing %zu allocations and %zu pools to vmaDefragmentationBegin, while originally %zu allocations and %zu pools were passed.\n",
2981+
lineNumber,
2982+
allocations.size(), pools.size(),
2983+
allocationOrigPtrCount, poolOrigPtrCount);
2984+
}
2985+
}
2986+
2987+
if(cmdBufOrigPtr)
2988+
{
2989+
VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
2990+
cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2991+
VkResult res = vkBeginCommandBuffer(m_CommandBuffer, &cmdBufBeginInfo);
2992+
if(res == VK_SUCCESS)
2993+
{
2994+
defragInfo.commandBuffer = m_CommandBuffer;
2995+
}
2996+
else
2997+
{
2998+
printf("Line %zu: vkBeginCommandBuffer failed (%d)\n", lineNumber, res);
2999+
}
3000+
}
3001+
3002+
VmaDefragmentationContext defragCtx = nullptr;
3003+
VkResult res = vmaDefragmentationBegin(m_Allocator, &defragInfo, nullptr, &defragCtx);
3004+
3005+
if(defragInfo.commandBuffer)
3006+
{
3007+
vkEndCommandBuffer(m_CommandBuffer);
3008+
3009+
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
3010+
submitInfo.commandBufferCount = 1;
3011+
submitInfo.pCommandBuffers = &m_CommandBuffer;
3012+
vkQueueSubmit(m_TransferQueue, 1, &submitInfo, VK_NULL_HANDLE);
3013+
vkQueueWaitIdle(m_TransferQueue);
3014+
}
3015+
3016+
if(res >= VK_SUCCESS)
3017+
{
3018+
if(defragCtx)
3019+
{
3020+
if(defragCtxOrigPtr)
3021+
{
3022+
// We have defragmentation context, originally had defragmentation context: Store it.
3023+
m_DefragmentationContexts[defragCtxOrigPtr] = defragCtx;
3024+
}
3025+
else
3026+
{
3027+
// We have defragmentation context, originally it was null: End immediately.
3028+
vmaDefragmentationEnd(m_Allocator, defragCtx);
3029+
}
3030+
}
3031+
else
3032+
{
3033+
if(defragCtxOrigPtr)
3034+
{
3035+
// We have no defragmentation context, originally there was one: Store null.
3036+
m_DefragmentationContexts[defragCtxOrigPtr] = nullptr;
3037+
}
3038+
else
3039+
{
3040+
// We have no defragmentation context, originally there wasn't as well - nothing to do.
3041+
}
3042+
}
3043+
}
3044+
else
3045+
{
3046+
if(defragCtxOrigPtr)
3047+
{
3048+
// Currently failed, originally succeeded.
3049+
if(IssueWarning())
3050+
{
3051+
printf("Line %zu: vmaDefragmentationBegin failed (%d), while originally succeeded.\n", lineNumber, res);
3052+
}
3053+
}
3054+
else
3055+
{
3056+
// Currently failed, originally don't know.
3057+
if(IssueWarning())
3058+
{
3059+
printf("Line %zu: vmaDefragmentationBegin failed (%d).\n", lineNumber, res);
3060+
}
3061+
}
3062+
}
3063+
}
3064+
else
3065+
{
3066+
if(IssueWarning())
3067+
{
3068+
printf("Line %zu: Invalid parameters for vmaDefragmentationBegin.\n", lineNumber);
3069+
}
3070+
}
3071+
}
3072+
}
3073+
3074+
void Player::ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit)
3075+
{
3076+
m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationEnd);
3077+
3078+
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
3079+
{
3080+
uint64_t origPtr = 0;
3081+
3082+
if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
3083+
{
3084+
if(origPtr != 0)
3085+
{
3086+
const auto it = m_DefragmentationContexts.find(origPtr);
3087+
if(it != m_DefragmentationContexts.end())
3088+
{
3089+
vmaDefragmentationEnd(m_Allocator, it->second);
3090+
m_DefragmentationContexts.erase(it);
3091+
}
3092+
else
3093+
{
3094+
if(IssueWarning())
3095+
{
3096+
printf("Line %zu: Defragmentation context %llX not found.\n", lineNumber, origPtr);
3097+
}
3098+
}
3099+
}
3100+
}
3101+
else
3102+
{
3103+
if(IssueWarning())
3104+
{
3105+
printf("Line %zu: Invalid parameters for vmaDefragmentationEnd.\n", lineNumber);
3106+
}
3107+
}
3108+
}
3109+
}
3110+
28973111
////////////////////////////////////////////////////////////////////////////////
28983112
// Main functions
28993113

0 commit comments

Comments
 (0)