Summary
UniformTypeChangeTraverser widens loose scalar/vec2/vec3 uniforms to vec4, then inserts a shape conversion at each use. injectShapeConversion locates the node by switching on its parent's type — it handles TIntermAggregate, TIntermBinary, TIntermUnary, TIntermSelection and (since #1816) TIntermBranch, then throws.
A uniform that is the direct child of a loop or switch still fails shader compilation, surfacing to JS as Error: [object Object] with no shader location or uniform name.
Measured
Win32 D3D11 RelWithDebInfo, via engine.createEffect:
| shader |
parent node |
result |
while (flag) { ... } |
TIntermLoop |
fails |
switch (mode) { ... } |
TIntermSwitch |
fails |
vec3 f() { return tint; } |
TIntermBranch |
fixed by #1816 |
while (flag == true) |
TIntermBinary |
ok |
| ESSL 300, uniform under a binary op |
TIntermBinary |
ok |
The last row is the control for switch — that case fails on the node type, not the GLSL version. tints.length() was also checked and does not trigger.
Notes for the fix
TIntermBranch exposed setExpression, which is what made #1816's fix possible. TIntermLoop and TIntermSwitch expose no setter for their child (getTest() / getCondition() are read-only), so covering them needs setTest() / setCondition() in the BabylonJS/glslang fork plus a GIT_TAG bump.
The remaining throw should name the uniform and the unsupported construct.
[Filed by Copilot on behalf of @bghgary]
Summary
UniformTypeChangeTraverserwidens loose scalar/vec2/vec3uniforms tovec4, then inserts a shape conversion at each use.injectShapeConversionlocates the node by switching on its parent's type — it handlesTIntermAggregate,TIntermBinary,TIntermUnary,TIntermSelectionand (since #1816)TIntermBranch, then throws.A uniform that is the direct child of a loop or switch still fails shader compilation, surfacing to JS as
Error: [object Object]with no shader location or uniform name.Measured
Win32 D3D11
RelWithDebInfo, viaengine.createEffect:while (flag) { ... }TIntermLoopswitch (mode) { ... }TIntermSwitchvec3 f() { return tint; }TIntermBranchwhile (flag == true)TIntermBinaryTIntermBinaryThe last row is the control for
switch— that case fails on the node type, not the GLSL version.tints.length()was also checked and does not trigger.Notes for the fix
TIntermBranchexposedsetExpression, which is what made #1816's fix possible.TIntermLoopandTIntermSwitchexpose no setter for their child (getTest()/getCondition()are read-only), so covering them needssetTest()/setCondition()in theBabylonJS/glslangfork plus aGIT_TAGbump.The remaining
throwshould name the uniform and the unsupported construct.[Filed by Copilot on behalf of @bghgary]