From fb1979d7e26c20fe2b8d2c3d3dc998e5e00f2f61 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Mon, 20 Feb 2017 16:31:59 -0800 Subject: Core: Re-write frame limiter Now based on std::chrono, and also works in terms of emulated time instead of frames, so we can in the future frame-limit even when the display is disabled, etc. The frame limiter can also be enabled along with v-sync now, which should be useful for those with displays running at more than 60 Hz. --- src/core/perf_stats.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/core/perf_stats.cpp') diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 06bc788bd..eb59a1332 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -4,11 +4,16 @@ #include #include +#include +#include "common/math_util.h" #include "core/hw/gpu.h" #include "core/perf_stats.h" +#include "core/settings.h" +using namespace std::chrono_literals; using DoubleSecs = std::chrono::duration; using std::chrono::duration_cast; +using std::chrono::microseconds; namespace Core { @@ -69,4 +74,32 @@ double PerfStats::GetLastFrameTimeScale() { return duration_cast(previous_frame_length).count() / FRAME_LENGTH; } +void FrameLimiter::DoFrameLimiting(u64 current_system_time_us) { + // Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher + // values increases time needed to limit frame rate after spikes. + constexpr microseconds MAX_LAG_TIME_US = 25ms; + + if (!Settings::values.toggle_framelimit) { + return; + } + + auto now = Clock::now(); + + frame_limiting_delta_err += microseconds(current_system_time_us - previous_system_time_us); + frame_limiting_delta_err -= duration_cast(now - previous_walltime); + frame_limiting_delta_err = + MathUtil::Clamp(frame_limiting_delta_err, -MAX_LAG_TIME_US, MAX_LAG_TIME_US); + + if (frame_limiting_delta_err > microseconds::zero()) { + std::this_thread::sleep_for(frame_limiting_delta_err); + + auto now_after_sleep = Clock::now(); + frame_limiting_delta_err -= duration_cast(now_after_sleep - now); + now = now_after_sleep; + } + + previous_system_time_us = current_system_time_us; + previous_walltime = now; +} + } // namespace Core -- cgit v1.2.3