summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ameerj2021-05-15 20:34:20 -0400
committerGravatar ameerj2021-05-15 20:34:20 -0400
commit5bef54618a2850e42f7bab45120dab9166468a25 (patch)
treeadc5dbbe050488eb0d85b7a38a5c8310dca9ef92
parentMerge pull request #6300 from Morph1984/mbedtls (diff)
downloadyuzu-5bef54618a2850e42f7bab45120dab9166468a25.tar.gz
yuzu-5bef54618a2850e42f7bab45120dab9166468a25.tar.xz
yuzu-5bef54618a2850e42f7bab45120dab9166468a25.zip
perf_stats: Rework FPS counter to be more accurate
The FPS counter was based on metrics in the nvdisp swapbuffers call. This metric would be accurate if the gpu thread/renderer were synchronous with the nvdisp service, but that's no longer the case. This commit moves the frame counting responsibility onto the concrete renderers after their frame draw calls. Resulting in more meaningful metrics. The displayed FPS is now made up of the average framerate between the previous and most recent update, in order to avoid distracting FPS counter updates when framerate is oscillating between close values. The status bar update frequency was also changed from 2 seconds to 500ms.
Diffstat (limited to '')
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp1
-rw-r--r--src/core/perf_stats.cpp12
-rw-r--r--src/core/perf_stats.h9
-rw-r--r--src/video_core/gpu.cpp5
-rw-r--r--src/video_core/gpu.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp1
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp1
-rw-r--r--src/yuzu/main.cpp4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp2
10 files changed, 26 insertions, 14 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 434bf3262..47e70c157 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -289,7 +289,8 @@ struct System::Impl {
289 289
290 telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", 290 telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
291 perf_results.emulation_speed * 100.0); 291 perf_results.emulation_speed * 100.0);
292 telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); 292 telemetry_session->AddField(performance, "Shutdown_Framerate",
293 perf_results.average_game_fps);
293 telemetry_session->AddField(performance, "Shutdown_Frametime", 294 telemetry_session->AddField(performance, "Shutdown_Frametime",
294 perf_results.frametime * 1000.0); 295 perf_results.frametime * 1000.0);
295 telemetry_session->AddField(performance, "Mean_Frametime_MS", 296 telemetry_session->AddField(performance, "Mean_Frametime_MS",
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index bbef04a29..2cc0da124 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -52,7 +52,6 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
52 addr, offset, width, height, stride, static_cast<PixelFormat>(format), 52 addr, offset, width, height, stride, static_cast<PixelFormat>(format),
53 transform, crop_rect}; 53 transform, crop_rect};
54 54
55 system.GetPerfStats().EndGameFrame();
56 system.GetPerfStats().EndSystemFrame(); 55 system.GetPerfStats().EndSystemFrame();
57 system.GPU().SwapBuffers(&framebuffer); 56 system.GPU().SwapBuffers(&framebuffer);
58 system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); 57 system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index c92337079..526c017cd 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -69,9 +69,7 @@ void PerfStats::EndSystemFrame() {
69} 69}
70 70
71void PerfStats::EndGameFrame() { 71void PerfStats::EndGameFrame() {
72 std::lock_guard lock{object_mutex}; 72 game_frames.fetch_add(1, std::memory_order_relaxed);
73
74 game_frames += 1;
75} 73}
76 74
77double PerfStats::GetMeanFrametime() const { 75double PerfStats::GetMeanFrametime() const {
@@ -94,10 +92,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us
94 const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); 92 const auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
95 93
96 const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; 94 const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
97 95 const auto current_frames = static_cast<double>(game_frames.load(std::memory_order_relaxed));
96 const auto current_fps = current_frames / interval;
98 const PerfStatsResults results{ 97 const PerfStatsResults results{
99 .system_fps = static_cast<double>(system_frames) / interval, 98 .system_fps = static_cast<double>(system_frames) / interval,
100 .game_fps = static_cast<double>(game_frames) / interval, 99 .average_game_fps = (current_fps + previous_fps) / 2.0,
101 .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / 100 .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
102 static_cast<double>(system_frames), 101 static_cast<double>(system_frames),
103 .emulation_speed = system_us_per_second.count() / 1'000'000.0, 102 .emulation_speed = system_us_per_second.count() / 1'000'000.0,
@@ -108,7 +107,8 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us
108 reset_point_system_us = current_system_time_us; 107 reset_point_system_us = current_system_time_us;
109 accumulated_frametime = Clock::duration::zero(); 108 accumulated_frametime = Clock::duration::zero();
110 system_frames = 0; 109 system_frames = 0;
111 game_frames = 0; 110 game_frames.store(0, std::memory_order_relaxed);
111 previous_fps = current_fps;
112 112
113 return results; 113 return results;
114} 114}
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h
index 69256b960..90f9cc048 100644
--- a/src/core/perf_stats.h
+++ b/src/core/perf_stats.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <atomic>
8#include <chrono> 9#include <chrono>
9#include <cstddef> 10#include <cstddef>
10#include <mutex> 11#include <mutex>
@@ -15,8 +16,8 @@ namespace Core {
15struct PerfStatsResults { 16struct PerfStatsResults {
16 /// System FPS (LCD VBlanks) in Hz 17 /// System FPS (LCD VBlanks) in Hz
17 double system_fps; 18 double system_fps;
18 /// Game FPS (GSP frame submissions) in Hz 19 /// Average game FPS (GPU frame renders) in Hz
19 double game_fps; 20 double average_game_fps;
20 /// Walltime per system frame, in seconds, excluding any waits 21 /// Walltime per system frame, in seconds, excluding any waits
21 double frametime; 22 double frametime;
22 /// Ratio of walltime / emulated time elapsed 23 /// Ratio of walltime / emulated time elapsed
@@ -72,7 +73,7 @@ private:
72 /// Cumulative number of system frames (LCD VBlanks) presented since last reset 73 /// Cumulative number of system frames (LCD VBlanks) presented since last reset
73 u32 system_frames = 0; 74 u32 system_frames = 0;
74 /// Cumulative number of game frames (GSP frame submissions) since last reset 75 /// Cumulative number of game frames (GSP frame submissions) since last reset
75 u32 game_frames = 0; 76 std::atomic<u32> game_frames = 0;
76 77
77 /// Point when the previous system frame ended 78 /// Point when the previous system frame ended
78 Clock::time_point previous_frame_end = reset_point; 79 Clock::time_point previous_frame_end = reset_point;
@@ -80,6 +81,8 @@ private:
80 Clock::time_point frame_begin = reset_point; 81 Clock::time_point frame_begin = reset_point;
81 /// Total visible duration (including frame-limiting, etc.) of the previous system frame 82 /// Total visible duration (including frame-limiting, etc.) of the previous system frame
82 Clock::duration previous_frame_length = Clock::duration::zero(); 83 Clock::duration previous_frame_length = Clock::duration::zero();
84 /// Previously computed fps
85 double previous_fps = 0;
83}; 86};
84 87
85class FrameLimiter { 88class FrameLimiter {
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index a38024242..37f7b24e1 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -13,6 +13,7 @@
13#include "core/frontend/emu_window.h" 13#include "core/frontend/emu_window.h"
14#include "core/hardware_interrupt_manager.h" 14#include "core/hardware_interrupt_manager.h"
15#include "core/memory.h" 15#include "core/memory.h"
16#include "core/perf_stats.h"
16#include "video_core/engines/fermi_2d.h" 17#include "video_core/engines/fermi_2d.h"
17#include "video_core/engines/kepler_compute.h" 18#include "video_core/engines/kepler_compute.h"
18#include "video_core/engines/kepler_memory.h" 19#include "video_core/engines/kepler_memory.h"
@@ -191,6 +192,10 @@ u64 GPU::GetTicks() const {
191 return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; 192 return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den;
192} 193}
193 194
195void GPU::RendererFrameEndNotify() {
196 system.GetPerfStats().EndGameFrame();
197}
198
194void GPU::FlushCommands() { 199void GPU::FlushCommands() {
195 rasterizer->FlushCommands(); 200 rasterizer->FlushCommands();
196} 201}
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 8669e9940..29a867863 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -247,6 +247,8 @@ public:
247 return use_nvdec; 247 return use_nvdec;
248 } 248 }
249 249
250 void RendererFrameEndNotify();
251
250 enum class FenceOperation : u32 { 252 enum class FenceOperation : u32 {
251 Acquire = 0, 253 Acquire = 0,
252 Increment = 1, 254 Increment = 1,
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index cc2e499f9..a718bff7a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -155,6 +155,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
155 155
156 ++m_current_frame; 156 ++m_current_frame;
157 157
158 gpu.RendererFrameEndNotify();
158 rasterizer.TickFrame(); 159 rasterizer.TickFrame();
159 160
160 context->SwapBuffers(); 161 context->SwapBuffers();
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 2e0cf4232..3986eb172 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -154,6 +154,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
154 if (swapchain.Present(render_semaphore)) { 154 if (swapchain.Present(render_semaphore)) {
155 blit_screen.Recreate(); 155 blit_screen.Recreate();
156 } 156 }
157 gpu.RendererFrameEndNotify();
157 rasterizer.TickFrame(); 158 rasterizer.TickFrame();
158 } 159 }
159 160
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 9e72acbf7..0eb1cd7ee 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1377,7 +1377,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
1377 game_list->hide(); 1377 game_list->hide();
1378 game_list_placeholder->hide(); 1378 game_list_placeholder->hide();
1379 } 1379 }
1380 status_bar_update_timer.start(2000); 1380 status_bar_update_timer.start(500);
1381 async_status_button->setDisabled(true); 1381 async_status_button->setDisabled(true);
1382 multicore_status_button->setDisabled(true); 1382 multicore_status_button->setDisabled(true);
1383 renderer_status_button->setDisabled(true); 1383 renderer_status_button->setDisabled(true);
@@ -2797,7 +2797,7 @@ void GMainWindow::UpdateStatusBar() {
2797 } else { 2797 } else {
2798 emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); 2798 emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
2799 } 2799 }
2800 game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); 2800 game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0));
2801 emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); 2801 emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
2802 2802
2803 emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); 2803 emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index d64f81106..06b20c975 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -215,7 +215,7 @@ void EmuWindow_SDL2::WaitEvent() {
215 const auto results = Core::System::GetInstance().GetAndResetPerfStats(); 215 const auto results = Core::System::GetInstance().GetAndResetPerfStats();
216 const auto title = 216 const auto title =
217 fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, 217 fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname,
218 Common::g_scm_branch, Common::g_scm_desc, results.game_fps, 218 Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps,
219 results.emulation_speed * 100.0); 219 results.emulation_speed * 100.0);
220 SDL_SetWindowTitle(render_window, title.c_str()); 220 SDL_SetWindowTitle(render_window, title.c_str());
221 last_time = current_time; 221 last_time = current_time;