ParseHelper: assign xfb_offset for struct members too

If the out variable is a struct type, with a xfb_offset explicitly
assigned, the members need to get their xfb_offset assigned. This is
specially relevant, as we cannot use layout qualifiers on struct
members.
This commit is contained in:
Alejandro Piñeiro 2018-10-26 12:35:54 +02:00
parent 0ac199df32
commit af8c1bdb16
7 changed files with 129 additions and 7 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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&);

View File

@ -440,6 +440,7 @@ INSTANTIATE_TEST_CASE_P(
"spv.rankShift.comp",
"spv.specConst.vert",
"spv.OVR_multiview.vert",
"spv.xfbOffsetOnStructMembersAssignment.vert",
})),
FileNameAsCustomTestSuffix
);

View File

@ -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

View File

@ -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&);