summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-02-19 14:34:47 -0800
committerGravatar Yuri Kunde Schlesner2017-02-26 17:22:03 -0800
commitc75ae6c585f651a1b7c162c2e1ecccd22a1c587d (patch)
tree30d51f39c6b57244e1ede29820c3f5d98ca38451 /src/core
parentSynchronizedWrapper: Add Lock convenience method (diff)
downloadyuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.gz
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.xz
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.zip
Add performance statistics to status bar
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp9
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/hle/service/gsp_gpu.cpp3
-rw-r--r--src/core/hw/gpu.cpp4
-rw-r--r--src/core/hw/gpu.h2
-rw-r--r--src/core/perf_stats.cpp53
-rw-r--r--src/core/perf_stats.h43
8 files changed, 120 insertions, 3 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 5332e35a3..1adc78d8d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -170,6 +170,7 @@ set(SRCS
170 loader/smdh.cpp 170 loader/smdh.cpp
171 tracer/recorder.cpp 171 tracer/recorder.cpp
172 memory.cpp 172 memory.cpp
173 perf_stats.cpp
173 settings.cpp 174 settings.cpp
174 ) 175 )
175 176
@@ -357,6 +358,7 @@ set(HEADERS
357 memory.h 358 memory.h
358 memory_setup.h 359 memory_setup.h
359 mmio.h 360 mmio.h
361 perf_stats.h
360 settings.h 362 settings.h
361 ) 363 )
362 364
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c9c9b7615..ca2c28ce4 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -109,6 +109,11 @@ void System::PrepareReschedule() {
109 reschedule_pending = true; 109 reschedule_pending = true;
110} 110}
111 111
112PerfStats::Results System::GetAndResetPerfStats() {
113 auto perf_stats = this->perf_stats.Lock();
114 return perf_stats->GetAndResetStats(CoreTiming::GetGlobalTimeUs());
115}
116
112void System::Reschedule() { 117void System::Reschedule() {
113 if (!reschedule_pending) { 118 if (!reschedule_pending) {
114 return; 119 return;
@@ -140,6 +145,10 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
140 145
141 LOG_DEBUG(Core, "Initialized OK"); 146 LOG_DEBUG(Core, "Initialized OK");
142 147
148 // Reset counters and set time origin to current frame
149 GetAndResetPerfStats();
150 perf_stats.Lock()->BeginSystemFrame();
151
143 return ResultStatus::Success; 152 return ResultStatus::Success;
144} 153}
145 154
diff --git a/src/core/core.h b/src/core/core.h
index 17572a74f..3efc20c3d 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -6,9 +6,10 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/synchronized_wrapper.h"
11#include "core/memory.h" 11#include "core/memory.h"
12#include "core/perf_stats.h"
12 13
13class EmuWindow; 14class EmuWindow;
14class ARM_Interface; 15class ARM_Interface;
@@ -83,6 +84,8 @@ public:
83 /// Prepare the core emulation for a reschedule 84 /// Prepare the core emulation for a reschedule
84 void PrepareReschedule(); 85 void PrepareReschedule();
85 86
87 PerfStats::Results GetAndResetPerfStats();
88
86 /** 89 /**
87 * Gets a reference to the emulated CPU. 90 * Gets a reference to the emulated CPU.
88 * @returns A reference to the emulated CPU. 91 * @returns A reference to the emulated CPU.
@@ -91,6 +94,8 @@ public:
91 return *cpu_core; 94 return *cpu_core;
92 } 95 }
93 96
97 Common::SynchronizedWrapper<PerfStats> perf_stats;
98
94private: 99private:
95 /** 100 /**
96 * Initialize the emulated system. 101 * Initialize the emulated system.
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 1457518d4..67bab38da 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -4,6 +4,7 @@
4 4
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7#include "core/core.h"
7#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
8#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/result.h" 10#include "core/hle/result.h"
@@ -280,6 +281,8 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
280 281
281 if (screen_id == 0) { 282 if (screen_id == 0) {
282 MicroProfileFlip(); 283 MicroProfileFlip();
284 auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
285 perf_stats->EndGameFrame();
283 } 286 }
284 287
285 return RESULT_SUCCESS; 288 return RESULT_SUCCESS;
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index fa8c13d36..7cf081aad 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -32,7 +32,7 @@ namespace GPU {
32Regs g_regs; 32Regs g_regs;
33 33
34/// 268MHz CPU clocks / 60Hz frames per second 34/// 268MHz CPU clocks / 60Hz frames per second
35const u64 frame_ticks = BASE_CLOCK_RATE_ARM11 / 60; 35const u64 frame_ticks = BASE_CLOCK_RATE_ARM11 / SCREEN_REFRESH_RATE;
36/// Event id for CoreTiming 36/// Event id for CoreTiming
37static int vblank_event; 37static int vblank_event;
38/// Total number of frames drawn 38/// Total number of frames drawn
@@ -41,7 +41,7 @@ static u64 frame_count;
41static u32 time_point; 41static u32 time_point;
42/// Total delay caused by slow frames 42/// Total delay caused by slow frames
43static float time_delay; 43static float time_delay;
44constexpr float FIXED_FRAME_TIME = 1000.0f / 60; 44constexpr float FIXED_FRAME_TIME = 1000.0f / SCREEN_REFRESH_RATE;
45// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher 45// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
46// values increases time needed to limit frame rate after spikes 46// values increases time needed to limit frame rate after spikes
47constexpr float MAX_LAG_TIME = 18; 47constexpr float MAX_LAG_TIME = 18;
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index d53381216..bdd997b2a 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -13,6 +13,8 @@
13 13
14namespace GPU { 14namespace GPU {
15 15
16constexpr float SCREEN_REFRESH_RATE = 60;
17
16// Returns index corresponding to the Regs member labeled by field_name 18// Returns index corresponding to the Regs member labeled by field_name
17// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions 19// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
18// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). 20// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])).
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 @@
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 "core/hw/gpu.h"
7#include "core/perf_stats.h"
8
9namespace Core {
10
11void PerfStats::BeginSystemFrame() {
12 frame_begin = Clock::now();
13}
14
15void PerfStats::EndSystemFrame() {
16 auto frame_end = Clock::now();
17 accumulated_frametime += frame_end - frame_begin;
18 system_frames += 1;
19}
20
21void PerfStats::EndGameFrame() {
22 game_frames += 1;
23}
24
25PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) {
26 using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
27 using std::chrono::duration_cast;
28
29 auto now = Clock::now();
30 // Walltime elapsed since stats were reset
31 auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
32
33 auto system_us_per_second =
34 static_cast<double>(current_system_time_us - reset_point_system_us) / interval;
35
36 Results results{};
37 results.system_fps = static_cast<double>(system_frames) / interval;
38 results.game_fps = static_cast<double>(game_frames) / interval;
39 results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
40 static_cast<double>(system_frames);
41 results.emulation_speed = system_us_per_second / 1'000'000.0;
42
43 // Reset counters
44 reset_point = now;
45 reset_point_system_us = current_system_time_us;
46 accumulated_frametime = Clock::duration::zero();
47 system_frames = 0;
48 game_frames = 0;
49
50 return results;
51}
52
53} // namespace Core
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h
new file mode 100644
index 000000000..566a1419a
--- /dev/null
+++ b/src/core/perf_stats.h
@@ -0,0 +1,43 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <chrono>
8#include "common/common_types.h"
9
10namespace Core {
11
12class PerfStats {
13public:
14 using Clock = std::chrono::high_resolution_clock;
15
16 struct Results {
17 /// System FPS (LCD VBlanks) in Hz
18 double system_fps;
19 /// Game FPS (GSP frame submissions) in Hz
20 double game_fps;
21 /// Walltime per system frame, in seconds, excluding any waits
22 double frametime;
23 /// Ratio of walltime / emulated time elapsed
24 double emulation_speed;
25 };
26
27 void BeginSystemFrame();
28 void EndSystemFrame();
29 void EndGameFrame();
30
31 Results GetAndResetStats(u64 current_system_time_us);
32
33private:
34 Clock::time_point reset_point = Clock::now();
35
36 Clock::time_point frame_begin;
37 Clock::duration accumulated_frametime = Clock::duration::zero();
38 u64 reset_point_system_us = 0;
39 u32 system_frames = 0;
40 u32 game_frames = 0;
41};
42
43} // namespace Core