From 3a2048ea570b428ea34adbfea6b71280e1ae5cc0 Mon Sep 17 00:00:00 2001 From: comex Date: Sat, 6 Sep 2014 17:26:40 -0400 Subject: [PATCH] Add a central variable g_want_determinism which controls whether to try to make things deterministic. It now affects the GPU determinism mode as well as some miscellaneous things that were calling IsNetPlayRunning. Probably incomplete. Notably, this can change while paused, if the user starts recording a movie. The movie code appears to have been missing locking between setting g_playMode and doing other things, which probably had a small chance of causing crashes or even desynced movies; fix that with PauseAndLock. The next commit will add a hidden config variable to override GPU determinism mode. --- Source/Core/Core/Core.cpp | 31 +++++++++++++++++++ Source/Core/Core/Core.h | 5 +++ Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 4 +-- Source/Core/Core/IPC_HLE/WII_Socket.cpp | 14 ++++++--- Source/Core/Core/IPC_HLE/WII_Socket.h | 2 ++ Source/Core/Core/Movie.cpp | 9 ++++++ Source/Core/VideoCommon/Fifo.cpp | 28 ++++++++++++++++- Source/Core/VideoCommon/Fifo.h | 1 + Source/Core/VideoCommon/MainBase.cpp | 5 +++ Source/Core/VideoCommon/VideoBackendBase.h | 4 +++ 10 files changed, 95 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 5b6294d2c7..cce3576100 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -48,6 +48,7 @@ #include "Core/HW/VideoInterface.h" #include "Core/HW/Wiimote.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h" +#include "Core/IPC_HLE/WII_Socket.h" #include "Core/PowerPC/PowerPC.h" #ifdef USE_GDBSTUB @@ -65,6 +66,8 @@ bool g_aspect_wide; namespace Core { +bool g_want_determinism; + // Declarations and definitions static Common::Timer s_timer; static volatile u32 s_drawn_frame = 0; @@ -177,6 +180,8 @@ bool Init() s_emu_thread.join(); } + Core::UpdateWantDeterminism(/*initial*/ true); + INFO_LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "GameCube"); INFO_LOG(OSREPORT, "CPU Thread separate = %s", @@ -564,6 +569,9 @@ void RequestRefreshInfo() bool PauseAndLock(bool doLock, bool unpauseOnUnlock) { + if (!IsRunning()) + return true; + // let's support recursive locking to simplify things on the caller's side, // and let's do it at this outer level in case the individual systems don't support it. if (doLock ? s_pause_and_lock_depth++ : --s_pause_and_lock_depth) @@ -702,4 +710,27 @@ void SetOnStoppedCallback(StoppedCallbackFunc callback) s_on_stopped_callback = callback; } +void UpdateWantDeterminism(bool initial) +{ + // For now, this value is not itself configurable. Instead, individual + // settings that depend on it, such as GPU determinism mode. should have + // override options for testing, + bool new_want_determinism = + Movie::IsPlayingInput() || + Movie::IsRecordingInput() || + NetPlay::IsNetPlayRunning(); + if (new_want_determinism != g_want_determinism || initial) + { + WARN_LOG(COMMON, "Want determinism <- %s", new_want_determinism ? "true" : "false"); + + bool was_unpaused = Core::PauseAndLock(true); + + g_want_determinism = new_want_determinism; + WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism); + g_video_backend->UpdateWantDeterminism(new_want_determinism); + + Core::PauseAndLock(false, was_unpaused); + } +} + } // Core diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 2e9ccddfca..08ed7f1081 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -23,6 +23,8 @@ extern bool g_aspect_wide; namespace Core { +extern bool g_want_determinism; + bool GetIsFramelimiterTempDisabled(); void SetIsFramelimiterTempDisabled(bool disable); @@ -79,4 +81,7 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock=true); typedef void(*StoppedCallbackFunc)(void); void SetOnStoppedCallback(StoppedCallbackFunc callback); +// Run on the GUI thread when the factors change. +void UpdateWantDeterminism(bool initial = false); + } // namespace diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index cc3e5cdcf0..da24bbb280 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -331,7 +331,7 @@ bool Wiimote::Step() m_rumble->controls[0]->control_ref->State(m_rumble_on); // when a movie is active, this button status update is disabled (moved), because movies only record data reports. - if (!(Movie::IsMovieActive()) || NetPlay::IsNetPlayRunning()) + if (!Core::g_want_determinism) { UpdateButtonsStatus(); } @@ -385,7 +385,7 @@ void Wiimote::UpdateButtonsStatus() void Wiimote::GetCoreData(u8* const data) { // when a movie is active, the button update happens here instead of Wiimote::Step, to avoid potential desync issues. - if (Movie::IsMovieActive() || NetPlay::IsNetPlayRunning()) + if (Core::g_want_determinism) { UpdateButtonsStatus(); } diff --git a/Source/Core/Core/IPC_HLE/WII_Socket.cpp b/Source/Core/Core/IPC_HLE/WII_Socket.cpp index ce46a0fb3a..b5a130c2c6 100644 --- a/Source/Core/Core/IPC_HLE/WII_Socket.cpp +++ b/Source/Core/Core/IPC_HLE/WII_Socket.cpp @@ -4,8 +4,7 @@ #include -#include "Core/Movie.h" -#include "Core/NetPlayProto.h" +#include "Core/Core.h" #include "Core/IPC_HLE/WII_IPC_HLE.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device.h" #include "Core/IPC_HLE/WII_Socket.h" // No Wii socket support while using NetPlay or TAS @@ -559,9 +558,7 @@ void WiiSockMan::AddSocket(s32 fd) s32 WiiSockMan::NewSocket(s32 af, s32 type, s32 protocol) { - if (NetPlay::IsNetPlayRunning() || - Movie::IsRecordingInput() || - Movie::IsPlayingInput()) + if (Core::g_want_determinism) { return SO_ENOMEM; } @@ -664,5 +661,12 @@ void WiiSockMan::Convert(sockaddr_in const & from, WiiSockAddrIn& to, s32 addrle to.len = addrlen; } +void WiiSockMan::UpdateWantDeterminism(bool want) +{ + // If we switched into movie recording, kill existing sockets. + if (want) + Clean(); +} + #undef ERRORCODE #undef EITHER diff --git a/Source/Core/Core/IPC_HLE/WII_Socket.h b/Source/Core/Core/IPC_HLE/WII_Socket.h index f9b72f5425..abed7d9f29 100644 --- a/Source/Core/Core/IPC_HLE/WII_Socket.h +++ b/Source/Core/Core/IPC_HLE/WII_Socket.h @@ -242,6 +242,8 @@ public: } } + void UpdateWantDeterminism(bool want); + private: WiiSockMan() = default; diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 5cba50a883..a06a7ca25b 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -437,6 +437,8 @@ bool BeginRecordingInput(int controllers) if (s_playMode != MODE_NONE || controllers == 0) return false; + bool was_unpaused = Core::PauseAndLock(true); + s_numPads = controllers; g_currentFrame = g_totalFrames = 0; g_currentLagCount = s_totalLagCount = 0; @@ -487,6 +489,10 @@ bool BeginRecordingInput(int controllers) s_currentByte = s_totalBytes = 0; + Core::UpdateWantDeterminism(); + + Core::PauseAndLock(false, was_unpaused); + Core::DisplayMessage("Starting movie recording", 2000); return true; } @@ -764,6 +770,8 @@ bool PlayInput(const std::string& filename) s_playMode = MODE_PLAYING; + Core::UpdateWantDeterminism(); + s_totalBytes = g_recordfd.GetSize() - 256; EnsureTmpInputSize((size_t)s_totalBytes); g_recordfd.ReadArray(tmpInput, (size_t)s_totalBytes); @@ -1097,6 +1105,7 @@ void EndPlayInput(bool cont) s_rerecords = 0; s_currentByte = 0; s_playMode = MODE_NONE; + Core::UpdateWantDeterminism(); Core::DisplayMessage("Movie End.", 2000); s_bRecordingFromSaveState = false; // we don't clear these things because otherwise we can't resume playback if we load a movie state later diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 87764ec85c..a47438c41e 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -11,13 +11,16 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreTiming.h" +#include "Core/NetPlayProto.h" #include "Core/HW/Memmap.h" #include "VideoCommon/CommandProcessor.h" +#include "VideoCommon/CPMemory.h" #include "VideoCommon/DataReader.h" #include "VideoCommon/Fifo.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/PixelEngine.h" +#include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VideoConfig.h" bool g_bSkipCurrentFrame = false; @@ -31,7 +34,7 @@ static u8 s_fifo_aux_data[FIFO_SIZE]; static u8* s_fifo_aux_write_ptr; static u8* s_fifo_aux_read_ptr; -bool g_use_deterministic_gpu_thread = true; // XXX +bool g_use_deterministic_gpu_thread; // STATE_TO_SAVE static std::mutex s_video_buffer_lock; @@ -413,3 +416,26 @@ void RunGpu() } CommandProcessor::SetCPStatusFromGPU(); } + +void Fifo_UpdateWantDeterminism(bool want) +{ + // We are paused (or not running at all yet) and have m_csHWVidOccupied, so + // it should be safe to change this. + g_use_deterministic_gpu_thread = want && SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; + + // Hack: For now movies are an exception to this being on (but not + // to wanting determinism in general). Once vertex arrays are + // fixed, there should be no reason to want this off for movies by + // default, so this can be removed. + if (NetPlay::IsNetPlayRunning()) + g_use_deterministic_gpu_thread = false; + + if (g_use_deterministic_gpu_thread) + { + // These haven't been updated in non-deterministic mode. + s_video_buffer_seen_ptr = g_video_buffer_pp_read_ptr = g_video_buffer_read_ptr; + CopyPreprocessCPStateFromMain(); + VertexLoaderManager::MarkAllDirty(); + } + +} diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index 175d6b6e4a..40a5ad84b7 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -27,6 +27,7 @@ u8* GetVideoBufferEndPtr(); void Fifo_DoState(PointerWrap &f); void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock); +void Fifo_UpdateWantDeterminism(bool want); // Used for diagnostics. enum SyncGPUReason { diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index 082c81c2ea..d775cfe64c 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -309,3 +309,8 @@ void VideoBackendHardware::RegisterCPMMIO(MMIO::Mapping* mmio, u32 base) CommandProcessor::RegisterMMIO(mmio, base); } +void VideoBackendHardware::UpdateWantDeterminism(bool want) +{ + Fifo_UpdateWantDeterminism(want); +} + diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 6ab9fce8f2..7d62dda37b 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -116,6 +116,8 @@ public: virtual void DoState(PointerWrap &p) = 0; virtual void CheckInvalidState() = 0; + + virtual void UpdateWantDeterminism(bool want) {} }; extern std::vector g_available_video_backends; @@ -151,6 +153,8 @@ class VideoBackendHardware : public VideoBackend void PauseAndLock(bool doLock, bool unpauseOnUnlock=true) override; void DoState(PointerWrap &p) override; + void UpdateWantDeterminism(bool want) override; + bool m_invalid; public: