From 7d1fadb07c99e1929743816bd1c54f20e4d2d949 Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Tue, 14 Jul 2026 10:08:54 -0700 Subject: [PATCH] runtime: report simulated-vblank FPS telemetry Adapted from NyperYuhgard's PR #13. Co-authored-by: NyperYuhgard <93950153+NyperYuhgard@users.noreply.github.com> --- docs/internal/upstream/pr13-fps-telemetry.md | 9 ++++++ runtime/src/main.cpp | 34 ++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 docs/internal/upstream/pr13-fps-telemetry.md diff --git a/docs/internal/upstream/pr13-fps-telemetry.md b/docs/internal/upstream/pr13-fps-telemetry.md new file mode 100644 index 000000000..2ae437d11 --- /dev/null +++ b/docs/internal/upstream/pr13-fps-telemetry.md @@ -0,0 +1,9 @@ +# PR #13 FPS telemetry provenance + +Parked from NyperYuhgard's PSXrecomp PR #13, commit +[`b49548e7b8f494c9584eb09039a8c325d7375b46`](https://github.com/mstan/psxrecomp/commit/b49548e7b8f494c9584eb09039a8c325d7375b46). + +This branch retains only the title-neutral simulated-vblank FPS and realtime-speed +telemetry. It was adapted to current master and guards window-title access in +headless/windowless operation. The overlay-cache inventory from the same upstream +commit is parked separately. diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 6b0418b86..994cb69b5 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -2045,6 +2045,40 @@ static void sdl_vblank_present(void) { runtime_perf_diag_tick(); + /* Lightweight frontend telemetry from PR #13. Count simulated vblanks rather + * than presents so turbo and skipped-frame modes still report game speed. */ + { + static Uint64 fps_last_time = 0; + static uint64_t fps_last_frame = 0; + static std::string fps_base_title; + extern uint64_t s_frame_count; + const Uint64 now = SDL_GetPerformanceCounter(); + const Uint64 frequency = SDL_GetPerformanceFrequency(); + if (!fps_last_time) { + fps_last_time = now; + fps_last_frame = s_frame_count; + if (sdl_window) { + const char *title = SDL_GetWindowTitle(sdl_window); + if (title) fps_base_title = title; + } + } else if (frequency && now - fps_last_time >= frequency) { + const double seconds = (double)(now - fps_last_time) / (double)frequency; + const double fps = (double)(s_frame_count - fps_last_frame) / seconds; + const double speed = fps / 59.94; + if (!g_headless && sdl_window) { + char title[256]; + snprintf(title, sizeof(title), "%s [%.0f fps %.2fx]", + fps_base_title.c_str(), fps, speed); + SDL_SetWindowTitle(sdl_window, title); + } + std::fprintf(stderr, "[FPS] game: %.1f fps (%.2fx) | frames: %llu\n", + fps, speed, (unsigned long long)s_frame_count); + std::fflush(stderr); + fps_last_time = now; + fps_last_frame = s_frame_count; + } + } + /* Host-stack-usage profile sample — frame counter is now current, and we are * on the guest fiber (see §17 block above). BEFORE the turbo/fast-boot early * returns so the curve is captured even when presents are skipped. */