Fixes in JSON dump format. Fixes in GpuMemDumpVis.py regarding image height calculation.

Added GpuMemDump.schema.json.
This commit is contained in:
Adam Sawicki 2022-04-05 13:34:45 +02:00
parent 2d7d710944
commit 19322e3194
4 changed files with 209 additions and 37 deletions

View File

@ -27,6 +27,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <cstdlib> #include <cstdlib>
#include <cstdint>
#include <malloc.h> // for _aligned_malloc, _aligned_free #include <malloc.h> // for _aligned_malloc, _aligned_free
#ifndef _WIN32 #ifndef _WIN32
#include <shared_mutex> #include <shared_mutex>
@ -378,6 +379,14 @@ static T RoundDiv(T x, T y) { return (x + (y / (T)2)) / y; }
template <typename T> template <typename T>
static T DivideRoundingUp(T x, T y) { return (x + y - 1) / y; } static T DivideRoundingUp(T x, T y) { return (x + y - 1) / y; }
static WCHAR HexDigitToChar(UINT8 digit)
{
if(digit < 10)
return L'0' + digit;
else
return L'A' + (digit - 10);
}
/* /*
Performs binary search and returns iterator to first element that is greater or Performs binary search and returns iterator to first element that is greater or
equal to `key`, according to comparison `cmp`. equal to `key`, according to comparison `cmp`.
@ -1180,6 +1189,7 @@ public:
void AddNewLine() { Add(L'\n'); } void AddNewLine() { Add(L'\n'); }
void AddNumber(UINT num); void AddNumber(UINT num);
void AddNumber(UINT64 num); void AddNumber(UINT64 num);
void AddPointer(const void* ptr);
private: private:
Vector<WCHAR> m_Data; Vector<WCHAR> m_Data;
@ -1224,6 +1234,22 @@ void StringBuilder::AddNumber(UINT64 num)
while (num); while (num);
Add(p); Add(p);
} }
void StringBuilder::AddPointer(const void* ptr)
{
WCHAR buf[21];
uintptr_t num = (uintptr_t)ptr;
buf[20] = L'\0';
WCHAR *p = &buf[20];
do
{
*--p = HexDigitToChar((UINT8)(num & 0xF));
num >>= 4;
}
while (num);
Add(p);
}
#endif // _D3D12MA_STRING_BUILDER_FUNCTIONS #endif // _D3D12MA_STRING_BUILDER_FUNCTIONS
#endif // _D3D12MA_STRING_BUILDER #endif // _D3D12MA_STRING_BUILDER
@ -1267,6 +1293,7 @@ public:
// Posts next part of an open string. The number is converted to decimal characters. // Posts next part of an open string. The number is converted to decimal characters.
void ContinueString(UINT num); void ContinueString(UINT num);
void ContinueString(UINT64 num); void ContinueString(UINT64 num);
void ContinueString_Pointer(const void* ptr);
// Posts next part of an open string. Pointer value is converted to characters // Posts next part of an open string. Pointer value is converted to characters
// using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00 // using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00
// void ContinueString_Pointer(const void* ptr); // void ContinueString_Pointer(const void* ptr);
@ -1452,6 +1479,12 @@ void JsonWriter::ContinueString(UINT64 num)
m_SB.AddNumber(num); m_SB.AddNumber(num);
} }
void JsonWriter::ContinueString_Pointer(const void* ptr)
{
D3D12MA_ASSERT(m_InsideString);
m_SB.AddPointer(ptr);
}
void JsonWriter::EndString(LPCWSTR pStr) void JsonWriter::EndString(LPCWSTR pStr)
{ {
D3D12MA_ASSERT(m_InsideString); D3D12MA_ASSERT(m_InsideString);
@ -1524,7 +1557,9 @@ void JsonWriter::AddAllocationToObject(const Allocation& alloc)
if (privateData) if (privateData)
{ {
WriteString(L"CustomData"); WriteString(L"CustomData");
WriteNumber((uintptr_t)privateData); BeginString();
ContinueString_Pointer(privateData);
EndString();
} }
LPCWSTR name = alloc.GetName(); LPCWSTR name = alloc.GetName();
@ -7196,9 +7231,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"DEFAULT"); json.WriteString(L"DEFAULT");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[0]); json.AddDetailedStatisticsInfoObject(stats.HeapType[0]);
} }
@ -7207,9 +7239,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"UPLOAD"); json.WriteString(L"UPLOAD");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[1]); json.AddDetailedStatisticsInfoObject(stats.HeapType[1]);
} }
@ -7218,9 +7247,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"READBACK"); json.WriteString(L"READBACK");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[2]); json.AddDetailedStatisticsInfoObject(stats.HeapType[2]);
} }
@ -7229,9 +7255,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"CUSTOM"); json.WriteString(L"CUSTOM");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(customHeaps[!IsUMA()]); json.AddDetailedStatisticsInfoObject(customHeaps[!IsUMA()]);
} }
@ -7245,13 +7268,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"L1"); json.WriteString(L"L1");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Size");
json.WriteNumber(0U);
json.WriteString(L"Budget"); json.WriteString(L"Budget");
WriteBudgetToJson(json, localBudget); WriteBudgetToJson(json, localBudget);
@ -7264,9 +7280,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"DEFAULT"); json.WriteString(L"DEFAULT");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(stats.HeapType[0]); json.AddDetailedStatisticsInfoObject(stats.HeapType[0]);
} }
@ -7275,9 +7288,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"CUSTOM"); json.WriteString(L"CUSTOM");
json.BeginObject(); json.BeginObject();
{ {
json.WriteString(L"Flags");
json.BeginArray(true);
json.EndArray();
json.WriteString(L"Stats"); json.WriteString(L"Stats");
json.AddDetailedStatisticsInfoObject(customHeaps[0]); json.AddDetailedStatisticsInfoObject(customHeaps[0]);
} }

View File

@ -322,10 +322,10 @@ static void ValidateAllocationsDataGPU(const TestContext& ctx, const ComPtr<D3D1
} }
} }
static void SaveStatsStringToFile(const TestContext& ctx, const wchar_t* dstFilePath) static void SaveStatsStringToFile(const TestContext& ctx, const wchar_t* dstFilePath, BOOL detailed = TRUE)
{ {
WCHAR* s = nullptr; WCHAR* s = nullptr;
ctx.allocator->BuildStatsString(&s, TRUE); ctx.allocator->BuildStatsString(&s, detailed);
SaveFile(dstFilePath, s, wcslen(s) * sizeof(WCHAR)); SaveFile(dstFilePath, s, wcslen(s) * sizeof(WCHAR));
ctx.allocator->FreeStatsString(s); ctx.allocator->FreeStatsString(s);
} }

View File

@ -0,0 +1,163 @@
{
"$id": "https://gpuopen.com/vulkan-memory-allocator/schemas/GpuMemDump",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"General": {
"type": "object",
"properties": {
"API": {"type": "string", "enum": ["Vulkan", "Direct3D 12"]},
"GPU": {"type": "string"}
},
"required": ["API", "GPU"]
},
"Total": {"$ref": "#/$defs/Stats"},
"MemoryInfo": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"Flags": {
"type": "array",
"items": {"type": "string"}
},
"Size": {"type": "integer"},
"Budget": {
"type": "object",
"properties": {
"BudgetBytes": {"type": "integer"},
"UsageBytes": {"type": "integer"}
},
"additionalProperties": false
},
"Stats": {"$ref": "#/$defs/Stats"},
"MemoryPools": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"Flags": {
"type": "array",
"items": {"type": "string"}
},
"Stats": {"$ref": "#/$defs/Stats"}
},
"additionalProperties": false
}
}
},
"required": ["Budget", "Stats"],
"additionalProperties": false
}
},
"DefaultPools": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"PreferredBlockSize": {"type": "integer"},
"Blocks": {
"type": "object",
"propertyNames": {"pattern": "[0-9]+"},
"additionalProperties": {"$ref": "#/$defs/Block"}
},
"DedicatedAllocations": {
"type": "array",
"items": {"$ref": "#/$defs/DedicatedAllocation"}
}
}
}
},
"CustomPools": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Name": {"type": "string"},
"Flags": {"type": "array"},
"PreferredBlockSize": {"type": "integer"},
"Blocks": {
"type": "object",
"additionalProperties": {"$ref": "#/$defs/Block"}
},
"DedicatedAllocations": {
"type": "array",
"items": {"$ref": "#/$defs/DedicatedAllocation"}
}
},
"required": ["PreferredBlockSize"],
"additionalProperties": false
}
}
}
},
"required": ["General", "Total", "MemoryInfo"],
"additionalProperties": false,
"$defs": {
"CustomData": {
"type": "string",
"pattern": "^[0-9a-zA-Z]+$"
},
"Stats": {
"type": "object",
"properties": {
"BlockCount": {"type": "integer"},
"BlockBytes": {"type": "integer"},
"AllocationCount": {"type": "integer"},
"AllocationBytes": {"type": "integer"},
"UnusedRangeCount": {"type": "integer"},
"AllocationSizeMin": {"type": "integer"},
"AllocationSizeMax": {"type": "integer"},
"UnusedRangeSizeMin": {"type": "integer"},
"UnusedRangeSizeMax": {"type": "integer"}
},
"required": [
"BlockCount", "BlockBytes",
"AllocationCount", "AllocationBytes",
"UnusedRangeCount"
],
"additionalProperties": false
},
"Block": {
"type": "object",
"properties": {
"MapRefCount": {"type": "integer"},
"TotalBytes": {"type": "integer"},
"UnusedBytes": {"type": "integer"},
"Allocations": {"type": "integer"},
"UnusedRanges": {"type": "integer"},
"Suballocations": {"type": "array", "items": {"$ref": "#/$defs/Suballocation"}}
},
"required": ["TotalBytes", "UnusedBytes", "Allocations", "UnusedRanges"]
},
"DedicatedAllocation": {
"type": "object",
"properties": {
"Type": {"type": "string"},
"Size": {"type": "integer"},
"Usage": {"type": "integer"},
"CustomData": {"$ref": "#/$defs/CustomData"},
"Name": {"type": "string"},
"Layout": {"type": "integer"}
},
"required": ["Type", "Size"],
"additionalProperties": false
},
"Suballocation": {
"type": "object",
"properties": {
"Offset": {"type": "integer"},
"Type": {"type": "string"},
"Size": {"type": "integer"},
"Usage": {"type": "integer"},
"CustomData": {"$ref": "#/$defs/CustomData"},
"Name": {"type": "string"},
"Layout": {"type": "integer"}
},
"required": ["Offset", "Type", "Size"],
"additionalProperties": false
}
}
}

View File

@ -106,9 +106,9 @@ def CalcParams():
maxBlockSize = 0 maxBlockSize = 0
# Get height occupied by every memory pool # Get height occupied by every memory pool
for poolData in data.values(): for poolData in data.values():
height += IMG_MARGIN + FONT_SIZE height += FONT_SIZE + IMG_MARGIN # Memory pool title
height += len(poolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) height += len(poolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
height += len(poolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) height += len(poolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
# Get longest block size # Get longest block size
for dedicatedAlloc in poolData['DedicatedAllocations']: for dedicatedAlloc in poolData['DedicatedAllocations']:
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size']) maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
@ -116,16 +116,15 @@ def CalcParams():
maxBlockSize = max(maxBlockSize, block['Size']) maxBlockSize = max(maxBlockSize, block['Size'])
# Same for custom pools # Same for custom pools
for customPoolData in poolData['CustomPools'].values(): for customPoolData in poolData['CustomPools'].values():
height += len(customPoolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) height += len(customPoolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
height += len(customPoolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) height += len(customPoolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
height += FONT_SIZE * 2 + IMG_MARGIN if len(customPoolData['DedicatedAllocations']) == 0 else 0
# Get longest block size # Get longest block size
for dedicatedAlloc in customPoolData['DedicatedAllocations']: for dedicatedAlloc in customPoolData['DedicatedAllocations']:
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size']) maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
for block in customPoolData['Blocks']: for block in customPoolData['Blocks']:
maxBlockSize = max(maxBlockSize, block['Size']) maxBlockSize = max(maxBlockSize, block['Size'])
return height + FONT_SIZE, (IMG_WIDTH - IMG_MARGIN * 2) / float(maxBlockSize) return height, (IMG_WIDTH - IMG_MARGIN * 2) / float(maxBlockSize)
def BytesToStr(bytes): def BytesToStr(bytes):
if bytes < 1024: if bytes < 1024:
@ -306,7 +305,7 @@ if __name__ == '__main__':
draw.text((IMG_MARGIN, y), "Custom pool %s block %s" % (poolName, block['ID']), fill=COLOR_TEXT_H2, font=font) draw.text((IMG_MARGIN, y), "Custom pool %s block %s" % (poolName, block['ID']), fill=COLOR_TEXT_H2, font=font)
y += FONT_SIZE + IMG_MARGIN y += FONT_SIZE + IMG_MARGIN
DrawBlock(draw, y, block, pixelsPerByte) DrawBlock(draw, y, block, pixelsPerByte)
y += 2 * (FONT_SIZE + IMG_MARGIN) y += MAP_SIZE + IMG_MARGIN
index = 0 index = 0
for dedicatedAlloc in pool['DedicatedAllocations']: for dedicatedAlloc in pool['DedicatedAllocations']:
draw.text((IMG_MARGIN, y), "Custom pool %s dedicated allocation %d" % (poolName, index), fill=COLOR_TEXT_H2, font=font) draw.text((IMG_MARGIN, y), "Custom pool %s dedicated allocation %d" % (poolName, index), fill=COLOR_TEXT_H2, font=font)