diff --git a/Test/baseResults/spv.xfbOffsetOnStructMembersAssignment.vert.out b/Test/baseResults/spv.xfbOffsetOnStructMembersAssignment.vert.out new file mode 100644 index 000000000..7eb459342 --- /dev/null +++ b/Test/baseResults/spv.xfbOffsetOnStructMembersAssignment.vert.out @@ -0,0 +1,93 @@ +spv.xfbOffsetOnStructMembersAssignment.vert +// Module Version 10000 +// Generated by (magic number): 80007 +// Id's are bound by 40 + + Capability Shader + Capability TransformFeedback + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 9 21 34 38 39 + ExecutionMode 4 Xfb + Source GLSL 450 + Name 4 "main" + Name 7 "S" + MemberName 7(S) 0 "x1_out" + MemberName 7(S) 1 "x2_out" + Name 9 "s1" + Name 19 "S2" + MemberName 19(S2) 0 "y1_out" + MemberName 19(S2) 1 "y2_out" + Name 21 "s2" + Name 32 "gl_PerVertex" + MemberName 32(gl_PerVertex) 0 "gl_Position" + MemberName 32(gl_PerVertex) 1 "gl_PointSize" + MemberName 32(gl_PerVertex) 2 "gl_ClipDistance" + MemberName 32(gl_PerVertex) 3 "gl_CullDistance" + Name 34 "" + Name 38 "gl_VertexID" + Name 39 "gl_InstanceID" + MemberDecorate 7(S) 0 Offset 16 + MemberDecorate 7(S) 1 Offset 20 + Decorate 9(s1) Location 0 + Decorate 9(s1) XfbBuffer 2 + Decorate 9(s1) XfbStride 24 + MemberDecorate 19(S2) 0 Offset 8 + MemberDecorate 19(S2) 1 Offset 12 + Decorate 21(s2) Location 5 + Decorate 21(s2) XfbBuffer 1 + Decorate 21(s2) XfbStride 28 + MemberDecorate 32(gl_PerVertex) 0 BuiltIn Position + MemberDecorate 32(gl_PerVertex) 1 BuiltIn PointSize + MemberDecorate 32(gl_PerVertex) 2 BuiltIn ClipDistance + MemberDecorate 32(gl_PerVertex) 3 BuiltIn CullDistance + Decorate 32(gl_PerVertex) Block + Decorate 34 XfbBuffer 0 + Decorate 34 XfbStride 0 + Decorate 38(gl_VertexID) BuiltIn VertexId + Decorate 39(gl_InstanceID) BuiltIn InstanceId + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7(S): TypeStruct 6(float) 6(float) + 8: TypePointer Output 7(S) + 9(s1): 8(ptr) Variable Output + 10: TypeInt 32 1 + 11: 10(int) Constant 0 + 12: 6(float) Constant 1084227584 + 13: TypePointer Output 6(float) + 15: 10(int) Constant 1 + 16: 6(float) Constant 1086324736 + 18: TypeVector 6(float) 4 + 19(S2): TypeStruct 6(float) 18(fvec4) + 20: TypePointer Output 19(S2) + 21(s2): 20(ptr) Variable Output + 22: 6(float) Constant 1088421888 + 24: 6(float) Constant 1065353216 + 25: 6(float) Constant 0 + 26: 18(fvec4) ConstantComposite 24 25 25 24 + 27: TypePointer Output 18(fvec4) + 29: TypeInt 32 0 + 30: 29(int) Constant 1 + 31: TypeArray 6(float) 30 +32(gl_PerVertex): TypeStruct 18(fvec4) 6(float) 31 31 + 33: TypePointer Output 32(gl_PerVertex) + 34: 33(ptr) Variable Output + 35: 18(fvec4) ConstantComposite 25 25 25 25 + 37: TypePointer Input 10(int) + 38(gl_VertexID): 37(ptr) Variable Input +39(gl_InstanceID): 37(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + 14: 13(ptr) AccessChain 9(s1) 11 + Store 14 12 + 17: 13(ptr) AccessChain 9(s1) 15 + Store 17 16 + 23: 13(ptr) AccessChain 21(s2) 11 + Store 23 22 + 28: 27(ptr) AccessChain 21(s2) 15 + Store 28 26 + 36: 27(ptr) AccessChain 34 11 + Store 36 35 + Return + FunctionEnd diff --git a/Test/spv.xfbOffsetOnStructMembersAssignment.vert b/Test/spv.xfbOffsetOnStructMembersAssignment.vert new file mode 100644 index 000000000..e6619c582 --- /dev/null +++ b/Test/spv.xfbOffsetOnStructMembersAssignment.vert @@ -0,0 +1,23 @@ +#version 450 + +layout(xfb_buffer=2) out; + +struct S { + float x1_out; + float x2_out; +}; + +layout(location=0, xfb_offset = 16) out S s1; + +layout(location=5, xfb_buffer=1, xfb_offset=8) out struct S2 { + float y1_out; + vec4 y2_out; +}s2; + +void main() { + s1.x1_out = 5.0; + s1.x2_out = 6.0; + s2.y1_out = 7.0; + s2.y2_out = vec4(1.0, 0.0, 0.0, 1.0); + gl_Position = vec4(0.0); +} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 3063d372e..574c6f0c0 100755 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -4030,7 +4030,7 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { if (!currentBlockQualifier.hasXfbBuffer()) currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - fixBlockXfbOffsets(currentBlockQualifier, newTypeList); + fixXfbOffsets(currentBlockQualifier, newTypeList); } // Edit and error check the container against the redeclaration @@ -6099,6 +6099,11 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden // fix up fixOffset(loc, *symbol); + if (symbol->getType().getBasicType() == EbtStruct) { + fixXfbOffsets(symbol->getWritableType().getQualifier(), + *(symbol->getWritableType().getWritableStruct())); + } + return initNode; } @@ -6823,7 +6828,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con // Process the members fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); - fixBlockXfbOffsets(currentBlockQualifier, typeList); + fixXfbOffsets(currentBlockQualifier, typeList); fixBlockUniformOffsets(currentBlockQualifier, typeList); for (unsigned int member = 0; member < typeList.size(); ++member) layoutTypeCheck(typeList[member].loc, *typeList[member].type); @@ -7065,7 +7070,7 @@ void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifi } } -void TParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList) +void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) { // "If a block is qualified with xfb_offset, all its // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index b513f4978..14421a267 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -403,7 +403,7 @@ public: void blockStageIoCheck(const TSourceLoc&, const TQualifier&); void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); - void fixBlockXfbOffsets(TQualifier&, TTypeList&); + void fixXfbOffsets(TQualifier&, TTypeList&); void fixBlockUniformOffsets(TQualifier&, TTypeList&); void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 5f03ac1f1..f0132f181 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -440,6 +440,7 @@ INSTANTIATE_TEST_CASE_P( "spv.rankShift.comp", "spv.specConst.vert", "spv.OVR_multiview.vert", + "spv.xfbOffsetOnStructMembersAssignment.vert", })), FileNameAsCustomTestSuffix ); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 135e1d288..ac2943284 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -8555,7 +8555,7 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS // Process the members fixBlockLocations(loc, type.getQualifier(), typeList, memberWithLocation, memberWithoutLocation); - fixBlockXfbOffsets(type.getQualifier(), typeList); + fixXfbOffsets(type.getQualifier(), typeList); fixBlockUniformOffsets(type.getQualifier(), typeList); // reverse merge, so that currentBlockQualifier now has all layout information @@ -8638,7 +8638,7 @@ void HlslParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qual } } -void HlslParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList) +void HlslParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) { // "If a block is qualified with xfb_offset, all its // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 7cb898cf4..f99d5c73f 100644 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -155,7 +155,7 @@ public: void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0); void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); - void fixBlockXfbOffsets(TQualifier&, TTypeList&); + void fixXfbOffsets(TQualifier&, TTypeList&); void fixBlockUniformOffsets(const TQualifier&, TTypeList&); void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);