diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index c875787337..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); @@ -603,10 +609,10 @@ static void FlushPrimState(int vcount) { u32 vbytes = 0; GetVertDataSizes(vcount, indices, vbytes, ibytes); - if (indices) { + if (indices && ibytes > 0) { EmitCommandWithRAM(CommandType::INDICES, indices, ibytes); } - if (verts) { + if (verts && vbytes > 0) { EmitCommandWithRAM(CommandType::VERTICES, verts, vbytes); } } @@ -631,7 +637,9 @@ static void EmitTransfer(u32 op) { u32 srcBytes = ((srcY + height - 1) * srcStride + (srcX + width)) * bpp; srcBytes = Memory::ValidSize(srcBasePtr, srcBytes); - EmitCommandWithRAM(CommandType::TRANSFERSRC, Memory::GetPointerUnchecked(srcBasePtr), srcBytes); + if (srcBytes != 0) { + EmitCommandWithRAM(CommandType::TRANSFERSRC, Memory::GetPointerUnchecked(srcBasePtr), srcBytes); + } lastRegisters.push_back(op); } @@ -641,7 +649,9 @@ static void EmitClut(u32 op) { u32 bytes = (op & 0x3F) * 32; bytes = Memory::ValidSize(addr, bytes); - EmitCommandWithRAM(CommandType::CLUT, Memory::GetPointerUnchecked(addr), bytes); + if (bytes != 0) { + EmitCommandWithRAM(CommandType::CLUT, Memory::GetPointerUnchecked(addr), bytes); + } lastRegisters.push_back(op); } @@ -671,6 +681,7 @@ bool IsActivePending() { bool Activate() { if (!nextFrame) { nextFrame = true; + flipLastAction = gpuStats.numFlips; return true; } return false; @@ -687,8 +698,8 @@ static void FinishRecording() { pushbuf.clear(); NOTICE_LOG(SYSTEM, "Recording finished"); - writePending = false; active = false; + flipLastAction = gpuStats.numFlips; if (writeCallback) writeCallback(filename); @@ -699,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); @@ -763,7 +770,9 @@ void NotifyMemcpy(u32 dest, u32 src, u32 sz) { memcpy(pushbuf.data() + cmd.ptr, &dest, sizeof(dest)); sz = Memory::ValidSize(dest, sz); - EmitCommandWithRAM(CommandType::MEMCPYDATA, Memory::GetPointer(dest), sz); + if (sz != 0) { + EmitCommandWithRAM(CommandType::MEMCPYDATA, Memory::GetPointer(dest), sz); + } } } @@ -796,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; } @@ -814,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(); } }