diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index 1874f4541a..2efd70d1f1 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -182,7 +182,7 @@ void DebugInterface::pauseCpu() { SysCoreThread& core = GetCoreThread(); if (!core.IsPaused()) - core.Pause(true); + core.Pause({}, true); } void DebugInterface::resumeCpu() diff --git a/pcsx2/GS.h b/pcsx2/GS.h index a2c88b85ea..a234ed8721 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -385,8 +385,8 @@ protected: void OnResumeReady(); void OnSuspendInThread(); - void OnPauseInThread() {} - void OnResumeInThread( bool IsSuspended ); + void OnPauseInThread(SystemsMask systemsToTearDown) override {} + void OnResumeInThread(SystemsMask systemsToReinstate) override; void OnCleanupInThread(); void GenericStall( uint size ); diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 4c613bb8d1..6e1a613eb2 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -603,12 +603,12 @@ void SysMtgsThread::OnSuspendInThread() _parent::OnSuspendInThread(); } -void SysMtgsThread::OnResumeInThread(bool isSuspended) +void SysMtgsThread::OnResumeInThread(SystemsMask systemsToReinstate) { - if (isSuspended) + if (systemsToReinstate & System_GS) OpenGS(); - _parent::OnResumeInThread(isSuspended); + _parent::OnResumeInThread(systemsToReinstate); } void SysMtgsThread::OnCleanupInThread() diff --git a/pcsx2/PAD/Windows/PAD.cpp b/pcsx2/PAD/Windows/PAD.cpp index c43cd2a093..0c8cec8c5c 100644 --- a/pcsx2/PAD/Windows/PAD.cpp +++ b/pcsx2/PAD/Windows/PAD.cpp @@ -962,13 +962,9 @@ ExtraWndProcResult StatusWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa void PADconfigure() { - HWND tmp = hWnd; - PADclose(); - ScopedCoreThreadPause paused_core; + ScopedCoreThreadPause paused_core(SystemsMask::System_PAD); Configure(); paused_core.AllowResume(); - if(tmp != nullptr) - PADopen(tmp); } s32 PADopen(void* pDsp) diff --git a/pcsx2/SPU2/spu2.cpp b/pcsx2/SPU2/spu2.cpp index ee6c863636..655ba34132 100644 --- a/pcsx2/SPU2/spu2.cpp +++ b/pcsx2/SPU2/spu2.cpp @@ -40,25 +40,9 @@ u32 lClocks = 0; void SPU2configure() { - ScopedCoreThreadPause paused_core; - - SndBuffer::Cleanup(); + ScopedCoreThreadPause paused_core(SystemsMask::System_SPU2); configure(); - - if (IsOpened) - { - try - { - Console.Warning("SPU2: Sound output module reset"); - SndBuffer::Init(); - } - catch (std::exception& ex) - { - fprintf(stderr, "SPU2 Error: Could not initialize device, or something.\nReason: %s", ex.what()); - SPU2close(); - } - } paused_core.AllowResume(); } diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 1b82b74bf9..60af3b828b 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -101,6 +101,12 @@ void SysCoreThread::OnStart() _parent::OnStart(); } +void SysCoreThread::OnSuspendInThread() +{ + TearDownSystems(static_cast(-1)); // All systems + GetMTGS().Suspend(); +} + void SysCoreThread::Start() { GSinit(); @@ -302,30 +308,26 @@ void SysCoreThread::ExecuteTaskInThread() PCSX2_PAGEFAULT_EXCEPT; } -void SysCoreThread::OnSuspendInThread() +void SysCoreThread::TearDownSystems(SystemsMask systemsToTearDown) { - DEV9close(); - USBclose(); - DoCDVDclose(); - FWclose(); - PADclose(); - SPU2close(); - FileMcd_EmuClose(); - GetMTGS().Suspend(); + if (systemsToTearDown & System_DEV9) DEV9close(); + if (systemsToTearDown & System_USB) USBclose(); + if (systemsToTearDown & System_CDVD) DoCDVDclose(); + if (systemsToTearDown & System_FW) FWclose(); + if (systemsToTearDown & System_PAD) PADclose(); + if (systemsToTearDown & System_SPU2) SPU2close(); + if (systemsToTearDown & System_MCD) FileMcd_EmuClose(); } -void SysCoreThread::OnResumeInThread(bool isSuspended) +void SysCoreThread::OnResumeInThread(SystemsMask systemsToReinstate) { GetMTGS().WaitForOpen(); - if (isSuspended) - { - DEV9open((void*)pDsp); - USBopen((void*)pDsp); - } - FWopen(); - SPU2open((void*)pDsp); - PADopen((void*)pDsp); - FileMcd_EmuOpen(); + if (systemsToReinstate & System_DEV9) DEV9open((void*)pDsp); + if (systemsToReinstate & System_USB) USBopen((void*)pDsp); + if (systemsToReinstate & System_FW) FWopen(); + if (systemsToReinstate & System_SPU2) SPU2open((void*)pDsp); + if (systemsToReinstate & System_PAD) PADopen((void*)pDsp); + if (systemsToReinstate & System_MCD) FileMcd_EmuOpen(); } diff --git a/pcsx2/System/SysThreadBase.cpp b/pcsx2/System/SysThreadBase.cpp index 6783b4509f..d070e181a9 100644 --- a/pcsx2/System/SysThreadBase.cpp +++ b/pcsx2/System/SysThreadBase.cpp @@ -129,7 +129,7 @@ void SysThreadBase::Suspend(bool isBlocking) // The previous suspension state; true if the thread was running or false if it was // closed, not running, or paused. // -void SysThreadBase::Pause(bool debug) +void SysThreadBase::Pause(SystemsMask systemsToTearDown, bool debug) { if (IsSelf() || !IsRunning()) return; @@ -146,6 +146,7 @@ void SysThreadBase::Pause(bool debug) if ((m_ExecMode == ExecMode_Closed) || (m_ExecMode == ExecMode_Paused)) return; + m_SystemsToTearDown.store(systemsToTearDown, std::memory_order_relaxed); if (m_ExecMode == ExecMode_Opened) m_ExecMode = ExecMode_Pausing; @@ -281,7 +282,7 @@ void SysThreadBase::OnCleanupInThread() } void SysThreadBase::OnSuspendInThread() {} -void SysThreadBase::OnResumeInThread(bool isSuspended) {} +void SysThreadBase::OnResumeInThread(SystemsMask systemsToReinstate) {} // Tests for Pause and Suspend/Close requests. If the thread is trying to be paused or // closed, it will enter a wait/holding pattern here in this method until the managing @@ -294,6 +295,8 @@ void SysThreadBase::OnResumeInThread(bool isSuspended) {} // continued execution unimpeded. bool SysThreadBase::StateCheckInThread() { + SystemsMask systemsToTearDown {}; // Used for Pausing/Paused + switch (m_ExecMode.load()) { @@ -314,7 +317,9 @@ bool SysThreadBase::StateCheckInThread() // ------------------------------------- case ExecMode_Pausing: { - OnPauseInThread(); + systemsToTearDown = m_SystemsToTearDown.exchange({}, std::memory_order_relaxed); + + OnPauseInThread(systemsToTearDown); m_ExecMode = ExecMode_Paused; m_RunningLock.Release(); } @@ -328,8 +333,12 @@ bool SysThreadBase::StateCheckInThread() if (m_ExecMode != ExecMode_Closing) { if (g_CDVDReset) - //AppCoreThread deals with Reseting CDVD - OnResumeInThread(false); + // AppCoreThread deals with Reseting CDVD + // Reinit all but GS, USB, DEV9, CDVD (just like with isSuspend = false previously) + OnResumeInThread(static_cast(~(System_GS|System_USB|System_DEV9|System_CDVD))); + else + // Reinit previously torn down systems + OnResumeInThread(systemsToTearDown); g_CDVDReset = false; break; @@ -353,7 +362,7 @@ bool SysThreadBase::StateCheckInThread() m_sem_Resume.WaitWithoutYield(); m_RunningLock.Acquire(); - OnResumeInThread(true); + OnResumeInThread(static_cast(-1)); // All systems g_CDVDReset = false; break; diff --git a/pcsx2/System/SysThreads.h b/pcsx2/System/SysThreads.h index 508fe1ef52..5dbfc72b1b 100644 --- a/pcsx2/System/SysThreads.h +++ b/pcsx2/System/SysThreads.h @@ -26,6 +26,18 @@ using namespace Threading; typedef SafeArray VmStateBuffer; +enum SystemsMask : uint8_t +{ + System_GS = 1 << 0, + System_SPU2 = 1 << 1, + System_PAD = 1 << 2, + System_FW = 1 << 3, + System_CDVD = 1 << 4, + System_USB = 1 << 5, + System_DEV9 = 1 << 6, + System_MCD = 1 << 7, +}; + // -------------------------------------------------------------------------------------- // SysThreadBase // -------------------------------------------------------------------------------------- @@ -65,6 +77,7 @@ public: protected: std::atomic m_ExecMode; + std::atomic m_SystemsToTearDown {}; // This lock is used to avoid simultaneous requests to Suspend/Resume/Pause from // contending threads. @@ -113,7 +126,7 @@ public: virtual void Suspend(bool isBlocking = true); virtual void Resume(); - virtual void Pause(bool debug = false); + virtual void Pause(SystemsMask systemsToTearDown, bool debug = false); virtual void PauseSelf(); virtual void PauseSelfDebug(); @@ -146,15 +159,16 @@ protected: // prior to pausing the thread (ie, when Pause() has been called on a separate thread, // requesting this thread pause itself temporarily). After this is called, the thread // enters a waiting state on the m_sem_Resume semaphore. - virtual void OnPauseInThread() = 0; + // Parameter: + // systemsToTearDown - a bitmask of systems to call Close functions on. + virtual void OnPauseInThread(SystemsMask systemsToTearDown) = 0; // Extending classes should implement this, but should not call it. The parent class // handles invocation by the following guidelines: Called from StateCheckInThread() after the // thread has been suspended and then subsequently resumed. // Parameter: - // isSuspended - set to TRUE if the thread is returning from a suspended state, or - // FALSE if it's returning from a paused state. - virtual void OnResumeInThread(bool isSuspended) = 0; + // systemsToTearDown - a bitmask of systems to call Open functions on. + virtual void OnResumeInThread(SystemsMask systemsToReinstate) = 0; }; @@ -220,15 +234,18 @@ protected: virtual void Start(); virtual void OnStart(); - virtual void OnSuspendInThread(); - virtual void OnPauseInThread() {} - virtual void OnResumeInThread(bool IsSuspended); + virtual void OnSuspendInThread() override; + virtual void OnPauseInThread(SystemsMask systemsToTearDown) override { TearDownSystems(systemsToTearDown); } + virtual void OnResumeInThread(SystemsMask systemsToReinstate) override; virtual void OnCleanupInThread(); virtual void ExecuteTaskInThread(); virtual void DoCpuReset(); virtual void DoCpuExecute(); void _StateCheckThrows(); + +private: + void TearDownSystems(SystemsMask systemsToTearDown); }; diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 42bff75503..06cd62748d 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -577,7 +577,7 @@ void AppCoreThread::DoCpuReset() _parent::DoCpuReset(); } -void AppCoreThread::OnResumeInThread(bool isSuspended) +void AppCoreThread::OnResumeInThread(SystemsMask systemsToReinstate) { if (m_resetCdvd) { @@ -586,10 +586,10 @@ void AppCoreThread::OnResumeInThread(bool isSuspended) DoCDVDopen(); m_resetCdvd = false; } - else if (isSuspended) + else if (systemsToReinstate & System_CDVD) DoCDVDopen(); - _parent::OnResumeInThread(isSuspended); + _parent::OnResumeInThread(systemsToReinstate); PostCoreStatus(CoreThread_Resumed); } @@ -720,7 +720,7 @@ void SysExecEvent_CoreThreadClose::InvokeEvent() void SysExecEvent_CoreThreadPause::InvokeEvent() { - ScopedCoreThreadPause paused_core; + ScopedCoreThreadPause paused_core(m_systemsToTearDown); _post_and_wait(paused_core); paused_core.AllowResume(); } @@ -820,7 +820,7 @@ ScopedCoreThreadClose::~ScopedCoreThreadClose() DESTRUCTOR_CATCHALL } -ScopedCoreThreadPause::ScopedCoreThreadPause() +ScopedCoreThreadPause::ScopedCoreThreadPause(SystemsMask systemsToTearDown) { if (ScopedCore_IsFullyClosed || ScopedCore_IsPaused) { @@ -829,11 +829,11 @@ ScopedCoreThreadPause::ScopedCoreThreadPause() return; } - if (!PostToSysExec(std::make_unique())) + if (!PostToSysExec(std::make_unique(systemsToTearDown))) { m_alreadyStopped = CoreThread.IsPaused(); if (!m_alreadyStopped) - CoreThread.Pause(); + CoreThread.Pause(systemsToTearDown); } ScopedCore_IsPaused = true; diff --git a/pcsx2/gui/AppCoreThread.h b/pcsx2/gui/AppCoreThread.h index 943fe56ae2..8fd16d9057 100644 --- a/pcsx2/gui/AppCoreThread.h +++ b/pcsx2/gui/AppCoreThread.h @@ -119,13 +119,17 @@ public: virtual ~SysExecEvent_CoreThreadPause() = default; SysExecEvent_CoreThreadPause* Clone() const { return new SysExecEvent_CoreThreadPause(*this); } - SysExecEvent_CoreThreadPause(SynchronousActionState* sync = NULL, SynchronousActionState* resume_sync = NULL, Threading::Mutex* mtx_resume = NULL) + SysExecEvent_CoreThreadPause(SystemsMask systemsToTearDown, SynchronousActionState* sync = NULL, SynchronousActionState* resume_sync = NULL, Threading::Mutex* mtx_resume = NULL) : BaseSysExecEvent_ScopedCore(sync, resume_sync, mtx_resume) + , m_systemsToTearDown(systemsToTearDown) { } protected: void InvokeEvent(); + +private: + SystemsMask m_systemsToTearDown; }; // -------------------------------------------------------------------------------------- @@ -160,7 +164,7 @@ protected: virtual void OnResumeReady(); virtual void OnPause(); virtual void OnPauseDebug(); - virtual void OnResumeInThread(bool IsSuspended); + virtual void OnResumeInThread(SystemsMask systemsToReinstate) override; virtual void OnSuspendInThread(); virtual void OnCleanupInThread(); virtual void VsyncInThread(); @@ -242,7 +246,7 @@ struct ScopedCoreThreadPause : public BaseScopedCoreThread typedef BaseScopedCoreThread _parent; public: - ScopedCoreThreadPause(); + ScopedCoreThreadPause(SystemsMask systemsToTearDown = {}); virtual ~ScopedCoreThreadPause(); }; diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 108ad0fd3f..bf481b373b 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -1016,7 +1016,7 @@ void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_As_Click(wxCommandEvent& e // Ensure emulation is paused so that the correct image is captured bool wasPaused = CoreThread.IsPaused(); if (!wasPaused) - CoreThread.Pause(); + CoreThread.Pause({}); wxFileDialog fileDialog(this, _("Select a file"), g_Conf->Folders.Snapshots.ToAscii(), wxEmptyString, "PNG files (*.png)|*.png", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp index d5a8e4854d..0115f0a44c 100644 --- a/pcsx2/gui/SysState.cpp +++ b/pcsx2/gui/SysState.cpp @@ -681,7 +681,7 @@ protected: PatchesVerboseReset(); - GetCoreThread().Pause(); + GetCoreThread().Pause({}); SysClearExecutionCache(); for (uint i = 0; i < ArraySize(SavestateEntries); ++i)