From d5d9ffbdfdc5a3af9eaef7b8f35bfc8f5064d225 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Tue, 18 Apr 2017 21:07:05 -0600 Subject: [PATCH] HLSL: vector shape conversions for all ops: Fix #839. Fix #653. Fix #631. --- Test/baseResults/hlsl.shapeConv.frag.out | 217 ++++++++++++++---- Test/hlsl.shapeConv.frag | 15 ++ glslang/MachineIndependent/Intermediate.cpp | 155 +++++++++++-- .../MachineIndependent/localintermediate.h | 4 +- hlsl/hlslParseHelper.cpp | 6 +- 5 files changed, 330 insertions(+), 67 deletions(-) diff --git a/Test/baseResults/hlsl.shapeConv.frag.out b/Test/baseResults/hlsl.shapeConv.frag.out index a26b81927..773134c1a 100755 --- a/Test/baseResults/hlsl.shapeConv.frag.out +++ b/Test/baseResults/hlsl.shapeConv.frag.out @@ -95,27 +95,66 @@ gl_FragCoord origin is upper left 0:22 Construct vec4 ( temp 4-component vector of float) 0:22 'f' ( in float) 0:22 'v' ( temp 4-component vector of float) -0:26 Compare Equal ( temp bool) -0:26 'f1' ( temp 1-component vector of float) -0:26 Construct float ( temp 1-component vector of float) -0:26 'v' ( temp 4-component vector of float) -0:27 Compare Less Than ( temp bool) -0:27 Construct float ( temp 1-component vector of float) -0:27 'v' ( temp 4-component vector of float) -0:27 'f1' ( temp 1-component vector of float) +0:26 Equal ( temp 4-component vector of bool) +0:26 Construct vec4 ( temp 4-component vector of float) +0:26 'f1' ( temp 1-component vector of float) +0:26 'v' ( temp 4-component vector of float) +0:27 Compare Less Than ( temp 4-component vector of bool) +0:27 'v' ( temp 4-component vector of float) +0:27 Construct vec4 ( temp 4-component vector of float) +0:27 'f1' ( temp 1-component vector of float) 0:28 Construct float ( temp float) 0:28 'f1' ( temp 1-component vector of float) 0:29 Construct vec3 ( temp 3-component vector of float) 0:29 Construct float ( temp float) 0:29 'f1' ( temp 1-component vector of float) -0:33 Branch: Return with expression -0:33 component-wise multiply ( temp 4-component vector of float) -0:33 'input' ( in 4-component vector of float) -0:33 Constant: -0:33 3.000000 -0:33 3.000000 -0:33 3.000000 -0:33 3.000000 +0:36 right-shift ( temp 3-component vector of uint) +0:36 Construct uvec3 ( temp 3-component vector of uint) +0:36 'ui' ( temp uint) +0:36 'ui3' ( temp 3-component vector of uint) +0:37 right-shift ( temp 3-component vector of uint) +0:37 'ui3' ( temp 3-component vector of uint) +0:37 'ui' ( temp uint) +0:39 multiply second child into first child ( temp 4-component vector of float) +0:39 'v' ( temp 4-component vector of float) +0:39 'f1' ( temp 1-component vector of float) +0:40 multiply second child into first child ( temp 1-component vector of float) +0:40 'f1' ( temp 1-component vector of float) +0:40 Construct float ( temp 1-component vector of float) +0:40 'v' ( temp 4-component vector of float) +0:42 Sequence +0:42 move second child to first child ( temp 3-component vector of float) +0:42 'mixed' ( temp 3-component vector of float) +0:42 component-wise multiply ( temp 3-component vector of float) +0:42 'u' ( temp 3-component vector of float) +0:42 Construct vec3 ( temp 3-component vector of float) +0:42 'v' ( temp 4-component vector of float) +0:43 move second child to first child ( temp float) +0:43 'f' ( in float) +0:43 Construct float ( in float) +0:43 'u' ( temp 3-component vector of float) +0:44 move second child to first child ( temp 1-component vector of float) +0:44 'f1' ( temp 1-component vector of float) +0:44 Construct float ( temp 1-component vector of float) +0:44 'u' ( temp 3-component vector of float) +0:45 Sequence +0:45 move second child to first child ( temp float) +0:45 'sf' ( temp float) +0:45 Construct float ( temp float) +0:45 'v' ( temp 4-component vector of float) +0:46 Sequence +0:46 move second child to first child ( temp 1-component vector of float) +0:46 'sf1' ( temp 1-component vector of float) +0:46 Construct float ( temp 1-component vector of float) +0:46 'v' ( temp 4-component vector of float) +0:48 Branch: Return with expression +0:48 component-wise multiply ( temp 4-component vector of float) +0:48 'input' ( in 4-component vector of float) +0:48 Constant: +0:48 3.000000 +0:48 3.000000 +0:48 3.000000 +0:48 3.000000 0:? Linker Objects @@ -219,32 +258,71 @@ gl_FragCoord origin is upper left 0:22 Construct vec4 ( temp 4-component vector of float) 0:22 'f' ( in float) 0:22 'v' ( temp 4-component vector of float) -0:26 Compare Equal ( temp bool) -0:26 'f1' ( temp 1-component vector of float) -0:26 Construct float ( temp 1-component vector of float) -0:26 'v' ( temp 4-component vector of float) -0:27 Compare Less Than ( temp bool) -0:27 Construct float ( temp 1-component vector of float) -0:27 'v' ( temp 4-component vector of float) -0:27 'f1' ( temp 1-component vector of float) +0:26 Equal ( temp 4-component vector of bool) +0:26 Construct vec4 ( temp 4-component vector of float) +0:26 'f1' ( temp 1-component vector of float) +0:26 'v' ( temp 4-component vector of float) +0:27 Compare Less Than ( temp 4-component vector of bool) +0:27 'v' ( temp 4-component vector of float) +0:27 Construct vec4 ( temp 4-component vector of float) +0:27 'f1' ( temp 1-component vector of float) 0:28 Construct float ( temp float) 0:28 'f1' ( temp 1-component vector of float) 0:29 Construct vec3 ( temp 3-component vector of float) 0:29 Construct float ( temp float) 0:29 'f1' ( temp 1-component vector of float) -0:33 Branch: Return with expression -0:33 component-wise multiply ( temp 4-component vector of float) -0:33 'input' ( in 4-component vector of float) -0:33 Constant: -0:33 3.000000 -0:33 3.000000 -0:33 3.000000 -0:33 3.000000 +0:36 right-shift ( temp 3-component vector of uint) +0:36 Construct uvec3 ( temp 3-component vector of uint) +0:36 'ui' ( temp uint) +0:36 'ui3' ( temp 3-component vector of uint) +0:37 right-shift ( temp 3-component vector of uint) +0:37 'ui3' ( temp 3-component vector of uint) +0:37 'ui' ( temp uint) +0:39 multiply second child into first child ( temp 4-component vector of float) +0:39 'v' ( temp 4-component vector of float) +0:39 'f1' ( temp 1-component vector of float) +0:40 multiply second child into first child ( temp 1-component vector of float) +0:40 'f1' ( temp 1-component vector of float) +0:40 Construct float ( temp 1-component vector of float) +0:40 'v' ( temp 4-component vector of float) +0:42 Sequence +0:42 move second child to first child ( temp 3-component vector of float) +0:42 'mixed' ( temp 3-component vector of float) +0:42 component-wise multiply ( temp 3-component vector of float) +0:42 'u' ( temp 3-component vector of float) +0:42 Construct vec3 ( temp 3-component vector of float) +0:42 'v' ( temp 4-component vector of float) +0:43 move second child to first child ( temp float) +0:43 'f' ( in float) +0:43 Construct float ( in float) +0:43 'u' ( temp 3-component vector of float) +0:44 move second child to first child ( temp 1-component vector of float) +0:44 'f1' ( temp 1-component vector of float) +0:44 Construct float ( temp 1-component vector of float) +0:44 'u' ( temp 3-component vector of float) +0:45 Sequence +0:45 move second child to first child ( temp float) +0:45 'sf' ( temp float) +0:45 Construct float ( temp float) +0:45 'v' ( temp 4-component vector of float) +0:46 Sequence +0:46 move second child to first child ( temp 1-component vector of float) +0:46 'sf1' ( temp 1-component vector of float) +0:46 Construct float ( temp 1-component vector of float) +0:46 'v' ( temp 4-component vector of float) +0:48 Branch: Return with expression +0:48 component-wise multiply ( temp 4-component vector of float) +0:48 'input' ( in 4-component vector of float) +0:48 Constant: +0:48 3.000000 +0:48 3.000000 +0:48 3.000000 +0:48 3.000000 0:? Linker Objects // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 88 +// Id's are bound by 127 Capability Shader 1: ExtInstImport "GLSL.std.450" @@ -263,6 +341,11 @@ gl_FragCoord origin is upper left Name 34 "MyVal" Name 37 "foo" Name 70 "f1" + Name 83 "ui" + Name 88 "ui3" + Name 103 "mixed" + Name 115 "sf" + Name 118 "sf1" 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 @@ -294,8 +377,11 @@ gl_FragCoord origin is upper left 56: TypeInt 32 0 57: 56(int) Constant 0 62: TypeVector 41(bool) 4 - 83: 6(float) Constant 1077936128 - 84: 7(fvec4) ConstantComposite 83 83 83 83 + 82: TypePointer Function 56(int) + 85: TypeVector 56(int) 3 + 87: TypePointer Function 85(ivec3) + 122: 6(float) Constant 1077936128 + 123: 7(fvec4) ConstantComposite 122 122 122 122 4(main): 2 Function None 3 5: Label Return @@ -311,6 +397,11 @@ gl_FragCoord origin is upper left 34(MyVal): 23(ptr) Variable Function 37(foo): 23(ptr) Variable Function 70(f1): 9(ptr) Variable Function + 83(ui): 82(ptr) Variable Function + 88(ui3): 87(ptr) Variable Function + 103(mixed): 23(ptr) Variable Function + 115(sf): 9(ptr) Variable Function + 118(sf1): 9(ptr) Variable Function Store 15(v) 17 Store 15(v) 19 20: 6(float) Load 12(f) @@ -346,17 +437,55 @@ gl_FragCoord origin is upper left 68: 62(bvec4) FOrdNotEqual 66 67 69: 41(bool) Any 68 71: 6(float) Load 70(f1) - 72: 7(fvec4) Load 15(v) - 73: 6(float) CompositeExtract 72 0 - 74: 41(bool) FOrdEqual 71 73 + 72: 7(fvec4) CompositeConstruct 71 71 71 71 + 73: 7(fvec4) Load 15(v) + 74: 62(bvec4) FOrdEqual 72 73 75: 7(fvec4) Load 15(v) - 76: 6(float) CompositeExtract 75 0 - 77: 6(float) Load 70(f1) - 78: 41(bool) FOrdLessThan 76 77 + 76: 6(float) Load 70(f1) + 77: 7(fvec4) CompositeConstruct 76 76 76 76 + 78: 62(bvec4) FOrdLessThan 75 77 79: 6(float) Load 70(f1) 80: 6(float) Load 70(f1) 81: 22(fvec3) CompositeConstruct 80 80 80 - 82: 7(fvec4) Load 11(input) - 85: 7(fvec4) FMul 82 84 - ReturnValue 85 + 84: 56(int) Load 83(ui) + 86: 85(ivec3) CompositeConstruct 84 84 84 + 89: 85(ivec3) Load 88(ui3) + 90: 85(ivec3) ShiftRightLogical 86 89 + 91: 85(ivec3) Load 88(ui3) + 92: 56(int) Load 83(ui) + 93: 85(ivec3) CompositeConstruct 92 92 92 + 94: 85(ivec3) ShiftRightLogical 91 93 + 95: 6(float) Load 70(f1) + 96: 7(fvec4) Load 15(v) + 97: 7(fvec4) CompositeConstruct 95 95 95 95 + 98: 7(fvec4) FMul 96 97 + Store 15(v) 98 + 99: 7(fvec4) Load 15(v) + 100: 6(float) CompositeExtract 99 0 + 101: 6(float) Load 70(f1) + 102: 6(float) FMul 101 100 + Store 70(f1) 102 + 104: 22(fvec3) Load 24(u) + 105: 7(fvec4) Load 15(v) + 106: 6(float) CompositeExtract 105 0 + 107: 6(float) CompositeExtract 105 1 + 108: 6(float) CompositeExtract 105 2 + 109: 22(fvec3) CompositeConstruct 106 107 108 + 110: 22(fvec3) FMul 104 109 + Store 103(mixed) 110 + 111: 22(fvec3) Load 24(u) + 112: 6(float) CompositeExtract 111 0 + Store 12(f) 112 + 113: 22(fvec3) Load 24(u) + 114: 6(float) CompositeExtract 113 0 + Store 70(f1) 114 + 116: 7(fvec4) Load 15(v) + 117: 6(float) CompositeExtract 116 0 + Store 115(sf) 117 + 119: 7(fvec4) Load 15(v) + 120: 6(float) CompositeExtract 119 0 + Store 118(sf1) 120 + 121: 7(fvec4) Load 11(input) + 124: 7(fvec4) FMul 121 123 + ReturnValue 124 FunctionEnd diff --git a/Test/hlsl.shapeConv.frag b/Test/hlsl.shapeConv.frag index 16a204574..bc09d80a3 100644 --- a/Test/hlsl.shapeConv.frag +++ b/Test/hlsl.shapeConv.frag @@ -30,5 +30,20 @@ float4 PixelShaderFunction(float4 input, float f) : COLOR0 const float4 f4 = 3.0; + uint ui; + uint3 ui3; + + ui >> ui3; + ui3 >> ui; + + v *= f1; + f1 *= v; + + float3 mixed = u * v; + f = u; + f1 = u; + float sf = v; + float1 sf1 = v; + return input * f4; } diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 399902222..1d25692a4 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -130,8 +130,9 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn } // Convert the children's type shape to be compatible. - right = addShapeConversion(op, left->getType(), right); - left = addShapeConversion(op, right->getType(), left); + addBiShapeConversion(op, left, right); + if (left == nullptr || right == nullptr) + return nullptr; // // Need a new node holding things together. Make @@ -238,7 +239,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm return nullptr; // convert shape - right = addShapeConversion(op, left->getType(), right); + right = addUniShapeConversion(op, left->getType(), right); // build the node TIntermBinary* node = addBinaryNode(op, left, right, loc); @@ -788,7 +789,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt } // Convert the node's shape of type for the given type, as allowed by the -// operation involved: 'op'. +// operation involved: 'op'. This is for situations where there is only one +// direction to consider doing the shape conversion. +// +// This implements policy, it call addShapeConversion() for the mechanism. // // Generally, the AST represents allowed GLSL shapes, so this isn't needed // for GLSL. Bad shapes are caught in conversion or promotion. @@ -796,7 +800,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // Return 'node' if no conversion was done. Promotion handles final shape // checking. // -TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type, TIntermTyped* node) +TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node) { // some source languages don't do this switch (source) { @@ -809,23 +813,137 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type, // some operations don't do this switch (op) { + case EOpFunctionCall: + case EOpReturn: + break; + + case EOpMulAssign: + // want to support vector *= scalar native ops in AST and lower, not smear, similarly for + // matrix *= scalar, etc. + + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpAndAssign: + case EOpInclusiveOrAssign: + case EOpExclusiveOrAssign: + case EOpRightShiftAssign: + case EOpLeftShiftAssign: + if (node->getVectorSize() == 1) + return node; + break; + case EOpAssign: + break; + + default: + return node; + } + + return addShapeConversion(type, node); +} + +// Convert the nodes' shapes to be compatible for the operation 'op'. +// +// This implements policy, it call addShapeConversion() for the mechanism. +// +// Generally, the AST represents allowed GLSL shapes, so this isn't needed +// for GLSL. Bad shapes are caught in conversion or promotion. +// +void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode) +{ + // some source languages don't do this + switch (source) { + case EShSourceHlsl: + break; + case EShSourceGlsl: + default: + return; + } + + // some operations don't do this + // 'break' will mean attempt bidirectional conversion + switch (op) { + case EOpMulAssign: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpAndAssign: + case EOpInclusiveOrAssign: + case EOpExclusiveOrAssign: + case EOpRightShiftAssign: + case EOpLeftShiftAssign: + // switch to unidirectional conversion (the lhs can't change) + rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode); + return; + + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + // want to support vector * scalar native ops in AST and lower, not smear, similarly for + // matrix * vector, etc. + if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1) + return; + break; + + case EOpRightShift: + case EOpLeftShift: + // can natively support the right operand being a scalar and the left a vector, + // but not the reverse + if (rhsNode->getVectorSize() == 1) + return; + break; + case EOpLessThan: case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: + case EOpEqual: case EOpNotEqual: - case EOpFunctionCall: - case EOpReturn: + case EOpLogicalAnd: case EOpLogicalOr: case EOpLogicalXor: + + case EOpAnd: + case EOpInclusiveOr: + case EOpExclusiveOr: break; + default: - return node; + return; } + // Do bidirectional conversions + if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) { + if (lhsNode->getType().isScalarOrVec1()) + lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); + else + rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); + } + lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); + rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); +} + +// Convert the node's shape of type for the given type. It's not necessarily +// an error if they are different and not converted, as some operations accept +// mixed types. Promotion will do final shape checking. +// +// If there is a chance of two nodes, with conversions possible in each direction, +// the policy for what to ask for must be in the caller; this will do what is asked. +// +// Return 'node' if no conversion was done. Promotion handles final shape +// checking. +// +TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node) +{ + // no conversion needed + if (node->getType() == type) + return node; + // structures and arrays don't change shape, either to or from if (node->getType().isStruct() || node->getType().isArray() || type.isStruct() || type.isArray()) @@ -834,12 +952,12 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type, // The new node that handles the conversion TOperator constructorOp = mapTypeToConstructorOp(type); - // scalar -> smeared -> vector, or - // vec1 -> scalar, or - // bigger vector -> smaller vector or scalar - if ((type.isVector() && node->getType().isScalar()) || - (node->getType().isVector() && node->getVectorSize() == 1 && type.isScalar()) || - (node->getVectorSize() > type.getVectorSize() && type.isVector())) + // scalar -> vector or vec1 -> vector or + // vector -> scalar or + // bigger vector -> smaller vector + if ((node->getType().isScalarOrVec1() && type.isVector()) || + (node->getType().isVector() && type.isScalar()) || + (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize())) return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); return node; @@ -1314,9 +1432,9 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true cond->getType().getVectorSize()); // smear true/false operations if needed if (trueBlock->getType().isScalarOrVec1()) - trueBlock = addShapeConversion(EOpAssign, targetVectorType, trueBlock); + trueBlock = addShapeConversion(targetVectorType, trueBlock); if (falseBlock->getType().isScalarOrVec1()) - falseBlock = addShapeConversion(EOpAssign, targetVectorType, falseBlock); + falseBlock = addShapeConversion(targetVectorType, falseBlock); // make the mix operation TIntermAggregate* mix = makeAggregate(loc); @@ -2139,8 +2257,6 @@ bool TIntermediate::promoteBinary(TIntermBinary& node) case EOpLogicalXor: return left->getType() == right->getType(); - // no shifts: they can mix types (scalar int can shift a vector uint, etc.) - case EOpMod: case EOpModAssign: @@ -2154,6 +2270,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node) case EOpAdd: case EOpSub: case EOpDiv: + case EOpAddAssign: case EOpSubAssign: case EOpDivAssign: @@ -2178,7 +2295,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node) return true; // Finish handling the case, for all ops, where there are two vectors of different sizes - if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) + if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1) return false; // diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 2cd912b0a..ece390ed9 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -243,7 +243,9 @@ public: TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); TIntermSymbol* addSymbol(const TIntermSymbol&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const; - TIntermTyped* addShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index a2a490ca7..63c6eb5dc 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -2087,7 +2087,7 @@ TIntermNode* HlslParseContext::handleReturnValue(const TSourceLoc& loc, TIntermT } else if (*currentFunctionType != value->getType()) { value = intermediate.addConversion(EOpReturn, *currentFunctionType, value); if (value && *currentFunctionType != value->getType()) - value = intermediate.addShapeConversion(EOpReturn, *currentFunctionType, value); + value = intermediate.addUniShapeConversion(EOpReturn, *currentFunctionType, value); if (value == nullptr) { error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); return value; @@ -4105,7 +4105,7 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI // convert to the correct type. TIntermTyped* convArg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); if (convArg != nullptr) - convArg = intermediate.addShapeConversion(EOpFunctionCall, *function[i].type, convArg); + convArg = intermediate.addUniShapeConversion(EOpFunctionCall, *function[i].type, convArg); if (convArg != nullptr) setArg(i, convArg); else @@ -6439,7 +6439,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); if (initializer != nullptr && variable->getType() != initializer->getType()) - initializer = intermediate.addShapeConversion(EOpAssign, variable->getType(), initializer); + initializer = intermediate.addUniShapeConversion(EOpAssign, variable->getType(), initializer); if (initializer == nullptr || !initializer->getAsConstantUnion() || variable->getType() != initializer->getType()) { error(loc, "non-matching or non-convertible constant type for const initializer", -- GitLab