ui: measure guest FPS as frame intervals per second

This commit is contained in:
mchughalex 2026-07-24 13:33:44 +01:00
parent ae6ea8e925
commit 9100b278b7

View file

@ -808,19 +808,31 @@ Presenter::GuestFrameStats Presenter::GetGuestFrameStats() const {
} }
const double span_to_now_seconds = const double span_to_now_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(now - oldest_in_window).count(); std::chrono::duration_cast<std::chrono::duration<double>>(now - oldest_in_window).count();
if (span_to_now_seconds > 0.0) { double span_between_frames_seconds = 0.0;
stats.fps = double(frames_in_window) / span_to_now_seconds;
}
if (frames_in_window >= 2) { if (frames_in_window >= 2) {
const double span_between_frames_seconds = span_between_frames_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(newest_in_window - std::chrono::duration_cast<std::chrono::duration<double>>(newest_in_window -
oldest_in_window) oldest_in_window)
.count(); .count();
if (span_between_frames_seconds > 0.0) { }
stats.frame_time_ms = if (span_between_frames_seconds > 0.0 && span_to_now_seconds > 0.0) {
span_between_frames_seconds * 1000.0 / double(frames_in_window - 1); const double mean_interval_seconds =
} span_between_frames_seconds / double(frames_in_window - 1);
} else if (stats.fps > 0.0) { stats.frame_time_ms = mean_interval_seconds * 1000.0;
// Rate = frame intervals per second, not frames per second: N frames span
// only N - 1 intervals, so dividing the frame count by the span reads up
// to one FPS high (oscillating with sampling phase, e.g. 140-141 at a
// steady 140). The partial interval elapsed since the newest frame is
// included so a steady source reads exactly its rate regardless of
// phase, but clamped to one interval so the estimate still decays toward
// zero when the guest stops producing frames.
const double partial_interval = std::min(
(span_to_now_seconds - span_between_frames_seconds) / mean_interval_seconds, 1.0);
stats.fps = (double(frames_in_window - 1) + partial_interval) / span_to_now_seconds;
} else if (span_to_now_seconds > 0.0) {
// A single frame in the window (or coincident timestamps): no interval to
// measure, keep the frame-count estimate.
stats.fps = double(frames_in_window) / span_to_now_seconds;
stats.frame_time_ms = 1000.0 / stats.fps; stats.frame_time_ms = 1000.0 / stats.fps;
} }
return stats; return stats;