diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0228ab24b..945dcadbe4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 3ecf5c41ed..2b5d570753 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -450,6 +450,7 @@
+
@@ -894,6 +895,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 719cbe3e64..bd6cb81587 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -449,9 +449,6 @@
Render
-
- GPU
-
GPU\Vulkan
@@ -503,6 +500,12 @@
GPU\OpenGL
+
+ GPU
+
+
+ GPU
+
@@ -941,6 +944,9 @@
Data\Collections
+
+ GPU
+
@@ -1089,4 +1095,4 @@
ext\basis_universal
-
+
\ No newline at end of file
diff --git a/Common/GPU/GPUBackendCommon.cpp b/Common/GPU/GPUBackendCommon.cpp
new file mode 100644
index 0000000000..b53001484d
--- /dev/null
+++ b/Common/GPU/GPUBackendCommon.cpp
@@ -0,0 +1,28 @@
+#include
+#include
+
+#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 g_pushBuffers;
+
+std::vector GetActiveGPUMemoryManagers() {
+ std::vector buffers;
+ std::lock_guard guard(g_pushBufferListMutex);
+ for (auto iter : g_pushBuffers) {
+ buffers.push_back(iter);
+ }
+ return buffers;
+}
+
+void RegisterGPUMemoryManager(GPUMemoryManager *manager) {
+ std::lock_guard guard(g_pushBufferListMutex);
+ g_pushBuffers.insert(manager);
+}
+
+void UnregisterGPUMemoryManager(GPUMemoryManager *manager) {
+ std::lock_guard guard(g_pushBufferListMutex);
+ g_pushBuffers.erase(manager);
+}
diff --git a/Common/GPU/GPUBackendCommon.h b/Common/GPU/GPUBackendCommon.h
new file mode 100644
index 0000000000..e465b75df4
--- /dev/null
+++ b/Common/GPU/GPUBackendCommon.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include
+
+// 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 GetActiveGPUMemoryManagers();
+
+void RegisterGPUMemoryManager(GPUMemoryManager *manager);
+void UnregisterGPUMemoryManager(GPUMemoryManager *manager);
diff --git a/Common/GPU/OpenGL/GLMemory.cpp b/Common/GPU/OpenGL/GLMemory.cpp
index 9bd61fb497..8680a82a54 100644
--- a/Common/GPU/OpenGL/GLMemory.cpp
+++ b/Common/GPU/OpenGL/GLMemory.cpp
@@ -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());
+}
diff --git a/Common/GPU/OpenGL/GLMemory.h b/Common/GPU/OpenGL/GLMemory.h
index 835188f41a..0c28aee6de 100644
--- a/Common/GPU/OpenGL/GLMemory.h
+++ b/Common/GPU/OpenGL/GLMemory.h
@@ -4,6 +4,7 @@
#include
#include
+#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;
diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp
index 1a718c95a7..910288ff3a 100644
--- a/Common/GPU/Vulkan/VulkanMemory.cpp
+++ b/Common/GPU/Vulkan/VulkanMemory.cpp
@@ -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 g_pushBuffers;
-
-std::vector GetActiveVulkanMemoryManagers() {
- std::vector buffers;
- std::lock_guard 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 guard(g_pushBufferListMutex);
- g_pushBuffers.insert(this);
- }
-
+ RegisterGPUMemoryManager(this);
bool res = AddBuffer();
_assert_(res);
}
VulkanPushBuffer::~VulkanPushBuffer() {
- {
- std::lock_guard 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 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 guard(g_pushBufferListMutex);
- g_pushBuffers.erase(this);
- }
-
+ UnregisterGPUMemoryManager(this);
_dbg_assert_(blocks_.empty());
}
diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h
index 766f497a79..53f96ae689 100644
--- a/Common/GPU/Vulkan/VulkanMemory.h
+++ b/Common/GPU/Vulkan/VulkanMemory.h
@@ -6,6 +6,7 @@
#include
#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 GetActiveVulkanMemoryManagers();
-
diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp
index 23994d4e4e..7fa7b55fe0 100644
--- a/GPU/Vulkan/DebugVisVulkan.cpp
+++ b/GPU/Vulkan/DebugVisVulkan.cpp
@@ -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 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 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];
diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp
index b9e739239a..36aaf564f7 100644
--- a/UI/DevScreens.cpp
+++ b/UI/DevScreens.cpp
@@ -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")));
diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj
index 353aa305bb..bc4f8a41f5 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj
+++ b/UWP/CommonUWP/CommonUWP.vcxproj
@@ -287,6 +287,7 @@
+
@@ -443,6 +444,7 @@
+
diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters
index 18faba3ae6..feefa90d95 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj.filters
+++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters
@@ -435,6 +435,9 @@
File
+
+ GPU
+
@@ -823,6 +826,9 @@
File
+
+ GPU
+
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 05d45cac5e..f28625f35b 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -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 \
diff --git a/libretro/Makefile.common b/libretro/Makefile.common
index 2ad3b8a43d..ac0d81c09c 100644
--- a/libretro/Makefile.common
+++ b/libretro/Makefile.common
@@ -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 \