Merge pull request #2781 from kevin-mccullough/FixLinkTimeValidationForGl_PerVertex

Fix incorrect link time validation for unused gl_PerVertex members
diff --git a/Test/baseResults/link.redeclareBuiltin.vert.out b/Test/baseResults/link.redeclareBuiltin.vert.out
new file mode 100644
index 0000000..2cd42b9
--- /dev/null
+++ b/Test/baseResults/link.redeclareBuiltin.vert.out
@@ -0,0 +1,154 @@
+link.redeclareBuiltin.vert
+Shader version: 410
+0:? Sequence
+0:8  Function Definition: main( ( global void)
+0:8    Function Parameters: 
+0:10    Sequence
+0:10      move second child to first child ( temp 4-component vector of float)
+0:10        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:10          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position})
+0:10          Constant:
+0:10            0 (const uint)
+0:10        Constant:
+0:10          1.000000
+0:10          1.000000
+0:10          1.000000
+0:10          1.000000
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.redeclareBuiltin.geom
+Shader version: 410
+invocations = -1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      move second child to first child ( temp 4-component vector of float)
+0:13        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:13          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:13          Constant:
+0:13            0 (const uint)
+0:13        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:13          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:13            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:13            Constant:
+0:13              0 (const int)
+0:13          Constant:
+0:13            0 (const int)
+0:14      EmitVertex ( global void)
+0:16      move second child to first child ( temp 4-component vector of float)
+0:16        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:16          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:16          Constant:
+0:16            0 (const uint)
+0:16        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:16          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:16            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:16            Constant:
+0:16              1 (const int)
+0:16          Constant:
+0:16            0 (const int)
+0:17      EmitVertex ( global void)
+0:19      move second child to first child ( temp 4-component vector of float)
+0:19        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:19          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:19          Constant:
+0:19            0 (const uint)
+0:19        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:19          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:19            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:19            Constant:
+0:19              2 (const int)
+0:19          Constant:
+0:19            0 (const int)
+0:20      EmitVertex ( global void)
+0:22      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:?     'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+
+
+Linked vertex stage:
+
+
+Linked geometry stage:
+
+
+Shader version: 410
+0:? Sequence
+0:8  Function Definition: main( ( global void)
+0:8    Function Parameters: 
+0:10    Sequence
+0:10      move second child to first child ( temp 4-component vector of float)
+0:10        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:10          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position})
+0:10          Constant:
+0:10            0 (const uint)
+0:10        Constant:
+0:10          1.000000
+0:10          1.000000
+0:10          1.000000
+0:10          1.000000
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+Shader version: 410
+invocations = 1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      move second child to first child ( temp 4-component vector of float)
+0:13        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:13          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+0:13          Constant:
+0:13            0 (const uint)
+0:13        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:13          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:13            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:13            Constant:
+0:13              0 (const int)
+0:13          Constant:
+0:13            0 (const int)
+0:14      EmitVertex ( global void)
+0:16      move second child to first child ( temp 4-component vector of float)
+0:16        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:16          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+0:16          Constant:
+0:16            0 (const uint)
+0:16        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:16          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:16            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:16            Constant:
+0:16              1 (const int)
+0:16          Constant:
+0:16            0 (const int)
+0:17      EmitVertex ( global void)
+0:19      move second child to first child ( temp 4-component vector of float)
+0:19        gl_Position: direct index for structure (layout( stream=0) gl_Position 4-component vector of float Position)
+0:19          'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+0:19          Constant:
+0:19            0 (const uint)
+0:19        gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:19          direct index ( temp block{ in 4-component vector of float Position gl_Position})
+0:19            'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:19            Constant:
+0:19              2 (const int)
+0:19          Constant:
+0:19            0 (const int)
+0:20      EmitVertex ( global void)
+0:22      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'gl_in' ( in 3-element array of block{ in 4-component vector of float Position gl_Position})
+0:?     'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+
diff --git a/Test/link.redeclareBuiltin.geom b/Test/link.redeclareBuiltin.geom
new file mode 100644
index 0000000..a2ceff6
--- /dev/null
+++ b/Test/link.redeclareBuiltin.geom
@@ -0,0 +1,23 @@
+#version 410

