Repository navigation
[Draft, result not reproducible] The 60 Hz display link is turned off in fullscreen on a fixed-rate screen whose presents keep turning a refresh late - #2348
Conversation
…reen whose presents keep turning a refresh late, and the present thread takes the drawables until the window leaves fullscreen In fullscreen on an external fixed 60 Hz 5K screen (M5 Pro, macOS 27.2) the system showed 3,190 of 7,201 presents a refresh after the display link's target, on and off: 14-29 presents per 300 turned late after one on time, against 0-3 in a window or on the built-in screen. Each turn costs a frame of two vsyncs and the frame step then holds 2 or 3 vsyncs on frames that cost 0.8-1.3. Steady lateness is harmless (600 late presents in a row in a window at frame p95 17.3 ms), so the turns are what is counted. link_late_note (nvn_mtl.m) counts the turns from each present's presented time and its tick's target, per 300 presents at one frame per tick. Two windows in a row with 8 or more turn the link off (link_late_mode in link_sync), as DM_PRESENT_LINK=0 and the rescue of a silent link do; leaving fullscreen or the fixed-rate screen gives it back. A set DM_PRESENT_LINK or DM_PRESENT_LATENCY is left alone; DM_PRESENT_LINK_AUTO=0 keeps the link. This is a workaround: why the system misses the target at a 32 ms lead is open, and the code comment and the reference entry say so. Measured on Ocarina of Time (v131072), a scripted 150 s walk of Kakariko Village from one autosave, about 7,500 frames, one run each, the external screen as the only one lit: 1,021-1,245 [longframe] lines with the link (1 of 26 windows of 300 frames with frame p95 under 20 ms), 59 with this change (28 of 30, link off at frame 2864, menus kept it). Two of the three baseline runs and the run with the change were on a tree with DM_NVN_ENC_THREAD=1 and a local change that is not in main. Known cost, from a DM_PRESENT_LINK=0 run: frame interval p99 48 ms in one window of 300 frames. Also recorded, open: with a ProMotion built-in screen lit beside the external one, the fullscreen walk is slow in every mode (205-257 lines, the link skipping 47 of 300 ticks in the title menu); 22 with the built-in screen set to a fixed 60 Hz, 21 in a window. The host does nothing about it yet. Checked: t_present_rescue (late) 112 checks, 0 failed. Not run: regress.py on other games, docs_symptoms.py (no heading added), an iPhone, another external screen or Mac. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Correction: the result in this PR does not reproduce. Marked as draft; please do not merge. Later the same day, with the same policy, the same screens (external fixed 60 Hz screen as the main display, the game fullscreen on it, lid open, built-in screen at a fixed 60 Hz, mains power) and the same scripted walk, five runs in a row had 598-793 What separates the smooth runs from the others, in the
In the smooth runs the game blocks about a GPU frame in its fence wait each frame and the present thread gets its drawable at once. In the others the fence wait is near 0 and the present thread waits 22 ms on average in Explanations I gave and that later runs contradict:
What still stands: the counts of late turns per 300 presents (14-29 in fullscreen on this screen during play, 0-3 in a window), the window runs (21 and 83 lines), and the test ( One more uncontrolled difference: the five later runs were on a build that also had #2344 applied (one of them with I am leaving this as a draft with the measurements for whoever knows the pacing code; the two regimes may be the useful part. Happy to close it if it is only noise. |
|
Closing: the result does not reproduce (see the correction above), so there is nothing here to merge. The measurements stay in this thread in case the two pacing regimes are of use to someone working on the frame step or the display link. |
What
In fullscreen on a fixed-rate screen, the host turns the 60 Hz display link off when presents keep turning a refresh late, and the present thread takes the drawables until the window leaves fullscreen. General: no game or screen is named; a screen that shows presents on their targets keeps the link.
This is a workaround. Why the system misses the link's target at a 32 ms lead is open; the code comment and the reference entry say so.
Why
Ocarina of Time (v131072) on an M5 Pro (16-core GPU, macOS 27.2), fullscreen on an external fixed 60 Hz 5K screen (drawable 5120x2880,
display link: frame latency 1 (fullscreen, fixed refresh)): about one frame in six took two vsyncs with the GPU at 11-13 ms. TheDM_NVN_TSVrows of one run show 3,190 of 7,201 presents shown a refresh after the link's target, on and off, and 817 of the 1,274 frames over 25 ms were such a present or the frame after one.Steady lateness is harmless (600 late presents in a row in a window, frame p95 17.3 ms). The turns are what costs: a present late after one on time, 14-29 per 300 presents in fullscreen during play, 0-3 in a window or on the built-in screen.
How
link_late_note(nvn_mtl.m) counts the turns from each present's presented time and its tick's target, per 300 presents at one frame per tick.link_late_modeinlink_sync), asDM_PRESENT_LINK=0and the rescue of a silent link do.DM_PRESENT_LINKorDM_PRESENT_LATENCYis left alone.DM_PRESENT_LINK_AUTO=0keeps the link.Measurements
A scripted 150 s walk of Kakariko Village from one autosave, about 7,500 frames, one run each, 2026-11-11.
[longframe]linesDM_PRESENT_LINK=0, external screen aloneWith this change the menus kept the link (no bad window); play turned it off at frame 2864 (25 turns of 300); 4 frame-step changes against 11.
Known cost, from the
DM_PRESENT_LINK=0run: frame interval p99 48 ms in one window of 300 frames.Caveat: two of the three baseline runs and the run with the change were on a tree with
DM_NVN_ENC_THREAD=1and a local change that is not in main (a submission's end not waiting for the encode thread). The baseline without either had 1,245 lines.Also recorded, open (not fixed here)
With a ProMotion built-in screen lit beside the external one (lid open), the fullscreen walk is slow in every mode, from the title menu on:
[longframe]linesDM_PRESENT_LINK=0Battery or mains made no difference. The host does nothing about it yet:
front_screen_matchonly moves the screen the window is on. A log hint, or matching the neighbour screen while fullscreen, is for discussion.Checked
make -C dm/gfx/tests GAME=0400486024DEC000 check_t_present_rescue: 112 checks, 0 failed. The newlatecases: on-time presents, steadily late ones, a single bad window, held frames, window presents and set switches keep the link; two bad windows turn the 60 Hz link off and leave the 120 and 30 Hz links; leaving fullscreen gives it back.Not run
scripts/regress.py check --games: only Ocarina of Time was played. The policy acts only in fullscreen on a fixed-rate screen with the 60 Hz link, after 600 presents with late turns.dm/tools/docs_symptoms.pyandtest_docs.py(no heading was added; the entry "Fixed-rate display-link delay remains at latency 1" gained three bullets).🤖 Generated with Claude Code