From 77c4b26e6ce4d4c35b0789c361a9dda69c5a0d06 Mon Sep 17 00:00:00 2001 From: Hamish Milne Date: Sat, 11 Apr 2020 22:25:57 +0100 Subject: [PATCH] Attempt to improve save/load during frame advance --- src/citra_qt/main.cpp | 3 ++ src/core/core.cpp | 67 +++++++++++++++++++++-------------------- src/core/perf_stats.cpp | 12 +++++--- src/core/perf_stats.h | 1 + 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 0ef1e5bb19..bd1c95c52e 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -706,6 +706,7 @@ void GMainWindow::ConnectMenuEvents() { if (emulation_running) { ui.action_Enable_Frame_Advancing->setChecked(true); ui.action_Advance_Frame->setEnabled(true); + Core::System::GetInstance().frame_limiter.SetFrameAdvancing(true); Core::System::GetInstance().frame_limiter.AdvanceFrame(); } }); @@ -1640,6 +1641,7 @@ void GMainWindow::OnSaveState() { assert(action); Core::System::GetInstance().SendSignal(Core::System::Signal::Save, action->data().toUInt()); + Core::System::GetInstance().frame_limiter.AdvanceFrame(); newest_slot = action->data().toUInt(); } @@ -1648,6 +1650,7 @@ void GMainWindow::OnLoadState() { assert(action); Core::System::GetInstance().SendSignal(Core::System::Signal::Load, action->data().toUInt()); + Core::System::GetInstance().frame_limiter.AdvanceFrame(); } void GMainWindow::OnConfigure() { diff --git a/src/core/core.cpp b/src/core/core.cpp index 8768ba3e61..58f1ddefe9 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -89,6 +89,40 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } + Signal signal{Signal::None}; + u32 param{}; + { + std::lock_guard lock{signal_mutex}; + if (current_signal != Signal::None) { + signal = current_signal; + param = signal_param; + current_signal = Signal::None; + } + } + switch (signal) { + case Signal::Reset: + Reset(); + return ResultStatus::Success; + case Signal::Shutdown: + return ResultStatus::ShutdownRequested; + case Signal::Load: { + LOG_INFO(Core, "Begin load"); + System::LoadState(param); + LOG_INFO(Core, "Load completed"); + frame_limiter.WaitOnce(); + return ResultStatus::Success; + } + case Signal::Save: { + LOG_INFO(Core, "Begin save"); + System::SaveState(param); + LOG_INFO(Core, "Save completed"); + frame_limiter.WaitOnce(); + return ResultStatus::Success; + } + default: + break; + } + // All cores should have executed the same amount of ticks. If this is not the case an event was // scheduled with a cycles_into_future smaller then the current downcount. // So we have to get those cores to the same global time first @@ -163,39 +197,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) { HW::Update(); Reschedule(); - Signal signal{Signal::None}; - u32 param{}; - { - std::lock_guard lock{signal_mutex}; - if (current_signal != Signal::None) { - signal = current_signal; - param = signal_param; - current_signal = Signal::None; - } - } - switch (signal) { - case Signal::Reset: - Reset(); - break; - case Signal::Shutdown: - return ResultStatus::ShutdownRequested; - break; - case Signal::Load: { - LOG_INFO(Core, "Begin load"); - System::LoadState(param); - LOG_INFO(Core, "Load completed"); - break; - } - case Signal::Save: { - LOG_INFO(Core, "Begin save"); - System::SaveState(param); - LOG_INFO(Core, "Save completed"); - break; - } - default: - break; - } - return status; } diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 94d6c17ca0..00ab24dbcd 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -117,6 +117,14 @@ double PerfStats::GetLastFrameTimeScale() { return duration_cast(previous_frame_length).count() / FRAME_LENGTH; } +void FrameLimiter::WaitOnce() { + if (frame_advancing_enabled) { + // Frame advancing is enabled: wait on event instead of doing framelimiting + frame_advance_event.Wait(); + frame_advance_event.Reset(); + } +} + void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { if (frame_advancing_enabled) { // Frame advancing is enabled: wait on event instead of doing framelimiting @@ -164,10 +172,6 @@ void FrameLimiter::SetFrameAdvancing(bool value) { } void FrameLimiter::AdvanceFrame() { - if (!frame_advancing_enabled) { - // Start frame advancing - frame_advancing_enabled = true; - } frame_advance_event.Set(); } diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index 0ef5168faa..c7d22ef8ec 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h @@ -98,6 +98,7 @@ public: */ void SetFrameAdvancing(bool value); void AdvanceFrame(); + void WaitOnce(); private: /// Emulated system time (in microseconds) at the last limiter invocation