From a5d8616478077d7af6f1d28e04b220a7a2f3fca7 Mon Sep 17 00:00:00 2001 From: LoopDawg <sk_opengl@khasekhemwy.net> Date: Sun, 10 Sep 2017 09:46:55 -0600 Subject: [PATCH] HLSL: allow mixed user & builtin members in hull shader output structure Hull shaders have an implicitly arrayed output. This is handled by creating an arrayed form of the provided output type, and writing to the element of it indexed by InvocationID. The implicit indirection into that array was causing some troubles when copying to a split structure. handleAssign was able to handle simple symbol lvalues, but not an lvalue composed of an indirection into an array. --- SPIRV/GlslangToSpv.cpp | 2 +- Test/baseResults/hlsl.hull.1.tesc.out | 4 +- Test/baseResults/hlsl.hull.2.tesc.out | 4 +- Test/baseResults/hlsl.hull.3.tesc.out | 4 +- Test/baseResults/hlsl.hull.4.tesc.out | 241 +++++++++++++++++++ Test/baseResults/hlsl.hull.ctrlpt-1.tesc.out | 4 +- Test/baseResults/hlsl.hull.ctrlpt-2.tesc.out | 4 +- Test/baseResults/hlsl.hull.void.tesc.out | 4 +- Test/hlsl.hull.4.tesc | 17 ++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslParseHelper.cpp | 45 +++- 11 files changed, 310 insertions(+), 20 deletions(-) create mode 100644 Test/baseResults/hlsl.hull.4.tesc.out create mode 100644 Test/hlsl.hull.4.tesc diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 625dcd7bc..40f7508e4 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3555,7 +3555,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg const glslang::TIntermSequence& glslangArgs = node->getSequence(); const glslang::TQualifierList& qualifiers = node->getQualifierList(); - // Encapsulate lvalue logic, used in two places below, for safety. + // Encapsulate lvalue logic, used in several places below, for safety. const auto isLValue = [](int qualifier, const glslang::TType& paramType) -> bool { return qualifier != glslang::EvqConstReadOnly || paramType.containsOpaque(); }; diff --git a/Test/baseResults/hlsl.hull.1.tesc.out b/Test/baseResults/hlsl.hull.1.tesc.out index 151a0b397..ebfaf5997 100644 --- a/Test/baseResults/hlsl.hull.1.tesc.out +++ b/Test/baseResults/hlsl.hull.1.tesc.out @@ -32,7 +32,7 @@ vertex spacing = equal_spacing 0:? 'm_cpid' ( temp uint) 0:? 'm_cpid' ( in uint InvocationID) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'm_cpid' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint}) @@ -146,7 +146,7 @@ vertex spacing = equal_spacing 0:? 'm_cpid' ( temp uint) 0:? 'm_cpid' ( in uint InvocationID) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'm_cpid' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4];u1; ( temp structure{ temp 3-component vector of float cpoint}) diff --git a/Test/baseResults/hlsl.hull.2.tesc.out b/Test/baseResults/hlsl.hull.2.tesc.out index 11342eaca..d4d75b35f 100644 --- a/Test/baseResults/hlsl.hull.2.tesc.out +++ b/Test/baseResults/hlsl.hull.2.tesc.out @@ -28,7 +28,7 @@ vertex spacing = equal_spacing 0:? 'ip' ( temp 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 4-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) @@ -140,7 +140,7 @@ vertex spacing = equal_spacing 0:? 'ip' ( temp 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 4-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) diff --git a/Test/baseResults/hlsl.hull.3.tesc.out b/Test/baseResults/hlsl.hull.3.tesc.out index 39d923684..eecb6c81a 100755 --- a/Test/baseResults/hlsl.hull.3.tesc.out +++ b/Test/baseResults/hlsl.hull.3.tesc.out @@ -28,7 +28,7 @@ vertex spacing = equal_spacing 0:? 'ip' ( temp 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 4-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) @@ -140,7 +140,7 @@ vertex spacing = equal_spacing 0:? 'ip' ( temp 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 4-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 4-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[4]; ( temp structure{ temp 3-component vector of float cpoint}) diff --git a/Test/baseResults/hlsl.hull.4.tesc.out b/Test/baseResults/hlsl.hull.4.tesc.out new file mode 100644 index 000000000..9bce2518c --- /dev/null +++ b/Test/baseResults/hlsl.hull.4.tesc.out @@ -0,0 +1,241 @@ +hlsl.hull.4.tesc +Shader version: 500 +vertices = 3 +0:? Sequence +0:14 Function Definition: @main( ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Parameters: +0:? Sequence +0:15 Sequence +0:15 move second child to first child ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:15 'output' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:15 Constant: +0:15 0.000000 +0:15 0.000000 +0:15 0.000000 +0:15 0.000000 +0:16 Branch: Return with expression +0:16 'output' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Definition: main( ( temp void) +0:14 Function Parameters: +0:? Sequence +0:14 Sequence +0:14 move second child to first child ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Call: @main( ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 0 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 0 (const int) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 1 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 1 (const int) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 2 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 2 (const int) +0:14 move second child to first child ( temp float) +0:14 coord: direct index for structure ( temp float) +0:14 indirect index (layout( location=0) out structure{ temp float coord}) +0:14 '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp float coord}) +0:? 'InvocationId' ( in uint InvocationID) +0:14 Constant: +0:14 0 (const int) +0:14 coord: direct index for structure ( temp float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 1 (const int) +0:? Linker Objects +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp float coord}) +0:? 'InvocationId' ( in uint InvocationID) + + +Linked tessellation control stage: + + +Shader version: 500 +vertices = 3 +0:? Sequence +0:14 Function Definition: @main( ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Parameters: +0:? Sequence +0:15 Sequence +0:15 move second child to first child ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:15 'output' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:15 Constant: +0:15 0.000000 +0:15 0.000000 +0:15 0.000000 +0:15 0.000000 +0:16 Branch: Return with expression +0:16 'output' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Definition: main( ( temp void) +0:14 Function Parameters: +0:? Sequence +0:14 Sequence +0:14 move second child to first child ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Function Call: @main( ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 0 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 0 (const int) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 1 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 1 (const int) +0:14 move second child to first child ( temp float) +0:14 direct index ( patch out float TessLevelOuter) +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:14 Constant: +0:14 2 (const int) +0:14 direct index ( temp float) +0:14 tessFactor: direct index for structure ( temp 3-element array of float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 0 (const int) +0:14 Constant: +0:14 2 (const int) +0:14 move second child to first child ( temp float) +0:14 coord: direct index for structure ( temp float) +0:14 indirect index (layout( location=0) out structure{ temp float coord}) +0:14 '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp float coord}) +0:? 'InvocationId' ( in uint InvocationID) +0:14 Constant: +0:14 0 (const int) +0:14 coord: direct index for structure ( temp float) +0:14 'flattenTemp' ( temp structure{ temp 3-element array of float tessFactor, temp float coord}) +0:14 Constant: +0:14 1 (const int) +0:? Linker Objects +0:? '@entryPointOutput.tessFactor' ( patch out 4-element array of float TessLevelOuter) +0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp float coord}) +0:? 'InvocationId' ( in uint InvocationID) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 53 + + Capability Tessellation + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint TessellationControl 4 "main" 27 46 48 + ExecutionMode 4 OutputVertices 3 + ExecutionMode 4 Triangles + Source HLSL 500 + Name 4 "main" + Name 10 "HS_Output" + MemberName 10(HS_Output) 0 "tessFactor" + MemberName 10(HS_Output) 1 "coord" + Name 12 "@main(" + Name 15 "output" + Name 22 "flattenTemp" + Name 27 "@entryPointOutput.tessFactor" + Name 43 "HS_Output" + MemberName 43(HS_Output) 0 "coord" + Name 46 "@entryPointOutput" + Name 48 "InvocationId" + Decorate 27(@entryPointOutput.tessFactor) Patch + Decorate 27(@entryPointOutput.tessFactor) BuiltIn TessLevelOuter + Decorate 46(@entryPointOutput) Location 0 + Decorate 48(InvocationId) BuiltIn InvocationId + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeInt 32 0 + 8: 7(int) Constant 3 + 9: TypeArray 6(float) 8 + 10(HS_Output): TypeStruct 9 6(float) + 11: TypeFunction 10(HS_Output) + 14: TypePointer Function 10(HS_Output) + 16: 6(float) Constant 0 + 17: 9 ConstantComposite 16 16 16 + 18:10(HS_Output) ConstantComposite 17 16 + 24: 7(int) Constant 4 + 25: TypeArray 6(float) 24 + 26: TypePointer Output 25 +27(@entryPointOutput.tessFactor): 26(ptr) Variable Output + 28: TypeInt 32 1 + 29: 28(int) Constant 0 + 30: TypePointer Function 6(float) + 33: TypePointer Output 6(float) + 35: 28(int) Constant 1 + 39: 28(int) Constant 2 + 43(HS_Output): TypeStruct 6(float) + 44: TypeArray 43(HS_Output) 8 + 45: TypePointer Output 44 +46(@entryPointOutput): 45(ptr) Variable Output + 47: TypePointer Input 7(int) +48(InvocationId): 47(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + 22(flattenTemp): 14(ptr) Variable Function + 23:10(HS_Output) FunctionCall 12(@main() + Store 22(flattenTemp) 23 + 31: 30(ptr) AccessChain 22(flattenTemp) 29 29 + 32: 6(float) Load 31 + 34: 33(ptr) AccessChain 27(@entryPointOutput.tessFactor) 29 + Store 34 32 + 36: 30(ptr) AccessChain 22(flattenTemp) 29 35 + 37: 6(float) Load 36 + 38: 33(ptr) AccessChain 27(@entryPointOutput.tessFactor) 35 + Store 38 37 + 40: 30(ptr) AccessChain 22(flattenTemp) 29 39 + 41: 6(float) Load 40 + 42: 33(ptr) AccessChain 27(@entryPointOutput.tessFactor) 39 + Store 42 41 + 49: 7(int) Load 48(InvocationId) + 50: 30(ptr) AccessChain 22(flattenTemp) 35 + 51: 6(float) Load 50 + 52: 33(ptr) AccessChain 46(@entryPointOutput) 49 29 + Store 52 51 + Return + FunctionEnd + 12(@main():10(HS_Output) Function None 11 + 13: Label + 15(output): 14(ptr) Variable Function + Store 15(output) 18 + 19:10(HS_Output) Load 15(output) + ReturnValue 19 + FunctionEnd diff --git a/Test/baseResults/hlsl.hull.ctrlpt-1.tesc.out b/Test/baseResults/hlsl.hull.ctrlpt-1.tesc.out index 7fbe0cb50..9ccd7e3d0 100644 --- a/Test/baseResults/hlsl.hull.ctrlpt-1.tesc.out +++ b/Test/baseResults/hlsl.hull.ctrlpt-1.tesc.out @@ -29,7 +29,7 @@ triangle order = cw 0:? 'cpid' ( temp uint) 0:? 'cpid' ( in uint InvocationID) 0:27 move second child to first child ( temp structure{ temp 3-component vector of float val}) -0:27 indirect index ( temp structure{ temp 3-component vector of float val}) +0:27 indirect index (layout( location=0) out structure{ temp 3-component vector of float val}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float val}) 0:? 'cpid' ( in uint InvocationID) 0:27 Function Call: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) @@ -229,7 +229,7 @@ triangle order = cw 0:? 'cpid' ( temp uint) 0:? 'cpid' ( in uint InvocationID) 0:27 move second child to first child ( temp structure{ temp 3-component vector of float val}) -0:27 indirect index ( temp structure{ temp 3-component vector of float val}) +0:27 indirect index (layout( location=0) out structure{ temp 3-component vector of float val}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float val}) 0:? 'cpid' ( in uint InvocationID) 0:27 Function Call: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) diff --git a/Test/baseResults/hlsl.hull.ctrlpt-2.tesc.out b/Test/baseResults/hlsl.hull.ctrlpt-2.tesc.out index 32764f30b..b8e1562ab 100644 --- a/Test/baseResults/hlsl.hull.ctrlpt-2.tesc.out +++ b/Test/baseResults/hlsl.hull.ctrlpt-2.tesc.out @@ -36,7 +36,7 @@ triangle order = cw 0:? 'cpid' ( temp uint) 0:? 'cpid' ( in uint InvocationID) 0:28 move second child to first child ( temp structure{ temp 3-component vector of float val}) -0:28 indirect index ( temp structure{ temp 3-component vector of float val}) +0:28 indirect index (layout( location=0) out structure{ temp 3-component vector of float val}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float val}) 0:? 'cpid' ( in uint InvocationID) 0:28 Function Call: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) @@ -245,7 +245,7 @@ triangle order = cw 0:? 'cpid' ( temp uint) 0:? 'cpid' ( in uint InvocationID) 0:28 move second child to first child ( temp structure{ temp 3-component vector of float val}) -0:28 indirect index ( temp structure{ temp 3-component vector of float val}) +0:28 indirect index (layout( location=0) out structure{ temp 3-component vector of float val}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float val}) 0:? 'cpid' ( in uint InvocationID) 0:28 Function Call: @main(struct-hs_in_t-vf31[3];u1; ( temp structure{ temp 3-component vector of float val}) diff --git a/Test/baseResults/hlsl.hull.void.tesc.out b/Test/baseResults/hlsl.hull.void.tesc.out index 8dc38fcd0..412923594 100644 --- a/Test/baseResults/hlsl.hull.void.tesc.out +++ b/Test/baseResults/hlsl.hull.void.tesc.out @@ -29,7 +29,7 @@ triangle order = ccw 0:? 'ip' ( temp 3-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 3-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint}) @@ -85,7 +85,7 @@ triangle order = ccw 0:? 'ip' ( temp 3-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'ip' (layout( location=0) in 3-element array of structure{ temp 3-component vector of float cpoint}) 0:26 move second child to first child ( temp structure{ temp 3-component vector of float cpoint}) -0:26 indirect index ( temp structure{ temp 3-component vector of float cpoint}) +0:26 indirect index (layout( location=0) out structure{ temp 3-component vector of float cpoint}) 0:? '@entryPointOutput' (layout( location=0) out 3-element array of structure{ temp 3-component vector of float cpoint}) 0:? 'InvocationId' ( in uint InvocationID) 0:26 Function Call: @main(struct-VS_OUT-vf31[3]; ( temp structure{ temp 3-component vector of float cpoint}) diff --git a/Test/hlsl.hull.4.tesc b/Test/hlsl.hull.4.tesc new file mode 100644 index 000000000..93b7e7153 --- /dev/null +++ b/Test/hlsl.hull.4.tesc @@ -0,0 +1,17 @@ + +// Test mixed output structure: user and builtin members. Hull shaders involve extra +// logic in this case, over and above e.g. pixel or vertex stages, which is related to +// the implicit array dimension. +struct HS_Output +{ + float tessFactor[3] : SV_TessFactor; + float coord : TEXCOORD0; +}; + +[domain("tri")] +[outputcontrolpoints(3)] +HS_Output main ( ) +{ + HS_Output output = (HS_Output)0; + return output; +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 4dfe7d797..c07e26247 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -164,6 +164,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.hull.1.tesc", "main"}, {"hlsl.hull.2.tesc", "main"}, {"hlsl.hull.3.tesc", "main"}, + {"hlsl.hull.4.tesc", "main"}, {"hlsl.hull.void.tesc", "main"}, {"hlsl.hull.ctrlpt-1.tesc", "main"}, {"hlsl.hull.ctrlpt-2.tesc", "main"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 2ed252cd5..2aac482d6 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -2039,7 +2039,10 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct TIntermTyped* element = intermediate.addIndex(EOpIndexIndirect, intermediate.addSymbol(*entryPointOutput), invocationIdSym, loc); - element->setType(callReturn->getType()); + + // Set the type of the array element being dereferenced + const TType derefElementType(entryPointOutput->getType(), 0); + element->setType(derefElementType); returnAssign = handleAssign(loc, EOpAssign, element, callReturn); } else { @@ -2561,14 +2564,25 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op if (left->getAsOperator() && left->getAsOperator()->getOp() == EOpMatrixSwizzle) return handleAssignToMatrixSwizzle(loc, op, left, right); - const bool isSplitLeft = wasSplit(left); - const bool isSplitRight = wasSplit(right); + // Return true if the given node is an index operation into a split variable. + const auto indexesSplit = [this](const TIntermTyped* node) -> bool { + const TIntermBinary* binaryNode = node->getAsBinaryNode(); + + if (binaryNode == nullptr) + return false; + + return (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect) && + wasSplit(binaryNode->getLeft()); + }; + + const bool isSplitLeft = wasSplit(left) || indexesSplit(left); + const bool isSplitRight = wasSplit(right) || indexesSplit(right); const bool isFlattenLeft = wasFlattened(left); const bool isFlattenRight = wasFlattened(right); - // OK to do a single assign if both are split, or both are unsplit. But if one is and the other - // isn't, we fall back to a member-wise copy. + // OK to do a single assign if neither side is split or flattened. Otherwise, + // fall through to a member-wise copy. if (!isFlattenLeft && !isFlattenRight && !isSplitLeft && !isSplitRight) { // Clip and cull distance requires more processing. See comment above assignClipCullDistance. if (isClipOrCullDistance(left->getType()) || isClipOrCullDistance(right->getType())) { @@ -2803,8 +2817,25 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op // If either left or right was a split structure, we must read or write it, but still have to // parallel-recurse through the unsplit structure to identify the built-in IO vars. - if (isSplitLeft) - splitLeft = intermediate.addSymbol(*getSplitNonIoVar(left->getAsSymbolNode()->getId()), loc); + // The left can be either a symbol, or an index into a symbol (e.g, array reference) + if (isSplitLeft) { + if (indexesSplit(left)) { + // Index case: Refer to the indexed symbol, if the left is an index operator. + const TIntermSymbol* symNode = left->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + + TIntermTyped* splitLeftNonIo = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); + + splitLeft = intermediate.addIndex(left->getAsBinaryNode()->getOp(), splitLeftNonIo, + left->getAsBinaryNode()->getRight(), loc); + + const TType derefType(splitLeftNonIo->getType(), 0); + splitLeft->setType(derefType); + } else { + // Symbol case: otherwise, if not indexed, we have the symbol directly. + const TIntermSymbol* symNode = left->getAsSymbolNode(); + splitLeft = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); + } + } if (isSplitRight) splitRight = intermediate.addSymbol(*getSplitNonIoVar(right->getAsSymbolNode()->getId()), loc); -- GitLab