Added subsequent, unique, numeric IDs to memory blocks and custom pools. They are dumped in JSON. JSON format changed: "Pools" and "Blocks" arrays are now objects, where key is pool/block ID, and value is as before. Applied appropriate changes in VmaDumpVis.py - it now shows pool and block ID from the dump.

This commit is contained in:
Adam Sawicki 2018-06-01 15:20:49 +02:00
parent 31695cf349
commit 6a0a85a5c0
2 changed files with 61 additions and 33 deletions

View File

@ -4147,12 +4147,14 @@ public:
void Init( void Init(
uint32_t newMemoryTypeIndex, uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory, VkDeviceMemory newMemory,
VkDeviceSize newSize); VkDeviceSize newSize,
uint32_t id);
// Always call before destruction. // Always call before destruction.
void Destroy(VmaAllocator allocator); void Destroy(VmaAllocator allocator);
VkDeviceMemory GetDeviceMemory() const { return m_hMemory; } VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
uint32_t GetId() const { return m_Id; }
void* GetMappedData() const { return m_pMappedData; } void* GetMappedData() const { return m_pMappedData; }
// Validates all data structures inside this object. If not valid, returns false. // Validates all data structures inside this object. If not valid, returns false.
@ -4173,6 +4175,7 @@ public:
private: private:
uint32_t m_MemoryTypeIndex; uint32_t m_MemoryTypeIndex;
uint32_t m_Id;
VkDeviceMemory m_hMemory; VkDeviceMemory m_hMemory;
// Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory. // Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
@ -4276,6 +4279,7 @@ private:
of a VkDeviceMemory. */ of a VkDeviceMemory. */
bool m_HasEmptyBlock; bool m_HasEmptyBlock;
VmaDefragmentator* m_pDefragmentator; VmaDefragmentator* m_pDefragmentator;
uint32_t m_NextBlockId;
VkDeviceSize CalcMaxBlockSize() const; VkDeviceSize CalcMaxBlockSize() const;
@ -4295,17 +4299,21 @@ struct VmaPool_T
public: public:
VmaBlockVector m_BlockVector; VmaBlockVector m_BlockVector;
// Takes ownership.
VmaPool_T( VmaPool_T(
VmaAllocator hAllocator, VmaAllocator hAllocator,
const VmaPoolCreateInfo& createInfo); const VmaPoolCreateInfo& createInfo);
~VmaPool_T(); ~VmaPool_T();
VmaBlockVector& GetBlockVector() { return m_BlockVector; } VmaBlockVector& GetBlockVector() { return m_BlockVector; }
uint32_t GetId() const { return m_Id; }
void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
#if VMA_STATS_STRING_ENABLED #if VMA_STATS_STRING_ENABLED
//void PrintDetailedMap(class VmaStringBuilder& sb); //void PrintDetailedMap(class VmaStringBuilder& sb);
#endif #endif
private:
uint32_t m_Id;
}; };
class VmaDefragmentator class VmaDefragmentator
@ -4569,6 +4577,7 @@ private:
VMA_MUTEX m_PoolsMutex; VMA_MUTEX m_PoolsMutex;
// Protected by m_PoolsMutex. Sorted by pointer value. // Protected by m_PoolsMutex. Sorted by pointer value.
VmaVector<VmaPool, VmaStlAllocator<VmaPool> > m_Pools; VmaVector<VmaPool, VmaStlAllocator<VmaPool> > m_Pools;
uint32_t m_NextPoolId;
VmaVulkanFunctions m_VulkanFunctions; VmaVulkanFunctions m_VulkanFunctions;
@ -6366,6 +6375,7 @@ void VmaBlockMetadata::UnregisterFreeSuballocation(VmaSuballocationList::iterato
VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) : VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
m_Metadata(hAllocator), m_Metadata(hAllocator),
m_MemoryTypeIndex(UINT32_MAX), m_MemoryTypeIndex(UINT32_MAX),
m_Id(0),
m_hMemory(VK_NULL_HANDLE), m_hMemory(VK_NULL_HANDLE),
m_MapCount(0), m_MapCount(0),
m_pMappedData(VMA_NULL) m_pMappedData(VMA_NULL)
@ -6375,11 +6385,13 @@ VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
void VmaDeviceMemoryBlock::Init( void VmaDeviceMemoryBlock::Init(
uint32_t newMemoryTypeIndex, uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory, VkDeviceMemory newMemory,
VkDeviceSize newSize) VkDeviceSize newSize,
uint32_t id)
{ {
VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
m_MemoryTypeIndex = newMemoryTypeIndex; m_MemoryTypeIndex = newMemoryTypeIndex;
m_Id = id;
m_hMemory = newMemory; m_hMemory = newMemory;
m_Metadata.Init(newSize); m_Metadata.Init(newSize);
@ -6572,7 +6584,8 @@ VmaBlockVector::VmaBlockVector(
m_IsCustomPool(isCustomPool), m_IsCustomPool(isCustomPool),
m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())), m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
m_HasEmptyBlock(false), m_HasEmptyBlock(false),
m_pDefragmentator(VMA_NULL) m_pDefragmentator(VMA_NULL),
m_NextBlockId(0)
{ {
} }
@ -7000,7 +7013,8 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
pBlock->Init( pBlock->Init(
m_MemoryTypeIndex, m_MemoryTypeIndex,
mem, mem,
allocInfo.allocationSize); allocInfo.allocationSize,
m_NextBlockId++);
m_Blocks.push_back(pBlock); m_Blocks.push_back(pBlock);
if(pNewBlockIndex != VMA_NULL) if(pNewBlockIndex != VMA_NULL)
@ -7056,12 +7070,16 @@ void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
} }
json.WriteString("Blocks"); json.WriteString("Blocks");
json.BeginArray(); json.BeginObject();
for(size_t i = 0; i < m_Blocks.size(); ++i) for(size_t i = 0; i < m_Blocks.size(); ++i)
{ {
json.BeginString();
json.ContinueString(m_Blocks[i]->GetId());
json.EndString();
m_Blocks[i]->m_Metadata.PrintDetailedMap(json); m_Blocks[i]->m_Metadata.PrintDetailedMap(json);
} }
json.EndArray(); json.EndObject();
json.EndObject(); json.EndObject();
} }
@ -7481,7 +7499,8 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_PreferredLargeHeapBlockSize(0), m_PreferredLargeHeapBlockSize(0),
m_PhysicalDevice(pCreateInfo->physicalDevice), m_PhysicalDevice(pCreateInfo->physicalDevice),
m_CurrentFrameIndex(0), m_CurrentFrameIndex(0),
m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())) m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
m_NextPoolId(0)
{ {
VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device); VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device);
@ -8372,6 +8391,7 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo
// Add to m_Pools. // Add to m_Pools.
{ {
VmaMutexLock lock(m_PoolsMutex, m_UseMutex); VmaMutexLock lock(m_PoolsMutex, m_UseMutex);
(*pPool)->SetId(m_NextPoolId++);
VmaVectorInsertSorted<VmaPointerLess>(m_Pools, *pPool); VmaVectorInsertSorted<VmaPointerLess>(m_Pools, *pPool);
} }
@ -8662,12 +8682,16 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
if(poolCount > 0) if(poolCount > 0)
{ {
json.WriteString("Pools"); json.WriteString("Pools");
json.BeginArray(); json.BeginObject();
for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex) for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
{ {
json.BeginString();
json.ContinueString(m_Pools[poolIndex]->GetId());
json.EndString();
m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json); m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json);
} }
json.EndArray(); json.EndObject();
} }
} }
} }

