HUD and telemetry: report the game's fps and the displayed fps on both display servers
Description
Two meters on both display servers
The HUD's FPS row and game_exited's avg_fps used to carry one number. This PR reports two quantities, the same way on X11 and gamescope:
- Game fps: the frames the game produced.
- Displayed fps: the frames that could reach the panel.
What "game fps" counts today (unchanged by this PR):
| display server | what ticks FrameRating |
|---|---|
| X11 | One tick per content update of the tracked application window, i.e. per present the game sends to the app's X server (XServerScreen.onUpdateWindowContent). The renderer's per-frame listener is never enabled, and the Vulkan and SurfaceControl renderers do not implement it. |
| gamescope | One tick per GameNativeDrm.onFramePublished. The daemon raises it once per frame the ICD shim reports as produced: acquired, plus generated under frame generation (gamenative-drm asc.rs note_produced). It falls back to one per frame published to the panel only while no shim report has arrived for a second (GameNative/gamenative-drm#42). |
So with the shim reporting, both servers already count produced frames. A game rendering faster than the panel shows numbers the panel can never display.
Examples
| case | HUD FPS row |
|---|---|
| Hades II uncapped, 60 Hz panel | FPS 60 (287) |
| Capped at 60, 60 Hz panel | FPS 59.8 (game and displayed are equal) |
| 142 fps on a 120 Hz panel | FPS 120 (142) |
New telemetry fields
game_exited.game_fps: the same value asavg_fps, under an explicit name.avg_fpsstays for continuity and is the game's fps.game_exited.displayed_fps.- Session metadata:
displayed_fpsnext toavg_fps. - The PowerMetrics log line gains
displayed=next tofps=.
What is approximate
Displayed fps is an estimate: the game's one-second readings clamped to the panel's refresh rate. A frame the panel dropped below its rate is not seen. A measured count needs two things this app-only change does not add:
- X11: a per-present counter in the Vulkan and SurfaceControl renderers.
- gamescope: a separate publish upcall from the daemon. Today the app receives only the produced-frame upcall, because the publish path is muted while shim reports flow.
Other approximations:
- Under gamescope with frame generation on, game fps includes the generated frames (as before).
- On X11 with frame generation, the HUD keeps using the layer's measured output fps (as before).
- The HUD's ceiling is
PerformanceMetricsCollector.refreshRateHz, which is read at session start.
Behaviour
Nothing changes beyond the HUD text and the new telemetry fields. The tuner, the frame ring and the existing fields are untouched.
Recording
Type of Change
- Bug fix
- Performance / stability improvement
- Compatibility improvements
- Other (requires prior approval)
Checklist
- If I have access to
#code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed. - This change aligns with the current project scope (core functionality, stability, or performance). If not, it has been explicitly approved beforehand.
- I have attached a recording of the change.
- I have read and agree to the contribution guidelines in
CONTRIBUTING.md.
Summary by cubic
Reports the game's fps and the displayed fps on both X11 and gamescope, so the HUD and telemetry no longer show numbers the panel cannot reach (e.g. an uncapped game at 287 fps on a 60 Hz panel).
The HUD FPS row now shows FPS 60 (287) when the game outruns the panel, and a single number when it does not. game_exited gains game_fps (same value as avg_fps) and displayed_fps; session metadata and the PowerMetrics log line carry the displayed figure too. The displayed fps is an estimate: the game's per-second readings clamped to the panel's refresh rate, since neither renderer reports the frames the panel actually latched. Existing fields, the tuner, and the frame ring are untouched.
Summary by CodeRabbit
- New Features
- The performance HUD now distinguishes the panel’s displayed frame rate from the game’s frame rate when the game runs faster than the panel refresh rate.
- Performance metrics and session summaries now report displayed FPS separately from game FPS.