renderer: an off-main present begins a Core Animation transaction only for a frame it shows

Merged
LA
14h ago
+121-13

Summary

IOSurfaceLayer.setSurfaceOffMain began and committed a Core Animation transaction before its checks. So every frame that it did not show still committed an empty transaction on the GPU completion thread:

  • frames that go through main: a new size while the embedder presents host sizes, a frame the embedder has not committed, or another size than the shown one;
  • frames that a newer frame superseded.

cmux FRAME OWNER REFACTOR S4 measured this with Time Profiler (cmux step 4b41c42c, held keys-stress, 14 terminals, motion.frameOwner.terminals on): 405 ms of CA::Context::commit_transaction under the GPU completion queue in one round. Presents per round went from 84 (switch off) to about 850 (switch on). The new IOSurface per size cost only about +100 ms in the same round, and WindowServer's create_surface was the same with the switch off and on.

The checks now run first, read-only, under the Core Animation lock (offMainDecisionLocked). Only a frame that it shows begins a transaction. The transaction begins under the lock (a begin commits nothing), takes the contents, and commits after the unlock. So the invariant "no commit while holding the lock" still holds. Renderer mode (the default) gets the same change: a superseded frame no longer commits.

No C API change. No change to which frame is shown, or when.

Testing

  • Red first: 694f7ffb7 adds host present: an off-main present that does not show its frame commits no transaction. It counts the presenting thread's commits with the existing CommitOrder swizzle, for each refusal (no host size, another size than the host's, a layer that shows another size, a present the embedder has not committed, an older frame), and expects one commit, outside the lock, for a frame that it shows.
  • Fork CI, host present: filter only (scratch branches):
    • Red at 694f7ffb7, run 41953548703: 110/111 tests pass. Only the new test fails, at IOSurfaceLayer.zig:862, expected 0, found 1 (a layer that shows another size: the off-main attempt committed an empty transaction).
    • Green at 7f2dcbf36, run 41953551466: 111/111 tests pass, and lib-vt 97/97.
  • After merge: release build, cmux pin PR, then the 8-row gate A/B and a profile on cmux24-perf, switch off and on.