+

+layout(triangles) in;

+layout(triangle_strip, max_vertices=3) out;

+

+in gl_PerVertex

+{

+  vec4 gl_Position;

+} gl_in[];

+

+void main()

+{

+    gl_Position = gl_in[0].gl_Position;

+    EmitVertex();

+

+    gl_Position = gl_in[1].gl_Position;

+    EmitVertex();

+

+    gl_Position = gl_in[2].gl_Position;

+    EmitVertex();

+

+    EndPrimitive();

+}
\ No newline at end of file
diff --git a/Test/link.redeclareBuiltin.vert b/Test/link.redeclareBuiltin.vert
new file mode 100644
index 0000000..7cda45c
--- /dev/null
+++ b/Test/link.redeclareBuiltin.vert
@@ -0,0 +1,11 @@
+#version 410

+

+out gl_PerVertex

+{

+    vec4 gl_Position;

+};

+

+void main()

+{

+    gl_Position = vec4(1.0);

+}
\ No newline at end of file
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index f4f3f34..e87f258 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -2469,6 +2469,14 @@
                     if (*(*structure)[li].type != *(*right.structure)[ri].type)
                         return false;
                 } else {
+                    // Skip hidden members
+                    if ((*structure)[li].type->hiddenMember()) {
+                        ri--;
+                        continue;
+                    } else if ((*right.structure)[ri].type->hiddenMember()) {
+                        li--;
+                        continue;
+                    }
                     // If one of the members is something that's inconsistently declared, skip over it
                     // for now.
                     if (isGLPerVertex) {
@@ -2485,10 +2493,10 @@
                 }
             // If we get here, then there should only be inconsistently declared members left
             } else if (li < structure->size()) {
-                if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
+                if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
                     return false;
             } else {
-                if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
+                if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
                     return false;
             }
         }
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index a790f93..b1adfc9 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -858,9 +858,19 @@
     if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
         symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
         symbol.getType().sameStructType(unitSymbol.getType())) {
-        for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) {
-            const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier();
-            const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier();
+        unsigned int li = 0;
+        unsigned int ri = 0;
+        while (li < symbol.getType().getStruct()->size() && ri < unitSymbol.getType().getStruct()->size()) {
+            if ((*symbol.getType().getStruct())[li].type->hiddenMember()) {
+                ++li;
+                continue;
+            }
+            if ((*unitSymbol.getType().getStruct())[ri].type->hiddenMember()) {
+                ++ri;
+                continue;
+            }
+            const TQualifier& qualifier = (*symbol.getType().getStruct())[li].type->getQualifier();
+            const TQualifier & unitQualifier = (*unitSymbol.getType().getStruct())[ri].type->getQualifier();
             if (qualifier.layoutMatrix     != unitQualifier.layoutMatrix ||
                 qualifier.layoutOffset     != unitQualifier.layoutOffset ||
                 qualifier.layoutAlign      != unitQualifier.layoutAlign ||
@@ -869,6 +879,8 @@
                 error(infoSink, "Interface block member layout qualifiers must match:");
                 writeTypeComparison = true;
             }
+            ++li;
+            ++ri;
         }
     }
 
diff --git a/gtests/Link.FromFile.cpp b/gtests/Link.FromFile.cpp
index a83d49d..9e029fc 100644
--- a/gtests/Link.FromFile.cpp
+++ b/gtests/Link.FromFile.cpp
@@ -108,6 +108,7 @@
         {"link.multiBlocksValid.1.0.vert", "link.multiBlocksValid.1.1.vert"},
         {"link.tesselation.vert", "link.tesselation.frag"},
         {"link.tesselation.tese", "link.tesselation.tesc"},
+        {"link.redeclareBuiltin.vert", "link.redeclareBuiltin.geom"},
     }))
 );
 // clang-format on