gamescope: payload 20261103.7, the FPS limiter holds a cap below the panel rate again

Merged
UT
7d ago
+1-1

Description

Depends on GameNative/gamenative-drm#49 (open). Do not merge before it.

This ships GameNative/gamenative-drm#49 at 5d1e0ae as gamescope payload 20261103.7. The only change in the app is GamescopePayload.VERSION = 20261103.7. libgamenative_drm.so is unchanged.

What was wrong

On master (payload 20261103.4 to .6) the FPS limiter under gamescope stops holding any cap below the panel's rate once a frame outlasts one vblank. A user set 20 for MGS V: The Phantom Pain on a 120 Hz phone and got 40-50 fps; at 60 Hz the cap held. Reproduced on the Retroid Pocket 6 at 120 Hz with Dave the Diver at 1080p, cap 20: the shim census showed cap=20 gate=vsync with gate_holds frozen and gate_late growing once per frame, at the game's own 53 fps.

Cause: GameNative/gamenative-drm#47 added, next to its fix for the cap-rate FIFO cell (kept), a rule that the release after a late start is never more than one grid instant after it. A cap below the rate holds the guest for a whole slot (six vblanks at 20 on 120 Hz); after that rule fired once, the next release was one vblank away, a frame longer than 8.8 ms was late for it too, and the gate never held again. At 60 Hz only games faster than ~58 fps recovered, which hid it there.

What changes

The shim (gamenative-drm#49): a late start keeps its slot's timeline, so the next release is where the cap puts it; only a start past the whole slot restarts the timeline. The cap-equals-rate cells from #47 and #48 are unchanged (slot and period are equal there).

Measured on the RP6 at 120 Hz, DTD 1080p, limiter switched live

capbefore (payload .6)after (this shim)
20~53 fps (gate never holds)20.0 fps, gate_holds +1 per frame
40—40.0 fps
60—52-53 fps (the game's own rate)

Each switch settled within the same second. A 100 s gameplay run: 2010 frames in 100.4 s = 20.02 fps. Shim unit tests: 90 of 90 on the device.

Payload 20261103.7

gamescope-gamenative-20261103.7.tzst, 14308927 B, sha256 1b2dc7308973d068852a77522206e3472cd89a9c8b2eb5b359954a99c66b4f55, served from both CDN hosts and verified. Same 1014 members as 20261103.6; only lib/libadrenotools_gamescope.so differs (sha256 b10cb50957c1b62b708d42311e49f6972cf154cdaa3fc75d05e6ddbd5f7a9122, build string 2026110317065d1e0ae).

Recording

Census excerpt from the RP6 run at cap 20, before and after, in GameNative/gamenative-drm#49.

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

Ships gamenative-drm#49 as gamescope payload 20261103.7, restoring the FPS limiter so a cap below the panel rate holds again. Only GamescopePayload.VERSION changes.

Bug Fixes

  • On payloads .4–.6, the limit stopped holding once a frame outlasted a vblank (cap 20 on a 120 Hz panel ran at 40–50 fps); a late start now keeps its slot's timeline, so the next release lands where the cap puts it.