Repository navigation
feat(compositor): the macOS shader effects pass (Metal) - #1206
Merged
EtienneLescot merged 3 commits intoOct 14, 2026
Merged
Conversation
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
EtienneLescot
added a commit
that referenced
this pull request
Oct 14, 2026
The parent folder's checks, adapted to the Metal pass (#1206) and to the agent tools of #1202: the MCP loop, the live view against the export, the codec floor on the effect's own pixels, and export time. The live view now gets the inspector's settings through setParam, which the Windows script skipped.
EtienneLescot
force-pushed
the
feat/shader-effects-macos
branch
from
October 14, 2026 15:11
6338417 to
80c6dde
Compare
EtienneLescot
changed the base branch from
feat/shader-effects-contract
to
integration/shader-effects
October 14, 2026 15:11
6 tasks done
Agent-written WGSL effects (docs/shader-effects.md) now draw on macOS, in preview and export alike. With the Windows and Linux passes, every backend draws them. - shader_fx.rs: naga 24 to MSL with the prelude's bindings mapped explicitly (texture 0, an inline constexpr sampler, ctx and params at buffers 2 and 3), so naga never invents a binding. Compiled with new_library_with_source and a Replace pipeline state on a background thread, under its own autorelease pool. checkShaderEffect compiles for Metal too: accepted means it will draw. - naga's force_loop_bounding is off: the validation already proved every loop bounded, and its volatile guard cost 7 to 10 % of the pass. - compositor_macos.rs: the same cache, blocking and lane order as the other passes. Each pass blits its target into ann_copy in the frame's command buffer, then repaints it in a pass that loads the target. draw_annotations takes the texture it draws on, which is how the text layer gets the annotations for `text` effects. - live.rs: every backend draws effects now, so the live view's non-blocking mode and its recompose-on-landing lose their cfg. - msl-out is declared for macOS instead of arriving through wgpu. Tests on the Metal device: the six GPU tests of the Windows pass, plus a real annotation that an `image` effect leaves alone and a `text` effect repaints, and the spec's ripple and the two MCP examples compiling. Measured on an M1: about 0.12 ms per frame() read at 1080p and 0.5 ms at 4K, thirty times the RTX 4070 Ti; a new source compiles in 120 ms (up to 375 ms for the first in a process). An agent's addEffect took 152 ms through the mcp CLI; preview and export agree within codec noise; export time and preview frame rate do not change.
3 tasks done
Same two lines as the Windows and Linux passes (#1213): the footage quad and its aspect, so fx_to_footage works under Metal too.
This was referenced Oct 14, 2026
EtienneLescot
force-pushed
the
feat/shader-effects-macos
branch
from
October 14, 2026 16:23
80c6dde to
e16a014
Compare
6 tasks done
EtienneLescot
marked this pull request as ready for review
October 14, 2026 16:32
… the footage plane Two things from the review of integration/shader-effects (#1213 and the review fix) that the Metal pass did not have yet. - The compiled-effect cache never evicts an effect the current scene shows (shader_fx::eviction_victim), as on Windows and Linux: set_scene installs the scene before it starts the compiles. - The Windows GPU test of fx_to_footage and fx_from_footage, ported to the Metal device: the footage plane maps back to what the compositor drew, flat, under a fixed angle (bilinear) and under the real camera (homography). It also checks their MSL translation.
EtienneLescot
added a commit
that referenced
this pull request
Oct 14, 2026
…the tiers on an M1 A Metal compile takes 120 ms for a new source on an M1, up to 375 ms for the first in a process (#1206), against 10 ms for FXC. checkShaderEffect ran it on the main process's thread. - The addon's checkShaderEffect is an AsyncTask on the libuv pool, like segmentFrame. The service and the checker type return a promise; the service awaits it inside its try, so a rejecting addon still reads as "not checked", as a throwing one did. - runDocumentTool asks first, for the code addEffect or setEffectDefinition will store (shaderEffectToCheck), then hands the answer to the executor, which stays synchronous, as the cursor read and the auto-zoom plan already do. Edits off: nothing is asked. - addEffect's description and the MCP contract resource give each tier in ms on the RTX 4070 Ti and on the M1, as the spec's C.7 asks.
EtienneLescot
added a commit
that referenced
this pull request
Oct 14, 2026
…the tiers on an M1 A Metal compile takes 120 ms for a new source on an M1, up to 375 ms for the first in a process (#1206), against 10 ms for FXC. checkShaderEffect ran it on the main process's thread. - The addon's checkShaderEffect is an AsyncTask on the libuv pool, like segmentFrame. The service and the checker type return a promise; the service awaits it inside its try, so a rejecting addon still reads as "not checked", as a throwing one did. - runDocumentTool asks first, for the code addEffect or setEffectDefinition will store (shaderEffectToCheck), then hands the answer to the executor, which stays synchronous, as the cursor read and the auto-zoom plan already do. Edits off: nothing is asked. - addEffect's description and the MCP contract resource give each tier in ms on the RTX 4070 Ti and on the M1, as the spec's C.7 asks.
6 tasks done
EtienneLescot
added a commit
that referenced
this pull request
Oct 15, 2026
…the tiers on an M1 A Metal compile takes 120 ms for a new source on an M1, up to 375 ms for the first in a process (#1206), against 10 ms for FXC. checkShaderEffect ran it on the main process's thread. - The addon's checkShaderEffect is an AsyncTask on the libuv pool, like segmentFrame. The service and the checker type return a promise; the service awaits it inside its try, so a rejecting addon still reads as "not checked", as a throwing one did. - runDocumentTool asks first, for the code addEffect or setEffectDefinition will store (shaderEffectToCheck), then hands the answer to the executor, which stays synchronous, as the cursor read and the auto-zoom plan already do. Edits off: nothing is asked. - addEffect's description and the MCP contract resource give each tier in ms on the RTX 4070 Ti and on the M1, as the spec's C.7 asks.
EtienneLescot
added a commit
that referenced
this pull request
Oct 15, 2026
…the tiers on an M1 A Metal compile takes 120 ms for a new source on an M1, up to 375 ms for the first in a process (#1206), against 10 ms for FXC. checkShaderEffect ran it on the main process's thread. - The addon's checkShaderEffect is an AsyncTask on the libuv pool, like segmentFrame. The service and the checker type return a promise; the service awaits it inside its try, so a rejecting addon still reads as "not checked", as a throwing one did. - runDocumentTool asks first, for the code addEffect or setEffectDefinition will store (shaderEffectToCheck), then hands the answer to the executor, which stays synchronous, as the cursor read and the auto-zoom plan already do. Edits off: nothing is asked. - addEffect's description and the MCP contract resource give each tier in ms on the RTX 4070 Ti and on the M1, as the spec's C.7 asks.
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.
Summary
Third PR of agent-written shader effects, section L.3 of
docs/shader-effects.md: the macOS (Metal) pass. An effect now draws on macOS, in preview and export alike; with the Windows and Linux passes, every backend draws effects. Targetsintegration/shader-effects, which carries #1199, #1202 and the Linux pass.shader_fx.rs).constexpr(linear, clamp to edge, likesampNV),ctxandparamsat buffers 2 and 3. Without that map, naga emits[[user(fake0)]], which is not MSL.new_library_with_sourceand a pipeline state with no blending, on a background thread under its own autorelease pool.checkShaderEffectcompiles for Metal too, so "accepted" means "will draw".force_loop_boundingis off. The validation has already proved every loop bounded, and naga's guard (avolatileread on every iteration) cost 7 to 10 % of the pass on an M1.compositor_macos.rs).ann_copy, then a render pass that loads the target (an effect maydiscard).texttarget:draw_annotationsopened its pass onself.rt; it now takes the texture it draws on. The text layer is cleared in a pass of its own, receives the annotations, goes through its effects, and is drawn over the image bypipeline_fs_tex(premultiplied "over").live.rs: every backend draws effects now, so the live view's non-blocking mode and its recompose-on-landing lose theircfg.Cargo.toml:msl-outis declared for macOS instead of arriving through wgpu's features.native-compositor.md(the section; the known gap goes, every backend draws), the spec (C.7, D.4, D.5, new H.3, next to the Linux figures),rendering-performance.md, and a row in the e2e log.Related issue
Part of the shader effects work (#1199, #1202, and the Linux pass on
integration/shader-effects).Type of change
Release impact
Desktop impact
live.rslosing acfgthat now covers every backendTesting
cargo test -p openscreen-compositor --lib --testspasses on an M1 (macOS 26.5), 445 lib tests on top ofintegration/shader-effects. On the Metal device:imageeffect leaves alone and atexteffect repaints, while the image under it stays intact;shader_fx_tier_calibration, release, M1): about 0.12 ms perframe()read at 1080p and 0.5 ms at 4K, thirty times the RTX 4070 Ti. A heavy effect (128 reads) costs 16 ms per 1080p frame. The reads still dominate, so the tiers hold.electron . --user-data-dir=<test profile> mcp, headless:addEffectwith a typo is refused in 6 ms at the agent's line; the ripple is accepted in 152 ms, real Metal compile included;exportVideo+getFramesshow the ripple after each click;integration/shader-effects(ci.ymltriggers on main,feat/ai-editionandrelease/**).