Fix shape conversion for uniforms used as return expressions - #1816
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Self code review completed by the code-review workflow. No issues found. Representative inputs were traced through the guard: scalar, vec2, and vec3 uniforms remain widened; matrices, samplers, structs, blocks, and existing vec4/ivec4/uvec4/bvec4 uniforms remain untouched. The focused vec4-array regression and existing comprehensive shader compilation test both pass locally on D3D11/Win32. |
There was a problem hiding this comment.
Pull request overview
This PR fixes an issue in the shader AST normalization pass where uniforms that are already declared as vec4 (including vec4 arrays) could be unnecessarily rewritten during uniform widening, potentially producing an invalid shader AST and failing compilation. It also adds a regression test that compiles a shader containing an existing uniform vec4 values[2]; to ensure the traverser leaves it untouched.
Changes:
- Add a
type.getVectorSize() < 4guard to prevent rewriting existingvec4uniforms during uniform widening. - Add a regression unit test that compiles a shader containing a
vec4uniform array to validate the behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| Plugins/ShaderCompiler/Source/ShaderCompilerTraversers.cpp | Prevents the uniform-widening traverser from touching already-vec4 uniforms by gating on vector size. |
| Apps/UnitTests/Source/Tests.ShaderCompilation.cpp | Adds a regression test to ensure shaders with existing vec4 uniform arrays compile successfully. |
bghgary
left a comment
There was a problem hiding this comment.
[Reviewed by Copilot on behalf of @bghgary]
The change is worth keeping, but the description and title attribute the failure to the wrong thing — please update them. The bug is not vec4-array reshaping: return someVec3; fails identically, and this PR does not fix that. Details inline.
Root cause is the unhandled TIntermBranch parent in injectShapeConversion, not vec4 array reshaping. Keeps the vec4 skip as a fast path and adds a returned-uniform regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
TIntermBranchparents ininjectShapeConversion, so a uniform used directly as areturnexpression can be rewrittenvec4inUniformTypeChangeTraverseras a fast pathvec4uniform arrayRoot cause
UniformTypeChangeTraverserwidens loose scalar,vec2, andvec3uniforms tovec4, then injects a shape conversion and replaces the original node in its parent.injectShapeConversiononly handled aggregate, binary, unary, and selection parents, and threw for anything else:The failing trigger is the parent node type, not the vector width. For
return someUniform;the parent is aTIntermBranch, which was unhandled. Adding a branch handler is the actual fix.An earlier revision of this PR attributed the failure to
vec4array reshaping. That was wrong:return someVec3;fails identically, and avec3must be widened so it cannot be skipped. Thanks to @bghgary for catching this.Fast path (not the fix)
The
type.getVectorSize() < 4guard is retained because widening an existingvec4is a no-op — the type is unchanged andaddShapeConversionreturns the node as-is, so the rewrite is pointless AST churn. It is an optimization, not the fix, and it does not resolve the underlying bug on its own.Known remaining gaps
The same class of failure still exists for parents that glslang exposes without a setter, so they cannot be fixed here:
return u;TIntermBranchwhile (u)TIntermLoopTIntermLoophasgetTest()but no setterswitch (u)TIntermSwitchTIntermSwitchhasgetCondition()but no setterThese need an upstream glslang change to expose setters, so the underlying bug should not be considered fully closed.
Validation
Built
UnitTestsfrom a clean worktree based on upstreammaster. Win32 D3D11 Debug.ExistingVec4UniformArrayIsNotReshapedReturnedUniformIsShapeConvertedVec3 return effect should compile synchronouslyRow 2 shows the guard is not what fixes the bug. Row 3 shows the branch handler is.
ShaderCompilation.CompileComprehensiveGLSLpasses in all three configurations.