From f1841a20f39d3ac3b60a61ecb0f54b536e416fff Mon Sep 17 00:00:00 2001 From: Archez Date: Fri, 18 Oct 2024 11:05:31 +0900 Subject: [PATCH] add gfx debugger support (#4345) Co-authored-by: Malkierian --- CMakeLists.txt | 6 +++++- soh/soh/OTRGlobals.cpp | 6 ++++++ soh/soh/SohGui.cpp | 7 +++++++ soh/soh/SohMenuBar.cpp | 7 +++++++ soh/src/code/graph.c | 34 +++++++++++++++++++++++----------- 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e064233f7..606abeba727 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,9 +130,13 @@ include(CMake/GlobalSettingsInclude.cmake OPTIONAL) set_property(GLOBAL PROPERTY USE_FOLDERS ON) ################################################################################ -# Set GBI version +# Set LUS vars ################################################################################ +# Enable the Gfx debugger in LUS to use libgfxd from ZAPDTR +set(GFX_DEBUG_DISASSEMBLER ON) + +# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd) set(GBI_UCODE F3DEX_GBI_2) ################################################################################ diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0563ebe39e5..f406fd8445c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1433,6 +1433,12 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { int threshold = CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80); wnd->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); + // When the gfx debugger is active, only run with the final mtx + if (GfxDebuggerIsDebugging()) { + mtx_replacements.clear(); + mtx_replacements.emplace_back(); + } + RunCommands(commands, mtx_replacements); last_fps = fps; diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 2d47d2a3895..76e91acb537 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -113,6 +113,7 @@ namespace SohGui { std::shared_ptr mConsoleWindow; std::shared_ptr mStatsWindow; + std::shared_ptr mGfxDebuggerWindow; std::shared_ptr mInputEditorWindow; std::shared_ptr mAudioEditorWindow; @@ -161,6 +162,11 @@ namespace SohGui { SPDLOG_ERROR("Could not find console window"); } + mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow"); + if (mGfxDebuggerWindow == nullptr) { + SPDLOG_ERROR("Could not find input GfxDebuggerWindow"); + } + mInputEditorWindow = gui->GetGuiWindow("Controller Configuration"); if (mInputEditorWindow == nullptr) { SPDLOG_ERROR("Could not find input editor window"); @@ -237,6 +243,7 @@ namespace SohGui { mInputEditorWindow = nullptr; mStatsWindow = nullptr; mConsoleWindow = nullptr; + mGfxDebuggerWindow = nullptr; mSohMenuBar = nullptr; mInputViewer = nullptr; mInputViewerSettings = nullptr; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 17b4581afac..8ca29ea770c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -217,6 +217,7 @@ void DrawShipMenu() { } extern std::shared_ptr mInputEditorWindow; +extern std::shared_ptr mGfxDebuggerWindow; extern std::shared_ptr mInputViewer; extern std::shared_ptr mInputViewerSettings; extern std::shared_ptr mAdvancedResolutionSettingsWindow; @@ -1971,6 +1972,12 @@ void DrawDeveloperToolsMenu() { mMessageViewerWindow->ToggleVisibility(); } } + UIWidgets::Spacer(0); + if (mGfxDebuggerWindow) { + if (ImGui::Button(GetWindowButtonText("Gfx Debugger", CVarGetInteger(CVAR_WINDOW("GfxDebugger"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + mGfxDebuggerWindow->ToggleVisibility(); + } + } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index 3b9487f5593..6a49117ddfe 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -15,6 +15,15 @@ #define GFXPOOL_HEAD_MAGIC 0x1234 #define GFXPOOL_TAIL_MAGIC 0x5678 +// SOH [Port] Game State management for our render loop +static struct RunFrameContext { + GraphicsContext gfxCtx; + GameState* gameState; + GameStateOverlay* nextOvl; + GameStateOverlay* ovl; + int state; +} runFrameContext; + OSTime sGraphUpdateTime; OSTime sGraphSetTaskTime; FaultClient sGraphFaultClient; @@ -271,6 +280,12 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx) { void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) { u32 problem; + // Skip game frame updates while gfx debugger is active, and execute with the last frame's DL buffer + if (GfxDebuggerIsDebugging()) { + Graph_ProcessGfxCommands(runFrameContext.gfxCtx.workBuffer); + return; + } + gameState->unk_A0 = 0; Graph_InitTHGA(gfxCtx); @@ -443,15 +458,6 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) { uint64_t GetFrequency(); uint64_t GetPerfCounter(); -static struct RunFrameContext { - GraphicsContext gfxCtx; - GameState* gameState; - GameStateOverlay* nextOvl; - GameStateOverlay* ovl; - int state; -} runFrameContext; - - extern AudioMgr gAudioMgr; extern void ProcessSaveStateRequests(void); @@ -515,6 +521,10 @@ static void RunFrame() Graph_Update(&runFrameContext.gfxCtx, runFrameContext.gameState); //ticksB = GetPerfCounter(); + if (GfxDebuggerIsDebuggingRequested()) { + GfxDebuggerDebugDisplayList(runFrameContext.gfxCtx.workBuffer); + } + Graph_ProcessGfxCommands(runFrameContext.gfxCtx.workBuffer); @@ -565,7 +575,8 @@ void* Graph_Alloc2(GraphicsContext* gfxCtx, size_t size) { } void Graph_OpenDisps(Gfx** dispRefs, GraphicsContext* gfxCtx, const char* file, s32 line) { - if (HREG(80) == 7 && HREG(82) != 4) { + // SOH [Debugging] Force open/close disp string handling on so that the graphics debugger can leverage it + if (true || HREG(80) == 7 && HREG(82) != 4) { dispRefs[0] = gfxCtx->polyOpa.p; dispRefs[1] = gfxCtx->polyXlu.p; dispRefs[2] = gfxCtx->overlay.p; @@ -577,7 +588,8 @@ void Graph_OpenDisps(Gfx** dispRefs, GraphicsContext* gfxCtx, const char* file, } void Graph_CloseDisps(Gfx** dispRefs, GraphicsContext* gfxCtx, const char* file, s32 line) { - if (HREG(80) == 7 && HREG(82) != 4) { + // SOH [Debugging] Force open/close disp string handling on so that the graphics debugger can leverage it + if (true || HREG(80) == 7 && HREG(82) != 4) { if (dispRefs[0] + 1 == gfxCtx->polyOpa.p) { gfxCtx->polyOpa.p = dispRefs[0]; } else {