From: John Kessenich Date: Fri, 9 Sep 2016 22:32:09 +0000 (-0600) Subject: HLSL: Flatten vertex input and fragment output structures. X-Git-Tag: upstream/11.4.0~1514 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cd0a78a0d9974074f7244f6aa15bd14a66693330;p=platform%2Fupstream%2Fglslang.git HLSL: Flatten vertex input and fragment output structures. Vulkan can't handle structures into the vertex stage or out of the fragment stage. --- diff --git a/Test/baseResults/hlsl.entry-out.frag.out b/Test/baseResults/hlsl.entry-out.frag.out index b76d452..015136e 100755 --- a/Test/baseResults/hlsl.entry-out.frag.out +++ b/Test/baseResults/hlsl.entry-out.frag.out @@ -5,32 +5,26 @@ gl_FragCoord origin is upper left 0:7 Function Definition: PixelShaderFunction(vf4;vf4;struct-OutParam-vf2-vi21; (global 4-component vector of float) 0:7 Function Parameters: 0:7 'input' (layout(location=0 ) in 4-component vector of float) -0:7 'out1' (out 4-component vector of float) -0:7 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) +0:7 'out1' (layout(location=1 ) out 4-component vector of float) +0:7 'out2' (layout(location=2 ) out structure{temp 2-component vector of float v, temp 2-component vector of int i}) 0:? Sequence 0:8 move second child to first child (temp 4-component vector of float) -0:8 'out1' (out 4-component vector of float) +0:8 'out1' (layout(location=1 ) out 4-component vector of float) 0:8 'input' (layout(location=0 ) in 4-component vector of float) 0:9 move second child to first child (temp 2-component vector of float) -0:9 v: direct index for structure (temp 2-component vector of float) -0:9 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) -0:9 Constant: -0:9 0 (const int) +0:? 'v' (layout(location=2 ) out 2-component vector of float) 0:9 Constant: 0:9 2.000000 0:9 2.000000 0:10 move second child to first child (temp 2-component vector of int) -0:10 i: direct index for structure (temp 2-component vector of int) -0:10 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) -0:10 Constant: -0:10 1 (const int) +0:? 'i' (layout(location=3 ) out 2-component vector of int) 0:10 Constant: 0:10 3 (const int) 0:10 3 (const int) 0:11 Sequence 0:11 move second child to first child (temp 4-component vector of float) 0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float) -0:11 'out1' (out 4-component vector of float) +0:11 'out1' (layout(location=1 ) out 4-component vector of float) 0:11 Branch: Return 0:? Linker Objects @@ -44,54 +38,49 @@ gl_FragCoord origin is upper left 0:7 Function Definition: PixelShaderFunction(vf4;vf4;struct-OutParam-vf2-vi21; (global 4-component vector of float) 0:7 Function Parameters: 0:7 'input' (layout(location=0 ) in 4-component vector of float) -0:7 'out1' (out 4-component vector of float) -0:7 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) +0:7 'out1' (layout(location=1 ) out 4-component vector of float) +0:7 'out2' (layout(location=2 ) out structure{temp 2-component vector of float v, temp 2-component vector of int i}) 0:? Sequence 0:8 move second child to first child (temp 4-component vector of float) -0:8 'out1' (out 4-component vector of float) +0:8 'out1' (layout(location=1 ) out 4-component vector of float) 0:8 'input' (layout(location=0 ) in 4-component vector of float) 0:9 move second child to first child (temp 2-component vector of float) -0:9 v: direct index for structure (temp 2-component vector of float) -0:9 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) -0:9 Constant: -0:9 0 (const int) +0:? 'v' (layout(location=2 ) out 2-component vector of float) 0:9 Constant: 0:9 2.000000 0:9 2.000000 0:10 move second child to first child (temp 2-component vector of int) -0:10 i: direct index for structure (temp 2-component vector of int) -0:10 'out2' (out structure{temp 2-component vector of float v, temp 2-component vector of int i}) -0:10 Constant: -0:10 1 (const int) +0:? 'i' (layout(location=3 ) out 2-component vector of int) 0:10 Constant: 0:10 3 (const int) 0:10 3 (const int) 0:11 Sequence 0:11 move second child to first child (temp 4-component vector of float) 0:? '@entryPointOutput' (layout(location=0 ) out 4-component vector of float) -0:11 'out1' (out 4-component vector of float) +0:11 'out1' (layout(location=1 ) out 4-component vector of float) 0:11 Branch: Return 0:? Linker Objects // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 32 +// Id's are bound by 27 Capability Shader 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 4 "PixelShaderFunction" 9 11 18 29 + EntryPoint Fragment 4 "PixelShaderFunction" 9 11 15 21 24 ExecutionMode 4 OriginUpperLeft Name 4 "PixelShaderFunction" Name 9 "out1" Name 11 "input" - Name 16 "OutParam" - MemberName 16(OutParam) 0 "v" - MemberName 16(OutParam) 1 "i" - Name 18 "out2" - Name 29 "@entryPointOutput" + Name 15 "v" + Name 21 "i" + Name 24 "@entryPointOutput" + Decorate 9(out1) Location 1 Decorate 11(input) Location 0 - Decorate 29(@entryPointOutput) Location 0 + Decorate 15(v) Location 2 + Decorate 21(i) Location 3 + Decorate 24(@entryPointOutput) Location 0 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 @@ -101,29 +90,24 @@ gl_FragCoord origin is upper left 10: TypePointer Input 7(fvec4) 11(input): 10(ptr) Variable Input 13: TypeVector 6(float) 2 - 14: TypeInt 32 1 - 15: TypeVector 14(int) 2 - 16(OutParam): TypeStruct 13(fvec2) 15(ivec2) - 17: TypePointer Output 16(OutParam) - 18(out2): 17(ptr) Variable Output - 19: 14(int) Constant 0 - 20: 6(float) Constant 1073741824 - 21: 13(fvec2) ConstantComposite 20 20 - 22: TypePointer Output 13(fvec2) - 24: 14(int) Constant 1 - 25: 14(int) Constant 3 - 26: 15(ivec2) ConstantComposite 25 25 - 27: TypePointer Output 15(ivec2) -29(@entryPointOutput): 8(ptr) Variable Output + 14: TypePointer Output 13(fvec2) + 15(v): 14(ptr) Variable Output + 16: 6(float) Constant 1073741824 + 17: 13(fvec2) ConstantComposite 16 16 + 18: TypeInt 32 1 + 19: TypeVector 18(int) 2 + 20: TypePointer Output 19(ivec2) + 21(i): 20(ptr) Variable Output + 22: 18(int) Constant 3 + 23: 19(ivec2) ConstantComposite 22 22 +24(@entryPointOutput): 8(ptr) Variable Output 4(PixelShaderFunction): 2 Function None 3 5: Label 12: 7(fvec4) Load 11(input) Store 9(out1) 12 - 23: 22(ptr) AccessChain 18(out2) 19 - Store 23 21 - 28: 27(ptr) AccessChain 18(out2) 24 - Store 28 26 - 30: 7(fvec4) Load 9(out1) - Store 29(@entryPointOutput) 30 + Store 15(v) 17 + Store 21(i) 23 + 25: 7(fvec4) Load 9(out1) + Store 24(@entryPointOutput) 25 Return FunctionEnd diff --git a/Test/baseResults/hlsl.structin.vert.out b/Test/baseResults/hlsl.structin.vert.out new file mode 100755 index 0000000..c68ba83 --- /dev/null +++ b/Test/baseResults/hlsl.structin.vert.out @@ -0,0 +1,133 @@ +hlsl.structin.vert +Shader version: 450 +0:? Sequence +0:7 Function Definition: main(vf4;struct-VI-vf4[2]-vu21;vf4; (global 4-component vector of float Position) +0:7 Function Parameters: +0:7 'd' (layout(location=0 ) in 4-component vector of float) +0:7 'vi' (layout(location=1 ) in structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord}) +0:7 'e' (layout(location=4 ) in 4-component vector of float) +0:? Sequence +0:8 Sequence +0:8 move second child to first child (temp 4-component vector of float) +0:? '@entryPointOutput' (out 4-component vector of float Position) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 direct index (layout(location=1 ) temp 4-component vector of float) +0:? 'm' (layout(location=1 ) in 2-element array of 4-component vector of float) +0:8 Constant: +0:8 1 (const int) +0:8 direct index (layout(location=1 ) temp 4-component vector of float) +0:? 'm' (layout(location=1 ) in 2-element array of 4-component vector of float) +0:8 Constant: +0:8 0 (const int) +0:8 Construct vec4 (temp 4-component vector of float) +0:8 Convert uint to float (temp float) +0:8 direct index (temp uint) +0:? 'coord' (layout(location=3 ) in 2-component vector of uint) +0:8 Constant: +0:8 0 (const int) +0:8 'd' (layout(location=0 ) in 4-component vector of float) +0:8 'e' (layout(location=4 ) in 4-component vector of float) +0:8 Branch: Return +0:? Linker Objects + + +Linked vertex stage: + + +Shader version: 450 +0:? Sequence +0:7 Function Definition: main(vf4;struct-VI-vf4[2]-vu21;vf4; (global 4-component vector of float Position) +0:7 Function Parameters: +0:7 'd' (layout(location=0 ) in 4-component vector of float) +0:7 'vi' (layout(location=1 ) in structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord}) +0:7 'e' (layout(location=4 ) in 4-component vector of float) +0:? Sequence +0:8 Sequence +0:8 move second child to first child (temp 4-component vector of float) +0:? '@entryPointOutput' (out 4-component vector of float Position) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:8 direct index (layout(location=1 ) temp 4-component vector of float) +0:? 'm' (layout(location=1 ) in 2-element array of 4-component vector of float) +0:8 Constant: +0:8 1 (const int) +0:8 direct index (layout(location=1 ) temp 4-component vector of float) +0:? 'm' (layout(location=1 ) in 2-element array of 4-component vector of float) +0:8 Constant: +0:8 0 (const int) +0:8 Construct vec4 (temp 4-component vector of float) +0:8 Convert uint to float (temp float) +0:8 direct index (temp uint) +0:? 'coord' (layout(location=3 ) in 2-component vector of uint) +0:8 Constant: +0:8 0 (const int) +0:8 'd' (layout(location=0 ) in 4-component vector of float) +0:8 'e' (layout(location=4 ) in 4-component vector of float) +0:8 Branch: Return +0:? Linker Objects + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 41 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 9 14 26 34 37 + Name 4 "main" + Name 9 "@entryPointOutput" + Name 14 "m" + Name 26 "coord" + Name 34 "d" + Name 37 "e" + Decorate 9(@entryPointOutput) BuiltIn Position + Decorate 14(m) Location 1 + Decorate 26(coord) Location 3 + Decorate 34(d) Location 0 + Decorate 37(e) Location 4 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypePointer Output 7(fvec4) +9(@entryPointOutput): 8(ptr) Variable Output + 10: TypeInt 32 0 + 11: 10(int) Constant 2 + 12: TypeArray 7(fvec4) 11 + 13: TypePointer Input 12 + 14(m): 13(ptr) Variable Input + 15: TypeInt 32 1 + 16: 15(int) Constant 1 + 17: TypePointer Input 7(fvec4) + 20: 15(int) Constant 0 + 24: TypeVector 10(int) 2 + 25: TypePointer Input 24(ivec2) + 26(coord): 25(ptr) Variable Input + 27: 10(int) Constant 0 + 28: TypePointer Input 10(int) + 34(d): 17(ptr) Variable Input + 37(e): 17(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + 18: 17(ptr) AccessChain 14(m) 16 + 19: 7(fvec4) Load 18 + 21: 17(ptr) AccessChain 14(m) 20 + 22: 7(fvec4) Load 21 + 23: 7(fvec4) FAdd 19 22 + 29: 28(ptr) AccessChain 26(coord) 27 + 30: 10(int) Load 29 + 31: 6(float) ConvertUToF 30 + 32: 7(fvec4) CompositeConstruct 31 31 31 31 + 33: 7(fvec4) FAdd 23 32 + 35: 7(fvec4) Load 34(d) + 36: 7(fvec4) FAdd 33 35 + 38: 7(fvec4) Load 37(e) + 39: 7(fvec4) FAdd 36 38 + Store 9(@entryPointOutput) 39 + Return + FunctionEnd diff --git a/Test/hlsl.structin.vert b/Test/hlsl.structin.vert new file mode 100644 index 0000000..424624a --- /dev/null +++ b/Test/hlsl.structin.vert @@ -0,0 +1,9 @@ +struct VI { + float4 m[2]; + uint2 coord; +}; + +float4 main(float4 d, VI vi, float4 e) : SV_POSITION +{ + return vi.m[1] + vi.m[0] + float4(vi.coord.x) + d + e; +} \ No newline at end of file diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 85fd262..41f9a70 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1477" -#define GLSLANG_DATE "09-Sep-2016" +#define GLSLANG_REVISION "Overload400-PrecQual.1481" +#define GLSLANG_DATE "10-Sep-2016" diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 5b42092..d4206af 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -159,6 +159,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.semicolons.frag", "main"}, {"hlsl.shapeConv.frag", "main"}, {"hlsl.stringtoken.frag", "main"}, + {"hlsl.structin.vert", "main"}, {"hlsl.intrinsics.vert", "VertexShaderFunction"}, {"hlsl.matType.frag", "PixelShaderFunction"}, {"hlsl.max.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index ec2cc03..dbc2940 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -679,12 +679,16 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt } } if (fieldFound) { - if (base->getType().getQualifier().storage == EvqConst) - result = intermediate.foldDereference(base, member, loc); + if (base->getAsSymbolNode() && shouldFlatten(base->getType())) + result = flattenAccess(base, member); else { - TIntermTyped* index = intermediate.addConstantUnion(member, loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[member].type); + if (base->getType().getQualifier().storage == EvqConst) + result = intermediate.foldDereference(base, member, loc); + else { + TIntermTyped* index = intermediate.addConstantUnion(member, loc); + result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); + result->setType(*(*fields)[member].type); + } } } else error(loc, "no such field in structure", field.c_str(), ""); @@ -694,6 +698,54 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt return result; } +// Is this a structure that can't be passed down the stack? +// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage. +bool HlslParseContext::shouldFlatten(const TType& type) +{ + const TStorageQualifier qualifier = type.getQualifier().storage; + + return type.isStruct() && + ((language == EShLangVertex && qualifier == EvqVaryingIn) || + (language == EShLangFragment && qualifier == EvqVaryingOut)); +} + +// Figure out mapping between a structures top members and an +// equivalent set of individual variables. +// +// Assumes shouldFlatten() or equivalent was called first. +// +// TODO: generalize this to arbitrary nesting? +void HlslParseContext::flattenStruct(const TVariable& variable) +{ + TVector memberVariables; + + auto members = *variable.getType().getStruct(); + int location = variable.getType().getQualifier().layoutLocation; + for (int member = 0; member < (int)members.size(); ++member) { + TVariable* memberVariable = makeInternalVariable(members[member].type->getFieldName().c_str(), *members[member].type); + memberVariable->getWritableType().getQualifier() = variable.getType().getQualifier(); + memberVariable->getWritableType().getQualifier().layoutLocation = location; + location += intermediate.computeTypeLocationSize(memberVariable->getType()); + memberVariables.push_back(memberVariable); + } + + flattenMap[variable.getUniqueId()] = memberVariables; +} + +// Turn an access into structure that was flattened to instead be +// an access to the individual variable the member was flattened to. +// Assumes shouldFlatten() or equivalent was called first. +TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) +{ + const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); + + if (flattenMap.find(symbolNode.getId()) == flattenMap.end()) + return base; + + const TVariable* memberVariable = flattenMap[symbolNode.getId()][member]; + return intermediate.addSymbol(*memberVariable); +} + // // Handle seeing a function declarator in the grammar. This is the precursor // to recognizing a function prototype or function definition. @@ -800,6 +852,9 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*variable, loc), loc); + + if (shouldFlatten(*param.type)) + flattenStruct(*variable); } } else paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); @@ -861,20 +916,21 @@ void HlslParseContext::remapEntrypointIO(TFunction& function) // parameters are actually shader-scoped inputs and outputs (in or out) for (int i = 0; i < function.getParamCount(); i++) { - if (function[i].type->getQualifier().isParamInput()) { - function[i].type->getQualifier().storage = EvqVaryingIn; - if (function[i].type->getQualifier().builtIn == EbvNone) { - function[i].type->getQualifier().layoutLocation = inCount; + TType& paramType = *function[i].type; + if (paramType.getQualifier().isParamInput()) { + paramType.getQualifier().storage = EvqVaryingIn; + if (paramType.getQualifier().builtIn == EbvNone) { + paramType.getQualifier().layoutLocation = inCount; inCount += intermediate.computeTypeLocationSize(*function[i].type); } } else { - function[i].type->getQualifier().storage = EvqVaryingOut; - if (function[i].type->getQualifier().builtIn == EbvNone && language != EShLangFragment) { - function[i].type->getQualifier().layoutLocation = outCount; + paramType.getQualifier().storage = EvqVaryingOut; + if (paramType.getQualifier().builtIn == EbvNone) { + paramType.getQualifier().layoutLocation = outCount; outCount += intermediate.computeTypeLocationSize(*function[i].type); } } - remapBuiltInType(*function[i].type); + remapBuiltInType(paramType); } } diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index f422b3e..1e43dea 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -83,6 +83,9 @@ public: TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + bool shouldFlatten(const TType&); + void flattenStruct(const TVariable& variable); + TIntermTyped* flattenAccess(TIntermTyped* base, int member); TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); @@ -233,6 +236,8 @@ protected: // array-sizing declarations // TVector ioArraySymbolResizeList; + + TMap> flattenMap; }; } // end namespace glslang