Repository navigation
feat: Add onBefore and onAfter callbacks to all frame passes - #9788
Merged
Merged
Conversation
The onBefore and onAfter callbacks of ComputePass move to FramePass, so every frame pass can run code right before and after it executes. For a render pass, they run outside of its GPU render pass: the frame graph does not merge a pass with its neighbour when a callback runs between them, so onAfter can read back what the pass rendered. The luminance histogram of the auto exposure uses onAfter to read back its histogram, instead of replacing the after method of its pass.
Build size reportThis PR changes the size of the minified bundles.
|
mvaligursky
commented
Oct 16, 2026
mvaligursky
left a comment
Contributor
Author
There was a problem hiding this comment.
Automated PR review by Codex (OpenAI AI agent), posted through the account holder's authorized automated review process.
Reviewed f7e6c9353 against f8a0540a2. No actionable findings.
The callback placement preserves before/after ordering and the existing ComputePass execution/view-selection behavior. The merge restriction applies at the callback boundary: first.onAfter and second.onBefore prevent merging, while first.onBefore and second.onAfter still allow it. Callback references are released by destruction, and the generated polymorphic this signatures preserve subclass-specific parameter types.
Validation:
- Full unit suite: 4,396 passing, 43 pending.
- Full WebGPU/Metal suite: 4,395 passing, 39 pending, including existing compute callback/view-selection coverage.
- Declaration build, consumer type tests, and lint of all changed files passed.
- Real WebGL2/WebGPU readback probes verified both boundary callbacks run outside a GPU render pass and receive the correct pass. A deferred read requested between a red clear and a green draw returned red, while the final target was green. Outer callbacks retained merging and also ran outside the GPU pass.
- The auto-exposure histogram readback completed with exactly matching bins on base and head on both backends.
- Runtime-inspection/pixel-verification checks of ordinary rendering and CameraFrame with a depth prepass at two camera poses found 0 / 16,384 differing pixels per backend; repeated baseline captures also matched exactly.
This branch was successfully deployed
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.
Every frame pass can now run code right before and right after it executes, using the
onBeforeandonAftercallbacks thatComputePasshad.Changes:
onBeforeandonAftermove fromComputePasstoFramePass, so render passes and custom frame passes have them too.onBeforeis called after the pass'sbefore(), andonAfterafter itsafter(), with the pass as the argument. Likebefore()andafter(), they are called even ifexecuteEnabledis false, but not when the pass is disabled.onAftercan therefore read back what the pass rendered.onAfterof its pass, instead of replacing the pass'safter()method.Examples: