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

Add a trivial profiling tool to the OpenGL backend #17475

Merged
merged 1 commit into from
May 17, 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
9 changes: 9 additions & 0 deletions Common/GPU/OpenGL/GLFrameData.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ class GLDeleter {
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;
Expand All @@ -49,4 +56,6 @@ struct GLFrameData {
GLDeleter deleter;
GLDeleter deleter_prev;
std::set<GLPushBuffer *> activePushBuffers;

GLQueueProfileContext profile;
};
20 changes: 19 additions & 1 deletion Common/GPU/OpenGL/GLRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -341,14 +350,15 @@ 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

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);
Expand Down Expand Up @@ -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++) {
Expand All @@ -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_);
Expand Down
4 changes: 3 additions & 1 deletion Common/GPU/OpenGL/GLRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,10 @@ class GLRenderManager {
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();

Expand Down
7 changes: 6 additions & 1 deletion Common/GPU/OpenGL/thin3d_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ class OpenGLContext : public DrawContext {
DrawContext::SetTargetSize(w, h);
renderManager_.Resize(w, h);
}
void SetDebugFlags(DebugFlags flags) override {
debugFlags_ = flags;
}

const DeviceCaps &GetDeviceCaps() const override {
return caps_;
Expand Down Expand Up @@ -514,6 +517,8 @@ class OpenGLContext : public DrawContext {
GLPushBuffer *push;
};
FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]{};

DebugFlags debugFlags_ = DebugFlags::NONE;
};

static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) {
Expand Down Expand Up @@ -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);
}
Expand Down
3 changes: 3 additions & 0 deletions GPU/Common/GPUDebugInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ class GPUDebugInterface {
// 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);
Expand Down
5 changes: 5 additions & 0 deletions GPU/GLES/GPU_GLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
2 changes: 2 additions & 0 deletions GPU/GLES/GPU_GLES.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class GPU_GLES : public GPUCommonHW {
void BeginHostFrame() override;
void EndHostFrame() override;

std::string GetGpuProfileString() override;

protected:
void FinishDeferred() override;

Expand Down
11 changes: 9 additions & 2 deletions GPU/Vulkan/DebugVisVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion GPU/Vulkan/GPU_Vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class GPU_Vulkan : public GPUCommonHW {
return textureCacheVulkan_;
}

std::string GetGpuProfileString();
std::string GetGpuProfileString() override;

protected:
void FinishDeferred() override;
Expand Down
2 changes: 2 additions & 0 deletions UI/DevScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down