Merge pull request #1567 from Igalia/apinheiro/xfb-1535
ParseHelper: assign global XfbBuffer to a block missing it
diff --git a/Test/baseResults/spv.xfbOffsetOnBlockMembersAssignment.vert.out b/Test/baseResults/spv.xfbOffsetOnBlockMembersAssignment.vert.out
new file mode 100644
index 0000000..066aa3a
--- /dev/null
+++ b/Test/baseResults/spv.xfbOffsetOnBlockMembersAssignment.vert.out
@@ -0,0 +1,76 @@
+spv.xfbOffsetOnBlockMembersAssignment.vert
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 33
+
+ Capability Shader
+ Capability TransformFeedback
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main" 10 27 31 32
+ ExecutionMode 4 Xfb
+ Source GLSL 450
+ Name 4 "main"
+ Name 8 "block2"
+ MemberName 8(block2) 0 "y1_out"
+ MemberName 8(block2) 1 "y2_out"
+ Name 10 ""
+ Name 25 "gl_PerVertex"
+ MemberName 25(gl_PerVertex) 0 "gl_Position"
+ MemberName 25(gl_PerVertex) 1 "gl_PointSize"
+ MemberName 25(gl_PerVertex) 2 "gl_ClipDistance"
+ MemberName 25(gl_PerVertex) 3 "gl_CullDistance"
+ Name 27 ""
+ Name 31 "gl_VertexID"
+ Name 32 "gl_InstanceID"
+ MemberDecorate 8(block2) 0 Offset 0
+ MemberDecorate 8(block2) 1 Offset 4
+ Decorate 8(block2) Block
+ Decorate 10 Location 5
+ Decorate 10 XfbBuffer 2
+ Decorate 10 XfbStride 20
+ MemberDecorate 25(gl_PerVertex) 0 BuiltIn Position
+ MemberDecorate 25(gl_PerVertex) 1 BuiltIn PointSize
+ MemberDecorate 25(gl_PerVertex) 2 BuiltIn ClipDistance
+ MemberDecorate 25(gl_PerVertex) 3 BuiltIn CullDistance
+ Decorate 25(gl_PerVertex) Block
+ Decorate 27 XfbBuffer 0
+ Decorate 27 XfbStride 0
+ Decorate 31(gl_VertexID) BuiltIn VertexId
+ Decorate 32(gl_InstanceID) BuiltIn InstanceId
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8(block2): TypeStruct 6(float) 7(fvec4)
+ 9: TypePointer Output 8(block2)
+ 10: 9(ptr) Variable Output
+ 11: TypeInt 32 1
+ 12: 11(int) Constant 0
+ 13: 6(float) Constant 1088421888
+ 14: TypePointer Output 6(float)
+ 16: 11(int) Constant 1
+ 17: 6(float) Constant 1065353216
+ 18: 6(float) Constant 0
+ 19: 7(fvec4) ConstantComposite 17 18 18 17
+ 20: TypePointer Output 7(fvec4)
+ 22: TypeInt 32 0
+ 23: 22(int) Constant 1
+ 24: TypeArray 6(float) 23
+25(gl_PerVertex): TypeStruct 7(fvec4) 6(float) 24 24
+ 26: TypePointer Output 25(gl_PerVertex)
+ 27: 26(ptr) Variable Output
+ 28: 7(fvec4) ConstantComposite 18 18 18 18
+ 30: TypePointer Input 11(int)
+ 31(gl_VertexID): 30(ptr) Variable Input
+32(gl_InstanceID): 30(ptr) Variable Input
+ 4(main): 2 Function None 3
+ 5: Label
+ 15: 14(ptr) AccessChain 10 12
+ Store 15 13
+ 21: 20(ptr) AccessChain 10 16
+ Store 21 19
+ 29: 20(ptr) AccessChain 27 12
+ Store 29 28
+ Return
+ FunctionEnd
diff --git a/Test/baseResults/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert.out b/Test/baseResults/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert.out
new file mode 100644
index 0000000..ebc4962
--- /dev/null
+++ b/Test/baseResults/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert.out
@@ -0,0 +1,88 @@
+spv.xfbOverlapOffsetCheckWithBlockAndMember.vert
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 39
+
+ Capability Shader
+ Capability TransformFeedback
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main" 10 33 37 38
+ ExecutionMode 4 Xfb
+ Source GLSL 450
+ Name 4 "main"
+ Name 8 "block2"
+ MemberName 8(block2) 0 "v"
+ MemberName 8(block2) 1 "u"
+ MemberName 8(block2) 2 "w"
+ MemberName 8(block2) 3 "x"
+ Name 10 ""
+ Name 31 "gl_PerVertex"
+ MemberName 31(gl_PerVertex) 0 "gl_Position"
+ MemberName 31(gl_PerVertex) 1 "gl_PointSize"
+ MemberName 31(gl_PerVertex) 2 "gl_ClipDistance"
+ MemberName 31(gl_PerVertex) 3 "gl_CullDistance"
+ Name 33 ""
+ Name 37 "gl_VertexID"
+ Name 38 "gl_InstanceID"
+ MemberDecorate 8(block2) 0 Offset 12
+ MemberDecorate 8(block2) 1 Offset 28
+ MemberDecorate 8(block2) 2 Offset 40
+ MemberDecorate 8(block2) 3 Offset 56
+ Decorate 8(block2) Block
+ Decorate 10 Location 5
+ Decorate 10 XfbBuffer 3
+ Decorate 10 XfbStride 72
+ MemberDecorate 31(gl_PerVertex) 0 BuiltIn Position
+ MemberDecorate 31(gl_PerVertex) 1 BuiltIn PointSize
+ MemberDecorate 31(gl_PerVertex) 2 BuiltIn ClipDistance
+ MemberDecorate 31(gl_PerVertex) 3 BuiltIn CullDistance
+ Decorate 31(gl_PerVertex) Block
+ Decorate 33 XfbBuffer 0
+ Decorate 33 XfbStride 0
+ Decorate 37(gl_VertexID) BuiltIn VertexId
+ Decorate 38(gl_InstanceID) BuiltIn InstanceId
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8(block2): TypeStruct 7(fvec4) 6(float) 7(fvec4) 7(fvec4)
+ 9: TypePointer Output 8(block2)
+ 10: 9(ptr) Variable Output
+ 11: TypeInt 32 1
+ 12: 11(int) Constant 0
+ 13: 6(float) Constant 1065353216
+ 14: 6(float) Constant 0
+ 15: 7(fvec4) ConstantComposite 13 14 13 14
+ 16: TypePointer Output 7(fvec4)
+ 18: 11(int) Constant 1
+ 19: 6(float) Constant 1084227584
+ 20: TypePointer Output 6(float)
+ 22: 11(int) Constant 2
+ 23: 7(fvec4) ConstantComposite 13 14 14 13
+ 25: 11(int) Constant 3
+ 26: 7(fvec4) ConstantComposite 19 14 14 14
+ 28: TypeInt 32 0
+ 29: 28(int) Constant 1
+ 30: TypeArray 6(float) 29
+31(gl_PerVertex): TypeStruct 7(fvec4) 6(float) 30 30
+ 32: TypePointer Output 31(gl_PerVertex)
+ 33: 32(ptr) Variable Output
+ 34: 7(fvec4) ConstantComposite 14 14 14 14
+ 36: TypePointer Input 11(int)
+ 37(gl_VertexID): 36(ptr) Variable Input
+38(gl_InstanceID): 36(ptr) Variable Input
+ 4(main): 2 Function None 3
+ 5: Label
+ 17: 16(ptr) AccessChain 10 12
+ Store 17 15
+ 21: 20(ptr) AccessChain 10 18
+ Store 21 19
+ 24: 16(ptr) AccessChain 10 22
+ Store 24 23
+ 27: 16(ptr) AccessChain 10 25
+ Store 27 26
+ 35: 16(ptr) AccessChain 33 12
+ Store 35 34
+ Return
+ FunctionEnd
diff --git a/Test/spv.xfbOffsetOnBlockMembersAssignment.vert b/Test/spv.xfbOffsetOnBlockMembersAssignment.vert
new file mode 100644
index 0000000..40943f7
--- /dev/null
+++ b/Test/spv.xfbOffsetOnBlockMembersAssignment.vert
@@ -0,0 +1,13 @@
+#version 450
+
+layout(xfb_buffer=2) out;
+layout(location=5, xfb_offset=0) out block2 {
+ float y1_out;
+ vec4 y2_out;
+};
+
+void main() {
+ y1_out = 7.0;
+ y2_out = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_Position = vec4(0.0);
+}
diff --git a/Test/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert b/Test/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert
new file mode 100644
index 0000000..3f493dc
--- /dev/null
+++ b/Test/spv.xfbOverlapOffsetCheckWithBlockAndMember.vert
@@ -0,0 +1,19 @@
+#version 450
+
+/* block definition from GLSL spec 4.60, section 4.4.2, Output Layout Qualifiers */
+
+layout(location=5, xfb_buffer = 3, xfb_offset = 12) out block2 {
+ vec4 v; // v will be written to byte offsets 12 through 27 of buffer
+ float u; // u will be written to offset 28
+ layout(xfb_offset = 40) vec4 w;
+ vec4 x; // x will be written to offset 56, the next available offset
+};
+
+void main() {
+ v = vec4(1.0, 0.0, 1.0, 0.0);
+ u = 5.0;
+ w = vec4(1.0, 0.0, 0.0, 1.0);
+ x = vec4(5.0, 0.0, 0.0, 0.0);
+
+ gl_Position = vec4(0.0);
+}
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 5d1ff9e..67a861f 100755
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -6873,6 +6873,16 @@
layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes);
+ // Ensure that the block has an XfbBuffer assigned. This is needed
+ // because if the block has a XfbOffset assigned, then it is
+ // assumed that it has implicitly assigned the current global
+ // XfbBuffer, and because it's members need to be assigned a
+ // XfbOffset if they lack it.
+ if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
+ if (!currentBlockQualifier.hasXfbBuffer() && currentBlockQualifier.hasXfbOffset())
+ currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ }
+
// Process the members
fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
fixXfbOffsets(currentBlockQualifier, typeList);
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index efb8967..66780f7 100755
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -447,7 +447,9 @@
"spv.rankShift.comp",
"spv.specConst.vert",
"spv.OVR_multiview.vert",
+ "spv.xfbOffsetOnBlockMembersAssignment.vert",
"spv.xfbOffsetOnStructMembersAssignment.vert",
+ "spv.xfbOverlapOffsetCheckWithBlockAndMember.vert",
})),
FileNameAsCustomTestSuffix
);