Merge pull request #6317 from ameerj/fps-fix

perf_stats: Rework FPS counter to be more accurate
This commit is contained in:
bunnei 2021-05-18 19:56:29 -07:00 committed by GitHub
commit 7d86a6ff02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 26 additions and 14 deletions

View file

@ -289,7 +289,8 @@ struct System::Impl {
telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
perf_results.emulation_speed * 100.0); 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", telemetry_session->AddField(performance, "Shutdown_Frametime",
perf_results.frametime * 1000.0); perf_results.frametime * 1000.0);
telemetry_session->AddField(performance, "Mean_Frametime_MS", telemetry_session->AddField(performance, "Mean_Frametime_MS",

View file

@ -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<PixelFormat>(format), addr, offset, width, height, stride, static_cast<PixelFormat>(format),
transform, crop_rect}; transform, crop_rect};
system.GetPerfStats().EndGameFrame();
system.GetPerfStats().EndSystemFrame(); system.GetPerfStats().EndSystemFrame();
system.GPU().SwapBuffers(&framebuffer); system.GPU().SwapBuffers(&framebuffer);
system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());

View file

@ -69,9 +69,7 @@ void PerfStats::EndSystemFrame() {
} }
void PerfStats::EndGameFrame() { void PerfStats::EndGameFrame() {
std::lock_guard lock{object_mutex}; game_frames.fetch_add(1, std::memory_order_relaxed);
game_frames += 1;
} }
double PerfStats::GetMeanFrametime() const { double PerfStats::GetMeanFrametime() const {
@ -94,10 +92,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us
const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); const auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
const auto current_frames = static_cast<double>(game_frames.load(std::memory_order_relaxed));
const auto current_fps = current_frames / interval;
const PerfStatsResults results{ const PerfStatsResults results{
.system_fps = static_cast<double>(system_frames) / interval, .system_fps = static_cast<double>(system_frames) / interval,
.game_fps = static_cast<double>(game_frames) / interval, .average_game_fps = (current_fps + previous_fps) / 2.0,
.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
static_cast<double>(system_frames), static_cast<double>(system_frames),
.emulation_speed = system_us_per_second.count() / 1'000'000.0, .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; reset_point_system_us = current_system_time_us;
accumulated_frametime = Clock::duration::zero(); accumulated_frametime = Clock::duration::zero();
system_frames = 0; system_frames = 0;
game_frames = 0; game_frames.store(0, std::memory_order_relaxed);
previous_fps = current_fps;
return results; return results;
} }

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <atomic>
#include <chrono> #include <chrono>
#include <cstddef> #include <cstddef>
#include <mutex> #include <mutex>
@ -15,8 +16,8 @@ namespace Core {
struct PerfStatsResults { struct PerfStatsResults {
/// System FPS (LCD VBlanks) in Hz /// System FPS (LCD VBlanks) in Hz
double system_fps; double system_fps;
/// Game FPS (GSP frame submissions) in Hz /// Average game FPS (GPU frame renders) in Hz
double game_fps; double average_game_fps;
/// Walltime per system frame, in seconds, excluding any waits /// Walltime per system frame, in seconds, excluding any waits
double frametime; double frametime;
/// Ratio of walltime / emulated time elapsed /// Ratio of walltime / emulated time elapsed
@ -72,7 +73,7 @@ private:
/// Cumulative number of system frames (LCD VBlanks) presented since last reset /// Cumulative number of system frames (LCD VBlanks) presented since last reset
u32 system_frames = 0; u32 system_frames = 0;
/// Cumulative number of game frames (GSP frame submissions) since last reset /// Cumulative number of game frames (GSP frame submissions) since last reset
u32 game_frames = 0; std::atomic<u32> game_frames = 0;
/// Point when the previous system frame ended /// Point when the previous system frame ended
Clock::time_point previous_frame_end = reset_point; Clock::time_point previous_frame_end = reset_point;
@ -80,6 +81,8 @@ private:
Clock::time_point frame_begin = reset_point; Clock::time_point frame_begin = reset_point;
/// Total visible duration (including frame-limiting, etc.) of the previous system frame /// Total visible duration (including frame-limiting, etc.) of the previous system frame
Clock::duration previous_frame_length = Clock::duration::zero(); Clock::duration previous_frame_length = Clock::duration::zero();
/// Previously computed fps
double previous_fps = 0;
}; };
class FrameLimiter { class FrameLimiter {

View file

@ -13,6 +13,7 @@
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
#include "core/hardware_interrupt_manager.h" #include "core/hardware_interrupt_manager.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/perf_stats.h"
#include "video_core/engines/fermi_2d.h" #include "video_core/engines/fermi_2d.h"
#include "video_core/engines/kepler_compute.h" #include "video_core/engines/kepler_compute.h"
#include "video_core/engines/kepler_memory.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; return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den;
} }
void GPU::RendererFrameEndNotify() {
system.GetPerfStats().EndGameFrame();
}
void GPU::FlushCommands() { void GPU::FlushCommands() {
rasterizer->FlushCommands(); rasterizer->FlushCommands();
} }

View file

@ -247,6 +247,8 @@ public:
return use_nvdec; return use_nvdec;
} }
void RendererFrameEndNotify();
enum class FenceOperation : u32 { enum class FenceOperation : u32 {
Acquire = 0, Acquire = 0,
Increment = 1, Increment = 1,

View file

@ -155,6 +155,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
++m_current_frame; ++m_current_frame;
gpu.RendererFrameEndNotify();
rasterizer.TickFrame(); rasterizer.TickFrame();
context->SwapBuffers(); context->SwapBuffers();

View file

@ -154,6 +154,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (swapchain.Present(render_semaphore)) { if (swapchain.Present(render_semaphore)) {
blit_screen.Recreate(); blit_screen.Recreate();
} }
gpu.RendererFrameEndNotify();
rasterizer.TickFrame(); rasterizer.TickFrame();
} }

View file

@ -1378,7 +1378,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
game_list->hide(); game_list->hide();
game_list_placeholder->hide(); game_list_placeholder->hide();
} }
status_bar_update_timer.start(2000); status_bar_update_timer.start(500);
async_status_button->setDisabled(true); async_status_button->setDisabled(true);
multicore_status_button->setDisabled(true); multicore_status_button->setDisabled(true);
renderer_status_button->setDisabled(true); renderer_status_button->setDisabled(true);
@ -2809,7 +2809,7 @@ void GMainWindow::UpdateStatusBar() {
} else { } else {
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); 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_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()); emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());

View file

@ -215,7 +215,7 @@ void EmuWindow_SDL2::WaitEvent() {
const auto results = Core::System::GetInstance().GetAndResetPerfStats(); const auto results = Core::System::GetInstance().GetAndResetPerfStats();
const auto title = const auto title =
fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, 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); results.emulation_speed * 100.0);
SDL_SetWindowTitle(render_window, title.c_str()); SDL_SetWindowTitle(render_window, title.c_str());
last_time = current_time; last_time = current_time;