Skip to content

feat(rendering)!: blend each attachment of a multi-target draw on its own terms - #755

Merged
Exoridus merged 4 commits into
nextfrom
feat/blend-state-per-attachment
Sep 16, 2026
Merged

Exoridus merged 4 commits into
nextfrom
feat/blend-state-per-attachment

Conversation

@Exoridus

Copy link
Copy Markdown
Owner

One blend mode per colour attachment of a multi-target draw. Until now a single blend setting applied to the whole draw; a G-buffer wants alpha blending on albedo and none on a normal or id slot, where a blended vector or id is meaningless.

MeshMaterial takes blendModes, one entry per attachment index in fragment-output order; entries past the target's attachment count are ignored, attachments past the end of the list keep the draw's own mode, and a list entry wins over a per-mesh blend override on the attachments it covers. The list is part of the pipeline key. On WebGPU each targets[i].blend is set from it, one code path for single- and multi-attachment targets. On WebGL2 it needs OES_draw_buffers_indexed: when the effective modes agree the whole-draw call is issued and no extension is needed; when they differ the indexed calls are issued per attachment and restored afterwards by re-issuing the non-indexed state, which resets every draw buffer. Differing modes on a device without the extension throw a RenderError before the draw is queued, from the same entry point that already refuses a material that does not write every attachment, so nothing is pooled and no transform slot is consumed. The capability is RenderBackend.supportsPerAttachmentBlend, re-probed after context loss. An instanced batch refuses a multi-attachment target on both backends the same way, because the batch pipeline is built for one target.

Tests: unit coverage of plumbing, pipeline-key identity, the indexed GL calls and their restore (including the cached-mode trap where the restore would otherwise be suppressed), the refusal through renderTo with a clean following frame; browser readback in both lanes with a two-attachment target and [Normal, Additive], identical numbers on WebGL2 and WebGPU. Marked breaking because RenderBackend gains a member a third-party backend has to implement.

@Exoridus
Exoridus enabled auto-merge (squash) September 16, 2026 02:19
@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 35.1kB (0.11%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
exo-esm-esm 1.27MB 2.93kB (0.23%) ⬆️
exo-esm-modules-esm 3.66MB 8.96kB (0.25%) ⬆️
exo-iife-min-Exo-iife 1.27MB 2.92kB (0.23%) ⬆️
exo-full-iife-Exo-iife 5.49MB 8.75kB (0.16%) ⬆️
exo-iife-Exo-iife 3.54MB 8.61kB (0.24%) ⬆️
exo-full-iife-min-Exo-iife 1.99MB 2.94kB (0.15%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: exo-iife-Exo-iife

Assets Changed:

Asset Name Size Change Total Size Change (%)
exo.iife.js 8.61kB 3.54MB 0.24%

Files in exo.iife.js:

  • ./src/rendering/RenderBackend.ts → Total Size: 624 bytes

  • ./src/rendering/webgpu/WebGpuMeshRenderer.ts → Total Size: 76.85kB

  • ./src/rendering/webgl2/WebGl2Backend.ts → Total Size: 86.69kB

  • ./src/rendering/multiAttachmentGuard.ts → Total Size: 5.65kB

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.89kB

  • ./src/rendering/material/MeshMaterial.ts → Total Size: 3.88kB

  • ./src/rendering/webgl2/WebGl2MeshRenderer.ts → Total Size: 37.24kB

  • ./src/rendering/webgpu/WebGpuBackend.ts → Total Size: 95.75kB

view changes for bundle: exo-full-iife-min-Exo-iife

Assets Changed:

Asset Name Size Change Total Size Change (%)
exo.full.iife.min.js 2.94kB 1.99MB 0.15%

Files in exo.full.iife.min.js:

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.89kB
view changes for bundle: exo-full-iife-Exo-iife

Assets Changed:

Asset Name Size Change Total Size Change (%)
exo.full.iife.js 8.75kB 5.49MB 0.16%

Files in exo.full.iife.js:

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.89kB
view changes for bundle: exo-esm-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
exo.esm.js 2.93kB 1.27MB 0.23%

Files in exo.esm.js:

  • ./src/rendering/material/MeshMaterial.ts → Total Size: 3.8kB

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.69kB

  • ./src/rendering/RenderBackend.ts → Total Size: 615 bytes

  • ./src/rendering/multiAttachmentGuard.ts → Total Size: 5.55kB

  • ./src/rendering/webgl2/WebGl2Backend.ts → Total Size: 84.58kB

  • ./src/rendering/webgpu/WebGpuBackend.ts → Total Size: 93.42kB

  • ./src/rendering/webgl2/WebGl2MeshRenderer.ts → Total Size: 36.47kB

  • ./src/rendering/webgpu/WebGpuMeshRenderer.ts → Total Size: 75.08kB

view changes for bundle: exo-iife-min-Exo-iife

Assets Changed:

Asset Name Size Change Total Size Change (%)
exo.iife.min.js 2.92kB 1.27MB 0.23%

Files in exo.iife.min.js:

  • ./src/rendering/webgpu/WebGpuBackend.ts → Total Size: 95.75kB

  • ./src/rendering/multiAttachmentGuard.ts → Total Size: 5.65kB

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.89kB

  • ./src/rendering/RenderBackend.ts → Total Size: 624 bytes

  • ./src/rendering/webgl2/WebGl2MeshRenderer.ts → Total Size: 37.24kB

  • ./src/rendering/material/MeshMaterial.ts → Total Size: 3.88kB

  • ./src/rendering/webgpu/WebGpuMeshRenderer.ts → Total Size: 76.85kB

  • ./src/rendering/webgl2/WebGl2Backend.ts → Total Size: 86.69kB

view changes for bundle: exo-esm-modules-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
rendering/webgpu/WebGpuBackend.js 213 bytes 96.25kB 0.22%
rendering/webgl2/WebGl2Backend.js 3.7kB 87.21kB 4.43%
rendering/webgpu/WebGpuMeshRenderer.js 150 bytes 76.31kB 0.2%
rendering/webgl2/WebGl2MeshRenderer.js 377 bytes 37.27kB 1.02%
rendering/material/MaterialKey.js 139 bytes 9.0kB 1.57%
rendering/multiAttachmentGuard.js 2.47kB 6.04kB 69.21% ⚠️
rendering/material/MeshMaterial.js 1.91kB 4.13kB 85.43% ⚠️

Files in rendering/webgpu/WebGpuBackend.js:

  • ./src/rendering/webgpu/WebGpuBackend.ts → Total Size: 93.42kB

Files in rendering/webgl2/WebGl2Backend.js:

  • ./src/rendering/webgl2/WebGl2Backend.ts → Total Size: 84.58kB

Files in rendering/webgpu/WebGpuMeshRenderer.js:

  • ./src/rendering/webgpu/WebGpuMeshRenderer.ts → Total Size: 75.03kB

Files in rendering/webgl2/WebGl2MeshRenderer.js:

  • ./src/rendering/webgl2/WebGl2MeshRenderer.ts → Total Size: 36.4kB

Files in rendering/material/MaterialKey.js:

  • ./src/rendering/material/MaterialKey.ts → Total Size: 8.68kB

Files in rendering/multiAttachmentGuard.js:

  • ./src/rendering/multiAttachmentGuard.ts → Total Size: 5.55kB

Files in rendering/material/MeshMaterial.js:

  • ./src/rendering/material/MeshMaterial.ts → Total Size: 3.8kB

@Exoridus
Exoridus merged commit 358dc1a into next Sep 16, 2026
17 checks passed
@Exoridus
Exoridus deleted the feat/blend-state-per-attachment branch September 16, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant