diff options
Diffstat (limited to 'src/core/perf_stats.h')
-rw-r--r-- | src/core/perf_stats.h | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h new file mode 100644 index 000000000..362b205c8 --- /dev/null +++ b/src/core/perf_stats.h @@ -0,0 +1,83 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <chrono> +#include <mutex> +#include "common/common_types.h" + +namespace Core { + +/** + * Class to manage and query performance/timing statistics. All public functions of this class are + * thread-safe unless stated otherwise. + */ +class PerfStats { +public: + using Clock = std::chrono::high_resolution_clock; + + struct Results { + /// System FPS (LCD VBlanks) in Hz + double system_fps; + /// Game FPS (GSP frame submissions) in Hz + double game_fps; + /// Walltime per system frame, in seconds, excluding any waits + double frametime; + /// Ratio of walltime / emulated time elapsed + double emulation_speed; + }; + + void BeginSystemFrame(); + void EndSystemFrame(); + void EndGameFrame(); + + Results GetAndResetStats(u64 current_system_time_us); + + /** + * Gets the ratio between walltime and the emulated time of the previous system frame. This is + * useful for scaling inputs or outputs moving between the two time domains. + */ + double GetLastFrameTimeScale(); + +private: + std::mutex object_mutex; + + /// Point when the cumulative counters were reset + Clock::time_point reset_point = Clock::now(); + /// System time when the cumulative counters were reset + u64 reset_point_system_us = 0; + + /// Cumulative duration (excluding v-sync/frame-limiting) of frames since last reset + Clock::duration accumulated_frametime = Clock::duration::zero(); + /// Cumulative number of system frames (LCD VBlanks) presented since last reset + u32 system_frames = 0; + /// Cumulative number of game frames (GSP frame submissions) since last reset + u32 game_frames = 0; + + /// Point when the previous system frame ended + Clock::time_point previous_frame_end = reset_point; + /// Point when the current system frame began + Clock::time_point frame_begin = reset_point; + /// Total visible duration (including frame-limiting, etc.) of the previous system frame + Clock::duration previous_frame_length = Clock::duration::zero(); +}; + +class FrameLimiter { +public: + using Clock = std::chrono::high_resolution_clock; + + void DoFrameLimiting(u64 current_system_time_us); + +private: + /// Emulated system time (in microseconds) at the last limiter invocation + u64 previous_system_time_us = 0; + /// Walltime at the last limiter invocation + Clock::time_point previous_walltime = Clock::now(); + + /// Accumulated difference between walltime and emulated time + std::chrono::microseconds frame_limiting_delta_err{0}; +}; + +} // namespace Core |