mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Allow other backends than Vulkan to have GPU memory stats. Implement for GL.
This commit is contained in:
parent
62b41c6640
commit
dfb446f89d
@ -631,6 +631,8 @@ add_library(Common STATIC
|
||||
Common/File/FileDescriptor.h
|
||||
Common/GPU/DataFormat.h
|
||||
Common/GPU/MiscTypes.h
|
||||
Common/GPU/GPUBackendCommon.cpp
|
||||
Common/GPU/GPUBackendCommon.h
|
||||
Common/GPU/thin3d.cpp
|
||||
Common/GPU/thin3d.h
|
||||
Common/GPU/thin3d_create.h
|
||||
|
@ -450,6 +450,7 @@
|
||||
<ClInclude Include="GPU\D3D9\D3D9ShaderCompiler.h" />
|
||||
<ClInclude Include="GPU\D3D9\D3D9StateCache.h" />
|
||||
<ClInclude Include="GPU\DataFormat.h" />
|
||||
<ClInclude Include="GPU\GPUBackendCommon.h" />
|
||||
<ClInclude Include="GPU\MiscTypes.h" />
|
||||
<ClInclude Include="GPU\OpenGL\DataFormatGL.h" />
|
||||
<ClInclude Include="GPU\OpenGL\gl3stub.h" />
|
||||
@ -894,6 +895,7 @@
|
||||
<ClCompile Include="GPU\D3D9\D3D9ShaderCompiler.cpp" />
|
||||
<ClCompile Include="GPU\D3D9\D3D9StateCache.cpp" />
|
||||
<ClCompile Include="GPU\D3D9\thin3d_d3d9.cpp" />
|
||||
<ClCompile Include="GPU\GPUBackendCommon.cpp" />
|
||||
<ClCompile Include="GPU\OpenGL\DataFormatGL.cpp" />
|
||||
<ClCompile Include="GPU\OpenGL\gl3stub.c" />
|
||||
<ClCompile Include="GPU\OpenGL\GLFeatures.cpp" />
|
||||
|
@ -449,9 +449,6 @@
|
||||
<ClInclude Include="Render\ManagedTexture.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU\MiscTypes.h">
|
||||
<Filter>GPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU\Vulkan\VulkanFramebuffer.h">
|
||||
<Filter>GPU\Vulkan</Filter>
|
||||
</ClInclude>
|
||||
@ -503,6 +500,12 @@
|
||||
<ClInclude Include="GPU\OpenGL\GLMemory.h">
|
||||
<Filter>GPU\OpenGL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU\GPUBackendCommon.h">
|
||||
<Filter>GPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU\MiscTypes.h">
|
||||
<Filter>GPU</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ABI.cpp" />
|
||||
@ -941,6 +944,9 @@
|
||||
<ClCompile Include="Data\Collections\FastVec.h">
|
||||
<Filter>Data\Collections</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPU\GPUBackendCommon.cpp">
|
||||
<Filter>GPU</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Crypto">
|
||||
@ -1089,4 +1095,4 @@
|
||||
<Filter>ext\basis_universal</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
28
Common/GPU/GPUBackendCommon.cpp
Normal file
28
Common/GPU/GPUBackendCommon.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
#include "Common/GPU/GPUBackendCommon.h"
|
||||
|
||||
// Global push buffer tracker for GPU memory profiling.
|
||||
// Don't want to manually dig up all the active push buffers.
|
||||
static std::mutex g_pushBufferListMutex;
|
||||
static std::set<GPUMemoryManager *> g_pushBuffers;
|
||||
|
||||
std::vector<GPUMemoryManager *> GetActiveGPUMemoryManagers() {
|
||||
std::vector<GPUMemoryManager *> buffers;
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
for (auto iter : g_pushBuffers) {
|
||||
buffers.push_back(iter);
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
void RegisterGPUMemoryManager(GPUMemoryManager *manager) {
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.insert(manager);
|
||||
}
|
||||
|
||||
void UnregisterGPUMemoryManager(GPUMemoryManager *manager) {
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.erase(manager);
|
||||
}
|
17
Common/GPU/GPUBackendCommon.h
Normal file
17
Common/GPU/GPUBackendCommon.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Just an abstract thing to get debug information.
|
||||
class GPUMemoryManager {
|
||||
public:
|
||||
virtual ~GPUMemoryManager() {}
|
||||
|
||||
virtual void GetDebugString(char *buffer, size_t bufSize) const = 0;
|
||||
virtual const char *Name() const = 0; // for sorting
|
||||
};
|
||||
|
||||
std::vector<GPUMemoryManager *> GetActiveGPUMemoryManagers();
|
||||
|
||||
void RegisterGPUMemoryManager(GPUMemoryManager *manager);
|
||||
void UnregisterGPUMemoryManager(GPUMemoryManager *manager);
|
@ -2,6 +2,7 @@
|
||||
#include "Common/GPU/OpenGL/GLMemory.h"
|
||||
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
||||
#include "Common/GPU/OpenGL/GLFeatures.h"
|
||||
#include "Common/Data/Text/Parsers.h"
|
||||
|
||||
extern std::thread::id renderThreadId;
|
||||
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||
@ -64,9 +65,11 @@ bool GLRBuffer::Unmap() {
|
||||
GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size, const char *tag) : render_(render), size_(size), target_(target), tag_(tag) {
|
||||
bool res = AddBuffer();
|
||||
_assert_(res);
|
||||
RegisterGPUMemoryManager(this);
|
||||
}
|
||||
|
||||
GLPushBuffer::~GLPushBuffer() {
|
||||
UnregisterGPUMemoryManager(this);
|
||||
Destroy(true);
|
||||
}
|
||||
|
||||
@ -279,3 +282,7 @@ void GLPushBuffer::UnmapDevice() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLPushBuffer::GetDebugString(char *buffer, size_t bufSize) const {
|
||||
snprintf(buffer, bufSize, "%s: %d/%d", tag_, NiceSizeFormat(this->offset_).c_str(), NiceSizeFormat(this->size_).c_str());
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/GPU/GPUBackendCommon.h"
|
||||
#include "Common/GPU/OpenGL/GLCommon.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
@ -61,7 +62,7 @@ class GLRenderManager;
|
||||
// trouble.
|
||||
// We need to manage the lifetime of this together with the other resources so its destructor
|
||||
// runs on the render thread.
|
||||
class GLPushBuffer {
|
||||
class GLPushBuffer : public GPUMemoryManager {
|
||||
public:
|
||||
friend class GLRenderManager;
|
||||
|
||||
@ -78,6 +79,10 @@ public:
|
||||
|
||||
void Reset() { offset_ = 0; }
|
||||
|
||||
void GetDebugString(char *buffer, size_t bufSize) const override;
|
||||
|
||||
const char *Name() const override { return tag_; }; // for sorting
|
||||
|
||||
// Utility for users of this class, not used internally.
|
||||
const uint32_t INVALID_OFFSET = 0xFFFFFFFF;
|
||||
|
||||
|
@ -35,37 +35,15 @@ using namespace PPSSPP_VK;
|
||||
// Always keep around push buffers at least this long (seconds).
|
||||
static const double PUSH_GARBAGE_COLLECTION_DELAY = 10.0;
|
||||
|
||||
// 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<VulkanMemoryManager *> g_pushBuffers;
|
||||
|
||||
std::vector<VulkanMemoryManager *> GetActiveVulkanMemoryManagers() {
|
||||
std::vector<VulkanMemoryManager *> buffers;
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
for (auto iter : g_pushBuffers) {
|
||||
buffers.push_back(iter);
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage)
|
||||
: vulkan_(vulkan), name_(name), size_(size), usage_(usage) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.insert(this);
|
||||
}
|
||||
|
||||
RegisterGPUMemoryManager(this);
|
||||
bool res = AddBuffer();
|
||||
_assert_(res);
|
||||
}
|
||||
|
||||
VulkanPushBuffer::~VulkanPushBuffer() {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.erase(this);
|
||||
}
|
||||
|
||||
UnregisterGPUMemoryManager(this);
|
||||
_dbg_assert_(!writePtr_);
|
||||
_assert_(buffers_.empty());
|
||||
}
|
||||
@ -276,11 +254,7 @@ VkResult VulkanDescSetPool::Recreate(bool grow) {
|
||||
|
||||
VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage)
|
||||
: vulkan_(vulkan), name_(name), originalBlockSize_(originalBlockSize), usage_(usage) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.insert(this);
|
||||
}
|
||||
|
||||
RegisterGPUMemoryManager(this);
|
||||
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
|
||||
blocks_.push_back(CreateBlock(originalBlockSize));
|
||||
blocks_.back().original = true;
|
||||
@ -289,11 +263,7 @@ VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t o
|
||||
}
|
||||
|
||||
VulkanPushPool::~VulkanPushPool() {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_pushBufferListMutex);
|
||||
g_pushBuffers.erase(this);
|
||||
}
|
||||
|
||||
UnregisterGPUMemoryManager(this);
|
||||
_dbg_assert_(blocks_.empty());
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
#include "Common/GPU/GPUBackendCommon.h"
|
||||
|
||||
// Forward declaration
|
||||
VK_DEFINE_HANDLE(VmaAllocation);
|
||||
@ -14,22 +15,13 @@ VK_DEFINE_HANDLE(VmaAllocation);
|
||||
//
|
||||
// Vulkan memory management utils.
|
||||
|
||||
// Just an abstract thing to get debug information.
|
||||
class VulkanMemoryManager {
|
||||
public:
|
||||
virtual ~VulkanMemoryManager() {}
|
||||
|
||||
virtual void GetDebugString(char *buffer, size_t bufSize) const = 0;
|
||||
virtual const char *Name() const = 0; // for sorting
|
||||
};
|
||||
|
||||
// VulkanPushBuffer
|
||||
// Simple incrementing allocator.
|
||||
// Use these to push vertex, index and uniform data. Generally you'll have two or three of these
|
||||
// and alternate on each frame. Make sure not to reset until the fence from the last time you used it
|
||||
// has completed.
|
||||
// NOTE: This has now been replaced with VulkanPushPool for all uses except the vertex cache.
|
||||
class VulkanPushBuffer : public VulkanMemoryManager {
|
||||
class VulkanPushBuffer : public GPUMemoryManager {
|
||||
struct BufInfo {
|
||||
VkBuffer buffer;
|
||||
VmaAllocation allocation;
|
||||
@ -108,7 +100,7 @@ private:
|
||||
// Simple memory pushbuffer pool that can share blocks between the "frames", to reduce the impact of push memory spikes -
|
||||
// a later frame can gobble up redundant buffers from an earlier frame even if they don't share frame index.
|
||||
// NOT thread safe! Can only be used from one thread (our main thread).
|
||||
class VulkanPushPool : public VulkanMemoryManager {
|
||||
class VulkanPushPool : public GPUMemoryManager {
|
||||
public:
|
||||
VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage);
|
||||
~VulkanPushPool();
|
||||
@ -212,5 +204,3 @@ private:
|
||||
bool grow_;
|
||||
};
|
||||
|
||||
std::vector<VulkanMemoryManager *> GetActiveVulkanMemoryManagers();
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ext/vma/vk_mem_alloc.h"
|
||||
|
||||
#include "DebugVisVulkan.h"
|
||||
#include "Common/GPU/GPUBackendCommon.h"
|
||||
#include "Common/GPU/Vulkan/VulkanMemory.h"
|
||||
#include "Common/GPU/Vulkan/VulkanImage.h"
|
||||
#include "Common/Data/Text/Parsers.h"
|
||||
@ -41,7 +42,7 @@
|
||||
|
||||
#undef DrawText
|
||||
|
||||
bool comparePushBufferNames(const VulkanMemoryManager *a, const VulkanMemoryManager *b) {
|
||||
bool comparePushBufferNames(const GPUMemoryManager *a, const GPUMemoryManager *b) {
|
||||
return strcmp(a->Name(), b->Name()) < 0;
|
||||
}
|
||||
|
||||
@ -49,35 +50,34 @@ void DrawGPUMemoryVis(UIContext *ui, GPUInterface *gpu) {
|
||||
// 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;
|
||||
|
||||
VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
if (vulkan) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 managers = GetActiveVulkanMemoryManagers();
|
||||
auto managers = GetActiveGPUMemoryManagers();
|
||||
std::sort(managers.begin(), managers.end(), comparePushBufferNames);
|
||||
|
||||
char buffer[512];
|
||||
|
@ -100,8 +100,8 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
items->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &DevMenuScreen::OnDeveloperTools);
|
||||
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) {
|
||||
items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer")));
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("GPU Allocator Viewer")));
|
||||
}
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
items->Add(new CheckBox(&g_Config.bShowGpuProfile, dev->T("GPU Profile")));
|
||||
|
@ -287,6 +287,7 @@
|
||||
<ClInclude Include="..\..\Common\Data\Format\DDSLoad.h" />
|
||||
<ClInclude Include="..\..\Common\File\AndroidContentURI.h" />
|
||||
<ClInclude Include="..\..\Common\File\AndroidStorage.h" />
|
||||
<ClInclude Include="..\..\Common\GPU\GPUBackendCommon.h" />
|
||||
<ClInclude Include="..\..\Common\GPU\Vulkan\VulkanLoader.h" />
|
||||
<ClInclude Include="..\..\Common\Math\Statistics.h" />
|
||||
<ClInclude Include="..\..\Common\Net\NetBuffer.h" />
|
||||
@ -443,6 +444,7 @@
|
||||
<ClCompile Include="..\..\Common\Data\Format\DDSLoad.cpp" />
|
||||
<ClCompile Include="..\..\Common\File\AndroidContentURI.cpp" />
|
||||
<ClCompile Include="..\..\Common\File\AndroidStorage.cpp" />
|
||||
<ClCompile Include="..\..\Common\GPU\GPUBackendCommon.cpp" />
|
||||
<ClCompile Include="..\..\Common\GPU\Vulkan\VulkanLoader.cpp" />
|
||||
<ClCompile Include="..\..\Common\Math\Statistics.cpp" />
|
||||
<ClCompile Include="..\..\Common\Net\NetBuffer.cpp" />
|
||||
|
@ -435,6 +435,9 @@
|
||||
<ClCompile Include="..\..\Common\File\AndroidContentURI.cpp">
|
||||
<Filter>File</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Common\GPU\GPUBackendCommon.cpp">
|
||||
<Filter>GPU</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="targetver.h" />
|
||||
@ -823,6 +826,9 @@
|
||||
<ClInclude Include="..\..\Common\File\AndroidContentURI.h">
|
||||
<Filter>File</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Common\GPU\GPUBackendCommon.h">
|
||||
<Filter>GPU</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Common\Math\fast\fast_matrix_neon.S">
|
||||
|
@ -189,6 +189,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Common/File/DirListing.cpp \
|
||||
$(SRC)/Common/File/FileDescriptor.cpp \
|
||||
$(SRC)/Common/GPU/thin3d.cpp \
|
||||
$(SRC)/Common/GPU/GPUBackendCommon.cpp \
|
||||
$(SRC)/Common/GPU/Shader.cpp \
|
||||
$(SRC)/Common/GPU/ShaderWriter.cpp \
|
||||
$(SRC)/Common/GPU/ShaderTranslation.cpp \
|
||||
|
@ -286,6 +286,7 @@ SOURCES_CXX += \
|
||||
$(COMMONDIR)/File/DirListing.cpp \
|
||||
$(COMMONDIR)/GPU/thin3d.cpp \
|
||||
$(COMMONDIR)/GPU/Shader.cpp \
|
||||
$(COMMONDIR)/GPU/GPUBackendCommon.cpp \
|
||||
$(COMMONDIR)/GPU/ShaderWriter.cpp \
|
||||
$(COMMONDIR)/GPU/ShaderTranslation.cpp \
|
||||
$(COMMONDIR)/GPU/OpenGL/thin3d_gl.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user