diff --git a/Core/Config.cpp b/Core/Config.cpp index 4b914e608c..d73c00276c 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -979,6 +979,7 @@ static ConfigSetting debuggerSettings[] = { ConfigSetting("ShowGpuProfile", &g_Config.bShowGpuProfile, false, false), ConfigSetting("SkipDeadbeefFilling", &g_Config.bSkipDeadbeefFilling, false), ConfigSetting("FuncHashMap", &g_Config.bFuncHashMap, false), + ConfigSetting("DrawFrameGraph", &g_Config.bDrawFrameGraph, false), ConfigSetting(false), }; diff --git a/Core/Config.h b/Core/Config.h index e60e0224ef..68f938be79 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -401,6 +401,7 @@ public: // Double edged sword: much easier debugging, but not accurate. bool bSkipDeadbeefFilling; bool bFuncHashMap; + bool bDrawFrameGraph; // Volatile development settings bool bShowFrameProfiler; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 4644241f0b..972e2e759f 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -153,6 +153,11 @@ static double fpsHistory[120]; static int fpsHistorySize = (int)ARRAY_SIZE(fpsHistory); static int fpsHistoryPos = 0; static int fpsHistoryValid = 0; +static double frameTimeHistory[600]; +static int frameTimeHistorySize = (int)ARRAY_SIZE(frameTimeHistory); +static int frameTimeHistoryPos = 0; +static int frameTimeHistoryValid = 0; +static double lastFrameTimeHistory = 0.0; static double monitorFpsUntil = 0.0; static int lastNumFlips = 0; static float flips = 0.0f; @@ -235,6 +240,9 @@ void __DisplayInit() { lastNumFlips = 0; fpsHistoryValid = 0; fpsHistoryPos = 0; + frameTimeHistoryValid = 0; + frameTimeHistoryPos = 0; + lastFrameTimeHistory = 0.0; __KernelRegisterWaitTypeFuncs(WAITTYPE_VBLANK, __DisplayVblankBeginCallback, __DisplayVblankEndCallback); } @@ -463,6 +471,21 @@ static void CalculateFPS() { ++fpsHistoryValid; } } + + if (g_Config.bDrawFrameGraph) { + frameTimeHistory[frameTimeHistoryPos++] = now - lastFrameTimeHistory; + lastFrameTimeHistory = now; + frameTimeHistoryPos = frameTimeHistoryPos % frameTimeHistorySize; + if (frameTimeHistoryValid < frameTimeHistorySize) { + ++frameTimeHistoryValid; + } + } +} + +double* __DisplayGetFrameTimes(int *out_valid, int *out_pos) { + *out_valid = frameTimeHistoryValid; + *out_pos = frameTimeHistoryPos; + return frameTimeHistory; } void __DisplayGetDebugStats(char *stats, size_t bufsize) { diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index db6cbcd1e1..a19db5ff7f 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -40,6 +40,7 @@ void __DisplayGetDebugStats(char stats[], size_t bufsize); void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps); void __DisplayGetVPS(float *out_vps); void __DisplayGetAveragedFPS(float *out_vps, float *out_fps); +double* __DisplayGetFrameTimes(int *out_valid, int *out_pos); int __DisplayGetNumVblanks(); int __DisplayGetVCount(); int __DisplayGetFlipCount(); diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 372671d39d..a38eb6cde3 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -89,6 +89,7 @@ void DevMenu::CreatePopupContents(UI::ViewGroup *parent) { #ifdef USE_PROFILER items->Add(new CheckBox(&g_Config.bShowFrameProfiler, dev->T("Frame Profiler"), "")); #endif + items->Add(new CheckBox(&g_Config.bDrawFrameGraph, dev->T("Draw Frametimes Graph"))); scroll->Add(items); parent->Add(scroll); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7bbf0863df..6dc2768ce7 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1190,6 +1190,21 @@ static void DrawFPS(DrawBuffer *draw2d, const Bounds &bounds) { draw2d->SetFontScale(1.0f, 1.0f); } +static void DrawFrameTimes(UIContext *ctx) { + int valid, pos; + double *history = __DisplayGetFrameTimes(&valid, &pos); + + ctx->Flush(); + ctx->BeginNoTex(); + int bottom = ctx->GetBounds().y2(); + for (int i = 0; i < valid; ++i) { + ctx->Draw()->vLine(i, bottom, bottom - history[i]*10000, 0x7F3fFF3f); + } + ctx->Draw()->vLine(pos, bottom, bottom - 512, 0xFFffFFff); + ctx->Flush(); + ctx->Begin(); +} + void EmuScreen::preRender() { using namespace Draw; DrawContext *draw = screenManager()->getDrawContext(); @@ -1367,6 +1382,10 @@ void EmuScreen::renderUI() { DrawFPS(draw2d, ctx->GetBounds()); } + if (g_Config.bDrawFrameGraph && !invalid_) { + DrawFrameTimes(ctx); + } + #if !PPSSPP_PLATFORM(UWP) if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && g_Config.bShowAllocatorDebug) { DrawAllocatorVis(ctx, gpu);