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