From c75ae6c585f651a1b7c162c2e1ecccd22a1c587d Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 19 Feb 2017 14:34:47 -0800 Subject: Add performance statistics to status bar --- src/core/perf_stats.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/core/perf_stats.cpp (limited to 'src/core/perf_stats.cpp') diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp new file mode 100644 index 000000000..6d9e603e4 --- /dev/null +++ b/src/core/perf_stats.cpp @@ -0,0 +1,53 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/hw/gpu.h" +#include "core/perf_stats.h" + +namespace Core { + +void PerfStats::BeginSystemFrame() { + frame_begin = Clock::now(); +} + +void PerfStats::EndSystemFrame() { + auto frame_end = Clock::now(); + accumulated_frametime += frame_end - frame_begin; + system_frames += 1; +} + +void PerfStats::EndGameFrame() { + game_frames += 1; +} + +PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { + using DoubleSecs = std::chrono::duration; + using std::chrono::duration_cast; + + auto now = Clock::now(); + // Walltime elapsed since stats were reset + auto interval = duration_cast(now - reset_point).count(); + + auto system_us_per_second = + static_cast(current_system_time_us - reset_point_system_us) / interval; + + Results results{}; + results.system_fps = static_cast(system_frames) / interval; + results.game_fps = static_cast(game_frames) / interval; + results.frametime = duration_cast(accumulated_frametime).count() / + static_cast(system_frames); + results.emulation_speed = system_us_per_second / 1'000'000.0; + + // Reset counters + reset_point = now; + reset_point_system_us = current_system_time_us; + accumulated_frametime = Clock::duration::zero(); + system_frames = 0; + game_frames = 0; + + return results; +} + +} // namespace Core -- cgit v1.2.3 From 92c8bd4b1f650438274e50303a6d3f668924d071 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 19 Feb 2017 18:18:26 -0800 Subject: PerfStats: Add method to get the instantaneous time ratio --- src/core/perf_stats.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/core/perf_stats.cpp') diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 6d9e603e4..8d9e521a3 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -6,6 +6,9 @@ #include "core/hw/gpu.h" #include "core/perf_stats.h" +using DoubleSecs = std::chrono::duration; +using std::chrono::duration_cast; + namespace Core { void PerfStats::BeginSystemFrame() { @@ -16,6 +19,9 @@ void PerfStats::EndSystemFrame() { auto frame_end = Clock::now(); accumulated_frametime += frame_end - frame_begin; system_frames += 1; + + previous_frame_length = frame_end - previous_frame_end; + previous_frame_end = frame_end; } void PerfStats::EndGameFrame() { @@ -23,9 +29,6 @@ void PerfStats::EndGameFrame() { } PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { - using DoubleSecs = std::chrono::duration; - using std::chrono::duration_cast; - auto now = Clock::now(); // Walltime elapsed since stats were reset auto interval = duration_cast(now - reset_point).count(); @@ -50,4 +53,9 @@ PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { return results; } +double PerfStats::GetLastFrameTimeScale() { + constexpr double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE; + return duration_cast(previous_frame_length).count() / FRAME_LENGTH; +} + } // namespace Core -- cgit v1.2.3 From b285c2a4ed29a126b5bcfe46e2784bd1870bdf82 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Mon, 20 Feb 2017 13:56:58 -0800 Subject: Core: Make PerfStats internally locked More ergonomic to use and will be required for upcoming changes. --- src/core/perf_stats.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/core/perf_stats.cpp') diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 8d9e521a3..06bc788bd 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "core/hw/gpu.h" #include "core/perf_stats.h" @@ -12,10 +13,14 @@ using std::chrono::duration_cast; namespace Core { void PerfStats::BeginSystemFrame() { + std::lock_guard lock(object_mutex); + frame_begin = Clock::now(); } void PerfStats::EndSystemFrame() { + std::lock_guard lock(object_mutex); + auto frame_end = Clock::now(); accumulated_frametime += frame_end - frame_begin; system_frames += 1; @@ -25,10 +30,14 @@ void PerfStats::EndSystemFrame() { } void PerfStats::EndGameFrame() { + std::lock_guard lock(object_mutex); + game_frames += 1; } PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { + std::lock_guard lock(object_mutex); + auto now = Clock::now(); // Walltime elapsed since stats were reset auto interval = duration_cast(now - reset_point).count(); @@ -54,6 +63,8 @@ PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { } double PerfStats::GetLastFrameTimeScale() { + std::lock_guard lock(object_mutex); + constexpr double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE; return duration_cast(previous_frame_length).count() / FRAME_LENGTH; } -- cgit v1.2.3 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 From 174464a87f2e1709597bc1e0cb08c877487a771b Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 26 Feb 2017 17:13:12 -0800 Subject: PerfStats: Re-order and document members better --- src/core/perf_stats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/perf_stats.cpp') diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index eb59a1332..2cdfb9ded 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -76,7 +76,7 @@ double PerfStats::GetLastFrameTimeScale() { 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. + // values increase the time needed to recover and limit framerate again after spikes. constexpr microseconds MAX_LAG_TIME_US = 25ms; if (!Settings::values.toggle_framelimit) { -- cgit v1.2.3