Skip to content

[Shaders] fix: a stage composition is supplied at the root, and the voxel marchers own their samplers slot - #3449

Merged
xen2 merged 3 commits into
stride3d:masterfrom
Nicogo1705:stage-compose-root
Sep 20, 2026
Merged

xen2 merged 3 commits into
stride3d:masterfrom
Nicogo1705:stage-compose-root

Conversation

@Nicogo1705

Copy link
Copy Markdown
Contributor

PR Details

A shader declaring a stage member is promoted to the root of the effect. When such a shader declares a stage compose, a value supplied for it at a nested composition path had nothing to attach to, and the merge failed later with a missing composition (#3374 on beta7).

  • Mixer: the rule agreed in [Shaders] stage compose supplied from a nested composition: which rule for the mixer? #3423. A stage compose can be declared anywhere, but its value can only be supplied at the root. Supplying it from a nested node is reported with the slot, the declaring shader and the path it was supplied at. The composition evaluation now runs under the same error handling as the merge, so it lands in the log like the other mixer errors.
  • Stride.Voxels: AttributeSamplers was supplied by LightVoxelEffect, itself composed under environmentLights[i]. The slot moves to the marchers, the only shaders that read it: MarchAttributes loses stage, LightVoxelShader and VoxelVisualizationViewShader no longer inherit it, and IVoxelMarchMethod / IVoxelMarchSet.GetMarchingShader take the samplers to compose. LightVoxelRenderer and VoxelVisualizationView bind the attribute once per marcher path. MarchAttributesEffect had no user and goes with the key it served.
  • Test: StageCompositionSuppliedFromNestedIsReported.

Verified on Direct3D 11: the shader test suite (846), the voxel GI demo (Cornell box, bounce and cones fine), and the MyGame2 project attached to #3374, which gets past the mixer.

Note: MyGame2 then hits a separate compiler gap, SV_Coverage as a fragment input is not mapped in BuiltinProcessor (used by VoxelAttributeDirectionalCoverageShader). That one is not in this PR; it will come as its own fix.

Related Issue

Fixes #3423. Part of #3374.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change): GetMarchingShader gains a parameter on the two marcher interfaces.

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

⚠️ Written with AI assistance (Claude Code), driven and verified by me; needs a real review. 🤖 Generated with Claude Code

…e voxel marchers own their samplers slot

A shader declaring a stage member is promoted to the root, so a value supplied for its
stage compose at a nested composition path had nothing to attach to (stride3d#3423). The mixer now
reports it instead of failing later with a missing composition.

Stride.Voxels supplied AttributeSamplers from LightVoxelEffect, which is itself composed under
environmentLights[i]. The slot moves to the marchers, the only shaders that read it: each
marcher composes the samplers it is given, and the renderers bind the attribute once per marcher
path. MarchAttributesEffect had no user and goes with the key it served.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Draft PR — automatic CI is skipped to save runner minutes.

  • Mark the PR ready for review to run the full automatic CI — or add a ci-run-on-draft label to run it now without leaving draft.
  • Or arm a specific opt-in suite: ci-enduser, ci-editor, ci-ios, ci-android.

@Nicogo1705
Nicogo1705 marked this pull request as ready for review September 18, 2026 12:15
@xen2

xen2 commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

Thanks, the Voxels rewrite LGTM. I pushed two commits on top, please pull before continuing.

  • Mixer: a stage compose declared only by a nested shader could not be supplied at the root either. Now a stage slot always takes its value from the root. Two tests added.
  • Voxels: marchers bind their own samplers (ApplyAttributeSamplers), so LightVoxelRenderer no longer hard-codes the Marcher path.

Shader tests pass (849). I did not run the voxel GI demo, could you check it once?

@Nicogo1705

Copy link
Copy Markdown
Contributor Author

Pulled your two commits, thanks.

Tested with the VoxelGI Demo and the MyGame2 repro from #3374 (with #3450 on top, its compositor uses SV_Coverage) => seems good.

@xen2
xen2 merged commit 163fadc into stride3d:master Sep 20, 2026
31 checks passed
@Nicogo1705
Nicogo1705 deleted the stage-compose-root branch September 22, 2026 13:06
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.

[Shaders] stage compose supplied from a nested composition: which rule for the mixer?

2 participants