Skip to content

fix(ir): Fix vertex index detection inside control flow - #8

Merged
odvcencio merged 1 commit into
mainfrom
fix/ir-walker-exhaustiveness
Jul 27, 2026
Merged

fix(ir): Fix vertex index detection inside control flow#8
odvcencio merged 1 commit into
mainfrom
fix/ir-walker-exhaustiveness

Conversation

@odvcencio

Copy link
Copy Markdown
Contributor

Summary

The previous vertex-index detection logic only scanned top-level IR statements, missing reads nested inside control flow (e.g., an if reassignment). This caused emitted shaders to omit the per-backend vertex-index binding while still referencing it, resulting in invalid code. Refactored the IR's usage walkers to dispatch through interface methods, making exhaustive control-flow cases enforceable at compile time.

Changes

  • Refactored Expr and StmtCF interfaces to require children() and exprs()/nestedStmts() methods, replacing brittle type switches in usage walkers with safe interface dispatch.
  • Replaced the ad-hoc irStageUsesVertexIndex vertex-index walker with the new exhaustive ir.StageUsesVertexIndexBuiltin, correctly detecting references inside if/for/assign statements.
  • Added unit tests in ir/uses_test.go and lower/lower_test.go to verify derivatives and vertex-index are found inside control flow.
  • Added conformance material and golden shader outputs (WGSL, Metal, GLSL, GLES) exercising the new path.
  • Added validate/validate_test.go test to prove the previous output failed Naga validation.

Testing

  • Run the new regression tests: go test ./ir ./lower ./validate -run 'TestUsesDerivativesFindsCallInsideReturnCF|TestStageUsesVertexIndexBuiltinFindsRefInsideIf|TestLowerMeshAuthoredVertexUsesVertexIndexInsideControlFlow'

- vertexIndex reads nested inside if/for/assign/return were invisible to UsesVertexIndex, so backends emitted shaders referencing vertexIndex without the @Builtin(vertex_index)/[[vertex_id]]/gl_VertexID declaration the reference needed — naga rejects the resulting WGSL outright
- replace type-switch walkers in stmtMatches/exprMatches with interface methods (StmtCF.exprs/nestedStmts, Expr.children) so a new CF or Expr variant missing these methods is a compile error instead of a silently-false walker result
- remove the hand-rolled vertexIndex walker in lower/lower_vertex.go, replacing it with ir.StageUsesVertexIndexBuiltin which routes through the exhaustive shared walker the same way UsesDerivatives already does for dpdx/dpdy/fwidth
- add regression tests: IR walker unit tests for the walker, an end-to-end lowering test through the compiler, a new conformance material with golden outputs for all six backends, and a validation test proving naga rejects the old invalid WGSL
@odvcencio
odvcencio merged commit d8a90ac 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