summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/citra_qt/main.cpp27
-rw-r--r--src/citra_qt/main.h3
-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
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp9
11 files changed, 159 insertions, 3 deletions
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 43530b275..41356a6ca 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -253,6 +253,8 @@ void GMainWindow::ConnectWidgetEvents() {
253 connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window, 253 connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window,
254 SLOT(OnEmulationStarting(EmuThread*))); 254 SLOT(OnEmulationStarting(EmuThread*)));
255 connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping())); 255 connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping()));
256
257 connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
256} 258}
257 259
258void GMainWindow::ConnectMenuEvents() { 260void GMainWindow::ConnectMenuEvents() {
@@ -401,6 +403,8 @@ void GMainWindow::BootGame(const QString& filename) {
401 if (ui.action_Single_Window_Mode->isChecked()) { 403 if (ui.action_Single_Window_Mode->isChecked()) {
402 game_list->hide(); 404 game_list->hide();
403 } 405 }
406 status_bar_update_timer.start(1000);
407
404 render_window->show(); 408 render_window->show();
405 render_window->setFocus(); 409 render_window->setFocus();
406 410
@@ -435,6 +439,12 @@ void GMainWindow::ShutdownGame() {
435 render_window->hide(); 439 render_window->hide();
436 game_list->show(); 440 game_list->show();
437 441
442 // Disable status bar updates
443 status_bar_update_timer.stop();
444 emu_speed_label->setVisible(false);
445 game_fps_label->setVisible(false);
446 emu_frametime_label->setVisible(false);
447
438 emulation_running = false; 448 emulation_running = false;
439} 449}
440 450
@@ -614,6 +624,23 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() {
614 graphicsSurfaceViewerWidget->show(); 624 graphicsSurfaceViewerWidget->show();
615} 625}
616 626
627void GMainWindow::UpdateStatusBar() {
628 if (emu_thread == nullptr) {
629 status_bar_update_timer.stop();
630 return;
631 }
632
633 auto results = Core::System::GetInstance().GetAndResetPerfStats();
634
635 emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 2));
636 game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 1));
637 emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
638
639 emu_speed_label->setVisible(true);
640 game_fps_label->setVisible(true);
641 emu_frametime_label->setVisible(true);
642}
643
617bool GMainWindow::ConfirmClose() { 644bool GMainWindow::ConfirmClose() {
618 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) 645 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
619 return true; 646 return true;
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 3cbf4ea99..ec841eaa5 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -127,6 +127,8 @@ private slots:
127 void OnCreateGraphicsSurfaceViewer(); 127 void OnCreateGraphicsSurfaceViewer();
128 128
129private: 129private:
130 void UpdateStatusBar();
131
130 Ui::MainWindow ui; 132 Ui::MainWindow ui;
131 133
132 GRenderWindow* render_window; 134 GRenderWindow* render_window;
@@ -136,6 +138,7 @@ private:
136 QLabel* emu_speed_label = nullptr; 138 QLabel* emu_speed_label = nullptr;
137 QLabel* game_fps_label = nullptr; 139 QLabel* game_fps_label = nullptr;
138 QLabel* emu_frametime_label = nullptr; 140 QLabel* emu_frametime_label = nullptr;
141 QTimer status_bar_update_timer;
139 142
140 std::unique_ptr<Config> config; 143 std::unique_ptr<Config> config;
141 144
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
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 2aa90e5c1..0b90dcb3d 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -12,6 +12,7 @@
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/profiler_reporting.h" 13#include "common/profiler_reporting.h"
14#include "common/synchronized_wrapper.h" 14#include "common/synchronized_wrapper.h"
15#include "core/core.h"
15#include "core/frontend/emu_window.h" 16#include "core/frontend/emu_window.h"
16#include "core/hw/gpu.h" 17#include "core/hw/gpu.h"
17#include "core/hw/hw.h" 18#include "core/hw/hw.h"
@@ -151,6 +152,10 @@ void RendererOpenGL::SwapBuffers() {
151 auto aggregator = Common::Profiling::GetTimingResultsAggregator(); 152 auto aggregator = Common::Profiling::GetTimingResultsAggregator();
152 aggregator->AddFrame(profiler.GetPreviousFrameResults()); 153 aggregator->AddFrame(profiler.GetPreviousFrameResults());
153 } 154 }
155 {
156 auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
157 perf_stats->EndSystemFrame();
158 }
154 159
155 // Swap buffers 160 // Swap buffers
156 render_window->PollEvents(); 161 render_window->PollEvents();
@@ -159,6 +164,10 @@ void RendererOpenGL::SwapBuffers() {
159 prev_state.Apply(); 164 prev_state.Apply();
160 165
161 profiler.BeginFrame(); 166 profiler.BeginFrame();
167 {
168 auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
169 perf_stats->BeginSystemFrame();
170 }
162 171
163 RefreshRasterizerSetting(); 172 RefreshRasterizerSetting();
164 173