8000 macos: honour swap_interval: Some(0) by benface · Pull Request #694 · not-fl3/miniquad · GitHub
[go: up one dir, main page]

Skip to content

macos: honour swap_interval: Some(0) - #694

Open
benface wants to merge 1 commit into
not-fl3:masterfrom
benface:macos-swap-interval
Open

benface wants to merge 1 commit into
not-fl3:masterfrom
benface:macos-swap-interval

Conversation

@benface
@benface benface commented Oct 19, 2026 •
Copy link
Copy Markdown
Contributor

Why

macOS ignores swap_interval, and three things keep its frames to the display:

  • The event loop waits for the next tick of a CVDisplayLink before each frame.
  • The Metal layer presents each drawable on a vertical blank.
  • An occluded window sleeps in perform_redraw so it draws at most 60 frames a second.

So on macOS nothing can draw faster than the display refreshes. A tool that draws frames off-screen to save them needs to, and so does a benchmark. On Windows and Linux, swap_interval: Some(0) sets a swap interval of 0, and nothing slows a hidden window.

Change

With swap_interval: Some(0) on macOS:

  • the event loop doesn't wait for the display link;
  • the Metal layer's displaySyncEnabled is off (OpenGL's swap interval is already 0);
  • an occluded window isn't slowed down.

Any other value, None included, keeps to the display's refresh rate, as before. The doc comment on swap_interval says so.

A macroquad game (CHOMP) has a capture mode that plays a level and saves its frames, drawn into render targets, and its window shows nothing. With this, #693 and not-fl3/macroquad#1081, its frames no longer wait for the display.

Measurements

These are the capture's times for 2,400 frames, saving 8 of them, on an M2 Max with a 120 Hz screen. Every frame came out byte-identical:

Load average Time
Metal, before 25–35 20.9–21.4 s
Metal, with the three changes 25–35 6.1–6.5 s
OpenGL, before 30 22.2 s
OpenGL, with this and macroquad's clear_screen: false 30 5.2 s

On Metal, this alone makes no difference while the frame still takes a drawable. The display only lets go of drawables at its own pace, with display sync on or off: 22.3 s before and 22.8 s with this, at a load average of 190 to 330.

Verification

  • cargo check passes for aarch64-apple-darwin, aarch64-apple-ios and x86_64-unknown-linux-gnu.
  • CHOMP's capture tests pass with the three changes, and its captures save the same frames, byte for byte.

🤖 Generated with Claude Code

macOS ignored `swap_interval`. Each frame waited for the next tick of
a `CVDisplayLink`, Metal presented each drawable on a vertical blank,
and an occluded window slept between frames to save power. So frames
could never come faster than the display refreshes, as a tool drawing
frames off-screen to save them needs, or a benchmark.

With `swap_interval: Some(0)`, a frame now starts as soon as the last
one is done: there's no frame pacer, the Metal layer doesn't sync to
the display, and a hidden window isn't slowed down, as on Windows and
Linux, where `Some(0)` turns vsync off and nothing slows a hidden
window. Any other value keeps to the display's refresh rate, as
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0