Fixes in GpuMemDumpVis.py regarding image height calculation

Added GpuMemDump.schema.json.
Minor improvement in SaveAllocatorStatsToFile.
diff --git a/src/SparseBindingTest.cpp b/src/SparseBindingTest.cpp
index c5383c8..9f58330 100644
--- a/src/SparseBindingTest.cpp
+++ b/src/SparseBindingTest.cpp
@@ -38,7 +38,7 @@
 
 void BeginSingleTimeCommands();
 void EndSingleTimeCommands();
-void SaveAllocatorStatsToFile(const wchar_t* filePath);
+void SaveAllocatorStatsToFile(const wchar_t* filePath, bool detailed = true);
 void LoadShader(std::vector<char>& out, const char* fileName);
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 5c90ef0..dfa08d6 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -719,12 +719,12 @@
     return res;
 }
 
-void SaveAllocatorStatsToFile(const wchar_t* filePath)
+void SaveAllocatorStatsToFile(const wchar_t* filePath, bool detailed = true)
 {
 #if !defined(VMA_STATS_STRING_ENABLED) || VMA_STATS_STRING_ENABLED
     wprintf(L"Saving JSON dump to file \"%s\"\n", filePath);
     char* stats;
-    vmaBuildStatsString(g_hAllocator, &stats, VK_TRUE);
+    vmaBuildStatsString(g_hAllocator, &stats, detailed ? VK_TRUE : VK_FALSE);
     SaveFile(filePath, stats, strlen(stats));
     vmaFreeStatsString(g_hAllocator, stats);
 #endif
diff --git a/tools/GpuMemDumpVis/GpuMemDump.schema.json b/tools/GpuMemDumpVis/GpuMemDump.schema.json
new file mode 100644
index 0000000..4d3331c
--- /dev/null
+++ b/tools/GpuMemDumpVis/GpuMemDump.schema.json
@@ -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

+        }

+    }

+}

diff --git a/tools/GpuMemDumpVis/GpuMemDumpVis.py b/tools/GpuMemDumpVis/GpuMemDumpVis.py
index b225306..42800ea 100644
--- a/tools/GpuMemDumpVis/GpuMemDumpVis.py
+++ b/tools/GpuMemDumpVis/GpuMemDumpVis.py
@@ -106,9 +106,9 @@
     maxBlockSize = 0
     # Get height occupied by every memory pool
     for poolData in data.values():
-        height += IMG_MARGIN + FONT_SIZE
-        height += len(poolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
-        height += len(poolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
+        height += FONT_SIZE + IMG_MARGIN # Memory pool title
+        height += len(poolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
+        height += len(poolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
         # Get longest block size
         for dedicatedAlloc in poolData['DedicatedAllocations']:
             maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
@@ -116,16 +116,15 @@
             maxBlockSize = max(maxBlockSize, block['Size'])
         # Same for custom pools
         for customPoolData in poolData['CustomPools'].values():
-            height += len(customPoolData['DedicatedAllocations']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
-            height += len(customPoolData['Blocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
-            height += FONT_SIZE * 2 + IMG_MARGIN if len(customPoolData['DedicatedAllocations']) == 0 else 0
+            height += len(customPoolData['Blocks']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
+            height += len(customPoolData['DedicatedAllocations']) * (FONT_SIZE + MAP_SIZE + IMG_MARGIN * 2)
             # Get longest block size
             for dedicatedAlloc in customPoolData['DedicatedAllocations']:
                 maxBlockSize = max(maxBlockSize, dedicatedAlloc['Size'])
             for block in customPoolData['Blocks']:
                 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):
     if bytes < 1024:
@@ -306,7 +305,7 @@
                 draw.text((IMG_MARGIN, y), "Custom pool %s block %s" % (poolName, block['ID']), fill=COLOR_TEXT_H2, font=font)
                 y += FONT_SIZE + IMG_MARGIN
                 DrawBlock(draw, y, block, pixelsPerByte)
-                y += 2 * (FONT_SIZE + IMG_MARGIN)
+                y += MAP_SIZE + IMG_MARGIN
             index = 0
             for dedicatedAlloc in pool['DedicatedAllocations']:
                 draw.text((IMG_MARGIN, y), "Custom pool %s dedicated allocation %d" % (poolName, index), fill=COLOR_TEXT_H2, font=font)