From 853b25168956a619685bef03985d831dc2934aa6 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Thu, 14 Sep 2017 11:11:36 +0200 Subject: [PATCH] Fixed reporting custom pools and own allocations in statistics. Improved JSON printing of custom pools. Added convenience function VmaAllocator_T::MemoryTypeIndexToHeapIndex. --- bin/VulkanSample_Release_2015.exe | Bin 96768 -> 99328 bytes src/vk_mem_alloc.h | 198 ++++++++++++++++++++++-------- 2 files changed, 146 insertions(+), 52 deletions(-) diff --git a/bin/VulkanSample_Release_2015.exe b/bin/VulkanSample_Release_2015.exe index 6f5773fc47a63f9db401adcadff6b41e0c3792ba..fda2ba19f408b26b27740d89cea228f74b0b80f1 100644 GIT binary patch delta 37720 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 1) + { + json.WriteString("AllocationSize"); + json.BeginObject(true); + json.WriteString("Min"); + json.WriteNumber(stat.AllocationSizeMin); + json.WriteString("Avg"); + json.WriteNumber(stat.AllocationSizeAvg); + json.WriteString("Max"); + json.WriteNumber(stat.AllocationSizeMax); + json.EndObject(); + } - json.WriteString("UnusedRangeSize"); - json.BeginObject(true); - json.WriteString("Min"); - json.WriteNumber(stat.UnusedRangeSizeMin); - json.WriteString("Avg"); - json.WriteNumber(stat.UnusedRangeSizeAvg); - json.WriteString("Max"); - json.WriteNumber(stat.UnusedRangeSizeMax); - json.EndObject(); + if(stat.UnusedRangeCount > 1) + { + json.WriteString("UnusedRangeSize"); + json.BeginObject(true); + json.WriteString("Min"); + json.WriteNumber(stat.UnusedRangeSizeMin); + json.WriteString("Avg"); + json.WriteNumber(stat.UnusedRangeSizeAvg); + json.WriteString("Max"); + json.WriteNumber(stat.UnusedRangeSizeMax); + json.EndObject(); + } json.EndObject(); } @@ -4964,24 +4990,24 @@ static void InitStatInfo(VmaStatInfo& outInfo) outInfo.UnusedRangeSizeMin = UINT64_MAX; } -static void CalcAllocationStatInfo(VmaStatInfo& outInfo, const VmaDeviceMemoryBlock& alloc) +static void CalcAllocationStatInfo(VmaStatInfo& outInfo, const VmaDeviceMemoryBlock& block) { outInfo.BlockCount = 1; - const uint32_t rangeCount = (uint32_t)alloc.m_Suballocations.size(); - outInfo.AllocationCount = rangeCount - alloc.m_FreeCount; - outInfo.UnusedRangeCount = alloc.m_FreeCount; + const uint32_t rangeCount = (uint32_t)block.m_Suballocations.size(); + outInfo.AllocationCount = rangeCount - block.m_FreeCount; + outInfo.UnusedRangeCount = block.m_FreeCount; - outInfo.UnusedBytes = alloc.m_SumFreeSize; - outInfo.UsedBytes = alloc.m_Size - outInfo.UnusedBytes; + outInfo.UnusedBytes = block.m_SumFreeSize; + outInfo.UsedBytes = block.m_Size - outInfo.UnusedBytes; outInfo.AllocationSizeMin = UINT64_MAX; outInfo.AllocationSizeMax = 0; outInfo.UnusedRangeSizeMin = UINT64_MAX; outInfo.UnusedRangeSizeMax = 0; - for(VmaSuballocationList::const_iterator suballocItem = alloc.m_Suballocations.cbegin(); - suballocItem != alloc.m_Suballocations.cend(); + for(VmaSuballocationList::const_iterator suballocItem = block.m_Suballocations.cbegin(); + suballocItem != block.m_Suballocations.cend(); ++suballocItem) { const VmaSuballocation& suballoc = *suballocItem; @@ -5043,21 +5069,6 @@ VmaPool_T::~VmaPool_T() #if VMA_STATS_STRING_ENABLED -/* -void VmaPool_T::PrintDetailedMap(class VmaStringBuilder& sb) -{ - sb.Add("\n{\n\"This\": \""); - sb.AddPointer(this); - sb.Add("\",\n\"Flags\": "); - sb.AddNumber(m_Flags); - sb.Add(",\n\"FrameInUseCount\": "); - sb.AddNumber(m_FrameInUseCount); - sb.Add(",\n\"DeviceMemoryBlock\": "); - m_pDeviceMemoryBlock->PrintDetailedMap(sb); - sb.Add("\n}"); -} -*/ - #endif // #if VMA_STATS_STRING_ENABLED VmaBlockVector::VmaBlockVector( @@ -5477,12 +5488,60 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json) { VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + + json.BeginObject(); + + if(m_IsCustomPool) + { + json.WriteString("MemoryTypeIndex"); + json.WriteNumber(m_MemoryTypeIndex); + + if(m_BlockVectorType == VMA_BLOCK_VECTOR_TYPE_MAPPED) + { + json.WriteString("Mapped"); + json.WriteBool(true); + } + + json.WriteString("BlockSize"); + json.WriteNumber(m_PreferredBlockSize); + + json.WriteString("BlockCount"); + json.BeginObject(true); + if(m_MinBlockCount > 0) + { + json.WriteString("Min"); + json.WriteNumber(m_MinBlockCount); + } + if(m_MaxBlockCount < SIZE_MAX) + { + json.WriteString("Max"); + json.WriteNumber(m_MaxBlockCount); + } + json.WriteString("Cur"); + json.WriteNumber(m_Blocks.size()); + json.EndObject(); + + if(m_FrameInUseCount > 0) + { + json.WriteString("FrameInUseCount"); + json.WriteNumber(m_FrameInUseCount); + } + } + else + { + json.WriteString("PreferredBlockSize"); + json.WriteNumber(m_PreferredBlockSize); + } + + json.WriteString("Blocks"); json.BeginArray(); for(size_t i = 0; i < m_Blocks.size(); ++i) { m_Blocks[i]->PrintDetailedMap(json); } json.EndArray(); + + json.EndObject(); } #endif // #if VMA_STATS_STRING_ENABLED @@ -5621,8 +5680,11 @@ void VmaBlockVector::MakePoolAllocationsLost( } } -void VmaBlockVector::AddStats(VmaStats* pStats, uint32_t memTypeIndex, uint32_t memHeapIndex) +void VmaBlockVector::AddStats(VmaStats* pStats) { + const uint32_t memTypeIndex = m_MemoryTypeIndex; + const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex); + VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) @@ -5969,7 +6031,7 @@ VmaAllocator_T::~VmaAllocator_T() VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex) { - const VkDeviceSize heapSize = m_MemProps.memoryHeaps[m_MemProps.memoryTypes[memTypeIndex].heapIndex].size; + const VkDeviceSize heapSize = m_MemProps.memoryHeaps[MemoryTypeIndexToHeapIndex(memTypeIndex)].size; return (heapSize <= VMA_SMALL_HEAP_MAX_SIZE) ? m_PreferredSmallHeapBlockSize : m_PreferredLargeHeapBlockSize; } @@ -6226,23 +6288,55 @@ void VmaAllocator_T::FreeMemory(const VmaAllocation allocation) void VmaAllocator_T::CalculateStats(VmaStats* pStats) { + // Initialize. InitStatInfo(pStats->total); for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) InitStatInfo(pStats->memoryType[i]); for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) InitStatInfo(pStats->memoryHeap[i]); + // Process default pools. for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - const uint32_t heapIndex = m_MemProps.memoryTypes[memTypeIndex].heapIndex; + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); for(uint32_t blockVectorType = 0; blockVectorType < VMA_BLOCK_VECTOR_TYPE_COUNT; ++blockVectorType) { VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex][blockVectorType]; VMA_ASSERT(pBlockVector); - pBlockVector->AddStats(pStats, memTypeIndex, heapIndex); + pBlockVector->AddStats(pStats); } } + // Process custom pools. + { + VmaMutexLock lock(m_PoolsMutex, m_UseMutex); + for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex) + { + m_Pools[poolIndex]->GetBlockVector().AddStats(pStats); + } + } + + // Process own allocations. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + VmaMutexLock ownAllocationsLock(m_OwnAllocationsMutex[memTypeIndex], m_UseMutex); + for(uint32_t blockVectorType = 0; blockVectorType < VMA_BLOCK_VECTOR_TYPE_COUNT; ++blockVectorType) + { + AllocationVectorType* const pOwnAllocVector = m_pOwnAllocations[memTypeIndex][blockVectorType]; + VMA_ASSERT(pOwnAllocVector); + for(size_t allocIndex = 0, allocCount = pOwnAllocVector->size(); allocIndex < allocCount; ++allocIndex) + { + VmaStatInfo allocationStatInfo; + (*pOwnAllocVector)[allocIndex]->OwnAllocCalcStatsInfo(allocationStatInfo); + VmaAddStatInfo(pStats->total, allocationStatInfo); + VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo); + VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo); + } + } + } + + // Postprocess. VmaPostprocessCalcStatInfo(pStats->total); for(size_t i = 0; i < GetMemoryTypeCount(); ++i) VmaPostprocessCalcStatInfo(pStats->memoryType[i]); @@ -6258,7 +6352,7 @@ void VmaAllocator_T::UnmapPersistentlyMappedMemory() { if(m_PhysicalDeviceProperties.vendorID == VMA_VENDOR_ID_AMD) { - for(size_t memTypeIndex = m_MemProps.memoryTypeCount; memTypeIndex--; ) + for(uint32_t memTypeIndex = m_MemProps.memoryTypeCount; memTypeIndex--; ) { const VkMemoryPropertyFlags memFlags = m_MemProps.memoryTypes[memTypeIndex].propertyFlags; if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0 && @@ -6312,7 +6406,7 @@ VkResult VmaAllocator_T::MapPersistentlyMappedMemory() } } - for(size_t memTypeIndex = 0; memTypeIndex < m_MemProps.memoryTypeCount; ++memTypeIndex) + for(uint32_t memTypeIndex = 0; memTypeIndex < m_MemProps.memoryTypeCount; ++memTypeIndex) { const VkMemoryPropertyFlags memFlags = m_MemProps.memoryTypes[memTypeIndex].propertyFlags; if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0 && @@ -6637,7 +6731,7 @@ void VmaAllocator_T::FreeOwnMemory(VmaAllocation allocation) void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) { bool ownAllocationsStarted = false; - for(size_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { VmaMutexLock ownAllocationsLock(m_OwnAllocationsMutex[memTypeIndex], m_UseMutex); for(uint32_t blockVectorType = 0; blockVectorType < VMA_BLOCK_VECTOR_TYPE_COUNT; ++blockVectorType) @@ -6688,7 +6782,7 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) { bool allocationsStarted = false; - for(size_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { for(uint32_t blockVectorType = 0; blockVectorType < VMA_BLOCK_VECTOR_TYPE_COUNT; ++blockVectorType) { @@ -6697,7 +6791,7 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) if(allocationsStarted == false) { allocationsStarted = true; - json.WriteString("Allocations"); + json.WriteString("DefaultPools"); json.BeginObject(); } @@ -6874,7 +6968,7 @@ void vmaBuildStatsString( for(uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex) { - if(allocator->m_MemProps.memoryTypes[typeIndex].heapIndex == heapIndex) + if(allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex) { json.BeginString("Type "); json.ContinueString(typeIndex);