Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resurrect the Vulkan memory visualizer, but now it's global stats and pushbuffer stats. #17011

Merged
merged 2 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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