From afafa5fcd6975366d5ac9be9a20e01eaed00f55b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Nov 2013 20:58:42 -0800 Subject: [PATCH] Make sure the gpu thread has a chance to run. If the scheduler puts it on the same core, it may not even do anything before we check if the framebuffer is dirty, so SyncThread will quit since it's not even running. Instead, let's wait until it's at least done something. --- Core/System.cpp | 3 +++ Core/ThreadEventQueue.h | 13 ++++++++++--- GPU/GPUInterface.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Core/System.cpp b/Core/System.cpp index 285ce3a2a9..a073bb7b67 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -336,6 +336,9 @@ void PSP_RunLoopUntil(u64 globalticks) { } if (cpuThread != NULL) { + // Tell the gpu a new frame is about to begin, before we start the CPU. + gpu->SyncBeginFrame(); + cpuThreadUntil = globalticks; if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) { // The CPU doesn't actually respect cpuThreadUntil well, especially when skipping frames. diff --git a/Core/ThreadEventQueue.h b/Core/ThreadEventQueue.h index 110e63600c..1cfd805901 100644 --- a/Core/ThreadEventQueue.h +++ b/Core/ThreadEventQueue.h @@ -24,7 +24,7 @@ template struct ThreadEventQueue : public B { - ThreadEventQueue() : threadEnabled_(false), eventsRunning_(false) { + ThreadEventQueue() : threadEnabled_(false), eventsRunning_(false), eventsHaveRun_(false) { } void SetThreadEnabled(bool threadEnabled) { @@ -72,6 +72,7 @@ struct ThreadEventQueue : public B { void RunEventsUntil(u64 globalticks) { lock_guard guard(eventsLock_); eventsRunning_ = true; + eventsHaveRun_ = true; do { for (Event ev = GetNextEvent(); EventType(ev) != EVENT_INVALID; ev = GetNextEvent()) { @@ -107,6 +108,11 @@ struct ThreadEventQueue : public B { eventsRunning_ = false; } + void SyncBeginFrame() { + lock_guard guard(eventsLock_); + eventsHaveRun_ = false; + } + // Force ignores coreState. void SyncThread(bool force = false) { if (!threadEnabled_) { @@ -117,8 +123,8 @@ struct ThreadEventQueue : public B { // While processing the last event, HasEvents() will be false even while not done. // So we schedule a nothing event and wait for that to finish. ScheduleEvent(EVENT_SYNC); - while (HasEvents() && eventsRunning_ && (force || coreState == CORE_RUNNING)) { - eventsDrain_.wait_for(eventsLock_, 1); + while (HasEvents() && (eventsRunning_ || !eventsHaveRun_) && (force || coreState == CORE_RUNNING)) { + eventsDrain_.wait_for(eventsLock_, 1000); } } @@ -135,6 +141,7 @@ protected: private: bool threadEnabled_; bool eventsRunning_; + bool eventsHaveRun_; std::deque events_; recursive_mutex eventsLock_; condition_variable eventsWait_; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 82f812ec4d..1e3e2e6796 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -231,6 +231,7 @@ public: virtual void DeviceLost() = 0; virtual void ReapplyGfxState() = 0; virtual void SyncThread(bool force = false) = 0; + virtual void SyncBeginFrame() = 0; virtual u64 GetTickEstimate() = 0; virtual void DoState(PointerWrap &p) = 0;