Skip to content

fix(lower): reject fragment-only builtins in vertex stage - #6

Merged
odvcencio merged 1 commit into
mainfrom
fix/vertex-stage-fragment-only-builtins
Jul 27, 2026
Merged

fix(lower): reject fragment-only builtins in vertex stage#6
odvcencio merged 1 commit into
mainfrom
fix/vertex-stage-fragment-only-builtins

Conversation

@odvcencio

Copy link
Copy Markdown
Contributor

Summary

Fixes a bug where fragment-stage-only builtins (derivatives and texture sampling functions) were silently accepted in authored vertex() stages, causing validation failures on every backend. Introduces compile-time diagnostics to reject these calls in the vertex stage while preserving their functionality in the surface stage.

Changes

  • Introduce inVertexStage flag to resolver and typer during mesh authored vertex lowering.
  • Reject dpdx, dpdy, fwidth, sample, sampleLevel, and sampleCube inside vertex() with a CodeInvalidCall diagnostic.
  • Allow these builtins to function normally in surface() and other valid stages.
  • Add diagnostic hints guiding users to move derivative calls to surface() or use stateAt() for simulation state.
  • Update README, ROADMAP, and language-guide to accurately document authored vertex stage capabilities and the planned composing hook.
  • Add tests in lower and validate packages to verify compile-time rejection and prove the prior behavior failed backend validators.

Testing

  • Run go test ./lower -run "TestLowerRejects|TestLowerAllows" -v
  • Run go test ./validate -run "TestVertexStageRejects|TestPreFix" -v
  • Compile a material containing sample() or dpdx() inside vertex() and verify it produces a SEL2003 diagnostic instead of emitting invalid shaders.

- Derivatives (dpdx/dpdy/fwidth) are illegal in vertex shaders on every backend (WGSL, GLSL, Metal, GLES) — not merely unflagged — so they now produce a compile-time diagnostic (SEL2003) instead of reaching the emitter and failing naga or glslangValidator
- Texture sampling calls (sample/sampleLevel/sampleCube) had no binding wired through to the vertex scaffold on three of four backends (GLSL ES, GLES 3.00, Metal omit texture/sampler params from the vertex signature), so they are now rejected at compile time with a diagnostic rather than emitting an undeclared identifier
- inVertexStage guard added to resolver.go and typer.go, enabled from lower_vertex.go when lowering an authored vertex() body; the fragment resolver/typer for lowerMeshWithVertex is not affected
- Tests added to lower/ for rejection and for allowing derivatives in surface() alongside an authored vertex(); validate/ gains empirical proof via naga and glslangValidator that the old, unguarded behaviour would have failed validation
- README, roadmap, and language-guide updated to reflect that the full vertex() -> vec4 replacement stage shipped in v0.3.1; only the composing hook remains unimplemented
@odvcencio
odvcencio merged commit 5ca4387 into main Jul 27, 2026
1 check passed
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