View File

@ -46,10 +46,10 @@ args = argParser.parse_args()
data = {} data = {}
def ProcessBlock(dstBlockList, objBlock): def ProcessBlock(dstBlockList, iBlockId, objBlock):
iBlockSize = int(objBlock['TotalBytes']) iBlockSize = int(objBlock['TotalBytes'])
arrSuballocs = objBlock['Suballocations'] arrSuballocs = objBlock['Suballocations']
dstBlockObj = {'Size':iBlockSize, 'Suballocations':[]} dstBlockObj = {'ID': iBlockId, 'Size':iBlockSize, 'Suballocations':[]}
dstBlockList.append(dstBlockObj) dstBlockList.append(dstBlockObj)
for objSuballoc in arrSuballocs: for objSuballoc in arrSuballocs:
dstBlockObj['Suballocations'].append((objSuballoc['Type'], int(objSuballoc['Size']), int(objSuballoc['Usage']) if ('Usage' in objSuballoc) else 0)) dstBlockObj['Suballocations'].append((objSuballoc['Type'], int(objSuballoc['Size']), int(objSuballoc['Usage']) if ('Usage' in objSuballoc) else 0))
@ -60,7 +60,7 @@ def GetDataForMemoryType(iMemTypeIndex):
if iMemTypeIndex in data: if iMemTypeIndex in data:
return data[iMemTypeIndex] return data[iMemTypeIndex]
else: else:
newMemTypeData = {'DedicatedAllocations':[], 'DefaultPoolBlocks':[], 'CustomPoolBlocks':[]} newMemTypeData = {'DedicatedAllocations':[], 'DefaultPoolBlocks':[], 'CustomPools':{}}
data[iMemTypeIndex] = newMemTypeData data[iMemTypeIndex] = newMemTypeData
return newMemTypeData return newMemTypeData
@ -81,9 +81,10 @@ def CalcParams():
iImgSizeY += len(dictMemType['DefaultPoolBlocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) iImgSizeY += len(dictMemType['DefaultPoolBlocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
for objBlock in dictMemType['DefaultPoolBlocks']: for objBlock in dictMemType['DefaultPoolBlocks']:
iMaxBlockSize = max(iMaxBlockSize, objBlock['Size']) iMaxBlockSize = max(iMaxBlockSize, objBlock['Size'])
iImgSizeY += len(dictMemType['CustomPoolBlocks']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE) iImgSizeY += len(dictMemType['CustomPools']) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
for objBlock in dictMemType['CustomPoolBlocks']: for listPool in dictMemType['CustomPools'].values():
iMaxBlockSize = max(iMaxBlockSize, objBlock['Size']) for objBlock in listPool:
iMaxBlockSize = max(iMaxBlockSize, objBlock['Size'])
fPixelsPerByte = (IMG_SIZE_X - IMG_MARGIN * 2) / float(iMaxBlockSize) fPixelsPerByte = (IMG_SIZE_X - IMG_MARGIN * 2) / float(iMaxBlockSize)
return iImgSizeY, fPixelsPerByte return iImgSizeY, fPixelsPerByte
@ -180,16 +181,17 @@ if 'DefaultPools' in jsonSrc:
assert sType[:5] == 'Type ' assert sType[:5] == 'Type '
iType = int(sType[5:]) iType = int(sType[5:])
typeData = GetDataForMemoryType(iType) typeData = GetDataForMemoryType(iType)
for objBlock in tType[1]['Blocks']: for sBlockId, objBlock in tType[1]['Blocks'].items():
ProcessBlock(typeData['DefaultPoolBlocks'], objBlock) ProcessBlock(typeData['DefaultPoolBlocks'], int(sBlockId), objBlock)
if 'Pools' in jsonSrc: if 'Pools' in jsonSrc:
arrPools = jsonSrc['Pools'] objPools = jsonSrc['Pools']
for objPool in arrPools: for sPoolId, objPool in objPools.items():
iType = int(objPool['MemoryTypeIndex']) iType = int(objPool['MemoryTypeIndex'])
typeData = GetDataForMemoryType(iType) typeData = GetDataForMemoryType(iType)
arrBlocks = objPool['Blocks'] objBlocks = objPool['Blocks']
for objBlock in arrBlocks: for sBlockId, objBlock in objBlocks.items():
ProcessBlock(typeData['CustomPoolBlocks'], objBlock) typeData['CustomPools'][int(sPoolId)] = []
ProcessBlock(typeData['CustomPools'][int(sPoolId)], int(sBlockId), objBlock)
iImgSizeY, fPixelsPerByte = CalcParams() iImgSizeY, fPixelsPerByte = CalcParams()
@ -230,20 +232,19 @@ for iMemTypeIndex in sorted(data.keys()):
DrawDedicatedAllocationBlock(draw, y, tDedicatedAlloc) DrawDedicatedAllocationBlock(draw, y, tDedicatedAlloc)
y += MAP_SIZE + IMG_MARGIN y += MAP_SIZE + IMG_MARGIN
index += 1 index += 1
index = 0
for objBlock in dictMemType['DefaultPoolBlocks']: for objBlock in dictMemType['DefaultPoolBlocks']:
draw.text((IMG_MARGIN, y), "Default pool block %d" % index, fill=COLOR_TEXT_H2, font=font) draw.text((IMG_MARGIN, y), "Default pool block %d" % objBlock['ID'], fill=COLOR_TEXT_H2, font=font)
y += FONT_SIZE + IMG_MARGIN y += FONT_SIZE + IMG_MARGIN
DrawBlock(draw, y, objBlock) DrawBlock(draw, y, objBlock)
y += MAP_SIZE + IMG_MARGIN y += MAP_SIZE + IMG_MARGIN
index += 1
index = 0 index = 0
for objBlock in dictMemType['CustomPoolBlocks']: for iPoolId, listPool in dictMemType['CustomPools'].items():
draw.text((IMG_MARGIN, y), "Custom pool block %d" % index, fill=COLOR_TEXT_H2, font=font) for objBlock in listPool:
y += FONT_SIZE + IMG_MARGIN draw.text((IMG_MARGIN, y), "Custom pool %d block %d" % (iPoolId, objBlock['ID']), fill=COLOR_TEXT_H2, font=font)
DrawBlock(draw, y, objBlock) y += FONT_SIZE + IMG_MARGIN
y += MAP_SIZE + IMG_MARGIN DrawBlock(draw, y, objBlock)
index += 1 y += MAP_SIZE + IMG_MARGIN
index += 1
del draw del draw
img.save(args.output) img.save(args.output)
@ -254,9 +255,12 @@ Main data structure - variable `data` - is a dictionary. Key is integer - memory
- [1]: Size : integer - [1]: Size : integer
- [2]: Usage : integer (0 if unknown) - [2]: Usage : integer (0 if unknown)
- Fixed key 'DefaultPoolBlocks'. Value is list of objects, each containing dictionary with: - Fixed key 'DefaultPoolBlocks'. Value is list of objects, each containing dictionary with:
- Fixed key 'ID'. Value is int.
- Fixed key 'Size'. Value is int. - Fixed key 'Size'. Value is int.
- Fixed key 'Suballocations'. Value is list of tuples as above. - Fixed key 'Suballocations'. Value is list of tuples as above.
- Fixed key 'CustomPoolBlocks'. Value is list of objects, each containing dictionary with: - Fixed key 'CustomPools'. Value is dictionary.
- Key is integer pool ID. Value is list of objects, each containing dictionary with:
- Fixed key 'ID'. Value is int.
- Fixed key 'Size'. Value is int. - Fixed key 'Size'. Value is int.
- Fixed key 'Suballocations'. Value is list of tuples as above. - Fixed key 'Suballocations'. Value is list of tuples as above.
""" """