Repository navigation
macOS: pace the window's frame to the display, and never wait for a drawable on the main thread - #10
Merged
Conversation
albanmgicquel
force-pushed
the
macos-frame-loop
branch
from
October 15, 2026 23:17
be40071 to
dc68183
Compare
…and never waits for a drawable on the main thread (a window manager's click tap no longer holds clicks for half a second) The polled loop spent most of each frame in nextDrawable on the main thread, which serves a window manager's Accessibility requests (Magnet, BetterTouchTool) one per frame while their event tap holds the click: winit#1737. The frame now runs in RedrawRequested at a WaitUntil deadline one refresh apart, and a worker thread acquires each drawable, so a due frame without one is put off and re-checked (at most 100 ms) instead of waited for. Other platforms and the benchmark view keep polling.
albanmgicquel
force-pushed
the
macos-frame-loop
branch
from
October 16, 2026 02:17
dc68183 to
fc9da49
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On macOS the window host polled (
ControlFlow::Poll, the frame inabout_to_wait). Under FIFO presentation the frame spent most of its time inget_current_texture, which isnextDrawablewaiting for vsync, on the main thread: 90% of the run in a game we measured.Window managers with a click-filtering event tap, such as Magnet or BetterTouchTool's snap areas, hold each mouse-down while they ask the clicked app about its window over Accessibility. That request is served by the main run loop, one per turn, and each turn was a blocked frame. The result: every click, and the start of every title-bar drag, waited about 0.5 s at 60 Hz (less at 120 Hz), while the host's own timings looked perfect. This is rust-windowing/winit#1737; Godot ships a workaround that detects Magnet by its bundle id.
This change, on macOS:
WaitUntiluntil the next frame is due, one monitor refresh after the last. The frame is requested withrequest_redrawand runs inRedrawRequested.SurfaceandSurfaceTextureareSend + Sync). A reconfigure first settles the acquisition in flight.Measured with an equivalent diagnostic build, with Magnet running:
Alternatives tried and rejected:
CADisplayLink: no better than the timer once gated (and blocking without the gate).Other platforms and the benchmark's interactive view keep the polled loop. One caveat, documented: wgpu-hal's
occlusionStateread now runs on the acquisition worker thread.Tests:
pacing.rsunit tests (deadline, gate, its bound, no catch-up after a late frame, parked retry, the acquisition worker asking rather than waiting, settling, shutdown).cargo fmt,cargo clippy -p tecs-winit-host --all-targets -D warnings,cargo test -p tecs-winit-host(110) andnupp testpass. Verified by hand on macOS with Magnet running. Documented in a README design record anddocs/gfx/benchmarks.md.Not run here:
nupp task docs-check(this toolchain lacks thelunamarkrock).