mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #17475 from hrydgard/opengl-basic-profiler
Add a trivial profiling tool to the OpenGL backend
This commit is contained in:
commit
5d7a0516cc
11 changed files with 60 additions and 7 deletions
|
@ -35,6 +35,13 @@ public:
|
|||
std::vector<GLPushBuffer *> pushBuffers;
|
||||
};
|
||||
|
||||
struct GLQueueProfileContext {
|
||||
bool enabled;
|
||||
double cpuStartTime;
|
||||
double cpuEndTime;
|
||||
};
|
||||
|
||||
|
||||
// Per-frame data, round-robin so we can overlap submission with execution of the previous frame.
|
||||
struct GLFrameData {
|
||||
bool skipSwap = false;
|
||||
|
@ -49,4 +56,6 @@ struct GLFrameData {
|
|||
GLDeleter deleter;
|
||||
GLDeleter deleter_prev;
|
||||
std::set<GLPushBuffer *> activePushBuffers;
|
||||
|
||||
GLQueueProfileContext profile;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Common/Log.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
|
||||
#if 0 // def _DEBUG
|
||||
|
@ -187,6 +188,14 @@ void GLRenderManager::StopThread() {
|
|||
}
|
||||
}
|
||||
|
||||
std::string GLRenderManager::GetGpuProfileString() const {
|
||||
int curFrame = GetCurFrame();
|
||||
const GLQueueProfileContext &profile = frameData_[curFrame].profile;
|
||||
|
||||
float cputime_ms = 1000.0f * (profile.cpuEndTime - profile.cpuStartTime);
|
||||
return StringFromFormat("CPU time to run the list: %0.2f ms", cputime_ms);
|
||||
}
|
||||
|
||||
void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
|
||||
_assert_(insideFrame_);
|
||||
#ifdef _DEBUG
|
||||
|
@ -341,7 +350,7 @@ void GLRenderManager::CopyImageToMemorySync(GLRTexture *texture, int mipLevel, i
|
|||
queueRunner_.CopyFromReadbackBuffer(nullptr, w, h, Draw::DataFormat::R8G8B8A8_UNORM, destFormat, pixelStride, pixels);
|
||||
}
|
||||
|
||||
void GLRenderManager::BeginFrame() {
|
||||
void GLRenderManager::BeginFrame(bool enableProfiling) {
|
||||
#ifdef _DEBUG
|
||||
curProgram_ = nullptr;
|
||||
#endif
|
||||
|
@ -349,6 +358,7 @@ void GLRenderManager::BeginFrame() {
|
|||
int curFrame = GetCurFrame();
|
||||
|
||||
GLFrameData &frameData = frameData_[curFrame];
|
||||
frameData.profile.enabled = enableProfiling;
|
||||
{
|
||||
VLOG("PUSH: BeginFrame (curFrame = %d, readyForFence = %d, time=%0.3f)", curFrame, (int)frameData.readyForFence, time_now_d());
|
||||
std::unique_lock<std::mutex> lock(frameData.fenceMutex);
|
||||
|
@ -417,6 +427,10 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) {
|
|||
}
|
||||
}
|
||||
|
||||
if (frameData.profile.enabled) {
|
||||
frameData.profile.cpuStartTime = time_now_d();
|
||||
}
|
||||
|
||||
if (IsVREnabled()) {
|
||||
int passes = GetVRPassesCount();
|
||||
for (int i = 0; i < passes; i++) {
|
||||
|
@ -428,6 +442,10 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) {
|
|||
queueRunner_.RunSteps(task.steps, skipGLCalls_, false, false);
|
||||
}
|
||||
|
||||
if (frameData.profile.enabled) {
|
||||
frameData.profile.cpuEndTime = time_now_d();
|
||||
}
|
||||
|
||||
if (!skipGLCalls_) {
|
||||
for (auto iter : frameData.activePushBuffers) {
|
||||
iter->MapDevice(bufferStrategy_);
|
||||
|
|
|
@ -409,8 +409,10 @@ public:
|
|||
caps_ = caps;
|
||||
}
|
||||
|
||||
std::string GetGpuProfileString() const;
|
||||
|
||||
// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
|
||||
void BeginFrame();
|
||||
void BeginFrame(bool enableProfiling);
|
||||
// Can run on a different thread!
|
||||
void Finish();
|
||||
|
||||
|
|
|
@ -328,6 +328,9 @@ public:
|
|||
DrawContext::SetTargetSize(w, h);
|
||||
renderManager_.Resize(w, h);
|
||||
}
|
||||
void SetDebugFlags(DebugFlags flags) override {
|
||||
debugFlags_ = flags;
|
||||
}
|
||||
|
||||
const DeviceCaps &GetDeviceCaps() const override {
|
||||
return caps_;
|
||||
|
@ -514,6 +517,8 @@ private:
|
|||
GLPushBuffer *push;
|
||||
};
|
||||
FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]{};
|
||||
|
||||
DebugFlags debugFlags_ = DebugFlags::NONE;
|
||||
};
|
||||
|
||||
static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) {
|
||||
|
@ -778,7 +783,7 @@ OpenGLContext::~OpenGLContext() {
|
|||
}
|
||||
|
||||
void OpenGLContext::BeginFrame() {
|
||||
renderManager_.BeginFrame();
|
||||
renderManager_.BeginFrame(debugFlags_ & DebugFlags::PROFILE_TIMESTAMPS);
|
||||
FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
|
||||
renderManager_.BeginPushBuffer(frameData.push);
|
||||
}
|
||||
|
|
|
@ -257,6 +257,9 @@ public:
|
|||
// cached framebuffers / textures / vertices?
|
||||
// get content of specific framebuffer / texture?
|
||||
// vertex / texture decoding?
|
||||
|
||||
// Note: Wanted to name it GetProfileString but clashes with a Windows API.
|
||||
virtual std::string GetGpuProfileString() { return ""; }
|
||||
};
|
||||
|
||||
bool GPUDebugInitExpression(GPUDebugInterface *g, const char *str, PostfixExpression &exp);
|
||||
|
|
|
@ -305,3 +305,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
|
|||
shaderManagerGL_->GetNumPrograms()
|
||||
);
|
||||
}
|
||||
|
||||
std::string GPU_GLES::GetGpuProfileString() {
|
||||
GLRenderManager *rm = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
return rm->GetGpuProfileString();
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
void BeginHostFrame() override;
|
||||
void EndHostFrame() override;
|
||||
|
||||
std::string GetGpuProfileString() override;
|
||||
|
||||
protected:
|
||||
void FinishDeferred() override;
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "GPU/Vulkan/VulkanUtil.h"
|
||||
#include "GPU/Vulkan/TextureCacheVulkan.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
|
||||
#undef DrawText
|
||||
|
||||
bool comparePushBufferNames(const VulkanMemoryManager *a, const VulkanMemoryManager *b) {
|
||||
|
@ -107,9 +109,14 @@ void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu) {
|
|||
|
||||
ui->Begin();
|
||||
|
||||
GPU_Vulkan *gpuVulkan = static_cast<GPU_Vulkan *>(gpu);
|
||||
float scale = 0.4f;
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
// Don't have as much info, let's go bigger.
|
||||
scale = 0.7f;
|
||||
}
|
||||
|
||||
std::string text = gpuVulkan->GetGpuProfileString();
|
||||
GPUCommon *gpuCommon = static_cast<GPUCommon *>(gpu);
|
||||
std::string text = gpuCommon->GetGpuProfileString();
|
||||
|
||||
ui->SetFontScale(0.4f, 0.4f);
|
||||
ui->DrawTextShadow(text.c_str(), x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
return textureCacheVulkan_;
|
||||
}
|
||||
|
||||
std::string GetGpuProfileString();
|
||||
std::string GetGpuProfileString() override;
|
||||
|
||||
protected:
|
||||
void FinishDeferred() override;
|
||||
|
|
|
@ -102,6 +102,8 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
|||
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.bShowGpuProfile, dev->T("GPU Profile")));
|
||||
}
|
||||
items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenuScreen::OnFreezeFrame);
|
||||
|
|
|
@ -1616,7 +1616,7 @@ void EmuScreen::renderUI() {
|
|||
DrawAllocatorVis(ctx, gpu);
|
||||
}
|
||||
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && g_Config.bShowGpuProfile) {
|
||||
if ((g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) && g_Config.bShowGpuProfile) {
|
||||
DrawGPUProfilerVis(ctx, gpu);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue