From 82ae8c31e0ee4e665f37a97e86b0617dcdd4cce8 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Tue, 13 Jun 2017 23:13:10 -0600 Subject: [PATCH] HLSL: Fix #924: Convert between two different arrays with cast. --- Test/baseResults/hlsl.constructArray.vert.out | 381 ++++++++++++++++++ Test/hlsl.constructArray.vert | 10 + glslang/MachineIndependent/ParseHelper.cpp | 3 + gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslGrammar.cpp | 12 +- hlsl/hlslParseHelper.cpp | 102 ++++- hlsl/hlslParseHelper.h | 1 + 7 files changed, 503 insertions(+), 7 deletions(-) create mode 100755 Test/baseResults/hlsl.constructArray.vert.out create mode 100644 Test/hlsl.constructArray.vert diff --git a/Test/baseResults/hlsl.constructArray.vert.out b/Test/baseResults/hlsl.constructArray.vert.out new file mode 100755 index 000000000..dd2c2434a --- /dev/null +++ b/Test/baseResults/hlsl.constructArray.vert.out @@ -0,0 +1,381 @@ +hlsl.constructArray.vert +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:4 Sequence +0:4 move second child to first child ( temp 2-element array of 4-component vector of float) +0:4 'float4_array_times' ( temp 2-element array of 4-component vector of float) +0:4 Construct structure ( temp 2-element array of 4-component vector of float) +0:4 Convert int to float ( temp 4-component vector of float) +0:4 direct index ( temp 4-component vector of int) +0:4 'int4_array' ( temp 3-element array of 4-component vector of int) +0:4 Constant: +0:4 0 (const int) +0:4 Convert int to float ( temp 4-component vector of float) +0:4 direct index ( temp 4-component vector of int) +0:4 'int4_array' ( temp 3-element array of 4-component vector of int) +0:4 Constant: +0:4 1 (const int) +0:5 Sequence +0:5 move second child to first child ( temp 4-element array of 2-component vector of float) +0:5 'float2_array_times2' ( temp 4-element array of 2-component vector of float) +0:5 Construct structure ( temp 4-element array of 2-component vector of float) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 0 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 1 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 2 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 3 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 0 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 1 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 2 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 3 (const int) +0:6 Sequence +0:6 move second child to first child ( temp 2-element array of 4-component vector of int) +0:6 'int4_array2' ( temp 2-element array of 4-component vector of int) +0:6 Construct structure ( temp 2-element array of 4-component vector of int) +0:6 direct index ( temp 4-component vector of int) +0:6 'int4_array' ( temp 3-element array of 4-component vector of int) +0:6 Constant: +0:6 0 (const int) +0:6 direct index ( temp 4-component vector of int) +0:6 'int4_array' ( temp 3-element array of 4-component vector of int) +0:6 Constant: +0:6 1 (const int) +0:7 Sequence +0:7 move second child to first child ( temp 2-element array of int) +0:7 'int1_array' ( temp 2-element array of int) +0:7 Construct structure ( temp 2-element array of int) +0:7 direct index ( temp int) +0:7 direct index ( temp 4-component vector of int) +0:7 'int4_array' ( temp 3-element array of 4-component vector of int) +0:7 Constant: +0:7 0 (const int) +0:7 Constant: +0:7 0 (const int) +0:7 direct index ( temp int) +0:7 direct index ( temp 4-component vector of int) +0:7 'int4_array' ( temp 3-element array of 4-component vector of int) +0:7 Constant: +0:7 0 (const int) +0:7 Constant: +0:7 1 (const int) +0:9 Branch: Return with expression +0:9 Constant: +0:9 0.000000 +0:9 0.000000 +0:9 0.000000 +0:9 0.000000 +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:4 Sequence +0:4 move second child to first child ( temp 2-element array of 4-component vector of float) +0:4 'float4_array_times' ( temp 2-element array of 4-component vector of float) +0:4 Construct structure ( temp 2-element array of 4-component vector of float) +0:4 Convert int to float ( temp 4-component vector of float) +0:4 direct index ( temp 4-component vector of int) +0:4 'int4_array' ( temp 3-element array of 4-component vector of int) +0:4 Constant: +0:4 0 (const int) +0:4 Convert int to float ( temp 4-component vector of float) +0:4 direct index ( temp 4-component vector of int) +0:4 'int4_array' ( temp 3-element array of 4-component vector of int) +0:4 Constant: +0:4 1 (const int) +0:5 Sequence +0:5 move second child to first child ( temp 4-element array of 2-component vector of float) +0:5 'float2_array_times2' ( temp 4-element array of 2-component vector of float) +0:5 Construct structure ( temp 4-element array of 2-component vector of float) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 0 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 1 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 2 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 0 (const int) +0:5 Constant: +0:5 3 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 0 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 1 (const int) +0:5 Convert int to float ( temp 2-component vector of float) +0:5 Construct ivec2 ( temp 2-component vector of int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 2 (const int) +0:5 direct index ( temp int) +0:5 direct index ( temp 4-component vector of int) +0:5 'int4_array' ( temp 3-element array of 4-component vector of int) +0:5 Constant: +0:5 1 (const int) +0:5 Constant: +0:5 3 (const int) +0:6 Sequence +0:6 move second child to first child ( temp 2-element array of 4-component vector of int) +0:6 'int4_array2' ( temp 2-element array of 4-component vector of int) +0:6 Construct structure ( temp 2-element array of 4-component vector of int) +0:6 direct index ( temp 4-component vector of int) +0:6 'int4_array' ( temp 3-element array of 4-component vector of int) +0:6 Constant: +0:6 0 (const int) +0:6 direct index ( temp 4-component vector of int) +0:6 'int4_array' ( temp 3-element array of 4-component vector of int) +0:6 Constant: +0:6 1 (const int) +0:7 Sequence +0:7 move second child to first child ( temp 2-element array of int) +0:7 'int1_array' ( temp 2-element array of int) +0:7 Construct structure ( temp 2-element array of int) +0:7 direct index ( temp int) +0:7 direct index ( temp 4-component vector of int) +0:7 'int4_array' ( temp 3-element array of 4-component vector of int) +0:7 Constant: +0:7 0 (const int) +0:7 Constant: +0:7 0 (const int) +0:7 direct index ( temp int) +0:7 direct index ( temp 4-component vector of int) +0:7 'int4_array' ( temp 3-element array of 4-component vector of int) +0:7 Constant: +0:7 0 (const int) +0:7 Constant: +0:7 1 (const int) +0:9 Branch: Return with expression +0:9 Constant: +0:9 0.000000 +0:9 0.000000 +0:9 0.000000 +0:9 0.000000 +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 89 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 87 + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 15 "float4_array_times" + Name 21 "int4_array" + Name 36 "float2_array_times2" + Name 68 "int4_array2" + Name 76 "int1_array" + Name 87 "@entryPointOutput" + Decorate 87(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypeInt 32 0 + 12: 11(int) Constant 2 + 13: TypeArray 7(fvec4) 12 + 14: TypePointer Function 13 + 16: TypeInt 32 1 + 17: TypeVector 16(int) 4 + 18: 11(int) Constant 3 + 19: TypeArray 17(ivec4) 18 + 20: TypePointer Function 19 + 22: 16(int) Constant 0 + 23: TypePointer Function 17(ivec4) + 27: 16(int) Constant 1 + 32: TypeVector 6(float) 2 + 33: 11(int) Constant 4 + 34: TypeArray 32(fvec2) 33 + 35: TypePointer Function 34 + 37: 11(int) Constant 0 + 38: TypePointer Function 16(int) + 41: 11(int) Constant 1 + 44: TypeVector 16(int) 2 + 66: TypeArray 17(ivec4) 12 + 67: TypePointer Function 66 + 74: TypeArray 16(int) 12 + 75: TypePointer Function 74 + 82: 6(float) Constant 0 + 83: 7(fvec4) ConstantComposite 82 82 82 82 + 86: TypePointer Output 7(fvec4) +87(@entryPointOutput): 86(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 88: 7(fvec4) FunctionCall 9(@main() + Store 87(@entryPointOutput) 88 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label +15(float4_array_times): 14(ptr) Variable Function + 21(int4_array): 20(ptr) Variable Function +36(float2_array_times2): 35(ptr) Variable Function + 68(int4_array2): 67(ptr) Variable Function + 76(int1_array): 75(ptr) Variable Function + 24: 23(ptr) AccessChain 21(int4_array) 22 + 25: 17(ivec4) Load 24 + 26: 7(fvec4) ConvertSToF 25 + 28: 23(ptr) AccessChain 21(int4_array) 27 + 29: 17(ivec4) Load 28 + 30: 7(fvec4) ConvertSToF 29 + 31: 13 CompositeConstruct 26 30 + Store 15(float4_array_times) 31 + 39: 38(ptr) AccessChain 21(int4_array) 22 37 + 40: 16(int) Load 39 + 42: 38(ptr) AccessChain 21(int4_array) 22 41 + 43: 16(int) Load 42 + 45: 44(ivec2) CompositeConstruct 40 43 + 46: 32(fvec2) ConvertSToF 45 + 47: 38(ptr) AccessChain 21(int4_array) 22 12 + 48: 16(int) Load 47 + 49: 38(ptr) AccessChain 21(int4_array) 22 18 + 50: 16(int) Load 49 + 51: 44(ivec2) CompositeConstruct 48 50 + 52: 32(fvec2) ConvertSToF 51 + 53: 38(ptr) AccessChain 21(int4_array) 27 37 + 54: 16(int) Load 53 + 55: 38(ptr) AccessChain 21(int4_array) 27 41 + 56: 16(int) Load 55 + 57: 44(ivec2) CompositeConstruct 54 56 + 58: 32(fvec2) ConvertSToF 57 + 59: 38(ptr) AccessChain 21(int4_array) 27 12 + 60: 16(int) Load 59 + 61: 38(ptr) AccessChain 21(int4_array) 27 18 + 62: 16(int) Load 61 + 63: 44(ivec2) CompositeConstruct 60 62 + 64: 32(fvec2) ConvertSToF 63 + 65: 34 CompositeConstruct 46 52 58 64 + Store 36(float2_array_times2) 65 + 69: 23(ptr) AccessChain 21(int4_array) 22 + 70: 17(ivec4) Load 69 + 71: 23(ptr) AccessChain 21(int4_array) 27 + 72: 17(ivec4) Load 71 + 73: 66 CompositeConstruct 70 72 + Store 68(int4_array2) 73 + 77: 38(ptr) AccessChain 21(int4_array) 22 37 + 78: 16(int) Load 77 + 79: 38(ptr) AccessChain 21(int4_array) 22 41 + 80: 16(int) Load 79 + 81: 74 CompositeConstruct 78 80 + Store 76(int1_array) 81 + ReturnValue 83 + FunctionEnd diff --git a/Test/hlsl.constructArray.vert b/Test/hlsl.constructArray.vert new file mode 100644 index 000000000..52c4b6f0c --- /dev/null +++ b/Test/hlsl.constructArray.vert @@ -0,0 +1,10 @@ +float4 main() : SV_POSITION +{ + int4 int4_array[3]; + float4 float4_array_times[2] = (float4[2])int4_array; + float2 float2_array_times2[4] = (float2[4])int4_array; + int4 int4_array2[2] = (int4[2])int4_array; + int int1_array[2] = (int[2])int4_array; + + return (float4)0.0; +} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 12dbd1646..f2002341a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -5425,6 +5425,9 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const // Test for the correctness of the parameters passed to various constructor functions // and also convert them to the right data type, if allowed and required. // +// 'node' is what to construct from. +// 'type' is what type to construct. +// // Returns nullptr for an error or the constructed node (aggregate or typed) for no error. // TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 51f9d49e3..43c4c4015 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -100,6 +100,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.comparison.vec.frag", "main"}, {"hlsl.conditional.frag", "PixelShaderFunction"}, {"hlsl.constantbuffer.frag", "main"}, + {"hlsl.constructArray.vert", "main"}, {"hlsl.constructexpr.frag", "main"}, {"hlsl.constructimat.frag", "main"}, {"hlsl.depthGreater.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 5a546f5ba..aab3cb141 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -2732,9 +2732,14 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) if (acceptTokenClass(EHTokLeftParen)) { TType castType; if (acceptType(castType)) { + // recognize any array_specifier as part of the type + TArraySizes* arraySizes = nullptr; + acceptArraySpecifier(arraySizes); + if (arraySizes != nullptr) + castType.newArraySizes(*arraySizes); + TSourceLoc loc = token.loc; if (acceptTokenClass(EHTokRightParen)) { // We've matched "(type)" now, get the expression to cast - TSourceLoc loc = token.loc; if (! acceptUnaryExpression(node)) return false; @@ -2754,6 +2759,11 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) // the '(int' part. We must back up twice. recedeToken(); recedeToken(); + + // Note, there are no array constructors like + // (float[2](...)) + if (arraySizes != nullptr) + parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", ""); } } else { // This isn't a type cast, but it still started "(", so if it is a diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 67933b45d..e60ff60ef 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -5401,7 +5401,8 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node if (type.isImplicitlySizedArray()) { // auto adapt the constructor type to the number of arguments type.changeOuterArraySize(function.getParamCount()); - } else if (type.getOuterArraySize() != function.getParamCount()) { + } else if (type.getOuterArraySize() != function.getParamCount() && + type.computeNumComponents() > size) { error(loc, "array constructor needs one argument per array element", "constructor", ""); return true; } @@ -5430,6 +5431,12 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node } } + // Some array -> array type casts are okay + if (arrayArg && function.getParamCount() == 1 && op != EOpConstructStruct && type.isArray() && + !type.isArrayOfArrays() && !function[0].type->isArrayOfArrays() && + type.getVectorSize() >= 1 && function[0].type->getVectorSize() >= 1) + return false; + if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { error(loc, "constructing non-array constituent from array argument", "constructor", ""); return true; @@ -7336,17 +7343,20 @@ TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TInterm // Add a constructor, either from the grammar, or other programmatic reasons. // +// 'node' is what to construct from. +// 'type' is what type to construct. +// +// Returns the constructed object. // Return nullptr if it can't be done. // TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) { - TIntermAggregate* aggrNode = node->getAsAggregate(); TOperator op = intermediate.mapTypeToConstructorOp(type); // Combined texture-sampler constructors are completely semantic checked // in constructorTextureSamplerError() if (op == EOpConstructTextureSampler) - return intermediate.setAggregateOperator(aggrNode, op, type, loc); + return intermediate.setAggregateOperator(node->getAsAggregate(), op, type, loc); TTypeList::const_iterator memberTypes; if (op == EOpConstructStruct) @@ -7360,7 +7370,8 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp elementType.shallowCopy(type); bool singleArg; - if (aggrNode) { + TIntermAggregate* aggrNode = node->getAsAggregate(); + if (aggrNode != nullptr) { if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) singleArg = true; else @@ -7370,9 +7381,15 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp TIntermTyped *newNode; if (singleArg) { + // Handle array -> array conversion + // Constructing an array of one type from an array of another type is allowed, + // assuming there are enough components available (semantic-checked earlier). + if (type.isArray() && node->isArray()) + newNode = convertArray(node, type); + // If structure constructor or array constructor is being called // for only one parameter inside the structure, we need to call constructAggregate function once. - if (type.isArray()) + else if (type.isArray()) newNode = constructAggregate(node, elementType, 1, node->getLoc()); else if (op == EOpConstructStruct) newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); @@ -7537,13 +7554,86 @@ TIntermTyped* HlslParseContext::constructBuiltIn(const TType& type, TOperator op return intermediate.setAggregateOperator(newNode, op, type, loc); } +// Convert the array in node to the requested type, which is also an array. +// Returns nullptr on failure, otherwise returns aggregate holding the list of +// elements needed to construct the array. +TIntermTyped* HlslParseContext::convertArray(TIntermTyped* node, const TType& type) +{ + assert(node->isArray() && type.isArray()); + if (node->getType().computeNumComponents() < type.computeNumComponents()) + return nullptr; + + // TODO: write an argument replicator, for the case the argument should not be + // executed multiple times, yet multiple copies are needed. + + TIntermTyped* constructee = node->getAsTyped(); + // track where we are in consuming the argument + int constructeeElement = 0; + int constructeeComponent = 0; + + // bump up to the next component to consume + const auto getNextComponent = [&]() { + TIntermTyped* component; + component = handleBracketDereference(node->getLoc(), constructee, + intermediate.addConstantUnion(constructeeElement, node->getLoc())); + if (component->isVector()) + component = handleBracketDereference(node->getLoc(), component, + intermediate.addConstantUnion(constructeeComponent, node->getLoc())); + // bump component pointer up + ++constructeeComponent; + if (constructeeComponent == constructee->getVectorSize()) { + constructeeComponent = 0; + ++constructeeElement; + } + return component; + }; + + // make one subnode per constructed array element + TIntermAggregate* constructor = nullptr; + TType derefType(type, 0); + TType speculativeComponentType(derefType, 0); + TType* componentType = derefType.isVector() ? &speculativeComponentType : &derefType; + TOperator componentOp = intermediate.mapTypeToConstructorOp(*componentType); + TType crossType(node->getBasicType(), EvqTemporary, type.getVectorSize()); + for (int e = 0; e < type.getOuterArraySize(); ++e) { + // construct an element + TIntermTyped* elementArg; + if (type.getVectorSize() == constructee->getVectorSize()) { + // same element shape + elementArg = handleBracketDereference(node->getLoc(), constructee, + intermediate.addConstantUnion(e, node->getLoc())); + } else { + // mismatched element shapes + if (type.getVectorSize() == 1) + elementArg = getNextComponent(); + else { + // make a vector + TIntermAggregate* elementConstructee = nullptr; + for (int c = 0; c < type.getVectorSize(); ++c) + elementConstructee = intermediate.growAggregate(elementConstructee, getNextComponent()); + elementArg = addConstructor(node->getLoc(), elementConstructee, crossType); + } + } + // convert basic types + elementArg = intermediate.addConversion(componentOp, derefType, elementArg); + if (elementArg == nullptr) + return nullptr; + // combine with top-level constructor + constructor = intermediate.growAggregate(constructor, elementArg); + } + + return constructor; +} + // This function tests for the type of the parameters to the structure or array constructor. Raises // an error message if the expected type does not match the parameter passed to the constructor. // // Returns nullptr for an error or the input node itself if the expected and the given parameter types match. // -TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc) +TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, + const TSourceLoc& loc) { + // Handle cases that map more 1:1 between constructor arguments and constructed. TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); if (! converted || converted->getType() != type) { error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 9e772d166..9a881fbb6 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -146,6 +146,7 @@ public: void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit); TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&); TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&); + TIntermTyped* convertArray(TIntermTyped*, const TType&); TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0); -- GitLab