From 8ae6694e1dfd5cb6689b390d157e3cc36153c96e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 8 Sep 2013 11:49:24 -0700 Subject: [PATCH] Use a waiting thread list in sceGe as well. --- Core/HLE/KernelWaitHelpers.h | 4 +- Core/HLE/sceGe.cpp | 71 ++++++++++++++++++++++++++++-------- Core/HLE/sceGe.h | 2 +- GPU/GPUCommon.cpp | 4 +- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/Core/HLE/KernelWaitHelpers.h b/Core/HLE/KernelWaitHelpers.h index 88c5513e37..62775094e1 100644 --- a/Core/HLE/KernelWaitHelpers.h +++ b/Core/HLE/KernelWaitHelpers.h @@ -262,10 +262,12 @@ inline bool VerifyWait(SceUID threadID, WaitType waitType, SceUID uid) { // Resume a thread from waiting for a particular object. template -inline void ResumeFromWait(SceUID threadID, WaitType waitType, SceUID uid, T result) { +inline bool ResumeFromWait(SceUID threadID, WaitType waitType, SceUID uid, T result) { if (VerifyWait(threadID, waitType, uid)) { __KernelResumeThreadFromWait(threadID, result); + return true; } + return false; } }; diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 2242d0260d..9487701471 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -15,22 +15,30 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "HLE.h" -#include "../MIPS/MIPS.h" -#include "../System.h" -#include "../CoreParameter.h" -#include "../CoreTiming.h" -#include "../Reporting.h" -#include "sceGe.h" -#include "sceKernelMemory.h" -#include "sceKernelThread.h" -#include "sceKernelInterrupt.h" -#include "../GPU/GPUState.h" -#include "../GPU/GPUInterface.h" +#include +#include + +#include "Core/HLE/HLE.h" +#include "Core/MIPS/MIPS.h" +#include "Core/System.h" +#include "Core/CoreParameter.h" +#include "Core/CoreTiming.h" +#include "Core/Reporting.h" +#include "Core/HLE/sceGe.h" +#include "Core/HLE/sceKernelMemory.h" +#include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceKernelInterrupt.h" +#include "Core/HLE/KernelWaitHelpers.h" +#include "GPU/GPUState.h" +#include "GPU/GPUInterface.h" static PspGeCallbackData ge_callback_data[16]; static bool ge_used_callbacks[16] = {0}; +typedef std::vector WaitingThreadList; +static std::map listWaitingThreads; +static WaitingThreadList drawWaitingThreads; + struct GeInterruptData { int listid; @@ -162,7 +170,7 @@ void __GeExecuteSync(u64 userdata, int cyclesLate) { int listid = userdata >> 32; WaitType waitType = (WaitType) (userdata & 0xFFFFFFFF); - bool wokeThreads = __KernelTriggerWait(waitType, listid, 0, "GeSync", true); + bool wokeThreads = __GeTriggerWait(waitType, listid); gpu->SyncEnd(waitType, listid, wokeThreads); } @@ -202,6 +210,9 @@ void __GeInit() geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt); geCycleEvent = CoreTiming::RegisterEvent("GeCycleEvent", &__GeCheckCycles); + listWaitingThreads.clear(); + drawWaitingThreads.clear(); + // When we're using separate CPU/GPU threads, we need to keep them in sync. if (IsOnSeparateCPUThread()) { CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0); @@ -221,6 +232,9 @@ void __GeDoState(PointerWrap &p) p.Do(geCycleEvent); CoreTiming::RestoreRegisterEvent(geCycleEvent, "GeCycleEvent", &__GeCheckCycles); + p.Do(listWaitingThreads); + p.Do(drawWaitingThreads); + // Everything else is done in sceDisplay. p.DoMarker("sceGe"); } @@ -255,12 +269,35 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) void __GeWaitCurrentThread(WaitType type, SceUID waitId, const char *reason) { + if (type == WAITTYPE_GEDRAWSYNC) + drawWaitingThreads.push_back(__KernelGetCurThread()); + else if (type == WAITTYPE_GELISTSYNC) + listWaitingThreads[waitId].push_back(__KernelGetCurThread()); + else + ERROR_LOG_REPORT(SCEGE, "__GeWaitCurrentThread: bad wait type"); + __KernelWaitCurThread(type, waitId, 0, 0, false, reason); } -void __GeTriggerWait(WaitType type, SceUID waitId, const char *reason, bool noSwitch) +bool __GeTriggerWait(WaitType type, SceUID waitId, WaitingThreadList &waitingThreads) { - __KernelTriggerWait(type, waitId, 0, reason, noSwitch); + // TODO: Do they ever get a result other than 0? + bool wokeThreads = false; + for (auto it = waitingThreads.begin(), end = waitingThreads.end(); it != end; ++it) + wokeThreads |= HLEKernel::ResumeFromWait(*it, type, waitId, 0); + waitingThreads.clear(); + return wokeThreads; +} + +bool __GeTriggerWait(WaitType type, SceUID waitId) +{ + if (type == WAITTYPE_GEDRAWSYNC) + return __GeTriggerWait(type, waitId, drawWaitingThreads); + else if (type == WAITTYPE_GELISTSYNC) + return __GeTriggerWait(type, waitId, listWaitingThreads[waitId]); + else + ERROR_LOG_REPORT(SCEGE, "__GeTriggerWait: bad wait type"); + return false; } bool __GeHasPendingInterrupt() @@ -317,7 +354,9 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, int sceGeListDeQueue(u32 listID) { WARN_LOG(SCEGE, "sceGeListDeQueue(%08x)", listID); - return gpu->DequeueList(listID); + int result = gpu->DequeueList(listID); + hleReSchedule("dlist dequeued"); + return result; } int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) diff --git a/Core/HLE/sceGe.h b/Core/HLE/sceGe.h index a9b456f009..415b2db368 100644 --- a/Core/HLE/sceGe.h +++ b/Core/HLE/sceGe.h @@ -44,7 +44,7 @@ void __GeShutdown(); bool __GeTriggerSync(WaitType waitType, int id, u64 atTicks); bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks); void __GeWaitCurrentThread(WaitType type, SceUID waitId, const char *reason); -void __GeTriggerWait(WaitType type, SceUID waitId, const char *reason, bool noSwitch = false); +bool __GeTriggerWait(WaitType type, SceUID waitId); bool __GeHasPendingInterrupt(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 93cb15bd58..8b4c406850 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -265,7 +265,7 @@ u32 GPUCommon::DequeueList(int listid) { dlQueue.remove(listid); dls[listid].waitTicks = 0; - __GeTriggerWait(WAITTYPE_GELISTSYNC, listid, "GeListSync"); + __GeTriggerWait(WAITTYPE_GELISTSYNC, listid); CheckDrawSync(); @@ -893,7 +893,7 @@ void GPUCommon::InterruptEnd(int listid) { // TODO: Unless the signal handler could change it? if (dl.state == PSP_GE_DL_STATE_COMPLETED || dl.state == PSP_GE_DL_STATE_NONE) { dl.waitTicks = 0; - __GeTriggerWait(WAITTYPE_GELISTSYNC, listid, "GeListSync", true); + __GeTriggerWait(WAITTYPE_GELISTSYNC, listid); } if (dl.signal == PSP_GE_SIGNAL_HANDLER_PAUSE)