diff --git a/src/core/core.cpp b/src/core/core.cpp
index 434bf32626..47e70c1574 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 bbef04a29c..2cc0da124e 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<PixelFormat>(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 b185a38841..c42c437b72 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<DoubleSecs>(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<double>(game_frames.load(std::memory_order_relaxed));
+    const auto current_fps = current_frames / interval;
     const PerfStatsResults results{
         .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() /
                      static_cast<double>(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 ae46986969..e5d6037176 100644
--- a/src/core/perf_stats.h
+++ b/src/core/perf_stats.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <array>
+#include <atomic>
 #include <chrono>
 #include <cstddef>
 #include <mutex>
@@ -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<u32> 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 a380242422..37f7b24e14 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 8669e9940f..29a8678631 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 cc2e499f92..a718bff7aa 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 2e0cf42325..3986eb172a 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 1d36cc02db..9275cba53c 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 d64f811064..06b20c9756 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;