From 3819886e2e50a5cfc3252e422ad067e54ae08575 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 8 Aug 2013 00:10:30 -0700 Subject: [PATCH] Add a way to synchronize with the GPU thread. --- Core/HLE/sceGe.cpp | 3 +++ GPU/GPUCommon.cpp | 15 +++++++++++++++ GPU/GPUCommon.h | 2 ++ GPU/GPUInterface.h | 1 + 4 files changed, 21 insertions(+) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index f037b510d0..89c93a1f4b 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -379,6 +379,8 @@ u32 sceGeSaveContext(u32 ctxAddr) { DEBUG_LOG(HLE, "sceGeSaveContext(%08x)", ctxAddr); gpu->Flush(); + gpu->SyncThread(); + if (sizeof(gstate) > 512 * 4) { ERROR_LOG(HLE, "AARGH! sizeof(gstate) has grown too large!"); @@ -400,6 +402,7 @@ u32 sceGeRestoreContext(u32 ctxAddr) { DEBUG_LOG(HLE, "sceGeRestoreContext(%08x)", ctxAddr); gpu->Flush(); + gpu->SyncThread(); if (sizeof(gstate) > 512 * 4) { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 8c4136d789..f0c2c50223 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -539,6 +539,11 @@ GPUEvent GPUCommon::GetNextEvent() { return ev; } +bool GPUCommon::HasEvents() { + lock_guard guard(eventsLock); + return !events.empty(); +} + void GPUCommon::ScheduleEvent(GPUEvent ev) { lock_guard guard(eventsLock); events.push_back(ev); @@ -576,6 +581,16 @@ void GPUCommon::RunEventsUntil(u64 globalticks) { } while (CoreTiming::GetTicks() < globalticks); } +void GPUCommon::SyncThread() { + if (!g_Config.bUseCPUThread) { + _dbg_assert_msg_(G3D, !HasEvents(), "Should never have pending events when CPU/GPU on same thread."); + } + + while (HasEvents() && coreState == CORE_RUNNING) { + eventsCond.wait_for(eventsLock, 1); + }; +} + int GPUCommon::GetNextListIndex() { lock_guard guard(listLock); auto iter = dlQueue.begin(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8e810e5a46..c23f0a1359 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -33,6 +33,7 @@ public: virtual u32 Continue(); virtual u32 Break(int mode); virtual void ReapplyGfxState(); + virtual void SyncThread(); protected: // To avoid virtual calls to PreExecuteOp(). @@ -44,6 +45,7 @@ protected: void CheckDrawSync(); int GetNextListIndex(); GPUEvent GetNextEvent(); + bool HasEvents(); void ScheduleEvent(GPUEvent ev); void ProcessDLQueueInternal(); void ReapplyGfxStateInternal(); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 0f87ec3403..5c19d4f0e3 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -218,6 +218,7 @@ public: virtual void DeviceLost() = 0; virtual void Flush() = 0; virtual void ReapplyGfxState() = 0; + virtual void SyncThread() = 0; virtual void DoState(PointerWrap &p) = 0; // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.