From e977906d75f6ca7e12ddd1ec00adfd1d3f26725d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 3 Dec 2024 22:34:08 +0100 Subject: [PATCH] Lift out running the display list to the callers. This has one tricky case though... --- Core/HLE/sceGe.cpp | 43 +++++++++++++++++++++++++++++---------- GPU/Debugger/Playback.cpp | 12 +++++++++-- GPU/GPUCommon.cpp | 22 +++++++++++--------- GPU/GPUCommon.h | 8 ++++---- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 83f54fc3c5..1269be02a3 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -139,10 +139,13 @@ public: ge_pending_cb.pop_front(); gpu->InterruptEnd(intrdata.listid); - // Seen in GoW. if (subintr >= 0) DEBUG_LOG(Log::sceGe, "Ignoring interrupt for display list %d, already been released.", intrdata.listid); + + // 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(); return false; } @@ -178,6 +181,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(); } }; @@ -339,12 +344,16 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, u32 optP listAddress, stallAddress, callbackId, optParamAddr, CoreTiming::GetTicks()); auto optParam = PSPPointer::Create(optParamAddr); - u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, false); - hleEatCycles(490); - CoreTiming::ForceCheck(); - + bool runList; + u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, false, &runList); if ((int)listID >= 0) listID = LIST_ID_MAGIC ^ listID; + if (runList) { + gpu->RunGe(); + } + // The stuff here below must be deferred... + hleEatCycles(490); + CoreTiming::ForceCheck(); return hleLogSuccessX(Log::sceGe, listID); } @@ -354,12 +363,15 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, u32 listAddress, stallAddress, callbackId, optParamAddr, CoreTiming::GetTicks()); auto optParam = PSPPointer::Create(optParamAddr); - u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, true); - hleEatCycles(480); - CoreTiming::ForceCheck(); - + bool runList; + u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, true, &runList); if ((int)listID >= 0) listID = LIST_ID_MAGIC ^ listID; + if (runList) { + gpu->RunGe(); + } + hleEatCycles(480); + CoreTiming::ForceCheck(); return hleLogSuccessX(Log::sceGe, listID); } @@ -377,7 +389,12 @@ static int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) { CoreTiming::ForceCheck(); DEBUG_LOG(Log::sceGe, "sceGeListUpdateStallAddr(dlid=%i, stalladdr=%08x)", displayListID, stallAddress); - return gpu->UpdateStall(LIST_ID_MAGIC ^ displayListID, stallAddress); + bool runList; + int retval = gpu->UpdateStall(LIST_ID_MAGIC ^ displayListID, stallAddress, &runList); + if (runList) { + gpu->RunGe(); + } + return retval; } // 0 : wait for completion. 1:check and return @@ -399,7 +416,11 @@ static u32 sceGeDrawSync(u32 mode) { static int sceGeContinue() { DEBUG_LOG(Log::sceGe, "sceGeContinue()"); - int ret = gpu->Continue(); + bool runList; + int ret = gpu->Continue(&runList); + if (runList) { + gpu->RunGe(); + } hleEatCycles(220); hleReSchedule("ge continue"); return ret; diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index 9a48243feb..93732ff603 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -334,7 +334,11 @@ void DumpExecute::SyncStall() { return; } - gpu->UpdateStall(execListID, execListPos); + bool runList; + gpu->UpdateStall(execListID, execListPos, &runList); + if (runList) { + gpu->RunGe(); + } s64 listTicks = gpu->GetListTicks(execListID); if (listTicks != -1) { s64 nowTicks = CoreTiming::GetTicks(); @@ -365,7 +369,11 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) { gpu->EnableInterrupts(false); auto optParam = PSPPointer::Create(0); - execListID = gpu->EnqueueList(execListBuf, execListPos, -1, optParam, false); + bool runList; + execListID = gpu->EnqueueList(execListBuf, execListPos, -1, optParam, false, &runList); + if (runList) { + gpu->RunGe(); + } gpu->EnableInterrupts(true); } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 90cb365bef..7ac9dbccd7 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -359,7 +359,9 @@ void GPUCommon::ResetMatrices() { gstate_c.Dirty(DIRTY_WORLDMATRIX | DIRTY_VIEWMATRIX | DIRTY_PROJMATRIX | DIRTY_TEXMATRIX | DIRTY_FRAGMENTSHADER_STATE | DIRTY_BONE_UNIFORMS); } -u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) { +u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head, bool *runList) { + *runList = false; + // TODO Check the stack values in missing arg and ajust the stack depth // Check alignment @@ -468,7 +470,7 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE) return SCE_KERNEL_ERROR_INVALID_ID; auto &dl = dls[listid]; @@ -503,12 +506,13 @@ u32 GPUCommon::UpdateStall(int listid, u32 newstall) { return SCE_KERNEL_ERROR_ALREADY; dl.stall = newstall & 0x0FFFFFFF; - - SwitchToGe(); + + *runList = true; return 0; } -u32 GPUCommon::Continue() { +u32 GPUCommon::Continue(bool *runList) { + *runList = false; if (!currentList) return 0; @@ -544,11 +548,11 @@ u32 GPUCommon::Continue() { return -1; } - SwitchToGe(); + *runList = true; return 0; } -void GPUCommon::SwitchToGe() { +void GPUCommon::RunGe() { // Old method, although may make sense for performance if the ImDebugger isn't active. #if 1 // Call ProcessDLQueue directly. @@ -1552,8 +1556,6 @@ void GPUCommon::InterruptEnd(int listid) { dlQueue.remove(listid); } } - - SwitchToGe(); } // TODO: Maybe cleaner to keep this in GE and trigger the clear directly? diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 521e9bbd8f..8601e7eeae 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -245,8 +245,8 @@ public: DLResult ProcessDLQueue(bool fromCore); - u32 UpdateStall(int listid, u32 newstall); - u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head); + u32 UpdateStall(int listid, u32 newstall, bool *runList); + u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head, bool *runList); u32 DequeueList(int listid); virtual int ListSync(int listid, int mode); virtual u32 DrawSync(int mode); @@ -255,7 +255,7 @@ public: virtual void ResetMatrices(); virtual void DoState(PointerWrap &p); bool BusyDrawing(); - u32 Continue(); + u32 Continue(bool *runList); u32 Break(int mode); virtual bool FramebufferDirty() = 0; @@ -266,7 +266,7 @@ public: virtual void DeviceLost() = 0; virtual void DeviceRestore(Draw::DrawContext *draw) = 0; - void SwitchToGe(); + void RunGe(); void DrawImGuiDebugger();