Skip to content

Commit 19322e3

Browse files
Fixes in JSON dump format. Fixes in GpuMemDumpVis.py regarding image height calculation.
Added GpuMemDump.schema.json.
1 parent 2d7d710 commit 19322e3

File tree

4 files changed

+209
-37
lines changed

4 files changed

+209
-37
lines changed

src/D3D12MemAlloc.cpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <algorithm>
2828
#include <utility>
2929
#include <cstdlib>
30+
#include <cstdint>
3031
#include <malloc.h> // for _aligned_malloc, _aligned_free
3132
#ifndef _WIN32
3233
#include <shared_mutex>
@@ -377,7 +378,15 @@ template <typename T>
377378
static T RoundDiv(T x, T y) { return (x + (y / (T)2)) / y; }
378379
template <typename T>
379380
static T DivideRoundingUp(T x, T y) { return (x + y - 1) / y; }
380-
381+
382+
static WCHAR HexDigitToChar(UINT8 digit)
383+
{
384+
if(digit < 10)
385+
return L'0' + digit;
386+
else
387+
return L'A' + (digit - 10);
388+
}
389+
381390
/*
382391
Performs binary search and returns iterator to first element that is greater or
383392
equal to `key`, according to comparison `cmp`.
@@ -1180,6 +1189,7 @@ class StringBuilder
11801189
void AddNewLine() { Add(L'\n'); }
11811190
void AddNumber(UINT num);
11821191
void AddNumber(UINT64 num);
1192+
void AddPointer(const void* ptr);
11831193

11841194
private:
11851195
Vector<WCHAR> m_Data;
@@ -1224,6 +1234,22 @@ void StringBuilder::AddNumber(UINT64 num)
12241234
while (num);
12251235
Add(p);
12261236
}
1237+
1238+
void StringBuilder::AddPointer(const void* ptr)
1239+
{
1240+
WCHAR buf[21];
1241+
uintptr_t num = (uintptr_t)ptr;
1242+
buf[20] = L'\0';
1243+
WCHAR *p = &buf[20];
1244+
do
1245+
{
1246+
*--p = HexDigitToChar((UINT8)(num & 0xF));
1247+
num >>= 4;
1248+
}
1249+
while (num);
1250+
Add(p);
1251+
}
1252+
12271253
#endif // _D3D12MA_STRING_BUILDER_FUNCTIONS
12281254
#endif // _D3D12MA_STRING_BUILDER
12291255

@@ -1267,6 +1293,7 @@ class JsonWriter
12671293
// Posts next part of an open string. The number is converted to decimal characters.
12681294
void ContinueString(UINT num);
12691295
void ContinueString(UINT64 num);
1296+
void ContinueString_Pointer(const void* ptr);
12701297
// Posts next part of an open string. Pointer value is converted to characters
12711298
// using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00
12721299
// void ContinueString_Pointer(const void* ptr);
@@ -1452,6 +1479,12 @@ void JsonWriter::ContinueString(UINT64 num)
14521479
m_SB.AddNumber(num);
14531480
}
14541481

1482+
void JsonWriter::ContinueString_Pointer(const void* ptr)
1483+
{
1484+
D3D12MA_ASSERT(m_InsideString);
1485+
m_SB.AddPointer(ptr);
1486+
}
1487+
14551488
void JsonWriter::EndString(LPCWSTR pStr)
14561489
{
14571490
D3D12MA_ASSERT(m_InsideString);
@@ -1524,7 +1557,9 @@ void JsonWriter::AddAllocationToObject(const Allocation& alloc)
15241557
if (privateData)
15251558
{
15261559
WriteString(L"CustomData");
1527-
WriteNumber((uintptr_t)privateData);
1560+
BeginString();
1561+
ContinueString_Pointer(privateData);
1562+
EndString();
15281563
}
15291564

15301565
LPCWSTR name = alloc.GetName();
@@ -7196,9 +7231,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
71967231
json.WriteString(L"DEFAULT");
71977232
json.BeginObject();
71987233
{
7199-
json.WriteString(L"Flags");
7200-
json.BeginArray(true);
7201-
json.EndArray();
72027234
json.WriteString(L"Stats");
72037235
json.AddDetailedStatisticsInfoObject(stats.HeapType[0]);
72047236
}
@@ -7207,9 +7239,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72077239
json.WriteString(L"UPLOAD");
72087240
json.BeginObject();
72097241
{
7210-
json.WriteString(L"Flags");
7211-
json.BeginArray(true);
7212-
json.EndArray();
72137242
json.WriteString(L"Stats");
72147243
json.AddDetailedStatisticsInfoObject(stats.HeapType[1]);
72157244
}
@@ -7218,9 +7247,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72187247
json.WriteString(L"READBACK");
72197248
json.BeginObject();
72207249
{
7221-
json.WriteString(L"Flags");
7222-
json.BeginArray(true);
7223-
json.EndArray();
72247250
json.WriteString(L"Stats");
72257251
json.AddDetailedStatisticsInfoObject(stats.HeapType[2]);
72267252
}
@@ -7229,9 +7255,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72297255
json.WriteString(L"CUSTOM");
72307256
json.BeginObject();
72317257
{
7232-
json.WriteString(L"Flags");
7233-
json.BeginArray(true);
7234-
json.EndArray();
72357258
json.WriteString(L"Stats");
72367259
json.AddDetailedStatisticsInfoObject(customHeaps[!IsUMA()]);
72377260
}
@@ -7245,13 +7268,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72457268
json.WriteString(L"L1");
72467269
json.BeginObject();
72477270
{
7248-
json.WriteString(L"Flags");
7249-
json.BeginArray(true);
7250-
json.EndArray();
7251-
7252-
json.WriteString(L"Size");
7253-
json.WriteNumber(0U);
7254-
72557271
json.WriteString(L"Budget");
72567272
WriteBudgetToJson(json, localBudget);
72577273

@@ -7264,9 +7280,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72647280
json.WriteString(L"DEFAULT");
72657281
json.BeginObject();
72667282
{
7267-
json.WriteString(L"Flags");
7268-
json.BeginArray(true);
7269-
json.EndArray();
72707283
json.WriteString(L"Stats");
72717284
json.AddDetailedStatisticsInfoObject(stats.HeapType[0]);
72727285
}
@@ -7275,9 +7288,6 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
72757288
json.WriteString(L"CUSTOM");
72767289
json.BeginObject();
72777290
{
7278-
json.WriteString(L"Flags");
7279-
json.BeginArray(true);
7280-
json.EndArray();
72817291
json.WriteString(L"Stats");
72827292
json.AddDetailedStatisticsInfoObject(customHeaps[0]);
72837293
}

src/Tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,10 @@ static void ValidateAllocationsDataGPU(const TestContext& ctx, const ComPtr<D3D1
322322
}
323323
}
324324

325-
static void SaveStatsStringToFile(const TestContext& ctx, const wchar_t* dstFilePath)
325+
static void SaveStatsStringToFile(const TestContext& ctx, const wchar_t* dstFilePath, BOOL detailed = TRUE)
326326
{
327327
WCHAR* s = nullptr;
328-
ctx.allocator->BuildStatsString(&s, TRUE);
328+
ctx.allocator->BuildStatsString(&s, detailed);
329329
SaveFile(dstFilePath, s, wcslen(s) * sizeof(WCHAR));
330330
ctx.allocator->FreeStatsString(s);
331331
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
{
2+
"$id": "https://gpuopen.com/vulkan-memory-allocator/schemas/GpuMemDump",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"type": "object",
5+
"properties": {
6+
"General": {
7+
"type": "object",
8+
"properties": {
9+
"API": {"type": "string", "enum": ["Vulkan", "Direct3D 12"]},
10+
"GPU": {"type": "string"}
11+
},
12+
"required": ["API", "GPU"]
13+
},
14+
"Total": {"$ref": "#/$defs/Stats"},
15+
"MemoryInfo": {
16+
"type": "object",
17+
"additionalProperties": {
18+
"type": "object",
19+
"properties": {
20+
"Flags": {
21+
"type": "array",
22+
"items": {"type": "string"}
23+
},
24+
"Size": {"type": "integer"},
25+
"Budget": {
26+
"type": "object",
27+
"properties": {
28+
"BudgetBytes": {"type": "integer"},
29+
"UsageBytes": {"type": "integer"}
30+
},
31+
"additionalProperties": false
32+
},
33+
"Stats": {"$ref": "#/$defs/Stats"},
34+
"MemoryPools": {
35+
"type": "object",
36+
"additionalProperties": {
37+
"type": "object",
38+
"properties": {
39+
"Flags": {
40+
"type": "array",
41+
"items": {"type": "string"}
42+
},
43+
"Stats": {"$ref": "#/$defs/Stats"}
44+
},
45+
"additionalProperties": false
46+
}
47+
}
48+
},
49+
"required": ["Budget", "Stats"],
50+
"additionalProperties": false
51+
}
52+
},
53+
"DefaultPools": {
54+
"type": "object",
55+
"additionalProperties": {
56+
"type": "object",
57+
"properties": {
58+
"PreferredBlockSize": {"type": "integer"},
59+
"Blocks": {
60+
"type": "object",
61+
"propertyNames": {"pattern": "[0-9]+"},
62+
"additionalProperties": {"$ref": "#/$defs/Block"}
63+
},
64+
"DedicatedAllocations": {
65+
"type": "array",
66+
"items": {"$ref": "#/$defs/DedicatedAllocation"}
67+
}
68+
}
69+
}
70+
},
71+
"CustomPools": {
72+
"type": "object",
73+
"additionalProperties": {
74+
"type": "array",
75+
"items": {
76+
"type": "object",
77+
"properties": {
78+
"Name": {"type": "string"},
79+
"Flags": {"type": "array"},
80+
"PreferredBlockSize": {"type": "integer"},
81+
"Blocks": {
82+
"type": "object",
83+
"additionalProperties": {"$ref": "#/$defs/Block"}
84+
},
85+
"DedicatedAllocations": {
86+
"type": "array",
87+
"items": {"$ref": "#/$defs/DedicatedAllocation"}
88+
}
89+
},
90+
"required": ["PreferredBlockSize"],
91+
"additionalProperties": false
92+
}
93+
}
94+
}
95+
},
96+
"required": ["General", "Total", "MemoryInfo"],
97+
"additionalProperties": false,
98+
"$defs": {
99+
"CustomData": {
100+
"type": "string",
101+
"pattern": "^[0-9a-zA-Z]+$"
102+
},
103+
"Stats": {
104+
"type": "object",
105+
"properties": {
106+
"BlockCount": {"type": "integer"},
107+
"BlockBytes": {"type": "integer"},
108+
"AllocationCount": {"type": "integer"},
109+
"AllocationBytes": {"type": "integer"},
110+
"UnusedRangeCount": {"type": "integer"},
111+
"AllocationSizeMin": {"type": "integer"},
112+
"AllocationSizeMax": {"type": "integer"},
113+
"UnusedRangeSizeMin": {"type": "integer"},
114+
"UnusedRangeSizeMax": {"type": "integer"}
115+
},
116+
"required": [
117+
"BlockCount", "BlockBytes",
118+
"AllocationCount", "AllocationBytes",
119+
"UnusedRangeCount"
120+
],
121+
"additionalProperties": false
122+
},
123+
"Block": {
124+
"type": "object",
125+
"properties": {
126+
"MapRefCount": {"type": "integer"},
127+
"TotalBytes": {"type": "integer"},
128+
"UnusedBytes": {"type": "integer"},
129+
"Allocations": {"type": "integer"},
130+
"UnusedRanges": {"type": "integer"},
131+
"Suballocations": {"type": "array", "items": {"$ref": "#/$defs/Suballocation"}}
132+
},
133+
"required": ["TotalBytes", "UnusedBytes", "Allocations", "UnusedRanges"]
134+
},
135+
"DedicatedAllocation": {
136+
"type": "object",
137+
"properties": {
138+
"Type": {"type": "string"},
139+
"Size": {"type": "integer"},
140+
"Usage": {"type": "integer"},
141+
"CustomData": {"$ref": "#/$defs/CustomData"},
142+
"Name": {"type": "string"},
143+
"Layout": {"type": "integer"}
144+
},
145+
"required": ["Type", "Size"],
146+
"additionalProperties": false
147+
},
148+
"Suballocation": {
149+
"type": "object",
150+
"properties": {
151+
"Offset": {"type": "integer"},
152+
"Type": {"type": "string"},
153+
"Size": {"type": "integer"},
154+
"Usage": {"type": "integer"},
155+
"CustomData": {"$ref": "#/$defs/CustomData"},
156+
"Name": {"type": "string"},
157+
"Layout": {"type": "integer"}
158+
},
159+
"required": ["Offset", "Type", "Size"],
160+
"additionalProperties": false
161+
}
162+
}
163+
}

tools/GpuMemDumpVis/GpuMemDumpVis.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,25 @@ def CalcParams():
106106
maxBlockSize = 0
107107
# Get height occupied by every memory pool
108108
for poolData in data.values():
109-
height += IMG_MARGIN + FONT_SIZE
110-
height += len(poolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
111-
height += len(poolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
109+
height += FONT_SIZE + IMG_MARGIN # Memory pool title
110+
height += len(poolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
111+
height += len(poolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
112112
# Get longest block size
113113
for dedicatedAlloc in poolData['DedicatedAllocations']:
114114
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
115115
for block in poolData['Blocks']:
116116
maxBlockSize = max(maxBlockSize, block['Size'])
117117
# Same for custom pools
118118
for customPoolData in poolData['CustomPools'].values():
119-
height += len(customPoolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
120-
height += len(customPoolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
121-
height += FONT_SIZE * 2 + IMG_MARGIN if len(customPoolData['DedicatedAllocations']) == 0 else 0
119+
height += len(customPoolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
120+
height += len(customPoolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
122121
# Get longest block size
123122
for dedicatedAlloc in customPoolData['DedicatedAllocations']:
124123
maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
125124
for block in customPoolData['Blocks']:
126125
maxBlockSize = max(maxBlockSize, block['Size'])
127126

128-
return height + FONT_SIZE, (IMG_WIDTH - IMG_MARGIN * 2) / float(maxBlockSize)
127+
return height, (IMG_WIDTH - IMG_MARGIN * 2) / float(maxBlockSize)
129128

130129
def BytesToStr(bytes):
131130
if bytes < 1024:
@@ -306,7 +305,7 @@ def DrawDedicatedAllocationBlock(draw, y, dedicatedAlloc, pixelsPerByte):
306305
draw.text((IMG_MARGIN, y), "Custom pool %s block %s" % (poolName, block['ID']), fill=COLOR_TEXT_H2, font=font)
307306
y += FONT_SIZE + IMG_MARGIN
308307
DrawBlock(draw, y, block, pixelsPerByte)
309-
y += 2 * (FONT_SIZE + IMG_MARGIN)
308+
y += MAP_SIZE + IMG_MARGIN
310309
index = 0
311310
for dedicatedAlloc in pool['DedicatedAllocations']:
312311
draw.text((IMG_MARGIN, y), "Custom pool %s dedicated allocation %d" % (poolName, index), fill=COLOR_TEXT_H2, font=font)

0 commit comments

Comments
 (0)