diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h index ba90717009..0a83d127f2 100644 --- a/Source/Core/Common/Src/VideoBackendBase.h +++ b/Source/Core/Common/Src/VideoBackendBase.h @@ -88,6 +88,7 @@ public: virtual void Shutdown() = 0; virtual void DoState(PointerWrap &p) = 0; + virtual void RunLoop(bool enable) = 0; virtual std::string GetName() = 0; @@ -127,6 +128,7 @@ extern VideoBackend* g_video_backend; class VideoBackendHLE : public VideoBackend { void DoState(PointerWrap &p); + void RunLoop(bool enable); void EmuStateChange(EMUSTATE_CHANGE); diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index d20b26aaac..79005eeca2 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -88,6 +88,8 @@ void DoState(PointerWrap &p) return; } // Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM + // Pause the video thread in multi-threaded mode + g_video_backend->RunLoop(false); g_video_backend->DoState(p); if (Core::g_CoreStartupParameter.bWii) @@ -96,6 +98,9 @@ void DoState(PointerWrap &p) PowerPC::DoState(p); HW::DoState(p); CoreTiming::DoState(p); + + // Resume the video thread + g_video_backend->RunLoop(true); } void LoadBufferStateCallback(u64 userdata, int cyclesLate) diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index bdafa67fc1..a45b63f989 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -87,19 +87,8 @@ namespace CommandProcessor { -bool IsOnThread() -{ - return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; -} - int et_UpdateInterrupts; - -void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate) -{ - UpdateInterrupts(userdata); -} - // look for 1002 verts, breakpoint there, see why next draw is flushed // TODO(ector): Warn on bbox read/write @@ -109,8 +98,6 @@ UCPStatusReg m_CPStatusReg; UCPCtrlReg m_CPCtrlReg; UCPClearReg m_CPClearReg; -u32 HiWatermark_Tighter; - int m_bboxleft; int m_bboxtop; int m_bboxright; @@ -120,7 +107,7 @@ u16 m_tokenReg; static u32 fake_GPWatchdogLastToken = 0; static Common::EventEx s_fifoIdleEvent; static Common::CriticalSection sFifoCritical; -static bool bProcessFifoToLoWatemark = false; +static bool bProcessFifoToLoWatermark = false; static bool bProcessFifoAllDistance = false; volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data. @@ -130,6 +117,16 @@ volatile bool interruptTokenWaiting = false; volatile bool interruptFinishWaiting = false; volatile bool OnOverflow = false; +bool IsOnThread() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; +} + +void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate) +{ + UpdateInterrupts(userdata); +} + void FifoCriticalEnter() { sFifoCritical.Enter(); @@ -144,14 +141,23 @@ void DoState(PointerWrap &p) { p.Do(m_CPStatusReg); p.Do(m_CPCtrlReg); - //p.Do(m_CPClearReg); + p.Do(m_CPClearReg); p.Do(m_bboxleft); p.Do(m_bboxtop); p.Do(m_bboxright); p.Do(m_bboxbottom); p.Do(m_tokenReg); p.Do(fifo); - p.Do(HiWatermark_Tighter); + + p.Do(bProcessFifoToLoWatermark); + p.Do(bProcessFifoAllDistance); + + p.Do(isFifoBusy); + p.Do(interruptSet); + p.Do(interruptWaiting); + p.Do(interruptTokenWaiting); + p.Do(interruptFinishWaiting); + p.Do(OnOverflow); } //inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;} @@ -478,8 +484,8 @@ void Write16(const u16 _Value, const u32 _Address) ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd; } // If overflown happens process the fifo to LoWatemark - if (bProcessFifoToLoWatemark) - ProcessFifoToLoWatemark(); + if (bProcessFifoToLoWatermark) + ProcessFifoToLoWatermark(); INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value); @@ -501,7 +507,7 @@ void Write16(const u16 _Value, const u32 _Address) if (IsOnThread()) { if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow) - bProcessFifoToLoWatemark = true; + bProcessFifoToLoWatermark = true; } else @@ -890,7 +896,7 @@ void SetStatus() } } -void ProcessFifoToLoWatemark() +void ProcessFifoToLoWatermark() { if (IsOnThread()) { @@ -898,7 +904,7 @@ void ProcessFifoToLoWatemark() fifo.CPReadWriteDistance > fifo.CPLoWatermark && !AtBreakpoint()) Common::YieldCPU(); } - bProcessFifoToLoWatemark = false; + bProcessFifoToLoWatermark = false; } void ProcessFifoAllDistance() diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h index 78d01ebc06..720b43d81b 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.h +++ b/Source/Core/VideoCommon/Src/CommandProcessor.h @@ -171,7 +171,7 @@ void FifoCriticalEnter(); void FifoCriticalLeave(); void SetOverflowStatusFromGatherPipe(); -void ProcessFifoToLoWatemark(); +void ProcessFifoToLoWatermark(); void ProcessFifoAllDistance(); void ProcessFifoEvents(); void AbortFrame(); diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index fa0a375b01..29c8b99c04 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -194,8 +194,8 @@ void Fifo_EnterLoop() while (!EmuRunning) { g_video_backend->PeekMessages(); - VideoFifo_CheckAsyncRequest(); - Common::SleepCurrentThread(10); + VideoFifo_CheckStateRequest(); + Common::SleepCurrentThread(1); } } } diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h index 1b3f250518..81bc3c1d09 100644 --- a/Source/Core/VideoCommon/Src/Fifo.h +++ b/Source/Core/VideoCommon/Src/Fifo.h @@ -44,5 +44,6 @@ void Fifo_SetRendering(bool bEnabled); // Implemented by the Video Plugin void VideoFifo_CheckAsyncRequest(); +void VideoFifo_CheckStateRequest(); #endif // _FIFO_H diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 409b141d9f..2a3f0b2564 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -179,7 +179,8 @@ static volatile struct // Depending on the threading mode (DC/SC) this can be called // from either the GPU thread or the CPU thread -static void check_DoState() { +void VideoFifo_CheckStateRequest() +{ if (Common::AtomicLoadAcquire(s_doStateRequested)) { // Clear all caches that touch RAM @@ -215,14 +216,18 @@ void VideoBackendHLE::DoState(PointerWrap& p) Common::YieldCPU(); } else - check_DoState(); + VideoFifo_CheckStateRequest(); +} + +void VideoBackendHLE::RunLoop(bool enable) +{ + VideoCommon_RunLoop(enable); } void VideoFifo_CheckAsyncRequest() { VideoFifo_CheckSwapRequest(); VideoFifo_CheckEFBAccess(); - check_DoState(); } void VideoBackend::Video_GatherPipeBursted() diff --git a/Source/Core/VideoCommon/Src/VideoState.cpp b/Source/Core/VideoCommon/Src/VideoState.cpp index b7ca4c00c1..d82aaed46f 100644 --- a/Source/Core/VideoCommon/Src/VideoState.cpp +++ b/Source/Core/VideoCommon/Src/VideoState.cpp @@ -55,3 +55,8 @@ void VideoCommon_DoState(PointerWrap &p) DoState(p); //TODO: search for more data that should be saved and add it here } + +void VideoCommon_RunLoop(bool enable) +{ + Fifo_RunLoop(enable); +} diff --git a/Source/Core/VideoCommon/Src/VideoState.h b/Source/Core/VideoCommon/Src/VideoState.h index 849a81ecc6..b29cf17257 100644 --- a/Source/Core/VideoCommon/Src/VideoState.h +++ b/Source/Core/VideoCommon/Src/VideoState.h @@ -22,5 +22,6 @@ #include "ChunkFile.h" void VideoCommon_DoState(PointerWrap &p); +void VideoCommon_RunLoop(bool enable); #endif // _VIDEOSTATE_H