diff options
| author | 2017-02-20 16:31:59 -0800 | |
|---|---|---|
| committer | 2017-02-26 17:22:04 -0800 | |
| commit | fb1979d7e26c20fe2b8d2c3d3dc998e5e00f2f61 (patch) | |
| tree | 690461954bff040727fa2cb3b34c9d71c003ea9c /src/core/perf_stats.cpp | |
| parent | Core: Make PerfStats internally locked (diff) | |
| download | yuzu-fb1979d7e26c20fe2b8d2c3d3dc998e5e00f2f61.tar.gz yuzu-fb1979d7e26c20fe2b8d2c3d3dc998e5e00f2f61.tar.xz yuzu-fb1979d7e26c20fe2b8d2c3d3dc998e5e00f2f61.zip | |
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.
Diffstat (limited to 'src/core/perf_stats.cpp')
| -rw-r--r-- | src/core/perf_stats.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
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 @@ | |||
| 4 | 4 | ||
| 5 | #include <chrono> | 5 | #include <chrono> |
| 6 | #include <mutex> | 6 | #include <mutex> |
| 7 | #include <thread> | ||
| 8 | #include "common/math_util.h" | ||
| 7 | #include "core/hw/gpu.h" | 9 | #include "core/hw/gpu.h" |
| 8 | #include "core/perf_stats.h" | 10 | #include "core/perf_stats.h" |
| 11 | #include "core/settings.h" | ||
| 9 | 12 | ||
| 13 | using namespace std::chrono_literals; | ||
| 10 | using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; | 14 | using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; |
| 11 | using std::chrono::duration_cast; | 15 | using std::chrono::duration_cast; |
| 16 | using std::chrono::microseconds; | ||
| 12 | 17 | ||
| 13 | namespace Core { | 18 | namespace Core { |
| 14 | 19 | ||
| @@ -69,4 +74,32 @@ double PerfStats::GetLastFrameTimeScale() { | |||
| 69 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; | 74 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; |
| 70 | } | 75 | } |
| 71 | 76 | ||
| 77 | void FrameLimiter::DoFrameLimiting(u64 current_system_time_us) { | ||
| 78 | // Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher | ||
| 79 | // values increases time needed to limit frame rate after spikes. | ||
| 80 | constexpr microseconds MAX_LAG_TIME_US = 25ms; | ||
| 81 | |||
| 82 | if (!Settings::values.toggle_framelimit) { | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | auto now = Clock::now(); | ||
| 87 | |||
| 88 | frame_limiting_delta_err += microseconds(current_system_time_us - previous_system_time_us); | ||
| 89 | frame_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime); | ||
| 90 | frame_limiting_delta_err = | ||
| 91 | MathUtil::Clamp(frame_limiting_delta_err, -MAX_LAG_TIME_US, MAX_LAG_TIME_US); | ||
| 92 | |||
| 93 | if (frame_limiting_delta_err > microseconds::zero()) { | ||
| 94 | std::this_thread::sleep_for(frame_limiting_delta_err); | ||
| 95 | |||
| 96 | auto now_after_sleep = Clock::now(); | ||
| 97 | frame_limiting_delta_err -= duration_cast<microseconds>(now_after_sleep - now); | ||
| 98 | now = now_after_sleep; | ||
| 99 | } | ||
| 100 | |||
| 101 | previous_system_time_us = current_system_time_us; | ||
| 102 | previous_walltime = now; | ||
| 103 | } | ||
| 104 | |||
| 72 | } // namespace Core | 105 | } // namespace Core |