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 { telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", perf_results.emulation_speed * 100.0); - telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); + telemetry_session->AddField(performance, "Shutdown_Framerate", + perf_results.average_game_fps); telemetry_session->AddField(performance, "Shutdown_Frametime", perf_results.frametime * 1000.0); 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 addr, offset, width, height, stride, static_cast(format), transform, crop_rect}; - system.GetPerfStats().EndGameFrame(); system.GetPerfStats().EndSystemFrame(); system.GPU().SwapBuffers(&framebuffer); system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index b185a3884..c42c437b7 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -69,9 +69,7 @@ void PerfStats::EndSystemFrame() { } void PerfStats::EndGameFrame() { - std::lock_guard lock{object_mutex}; - - game_frames += 1; + game_frames.fetch_add(1, std::memory_order_relaxed); } double PerfStats::GetMeanFrametime() const { @@ -94,10 +92,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us const auto interval = duration_cast(now - reset_point).count(); const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; - + const auto current_frames = static_cast(game_frames.load(std::memory_order_relaxed)); + const auto current_fps = current_frames / interval; const PerfStatsResults results{ .system_fps = static_cast(system_frames) / interval, - .game_fps = static_cast(game_frames) / interval, + .average_game_fps = (current_fps + previous_fps) / 2.0, .frametime = duration_cast(accumulated_frametime).count() / static_cast(system_frames), .emulation_speed = system_us_per_second.count() / 1'000'000.0, @@ -108,7 +107,8 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us reset_point_system_us = current_system_time_us; accumulated_frametime = Clock::duration::zero(); system_frames = 0; - game_frames = 0; + game_frames.store(0, std::memory_order_relaxed); + previous_fps = current_fps; return results; } diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index ae4698696..e5d603717 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -15,8 +16,8 @@ namespace Core { struct PerfStatsResults { /// System FPS (LCD VBlanks) in Hz double system_fps; - /// Game FPS (GSP frame submissions) in Hz - double game_fps; + /// Average game FPS (GPU frame renders) in Hz + double average_game_fps; /// Walltime per system frame, in seconds, excluding any waits double frametime; /// Ratio of walltime / emulated time elapsed @@ -72,7 +73,7 @@ private: /// 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; + std::atomic game_frames = 0; /// Point when the previous system frame ended Clock::time_point previous_frame_end = reset_point; @@ -80,6 +81,8 @@ private: 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(); + /// Previously computed fps + double previous_fps = 0; }; class 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 @@ #include "core/frontend/emu_window.h" #include "core/hardware_interrupt_manager.h" #include "core/memory.h" +#include "core/perf_stats.h" #include "video_core/engines/fermi_2d.h" #include "video_core/engines/kepler_compute.h" #include "video_core/engines/kepler_memory.h" @@ -191,6 +192,10 @@ u64 GPU::GetTicks() const { return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; } +void GPU::RendererFrameEndNotify() { + system.GetPerfStats().EndGameFrame(); +} + void GPU::FlushCommands() { rasterizer->FlushCommands(); } 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: return use_nvdec; } + void RendererFrameEndNotify(); + enum class FenceOperation : u32 { Acquire = 0, 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) { ++m_current_frame; + gpu.RendererFrameEndNotify(); rasterizer.TickFrame(); 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) { if (swapchain.Present(render_semaphore)) { blit_screen.Recreate(); } + gpu.RendererFrameEndNotify(); rasterizer.TickFrame(); } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 1d36cc02d..9275cba53 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1378,7 +1378,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { game_list->hide(); game_list_placeholder->hide(); } - status_bar_update_timer.start(2000); + status_bar_update_timer.start(500); async_status_button->setDisabled(true); multicore_status_button->setDisabled(true); renderer_status_button->setDisabled(true); @@ -2809,7 +2809,7 @@ void GMainWindow::UpdateStatusBar() { } else { emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); } - game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); + game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); 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() { const auto results = Core::System::GetInstance().GetAndResetPerfStats(); const auto title = fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, - Common::g_scm_branch, Common::g_scm_desc, results.game_fps, + Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, results.emulation_speed * 100.0); SDL_SetWindowTitle(render_window, title.c_str()); last_time = current_time;