gamescope: start sessions at the panel refresh rate; daemon stamps flips on the latch grid

Closed
UT
8d ago
+36-24

Description

Drops the fixed 1200 Hz vblank grid (-r 1200) from gamescope sessions: gamescope now takes its refresh from the mode the gamenative-drm daemon advertises, which is the panel's active rate. Ships the daemon that stamps gamescope's flips on the panel latch grid.

Branch gamescope-panel-rate-vblank.

  • -r is removed from the launch command entirely (GamescopeSettings.gridArg and SESSION_GRID_HZ are gone). The daemon already learns the panel's active rate from nativeSetPanelRefreshHz, advertises it as the mode and measures its latch grid, so gamescope's tick follows it; a mode change mid-session is forwarded by the daemon as the gn_panel_refresh ConVar.
  • display/PanelRefresh.kt (new): PanelRefresh.activeHz reads the panel's active rate once, rounded to Hz, 60 when unreadable. nativeSetPanelRefreshHz and the FPS limiter ceiling both use it, so they always agree. A panel the user holds at 60 Hz counts as 60.
  • XServerScreen.detectRefreshRateHz delegates to PanelRefresh.activeHz.
  • jniLibs/arm64-v8a/libgamenative_drm.so: the daemon from the gamenative-drm PR flip-stamps-on-the-panel-latch-grid (0630e1a). It sets the latch grid for gamescope clients that ask for it (GNLG client cap) and forwards panel-rate changes to a running session as the gn_panel_refresh ConVar.

Depends on:

  • gamenative-drm flip-stamps-on-the-panel-latch-grid (the daemon in this PR's jniLibs);
  • gamenative-drm present-wait-answered-at-commit-in-mailbox (ICD shim, ships in the gamescope payload): the fix that takes cap 60 from 47 to 60 fps;
  • gamescope vblank-on-panel-latch-grid (A53/A54).

Not in this PR: the device test used payload 20261030.3 with the fix-1 gamescope binary and the fix-3 shim (libadrenotools_gamescope.so) swapped in by hand. Shipping needs a gamescope payload built with both and a payload VERSION bump, in a follow-up PR.

Compatibility: with the current payload's gamescope (no A53), dropping -r 1200 leaves gamescope on the daemon's advertised mode (the panel rate), which still cuts its wakeups; the daemon keeps its legacy timeline for it (the latch-grid cap is never requested). The A52 FPS limiter stays exact at the panel rate.

Results (Retroid Pocket 6, Dave the Diver):

Setup, every column. Retroid Pocket 6 (Adreno 740 class, 1080x1920 panel at 120 Hz, landscape), Dave the Diver (1868140), DXVK 2.7.1-gplasync, proton-10.0-arm64ec-2, container 1280x720, FPS limiter as listed, the same boat-deck scene. Segments are 180 s (launch 4: 60-120 s). "SF" = the game's SurfaceFlinger layer histogram; "PowerMetrics" = the app's own counter (5 s samples). gamescope-xwm is the steamcompmgr thread.

Cap 60, cursor hiddenX11Shipped gamescope (A52, -r 1200)Fix 1Fix 1 + shim fix
fps, SF59.8947.0546.9159.13 (47 s segment)
fps, PowerMetrics59.947.146.959.97 (59.3-60.3)
2x / 3x panel-period share, SF95.2 / 2.5 %41.5 / 41.3 %43.3 / 45.6 %94.2 / 2.7 %
frame interval p95 / p99, SF, ms16.7 / 25.033.3 / 41.633.3 / 33.316.7 / 25.0
game process CPU, % of a core176.1127.7128.4135.0 (fix 1 + shim + cursor plane run, 60 s)
gamescope CPU, % of a core—8.15.96.6 (same run)
gamescope wakeups/s—1723623not captured (segment cut)
gamescope-xwm voluntary wakeups/s—1411424~520 (same run)
GPU busy %, PowerMetrics79.960.459.877.3
CPU temp °C, PowerMetrics mean76.569.866.373.7
Cap 30, cursor hiddenX11Shipped gamescope (A52, -r 1200)Fix 1Fix 1 + shim fix
fps, SFnot run30.0030.00not run
2x / 3x / 4x share, SFnot run0.1 / 7.0 / 85.4 %0.1 / 5.3 / 88.9 %not run
gamescope CPU, % of a core—10.24.2not run
gamescope wakeups/s—1510401not run
gamescope-xwm voluntary wakeups/s—1281269not run
GPU busy %, PowerMetricsnot run38.538.1not run
CPU temp °C, PowerMetrics meannot run61.963.9not run

The fix 1 + shim fix column: SF fps and histogram from a 47 s cap-60 segment (launch 4); PowerMetrics 59.97 fps over 143 samples; game/gamescope CPU from the 60 s hidden-cursor segment of the cursor-plane run (fix 1 + shim + cursor layer, cursor hidden), where the SF fps was 60.00. Temperatures are loose: the X11 run started hot (CPU zone 92.7 °C at segment start).

Recording

No visible UI change. Measurements above.

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 CodeRabbit

  • New Features
    • Display refresh-rate detection now uses the active screen’s rate, with a 60 Hz fallback when a usable rate is unavailable.
  • Updates
    • Gamescope no longer applies a fixed refresh-rate setting when launching games. Other display settings remain unchanged.