summaryrefslogtreecommitdiff
path: root/src/core/perf_stats.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-02-26 17:51:15 -0800
committerGravatar GitHub2017-02-26 17:51:15 -0800
commitb250ce21b9a62cb573540fdb14f30c28fa66e6ad (patch)
treeef55a0cd4a531a097de2152f563d712551972c4b /src/core/perf_stats.cpp
parentMerge pull request #2595 from jroweboy/patch (diff)
parentPerfStats: Re-order and document members better (diff)
downloadyuzu-b250ce21b9a62cb573540fdb14f30c28fa66e6ad.tar.gz
yuzu-b250ce21b9a62cb573540fdb14f30c28fa66e6ad.tar.xz
yuzu-b250ce21b9a62cb573540fdb14f30c28fa66e6ad.zip
Merge pull request #2587 from yuriks/status-bar
Replace built-in Profiler with indicators in status bar
Diffstat (limited to 'src/core/perf_stats.cpp')
-rw-r--r--src/core/perf_stats.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
new file mode 100644
index 000000000..2cdfb9ded
--- /dev/null
+++ b/src/core/perf_stats.cpp
@@ -0,0 +1,105 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <chrono>
6#include <mutex>
7#include <thread>
8#include "common/math_util.h"
9#include "core/hw/gpu.h"
10#include "core/perf_stats.h"
11#include "core/settings.h"
12
13using namespace std::chrono_literals;
14using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
15using std::chrono::duration_cast;
16using std::chrono::microseconds;
17
18namespace Core {
19
20void PerfStats::BeginSystemFrame() {
21 std::lock_guard<std::mutex> lock(object_mutex);
22
23 frame_begin = Clock::now();
24}
25
26void PerfStats::EndSystemFrame() {
27 std::lock_guard<std::mutex> lock(object_mutex);
28
29 auto frame_end = Clock::now();
30 accumulated_frametime += frame_end - frame_begin;
31 system_frames += 1;
32
33 previous_frame_length = frame_end - previous_frame_end;
34 previous_frame_end = frame_end;
35}
36
37void PerfStats::EndGameFrame() {
38 std::lock_guard<std::mutex> lock(object_mutex);
39
40 game_frames += 1;
41}
42
43PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) {
44 std::lock_guard<std::mutex> lock(object_mutex);
45
46 auto now = Clock::now();
47 // Walltime elapsed since stats were reset
48 auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
49
50 auto system_us_per_second =
51 static_cast<double>(current_system_time_us - reset_point_system_us) / interval;
52
53 Results results{};
54 results.system_fps = static_cast<double>(system_frames) / interval;
55 results.game_fps = static_cast<double>(game_frames) / interval;
56 results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
57 static_cast<double>(system_frames);
58 results.emulation_speed = system_us_per_second / 1'000'000.0;
59
60 // Reset counters
61 reset_point = now;
62 reset_point_system_us = current_system_time_us;
63 accumulated_frametime = Clock::duration::zero();
64 system_frames = 0;
65 game_frames = 0;
66
67 return results;
68}
69
70double PerfStats::GetLastFrameTimeScale() {
71 std::lock_guard<std::mutex> lock(object_mutex);
72
73 constexpr double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE;
74 return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
75}
76
77void 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 increase the time needed to recover and limit framerate again 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
105} // namespace Core