From 3cf3985c8d48edc194a7769ee3549fa7782197e1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Nov 2018 22:12:45 -0800 Subject: [PATCH] GE Debugger: Support record for more render types. This should handle both games that use display, and games that don't. --- GPU/Debugger/Record.cpp | 62 ++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 3adf3be9cd..255612e3f6 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -52,7 +52,7 @@ static const int MIN_VERSION = 2; static bool active = false; static bool nextFrame = false; -static bool writePending = false; +static int flipLastAction = -1; static std::function writeCallback; enum class CommandType : u8 { @@ -389,6 +389,12 @@ static std::string GenRecordingFilename() { } static void BeginRecording() { + active = true; + nextFrame = false; + lastTextures.clear(); + lastRenderTargets.clear(); + flipLastAction = gpuStats.numFlips; + u32 ptr = (u32)pushbuf.size(); u32 sz = 512 * 4; pushbuf.resize(pushbuf.size() + sz); @@ -675,6 +681,7 @@ bool IsActivePending() { bool Activate() { if (!nextFrame) { nextFrame = true; + flipLastAction = gpuStats.numFlips; return true; } return false; @@ -691,8 +698,8 @@ static void FinishRecording() { pushbuf.clear(); NOTICE_LOG(SYSTEM, "Recording finished"); - writePending = false; active = false; + flipLastAction = gpuStats.numFlips; if (writeCallback) writeCallback(filename); @@ -703,10 +710,6 @@ void NotifyCommand(u32 pc) { if (!active) { return; } - if (writePending) { - FinishRecording(); - return; - } const u32 op = Memory::Read_U32(pc); const GECommand cmd = GECommand(op >> 24); @@ -802,6 +805,14 @@ void NotifyUpload(u32 dest, u32 sz) { } void NotifyDisplay(u32 framebuf, int stride, int fmt) { + bool writePending = false; + if (active && !commands.empty()) { + writePending = true; + } + if (nextFrame && (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) { + NOTICE_LOG(SYSTEM, "Recording starting on display..."); + BeginRecording(); + } if (!active) { return; } @@ -820,20 +831,39 @@ void NotifyDisplay(u32 framebuf, int stride, int fmt) { memcpy(pushbuf.data() + ptr, &disp, sz); commands.push_back({ CommandType::DISPLAY, sz, ptr }); + + if (writePending) { + NOTICE_LOG(SYSTEM, "Recording complete on display"); + FinishRecording(); + } } void NotifyFrame() { - if (active && !writePending && !commands.empty()) { - // Delay write until the first command of the next frame, so we get the right display buf. - NOTICE_LOG(SYSTEM, "Recording complete - waiting to get display buffer"); - writePending = true; + const bool noDisplayAction = flipLastAction + 4 < gpuStats.numFlips; + // We do this only to catch things that don't call NotifyDisplay. + if (active && !commands.empty() && noDisplayAction) { + NOTICE_LOG(SYSTEM, "Recording complete on frame"); + + struct DisplayBufData { + PSPPointer topaddr; + u32 linesize, pixelFormat; + }; + + DisplayBufData disp; + __DisplayGetFramebuf(&disp.topaddr, &disp.linesize, &disp.pixelFormat, 0); + + FlushRegisters(); + u32 ptr = (u32)pushbuf.size(); + u32 sz = (u32)sizeof(disp); + pushbuf.resize(pushbuf.size() + sz); + memcpy(pushbuf.data() + ptr, &disp, sz); + + commands.push_back({ CommandType::DISPLAY, sz, ptr }); + + FinishRecording(); } - if (nextFrame && (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) { - NOTICE_LOG(SYSTEM, "Recording starting..."); - active = true; - nextFrame = false; - lastTextures.clear(); - lastRenderTargets.clear(); + if (nextFrame && (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0 && noDisplayAction) { + NOTICE_LOG(SYSTEM, "Recording starting on frame..."); BeginRecording(); } }