From ef4f17e9985c6315cb66fde0e50b1c2342ac2e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 15:12:46 +0100 Subject: [PATCH 1/2] Resurrect the Vulkan memory visualizer, but now it's global stats and pushbuffer stats. --- Common/GPU/Vulkan/VulkanMemory.cpp | 31 +++++++++++++++ Common/GPU/Vulkan/VulkanMemory.h | 7 +++- GPU/Vulkan/DebugVisVulkan.cpp | 62 +++++++++++++++++++++++++++++- UI/DevScreens.cpp | 3 +- 4 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index d8184098a552..9a25e5cbb094 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -18,6 +18,9 @@ // Additionally, Common/Vulkan/* , including this file, are also licensed // under the public domain. +#include +#include + #include "Common/Math/math_util.h" #include "Common/Log.h" @@ -26,17 +29,41 @@ using namespace PPSSPP_VK; +// Global push buffer tracker for vulkan memory profiling. +// Don't want to manually dig up all the active push buffers. +static std::mutex g_pushBufferListMutex; +static std::set g_pushBuffers; + VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage, PushBufferType type) : vulkan_(vulkan), name_(name), size_(size), usage_(usage), type_(type) { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.insert(this); + } + bool res = AddBuffer(); _assert_(res); } VulkanPushBuffer::~VulkanPushBuffer() { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.erase(this); + } + _dbg_assert_(!writePtr_); _assert_(buffers_.empty()); } +std::vector VulkanPushBuffer::GetAllActive() { + std::vector buffers; + std::lock_guard guard(g_pushBufferListMutex); + for (auto iter : g_pushBuffers) { + buffers.push_back(iter); + } + return buffers; +} + bool VulkanPushBuffer::AddBuffer() { BufInfo info; VkDevice device = vulkan_->GetDevice(); @@ -122,6 +149,10 @@ size_t VulkanPushBuffer::GetTotalSize() const { return sum; } +size_t VulkanPushBuffer::GetTotalCapacity() const { + return size_ * buffers_.size(); +} + void VulkanPushBuffer::Map() { _dbg_assert_(!writePtr_); VkResult res = vmaMapMemory(vulkan_->Allocator(), buffers_[buf_].allocation, (void **)(&writePtr_)); diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 275ca4bb78e7..863e4f965e4c 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -131,7 +131,10 @@ class VulkanPushBuffer { info->range = sizeof(T); } - size_t GetTotalSize() const; + size_t GetTotalSize() const; // Used size + size_t GetTotalCapacity() const; + + static std::vector GetAllActive(); private: bool AddBuffer(); @@ -173,7 +176,7 @@ class VulkanDescSetPool { const char *tag_; VulkanContext *vulkan_ = nullptr; VkDescriptorPool descPool_ = VK_NULL_HANDLE; - VkDescriptorPoolCreateInfo info_; + VkDescriptorPoolCreateInfo info_{}; std::vector sizes_; std::function clear_; uint32_t usage_ = 0; diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index 82acb8c0fda7..ff03218efdbc 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -15,24 +15,84 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include +#include +#include + #include "Common/Render/DrawBuffer.h" #include "Common/GPU/thin3d.h" +#include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" #include "Common/System/Display.h" #include "Common/System/System.h" +#include "ext/vma/vk_mem_alloc.h" + #include "DebugVisVulkan.h" #include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanImage.h" +#include "Common/Data/Text/Parsers.h" #include "GPU/Vulkan/GPU_Vulkan.h" #include "GPU/Vulkan/VulkanUtil.h" #include "GPU/Vulkan/TextureCacheVulkan.h" #undef DrawText +bool comparePushBufferNames(const VulkanPushBuffer *a, const VulkanPushBuffer *b) { + return strcmp(a->Name(), b->Name()) < 0; +} + void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { - // TODO: Make a new allocator visualizer for VMA. + // This one will simply display stats. + Draw::DrawContext *draw = ui->GetDrawContext(); + + VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + if (!vulkan) { + return; + } + + VmaTotalStatistics vmaStats; + vmaCalculateStatistics(vulkan->Allocator(), &vmaStats); + + std::vector budgets; + budgets.resize(vulkan->GetMemoryProperties().memoryHeapCount); + vmaGetHeapBudgets(vulkan->Allocator(), &budgets[0]); + + size_t totalBudget = 0; + size_t totalUsedBytes = 0; + for (auto &budget : budgets) { + totalBudget += budget.budget; + totalUsedBytes += budget.usage; + } + + std::stringstream str; + str << vulkan->GetPhysicalDeviceProperties().properties.deviceName << std::endl; + str << "Allocated " << NiceSizeFormat(vmaStats.total.statistics.allocationBytes) << " in " << vmaStats.total.statistics.allocationCount << " allocs" << std::endl; + // Note: The overall number includes stuff like descriptor sets pools and other things that are not directly visible as allocations. + str << "Overall " << NiceSizeFormat(totalUsedBytes) << " used out of " << NiceSizeFormat(totalBudget) << " available" << std::endl; + + str << "Push buffers:" << std::endl; + + // Now list the various push buffers. + auto pushBuffers = VulkanPushBuffer::GetAllActive(); + std::sort(pushBuffers.begin(), pushBuffers.end(), comparePushBufferNames); + + for (auto push : pushBuffers) { + str << " " << push->Name() << " " + << NiceSizeFormat(push->GetTotalCapacity()) << ", used: " + << NiceSizeFormat(push->GetTotalSize()) << std::endl; + } + + const int padding = 10 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); + const int starty = 50 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP); + int x = padding; + int y = starty; + + ui->SetFontScale(0.7f, 0.7f); + ui->DrawTextShadow(str.str().c_str(), x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); + ui->SetFontScale(1.0f, 1.0f); + ui->Flush(); } void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu) { diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index eb3de255793b..82cb3c159e98 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -101,8 +101,7 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { items->Add(new Choice(dev->T("Jit Compare")))->OnClick.Handle(this, &DevMenuScreen::OnJitCompare); items->Add(new Choice(dev->T("Shader Viewer")))->OnClick.Handle(this, &DevMenuScreen::OnShaderView); if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - // TODO: Make a new allocator visualizer for VMA. - // items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer"))); + items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer"))); items->Add(new CheckBox(&g_Config.bShowGpuProfile, dev->T("GPU Profile"))); } items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenuScreen::OnFreezeFrame); From 5d5e02d94958dfdb81bd31287bc30f0ccef27af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 01:10:30 +0100 Subject: [PATCH 2/2] Attempted buildfix --- Common/GPU/Vulkan/VulkanLoader.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index 85b4bb551090..f85a09f55865 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -33,6 +33,11 @@ #include "ext/vulkan/vulkan.h" +// Hacky X11 header workaround +#ifdef Opposite +#undef Opposite +#endif + namespace PPSSPP_VK { // Putting our own Vulkan function pointers in a namespace ensures that ppsspp_libretro.so doesn't collide with libvulkan.so. extern PFN_vkCreateInstance vkCreateInstance;