Add independent blending for multiple render targets - #9140
Merged
Conversation
Public API reportThis PR changes the public API surface (+6 / −0), per the docs' rules (@ignore / @Private / undocumented are excluded). Show API diff+BlendState.clearAttachment(index: number): void
+BlendState.get hasAttachmentOverrides(): boolean
+BlendState.getAttachment(index: number, dst: BlendState): BlendState
+BlendState.setAttachment(index: number, src: BlendState | null): void
+GraphicsDevice.readonly supportsIndependentBlending: boolean
+WebglGraphicsDevice.readonly supportsIndependentBlending: booleanInformational only — this never fails the build. |
Build size reportThis PR changes the size of the minified bundles.
|
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for independent blending in MRT rendering by extending BlendState with per-attachment overrides and wiring that through both WebGPU and WebGL2 (via OES_draw_buffers_indexed), while exposing a capability flag on GraphicsDevice.
Changes:
- Extend
BlendStatewith per-attachment blend/write-mask overrides (with attachment inheritance semantics) and update hashing/equality accordingly. - WebGPU: build per-target
blend+writeMaskentries for render pipeline color targets. - WebGL2: when
OES_draw_buffers_indexedis available, apply indexed blend state per draw buffer; otherwise fall back to attachment 0 with a warning and exposesupportsIndependentBlending.
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/platform/graphics/blend-state.test.mjs | Adds unit tests for per-attachment overrides, key stability, copy/clone behavior, and dual-source detection. |
| src/platform/graphics/blend-state.js | Implements per-attachment blend state storage, override detection, and keying/equality updates. |
| src/platform/graphics/webgpu/webgpu-render-pipeline.js | Emits per-color-target blend state and write mask in pipeline descriptors. |
| src/platform/graphics/webgpu/webgpu-graphics-device.js | Sets supportsIndependentBlending = true for WebGPU devices. |
| src/platform/graphics/webgl/webgl-graphics-device.js | Detects OES_draw_buffers_indexed, exposes capability, and applies blend state per attachment when supported. |
| src/platform/graphics/graphics-device.js | Documents and exposes the new supportsIndependentBlending capability flag. |
| examples/src/examples/test/independent-blending.example.mjs | Adds a hidden example demonstrating different blend/write-mask behavior per MRT attachment. |
Comments suppressed due to low confidence (1)
src/platform/graphics/blend-state.js:342
- If per-attachment states are stored with a marker bit (bit 31) to make a packed value of
0representable,getAttachmentmust mask that bit out before assigning todst.attachment0. Otherwisedstwould appear to have attachment overrides (negativeattachment0) and itskey/ flags become inconsistent.
const state = this.hasAttachmentOverrides ? this._attachments[index] : 0;
dst.attachment0 = state !== 0 ? state : (this.attachment0 & stateMask);
return dst;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Adds support for giving each color attachment of a render target its own blend state and color write mask, exposing the full capability of WebGPU's per-target blend state and WebGL2's OES_draw_buffers_indexed extension. Previously a single blend state was applied to all attachments on both backends.
Changes:
BlendStategains per-attachment overrides. An attachment which has not been assigned its own state follows attachment 0, so existing behaviour is unchanged.OES_draw_buffers_indexedand uses its indexed entry points. When the extension is unavailable, the state of attachment 0 is used for all attachments and a warning is logged, so features relying on this must check the capability.API Changes:
BlendState#setAttachment(index, src)- assigns an independent blend state to a color attachment, in 1 to 7 range. The blend state of the supplied source is copied.BlendState#clearAttachment(index)- makes the attachment follow attachment 0 again.BlendState#getAttachment(index, dst)- stores the blend state of an attachment in the supplied blend state, avoiding allocations by allowing a single instance to be reused.BlendState#hasAttachmentOverrides- true when any attachment has been given an independent blend state.GraphicsDevice#supportsIndependentBlending- true on WebGPU, and on WebGL2 whenOES_draw_buffers_indexedis available.Note that the blend constant used by
BLENDMODE_CONSTANTis a single value on both APIs and so cannot vary per attachment, and dual-source blending remains limited to a single color target.Examples:
test/independent-blendingexample, rendering into a two attachment MRT with a different blend equation and write mask per attachment, and displaying both attachments side by side.