Skip to content

Commit

Permalink
Merge pull request #17011 from hrydgard/vulkan-memory-visualizer
Browse files Browse the repository at this point in the history
Resurrect the Vulkan memory visualizer, but now it's global stats and pushbuffer stats.
  • Loading branch information
hrydgard authored Feb 27, 2023
2 parents 86c1d57 + 5d5e02d commit bdc2713
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 5 deletions.
5 changes: 5 additions & 0 deletions Common/GPU/Vulkan/VulkanLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
31 changes: 31 additions & 0 deletions Common/GPU/Vulkan/VulkanMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
// Additionally, Common/Vulkan/* , including this file, are also licensed
// under the public domain.

#include <set>
#include <mutex>

#include "Common/Math/math_util.h"

#include "Common/Log.h"
Expand All @@ -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<VulkanPushBuffer *> 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<std::mutex> guard(g_pushBufferListMutex);
g_pushBuffers.insert(this);
}

bool res = AddBuffer();
_assert_(res);
}

VulkanPushBuffer::~VulkanPushBuffer() {
{
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
g_pushBuffers.erase(this);
}

_dbg_assert_(!writePtr_);
_assert_(buffers_.empty());
}

std::vector<VulkanPushBuffer *> VulkanPushBuffer::GetAllActive() {
std::vector<VulkanPushBuffer *> buffers;
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
for (auto iter : g_pushBuffers) {
buffers.push_back(iter);
}
return buffers;
}

bool VulkanPushBuffer::AddBuffer() {
BufInfo info;
VkDevice device = vulkan_->GetDevice();
Expand Down Expand Up @@ -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_));
Expand Down
7 changes: 5 additions & 2 deletions Common/GPU/Vulkan/VulkanMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<VulkanPushBuffer *> GetAllActive();

private:
bool AddBuffer();
Expand Down Expand Up @@ -173,7 +176,7 @@ class VulkanDescSetPool {
const char *tag_;
VulkanContext *vulkan_ = nullptr;
VkDescriptorPool descPool_ = VK_NULL_HANDLE;
VkDescriptorPoolCreateInfo info_;
VkDescriptorPoolCreateInfo info_{};
std::vector<VkDescriptorPoolSize> sizes_;
std::function<void()> clear_;
uint32_t usage_ = 0;
Expand Down
62 changes: 61 additions & 1 deletion GPU/Vulkan/DebugVisVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <algorithm>
#include <sstream>
#include <cstring>

#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<VmaBudget> 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) {
Expand Down
3 changes: 1 addition & 2 deletions UI/DevScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit bdc2713

Please sign in to comment.