From be8c543563727e1aae0abbe9783c5fb72639416d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 4 Dec 2024 11:24:51 +0100 Subject: [PATCH] Defer post-runGe actions --- Core/HLE/sceGe.cpp | 43 ++++++++++++++++++++++++++------------- Core/System.cpp | 1 + GPU/Debugger/Playback.cpp | 6 ++++-- GPU/GPUCommon.cpp | 20 +++++++++++++++--- GPU/GPUCommon.h | 11 +++++++++- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 1269be02a3..09500d691c 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -145,7 +145,12 @@ public: // Hm. This might be really tricky to get to behave the same in both modes. Here we are in __KernelReschedule, CoreTiming::Advance, ProcessEvents, GeExecuteInterrupt, ... .... __RunOnePendingInterrupt // But not sure how much it will matter. The test pause2 hits here. - gpu->RunGe(); + // Although, not sure we ever really execute commands here? + if (!gpu->GetDisplayLists().empty()) { + DEBUG_LOG(Log::sceGe, "Display lists queued after interrupt handler"); + } + DeferredAction action{}; + gpu->RunGe(action, true); // force to run directly return false; } @@ -182,7 +187,8 @@ public: gpu->InterruptEnd(intrdata.listid); // This is the last thing done here in the syscall (__KernelReturnFromInterrupt) so switching coreState should just work. - gpu->RunGe(); + DeferredAction action{}; + gpu->RunGe(action); } }; @@ -349,11 +355,13 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, u32 optP if ((int)listID >= 0) listID = LIST_ID_MAGIC ^ listID; if (runList) { - gpu->RunGe(); + DeferredAction action{ 490 }; + action.forceCheck = true; + gpu->RunGe(action); + } else { + hleEatCycles(490); + CoreTiming::ForceCheck(); } - // The stuff here below must be deferred... - hleEatCycles(490); - CoreTiming::ForceCheck(); return hleLogSuccessX(Log::sceGe, listID); } @@ -368,17 +376,20 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, u32 if ((int)listID >= 0) listID = LIST_ID_MAGIC ^ listID; if (runList) { - gpu->RunGe(); + DeferredAction action{ 480 }; + action.forceCheck = true; + gpu->RunGe(action); + } else { + hleEatCycles(480); + CoreTiming::ForceCheck(); } - hleEatCycles(480); - CoreTiming::ForceCheck(); return hleLogSuccessX(Log::sceGe, listID); } static int sceGeListDeQueue(u32 listID) { WARN_LOG(Log::sceGe, "sceGeListDeQueue(%08x)", listID); int result = gpu->DequeueList(LIST_ID_MAGIC ^ listID); - hleReSchedule("dlist dequeued"); + hleReSchedule("ListDeQueue"); return result; } @@ -392,7 +403,8 @@ static int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) { bool runList; int retval = gpu->UpdateStall(LIST_ID_MAGIC ^ displayListID, stallAddress, &runList); if (runList) { - gpu->RunGe(); + DeferredAction action{}; + gpu->RunGe(action); } return retval; } @@ -419,10 +431,13 @@ static int sceGeContinue() { bool runList; int ret = gpu->Continue(&runList); if (runList) { - gpu->RunGe(); + DeferredAction action{ 220 }; + action.reschedule = true; + gpu->RunGe(action); + } else { + hleEatCycles(220); + hleReSchedule("GeContinue"); } - hleEatCycles(220); - hleReSchedule("ge continue"); return ret; } diff --git a/Core/System.cpp b/Core/System.cpp index fceecc9206..054d743f50 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -643,6 +643,7 @@ void PSP_RunLoopUntil(u64 globalticks) { break; case CORE_RUNNING_GE: gpu->ProcessDLQueue(true); + gpu->RunDeferredAction(); coreState = CORE_RUNNING_CPU; break; } diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index 93732ff603..1edc63a7bc 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -337,7 +337,8 @@ void DumpExecute::SyncStall() { bool runList; gpu->UpdateStall(execListID, execListPos, &runList); if (runList) { - gpu->RunGe(); + DeferredAction action{}; + gpu->RunGe(action, true); // force to run directly } s64 listTicks = gpu->GetListTicks(execListID); if (listTicks != -1) { @@ -372,7 +373,8 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) { bool runList; execListID = gpu->EnqueueList(execListBuf, execListPos, -1, optParam, false, &runList); if (runList) { - gpu->RunGe(); + DeferredAction action{}; + gpu->RunGe(action, true); // force to run directly } gpu->EnableInterrupts(true); } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 1cc52532f2..c79b053124 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -552,24 +552,38 @@ u32 GPUCommon::Continue(bool *runList) { return 0; } -void GPUCommon::RunGe(bool forceRunDirect) { +void GPUCommon::RunGe(DeferredAction action, bool forceRunDirect) { + deferredAction_ = action; // Old method, although may make sense for performance if the ImDebugger isn't active. #if 1 // Call ProcessDLQueue directly. ProcessDLQueue(false); + RunDeferredAction(); #else // No sense in switching core mode if there's nothing to do, just maybe some bookkeeping. if (dlQueue.empty() || forceRunDirect) { ProcessDLQueue(false); + RunDeferredAction(); } else { // New method, will allow ImDebugger to step the GPU. - // ARGH, what makes this different appears to be what happens AFTER the call to - // EnqueueList inside sceGeListEnqueue. Like the cycle eating and CoreTiming forcecheck. + // Once done, Core will call RunDeferredAction. Core_SwitchToGe(); } #endif } +void GPUCommon::RunDeferredAction() { + if (deferredAction_.eatCycles) { + hleEatCycles(deferredAction_.eatCycles); + } + if (deferredAction_.forceCheck) { + CoreTiming::ForceCheck(); + } + if (deferredAction_.reschedule) { + hleReSchedule("ge deferred action"); + } +} + u32 GPUCommon::Break(int mode) { if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c5e7041094..7d8929e417 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -203,6 +203,12 @@ inline bool IsTrianglePrim(GEPrimitiveType prim) { return prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES; } +struct DeferredAction { + int eatCycles; + bool forceCheck; + bool reschedule; +}; + class GPUCommon : public GPUDebugInterface { public: GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); @@ -266,7 +272,8 @@ public: virtual void DeviceLost() = 0; virtual void DeviceRestore(Draw::DrawContext *draw) = 0; - void RunGe(bool forceRunDirect = false); + void RunGe(DeferredAction action, bool forceRunDirect = false); + void RunDeferredAction(); void DrawImGuiDebugger(); @@ -507,6 +514,8 @@ protected: std::string reportingPrimaryInfo_; std::string reportingFullInfo_; + DeferredAction deferredAction_; + private: void DoExecuteCall(u32 target); void PopDLQueue();