ソースを参照

Fix incorrect "Contradictory layout" link errors (#3920)

* Add tests that generate incorrect "Contradictory layout" link errors

* Add tests that generate correct "Contradictory layout" link errors

* Fix incorrect link errors when multiple compilation units don't declare layouts

when using multiple compilation units, input/output layouts don't need
to be declared in every unit.

In the same spirit as 6f723ebbe3b0eba0c543fa615b53fbdc3e6e22c7
Valentin Sarthou 2 ヶ月 前
コミット
4056002eb2

+ 0 - 2
Test/baseResults/150.tesc.out

@@ -962,8 +962,6 @@ ERROR: Linking tessellation evaluation stage: can't handle multiple entry points
 ERROR: Linking tessellation evaluation stage: Multiple function bodies in multiple compilation units for the same signature in the same stage:
     main(
 ERROR: Linking tessellation evaluation stage: can't handle multiple entry points per stage
-ERROR: Linking tessellation evaluation stage: Contradictory input vertex spacing
-ERROR: Linking tessellation evaluation stage: Contradictory triangle ordering
 ERROR: Linking tessellation evaluation stage: Multiple function bodies in multiple compilation units for the same signature in the same stage:
     main(
 ERROR: Linking tessellation evaluation stage: Multiple function bodies in multiple compilation units for the same signature in the same stage:

+ 64 - 0
Test/baseResults/link.multiUnitLayout.0.frag.out

@@ -0,0 +1,64 @@
+link.multiUnitLayout.0.frag
+Shader version: 450
+using depth_greater
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: outputColor(vf4; ( global void)
+0:9        Constant:
+0:9          1.000000
+0:9          0.000000
+0:9          0.000000
+0:9          1.000000
+0:10      move second child to first child ( temp float)
+0:10        'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:10        Constant:
+0:10          0.500000
+0:?   Linker Objects
+0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
+
+link.multiUnitLayout.1.frag
+Shader version: 450
+0:? Sequence
+0:5  Function Definition: outputColor(vf4; ( global void)
+0:5    Function Parameters: 
+0:5      'color' ( in 4-component vector of float)
+0:7    Sequence
+0:7      move second child to first child ( temp 4-component vector of float)
+0:7        'FragColor' (layout( location=0) out 4-component vector of float)
+0:7        'color' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'FragColor' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+using depth_greater
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: outputColor(vf4; ( global void)
+0:9        Constant:
+0:9          1.000000
+0:9          0.000000
+0:9          0.000000
+0:9          1.000000
+0:10      move second child to first child ( temp float)
+0:10        'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:10        Constant:
+0:10          0.500000
+0:5  Function Definition: outputColor(vf4; ( global void)
+0:5    Function Parameters: 
+0:5      'color' ( in 4-component vector of float)
+0:7    Sequence
+0:7      move second child to first child ( temp 4-component vector of float)
+0:7        'FragColor' (layout( location=0) out 4-component vector of float)
+0:7        'color' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:?     'FragColor' (layout( location=0) out 4-component vector of float)
+

+ 93 - 0
Test/baseResults/link.multiUnitLayout.0.mesh.out

@@ -0,0 +1,93 @@
+link.multiUnitLayout.0.mesh
+ERROR: 0:2: 'GL_EXT_mesh_shader' : not supported for current targeted SPIR-V version 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = 81
+max_primitives = 32
+output primitive = triangles
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      Function Call: do_process( ( global void)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( const 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+
+link.multiUnitLayout.1.mesh
+ERROR: 0:2: 'GL_EXT_mesh_shader' : not supported for current targeted SPIR-V version 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = -1
+max_primitives = -1
+output primitive = none
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:9  Function Definition: do_process( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp uint)
+0:11        indirect index (layout( column_major std430 offset=0) temp uint)
+0:11          data: direct index for structure (layout( column_major std430 offset=0) buffer runtime-sized array of uint)
+0:11            'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+0:11            Constant:
+0:11              0 (const int)
+0:11          direct index ( temp uint)
+0:11            'gl_LocalInvocationID' ( in 3-component vector of uint LocalInvocationID)
+0:11            Constant:
+0:11              0 (const int)
+0:11        direct index ( temp uint)
+0:11          'gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
+0:11          Constant:
+0:11            0 (const int)
+0:?   Linker Objects
+0:?     'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+
+
+Linked mesh stage:
+
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = 81
+max_primitives = 32
+output primitive = triangles
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      Function Call: do_process( ( global void)
+0:9  Function Definition: do_process( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp uint)
+0:11        indirect index (layout( column_major std430 offset=0) temp uint)
+0:11          data: direct index for structure (layout( column_major std430 offset=0) buffer runtime-sized array of uint)
+0:11            'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+0:11            Constant:
+0:11              0 (const int)
+0:11          direct index ( temp uint)
+0:11            'gl_LocalInvocationID' ( in 3-component vector of uint LocalInvocationID)
+0:11            Constant:
+0:11              0 (const int)
+0:11        direct index ( temp uint)
+0:11          'gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
+0:11          Constant:
+0:11            0 (const int)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( const 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?     'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+

+ 165 - 0
Test/baseResults/link.multiUnitLayout.0.tese.out

@@ -0,0 +1,165 @@
+link.multiUnitLayout.0.tese
+Shader version: 410
+input primitive = triangles
+vertex spacing = equal_spacing
+triangle order = cw
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Sequence
+0:9        move second child to first child ( temp 4-component vector of float)
+0:9          'p0' ( temp 4-component vector of float)
+0:9          vector-scale ( temp 4-component vector of float)
+0:9            direct index ( temp float)
+0:9              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:9              Constant:
+0:9                0 (const int)
+0:9            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:9              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                Constant:
+0:9                  0 (const int)
+0:9              Constant:
+0:9                0 (const int)
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'p1' ( temp 4-component vector of float)
+0:10          vector-scale ( temp 4-component vector of float)
+0:10            direct index ( temp float)
+0:10              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:10              Constant:
+0:10                1 (const int)
+0:10            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:10              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                Constant:
+0:10                  1 (const int)
+0:10              Constant:
+0:10                0 (const int)
+0:11      Sequence
+0:11        move second child to first child ( temp 4-component vector of float)
+0:11          'p2' ( temp 4-component vector of float)
+0:11          vector-scale ( temp 4-component vector of float)
+0:11            direct index ( temp float)
+0:11              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:11              Constant:
+0:11                2 (const int)
+0:11            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:11              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                Constant:
+0:11                  2 (const int)
+0:11              Constant:
+0:11                0 (const int)
+0:12      move second child to first child ( temp 4-component vector of float)
+0:12        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:12          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:12          Constant:
+0:12            0 (const uint)
+0:12        Function Call: transformPosition(vf4; ( global 4-component vector of float)
+0:12          add ( temp 4-component vector of float)
+0:12            add ( temp 4-component vector of float)
+0:12              'p0' ( temp 4-component vector of float)
+0:12              'p1' ( temp 4-component vector of float)
+0:12            'p2' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+
+link.multiUnitLayout.1.tese
+Shader version: 410
+input primitive = none
+vertex spacing = none
+triangle order = none
+0:? Sequence
+0:3  Function Definition: transformPosition(vf4; ( global 4-component vector of float)
+0:3    Function Parameters: 
+0:3      'position' ( in 4-component vector of float)
+0:5    Sequence
+0:5      Branch: Return with expression
+0:5        vector-scale ( temp 4-component vector of float)
+0:5          Constant:
+0:5            2.000000
+0:5          'position' ( in 4-component vector of float)
+0:?   Linker Objects
+
+
+Linked tessellation evaluation stage:
+
+
+Shader version: 410
+input primitive = triangles
+vertex spacing = equal_spacing
+triangle order = cw
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Sequence
+0:9        move second child to first child ( temp 4-component vector of float)
+0:9          'p0' ( temp 4-component vector of float)
+0:9          vector-scale ( temp 4-component vector of float)
+0:9            direct index ( temp float)
+0:9              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:9              Constant:
+0:9                0 (const int)
+0:9            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:9              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:9                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:9                Constant:
+0:9                  0 (const int)
+0:9              Constant:
+0:9                0 (const int)
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'p1' ( temp 4-component vector of float)
+0:10          vector-scale ( temp 4-component vector of float)
+0:10            direct index ( temp float)
+0:10              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:10              Constant:
+0:10                1 (const int)
+0:10            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:10              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:10                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:10                Constant:
+0:10                  1 (const int)
+0:10              Constant:
+0:10                0 (const int)
+0:11      Sequence
+0:11        move second child to first child ( temp 4-component vector of float)
+0:11          'p2' ( temp 4-component vector of float)
+0:11          vector-scale ( temp 4-component vector of float)
+0:11            direct index ( temp float)
+0:11              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:11              Constant:
+0:11                2 (const int)
+0:11            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:11              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:11                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in 1-element array of float ClipDistance gl_ClipDistance})
+0:11                Constant:
+0:11                  2 (const int)
+0:11              Constant:
+0:11                0 (const int)
+0:12      move second child to first child ( temp 4-component vector of float)
+0:12        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:12          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance})
+0:12          Constant:
+0:12            0 (const uint)
+0:12        Function Call: transformPosition(vf4; ( global 4-component vector of float)
+0:12          add ( temp 4-component vector of float)
+0:12            add ( temp 4-component vector of float)
+0:12              'p0' ( temp 4-component vector of float)
+0:12              'p1' ( temp 4-component vector of float)
+0:12            'p2' ( temp 4-component vector of float)
+0:3  Function Definition: transformPosition(vf4; ( global 4-component vector of float)
+0:3    Function Parameters: 
+0:3      'position' ( in 4-component vector of float)
+0:5    Sequence
+0:5      Branch: Return with expression
+0:5        vector-scale ( temp 4-component vector of float)
+0:5          Constant:
+0:5            2.000000
+0:5          'position' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance})
+

+ 80 - 0
Test/baseResults/link.multiUnitLayout.0.vert.out

@@ -0,0 +1,80 @@
+link.multiUnitLayout.0.vert
+Shader version: 450
+in xfb mode
+0:? Sequence
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp 4-component vector of float)
+0:11        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:11          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:11          Constant:
+0:11            0 (const uint)
+0:11        Function Call: computePosition(vf4; ( global 4-component vector of float)
+0:11          'in_position' (layout( location=0) in 4-component vector of float)
+0:?   Linker Objects
+0:?     'in_position' (layout( location=0) in 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiUnitLayout.1.vert
+Shader version: 450
+0:? Sequence
+0:3  Function Definition: computePosition(vf4; ( global 4-component vector of float)
+0:3    Function Parameters: 
+0:3      'position' ( in 4-component vector of float)
+0:5    Sequence
+0:5      Branch: Return with expression
+0:5        add ( temp 4-component vector of float)
+0:5          Constant:
+0:5            1.000000
+0:5            1.000000
+0:5            1.000000
+0:5            1.000000
+0:5          vector-scale ( temp 4-component vector of float)
+0:5            Constant:
+0:5              2.000000
+0:5            'position' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+in xfb mode
+0:? Sequence
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp 4-component vector of float)
+0:11        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:11          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:11          Constant:
+0:11            0 (const uint)
+0:11        Function Call: computePosition(vf4; ( global 4-component vector of float)
+0:11          'in_position' (layout( location=0) in 4-component vector of float)
+0:3  Function Definition: computePosition(vf4; ( global 4-component vector of float)
+0:3    Function Parameters: 
+0:3      'position' ( in 4-component vector of float)
+0:5    Sequence
+0:5      Branch: Return with expression
+0:5        add ( temp 4-component vector of float)
+0:5          Constant:
+0:5            1.000000
+0:5            1.000000
+0:5            1.000000
+0:5            1.000000
+0:5          vector-scale ( temp 4-component vector of float)
+0:5            Constant:
+0:5              2.000000
+0:5            'position' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'in_position' (layout( location=0) in 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+

+ 67 - 0
Test/baseResults/link.multiUnitLayout.2.frag.out

@@ -0,0 +1,67 @@
+link.multiUnitLayout.2.frag
+Shader version: 450
+using depth_less
+0:? Sequence
+0:8  Function Definition: outputColor(vf4; ( global void)
+0:8    Function Parameters: 
+0:8      'color' ( in 4-component vector of float)
+0:10    Sequence
+0:10      move second child to first child ( temp 4-component vector of float)
+0:10        'FragColor' (layout( location=0) out 4-component vector of float)
+0:10        'color' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:?     'FragColor' (layout( location=0) out 4-component vector of float)
+
+link.multiUnitLayout.0.frag
+Shader version: 450
+using depth_greater
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: outputColor(vf4; ( global void)
+0:9        Constant:
+0:9          1.000000
+0:9          0.000000
+0:9          0.000000
+0:9          1.000000
+0:10      move second child to first child ( temp float)
+0:10        'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:10        Constant:
+0:10          0.500000
+0:?   Linker Objects
+0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
+
+
+Linked fragment stage:
+
+ERROR: Linking fragment stage: Contradictory depth layouts
+
+Shader version: 450
+using depth_less
+0:? Sequence
+0:8  Function Definition: outputColor(vf4; ( global void)
+0:8    Function Parameters: 
+0:8      'color' ( in 4-component vector of float)
+0:10    Sequence
+0:10      move second child to first child ( temp 4-component vector of float)
+0:10        'FragColor' (layout( location=0) out 4-component vector of float)
+0:10        'color' ( in 4-component vector of float)
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: outputColor(vf4; ( global void)
+0:9        Constant:
+0:9          1.000000
+0:9          0.000000
+0:9          0.000000
+0:9          1.000000
+0:10      move second child to first child ( temp float)
+0:10        'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:10        Constant:
+0:10          0.500000
+0:?   Linker Objects
+0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
+0:?     'FragColor' (layout( location=0) out 4-component vector of float)
+

+ 94 - 0
Test/baseResults/link.multiUnitLayout.2.mesh.out

@@ -0,0 +1,94 @@
+link.multiUnitLayout.2.mesh
+ERROR: 0:2: 'GL_EXT_mesh_shader' : not supported for current targeted SPIR-V version 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = -1
+max_primitives = 34
+output primitive = none
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:12  Function Definition: do_process( ( global void)
+0:12    Function Parameters: 
+0:14    Sequence
+0:14      move second child to first child ( temp uint)
+0:14        indirect index (layout( column_major std430 offset=0) temp uint)
+0:14          data: direct index for structure (layout( column_major std430 offset=0) buffer runtime-sized array of uint)
+0:14            'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+0:14            Constant:
+0:14              0 (const int)
+0:14          direct index ( temp uint)
+0:14            'gl_LocalInvocationID' ( in 3-component vector of uint LocalInvocationID)
+0:14            Constant:
+0:14              0 (const int)
+0:14        direct index ( temp uint)
+0:14          'gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
+0:14          Constant:
+0:14            0 (const int)
+0:?   Linker Objects
+0:?     'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+
+link.multiUnitLayout.0.mesh
+ERROR: 0:2: 'GL_EXT_mesh_shader' : not supported for current targeted SPIR-V version 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = 81
+max_primitives = 32
+output primitive = triangles
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      Function Call: do_process( ( global void)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( const 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+
+
+Linked mesh stage:
+
+ERROR: Linking mesh stage: Contradictory layout max_primitives values
+
+Shader version: 460
+Requested GL_EXT_mesh_shader
+max_vertices = 81
+max_primitives = 34
+output primitive = triangles
+local_size = (1, 1, 1)
+ERROR: node is still EOpNull!
+0:12  Function Definition: do_process( ( global void)
+0:12    Function Parameters: 
+0:14    Sequence
+0:14      move second child to first child ( temp uint)
+0:14        indirect index (layout( column_major std430 offset=0) temp uint)
+0:14          data: direct index for structure (layout( column_major std430 offset=0) buffer runtime-sized array of uint)
+0:14            'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+0:14            Constant:
+0:14              0 (const int)
+0:14          direct index ( temp uint)
+0:14            'gl_LocalInvocationID' ( in 3-component vector of uint LocalInvocationID)
+0:14            Constant:
+0:14              0 (const int)
+0:14        direct index ( temp uint)
+0:14          'gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
+0:14          Constant:
+0:14            0 (const int)
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      Function Call: do_process( ( global void)
+0:?   Linker Objects
+0:?     'dataBuffer' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer runtime-sized array of uint data})
+0:?     'gl_WorkGroupSize' ( const 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+

+ 167 - 0
Test/baseResults/link.multiUnitLayout.2.tese.out

@@ -0,0 +1,167 @@
+link.multiUnitLayout.2.tese
+Shader version: 410
+input primitive = triangles
+vertex spacing = fractional_even_spacing
+triangle order = ccw
+0:? Sequence
+0:6  Function Definition: transformPosition(vf4; ( global 4-component vector of float)
+0:6    Function Parameters: 
+0:6      'position' ( in 4-component vector of float)
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        vector-scale ( temp 4-component vector of float)
+0:8          Constant:
+0:8            2.000000
+0:8          'position' ( in 4-component vector of float)
+0:?   Linker Objects
+
+link.multiUnitLayout.0.tese
+Shader version: 410
+input primitive = triangles
+vertex spacing = equal_spacing
+triangle order = cw
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Sequence
+0:9        move second child to first child ( temp 4-component vector of float)
+0:9          'p0' ( temp 4-component vector of float)
+0:9          vector-scale ( temp 4-component vector of float)
+0:9            direct index ( temp float)
+0:9              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:9              Constant:
+0:9                0 (const int)
+0:9            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:9              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                Constant:
+0:9                  0 (const int)
+0:9              Constant:
+0:9                0 (const int)
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'p1' ( temp 4-component vector of float)
+0:10          vector-scale ( temp 4-component vector of float)
+0:10            direct index ( temp float)
+0:10              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:10              Constant:
+0:10                1 (const int)
+0:10            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:10              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                Constant:
+0:10                  1 (const int)
+0:10              Constant:
+0:10                0 (const int)
+0:11      Sequence
+0:11        move second child to first child ( temp 4-component vector of float)
+0:11          'p2' ( temp 4-component vector of float)
+0:11          vector-scale ( temp 4-component vector of float)
+0:11            direct index ( temp float)
+0:11              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:11              Constant:
+0:11                2 (const int)
+0:11            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:11              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                Constant:
+0:11                  2 (const int)
+0:11              Constant:
+0:11                0 (const int)
+0:12      move second child to first child ( temp 4-component vector of float)
+0:12        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:12          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:12          Constant:
+0:12            0 (const uint)
+0:12        Function Call: transformPosition(vf4; ( global 4-component vector of float)
+0:12          add ( temp 4-component vector of float)
+0:12            add ( temp 4-component vector of float)
+0:12              'p0' ( temp 4-component vector of float)
+0:12              'p1' ( temp 4-component vector of float)
+0:12            'p2' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+
+
+Linked tessellation evaluation stage:
+
+ERROR: Linking tessellation evaluation stage: Contradictory input vertex spacing
+ERROR: Linking tessellation evaluation stage: Contradictory triangle ordering
+
+Shader version: 410
+input primitive = triangles
+vertex spacing = fractional_even_spacing
+triangle order = ccw
+0:? Sequence
+0:6  Function Definition: transformPosition(vf4; ( global 4-component vector of float)
+0:6    Function Parameters: 
+0:6      'position' ( in 4-component vector of float)
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        vector-scale ( temp 4-component vector of float)
+0:8          Constant:
+0:8            2.000000
+0:8          'position' ( in 4-component vector of float)
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Sequence
+0:9        move second child to first child ( temp 4-component vector of float)
+0:9          'p0' ( temp 4-component vector of float)
+0:9          vector-scale ( temp 4-component vector of float)
+0:9            direct index ( temp float)
+0:9              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:9              Constant:
+0:9                0 (const int)
+0:9            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:9              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:9                Constant:
+0:9                  0 (const int)
+0:9              Constant:
+0:9                0 (const int)
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'p1' ( temp 4-component vector of float)
+0:10          vector-scale ( temp 4-component vector of float)
+0:10            direct index ( temp float)
+0:10              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:10              Constant:
+0:10                1 (const int)
+0:10            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:10              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:10                Constant:
+0:10                  1 (const int)
+0:10              Constant:
+0:10                0 (const int)
+0:11      Sequence
+0:11        move second child to first child ( temp 4-component vector of float)
+0:11          'p2' ( temp 4-component vector of float)
+0:11          vector-scale ( temp 4-component vector of float)
+0:11            direct index ( temp float)
+0:11              'gl_TessCoord' ( in 3-component vector of float TessCoord)
+0:11              Constant:
+0:11                2 (const int)
+0:11            gl_Position: direct index for structure ( in 4-component vector of float Position)
+0:11              direct index ( temp block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                'gl_in' ( in 32-element array of block{ in 4-component vector of float Position gl_Position,  in float PointSize gl_PointSize,  in unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:11                Constant:
+0:11                  2 (const int)
+0:11              Constant:
+0:11                0 (const int)
+0:12      move second child to first child ( temp 4-component vector of float)
+0:12        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:12          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:12          Constant:
+0:12            0 (const uint)
+0:12        Function Call: transformPosition(vf4; ( global 4-component vector of float)
+0:12          add ( temp 4-component vector of float)
+0:12            add ( temp 4-component vector of float)
+0:12              'p0' ( temp 4-component vector of float)
+0:12              'p1' ( temp 4-component vector of float)
+0:12            'p2' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+

+ 82 - 0
Test/baseResults/link.multiUnitLayout.2.vert.out

@@ -0,0 +1,82 @@
+link.multiUnitLayout.2.vert
+Shader version: 450
+in xfb mode
+0:? Sequence
+0:6  Function Definition: computePosition(vf4; ( global 4-component vector of float)
+0:6    Function Parameters: 
+0:6      'position' ( in 4-component vector of float)
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        add ( temp 4-component vector of float)
+0:8          Constant:
+0:8            1.000000
+0:8            1.000000
+0:8            1.000000
+0:8            1.000000
+0:8          vector-scale ( temp 4-component vector of float)
+0:8            Constant:
+0:8              2.000000
+0:8            'position' ( in 4-component vector of float)
+0:?   Linker Objects
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiUnitLayout.0.vert
+Shader version: 450
+in xfb mode
+0:? Sequence
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp 4-component vector of float)
+0:11        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:11          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:11          Constant:
+0:11            0 (const uint)
+0:11        Function Call: computePosition(vf4; ( global 4-component vector of float)
+0:11          'in_position' (layout( location=0) in 4-component vector of float)
+0:?   Linker Objects
+0:?     'in_position' (layout( location=0) in 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+ERROR: Linking vertex stage: Contradictory xfb_stride
+
+Shader version: 450
+in xfb mode
+0:? Sequence
+0:6  Function Definition: computePosition(vf4; ( global 4-component vector of float)
+0:6    Function Parameters: 
+0:6      'position' ( in 4-component vector of float)
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        add ( temp 4-component vector of float)
+0:8          Constant:
+0:8            1.000000
+0:8            1.000000
+0:8            1.000000
+0:8            1.000000
+0:8          vector-scale ( temp 4-component vector of float)
+0:8            Constant:
+0:8              2.000000
+0:8            'position' ( in 4-component vector of float)
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:11    Sequence
+0:11      move second child to first child ( temp 4-component vector of float)
+0:11        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:11          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:11          Constant:
+0:11            0 (const uint)
+0:11        Function Call: computePosition(vf4; ( global 4-component vector of float)
+0:11          'in_position' (layout( location=0) in 4-component vector of float)
+0:?   Linker Objects
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+0:?     'in_position' (layout( location=0) in 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+

+ 151 - 0
Test/baseResults/link.vk.multiUnitLayout.0.comp.out

@@ -0,0 +1,151 @@
+link.vk.multiUnitLayout.0.comp
+Shader version: 450
+local_size = (1, 1, 1)
+local_size ids = (0, -1, -1)
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: do_compute(u1; ( global void)
+0:9        direct index ( temp highp uint)
+0:9          'gl_GlobalInvocationID' ( in highp 3-component vector of uint GlobalInvocationID)
+0:9          Constant:
+0:9            0 (const int)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( specialization-constant const highp 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+
+link.vk.multiUnitLayout.1.comp
+Shader version: 450
+local_size = (1, 1, 1)
+0:? Sequence
+0:7  Function Definition: do_compute(u1; ( global void)
+0:7    Function Parameters: 
+0:7      'index' ( in highp uint)
+0:9    Sequence
+0:9      add second child into first child ( temp highp 4-component vector of float)
+0:9        indirect index (layout( column_major std430) temp highp 4-component vector of float)
+0:9          data: direct index for structure (layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float)
+0:9            'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+0:9            Constant:
+0:9              0 (const int)
+0:9          'index' ( in highp uint)
+0:9        Constant:
+0:9          1.000000
+0:9          1.000000
+0:9          1.000000
+0:9          1.000000
+0:?   Linker Objects
+0:?     'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+
+
+Linked compute stage:
+
+
+Shader version: 450
+local_size = (1, 1, 1)
+local_size ids = (0, -1, -1)
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: do_compute(u1; ( global void)
+0:9        direct index ( temp highp uint)
+0:9          'gl_GlobalInvocationID' ( in highp 3-component vector of uint GlobalInvocationID)
+0:9          Constant:
+0:9            0 (const int)
+0:7  Function Definition: do_compute(u1; ( global void)
+0:7    Function Parameters: 
+0:7      'index' ( in highp uint)
+0:9    Sequence
+0:9      add second child into first child ( temp highp 4-component vector of float)
+0:9        indirect index (layout( column_major std430) temp highp 4-component vector of float)
+0:9          data: direct index for structure (layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float)
+0:9            'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+0:9            Constant:
+0:9              0 (const int)
+0:9          'index' ( in highp uint)
+0:9        Constant:
+0:9          1.000000
+0:9          1.000000
+0:9          1.000000
+0:9          1.000000
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( specialization-constant const highp 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?     'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+
+// Module Version 10000
+// Generated by (magic number): 8000b
+// Id's are bound by 40
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint GLCompute 4  "main" 14
+                              ExecutionMode 4 LocalSize 1 1 1
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 10  "do_compute(u1;"
+                              Name 9  "index"
+                              Name 14  "gl_GlobalInvocationID"
+                              Name 15  "param"
+                              Name 24  "DataBuf"
+                              MemberName 24(DataBuf) 0  "data"
+                              Name 26  "dataBuf"
+                              Decorate 14(gl_GlobalInvocationID) BuiltIn GlobalInvocationId
+                              Decorate 23 ArrayStride 16
+                              Decorate 24(DataBuf) BufferBlock
+                              MemberDecorate 24(DataBuf) 0 Offset 0
+                              Decorate 26(dataBuf) Binding 0
+                              Decorate 26(dataBuf) DescriptorSet 0
+                              Decorate 37 SpecId 0
+                              Decorate 39 BuiltIn WorkgroupSize
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               8:             TypeFunction 2 7(ptr)
+              12:             TypeVector 6(int) 3
+              13:             TypePointer Input 12(ivec3)
+14(gl_GlobalInvocationID):     13(ptr) Variable Input
+              16:      6(int) Constant 0
+              17:             TypePointer Input 6(int)
+              21:             TypeFloat 32
+              22:             TypeVector 21(float) 4
+              23:             TypeRuntimeArray 22(fvec4)
+     24(DataBuf):             TypeStruct 23
+              25:             TypePointer Uniform 24(DataBuf)
+     26(dataBuf):     25(ptr) Variable Uniform
+              27:             TypeInt 32 1
+              28:     27(int) Constant 0
+              30:   21(float) Constant 1065353216
+              31:   22(fvec4) ConstantComposite 30 30 30 30
+              32:             TypePointer Uniform 22(fvec4)
+              37:      6(int) SpecConstant 1
+              38:      6(int) Constant 1
+              39:   12(ivec3) SpecConstantComposite 37 38 38
+         4(main):           2 Function None 3
+               5:             Label
+       15(param):      7(ptr) Variable Function
+              18:     17(ptr) AccessChain 14(gl_GlobalInvocationID) 16
+              19:      6(int) Load 18
+                              Store 15(param) 19
+              20:           2 FunctionCall 10(do_compute(u1;) 15(param)
+                              Return
+                              FunctionEnd
+10(do_compute(u1;):           2 Function None 8
+        9(index):      7(ptr) FunctionParameter
+              11:             Label
+              29:      6(int) Load 9(index)
+              33:     32(ptr) AccessChain 26(dataBuf) 28 29
+              34:   22(fvec4) Load 33
+              35:   22(fvec4) FAdd 34 31
+              36:     32(ptr) AccessChain 26(dataBuf) 28 29
+                              Store 36 35
+                              Return
+                              FunctionEnd

+ 89 - 0
Test/baseResults/link.vk.multiUnitLayout.2.comp.out

@@ -0,0 +1,89 @@
+link.vk.multiUnitLayout.2.comp
+Shader version: 450
+local_size = (1, 1, 1)
+local_size ids = (1, -1, -1)
+0:? Sequence
+0:10  Function Definition: do_compute(u1; ( global void)
+0:10    Function Parameters: 
+0:10      'index' ( in highp uint)
+0:12    Sequence
+0:12      add second child into first child ( temp highp 4-component vector of float)
+0:12        indirect index (layout( column_major std430) temp highp 4-component vector of float)
+0:12          data: direct index for structure (layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float)
+0:12            'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+0:12            Constant:
+0:12              0 (const int)
+0:12          'index' ( in highp uint)
+0:12        Constant:
+0:12          1.000000
+0:12          1.000000
+0:12          1.000000
+0:12          1.000000
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( specialization-constant const highp 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?     'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+
+link.vk.multiUnitLayout.0.comp
+Shader version: 450
+local_size = (1, 1, 1)
+local_size ids = (0, -1, -1)
+0:? Sequence
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: do_compute(u1; ( global void)
+0:9        direct index ( temp highp uint)
+0:9          'gl_GlobalInvocationID' ( in highp 3-component vector of uint GlobalInvocationID)
+0:9          Constant:
+0:9            0 (const int)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( specialization-constant const highp 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+
+
+Linked compute stage:
+
+ERROR: Linking compute stage: Contradictory local size specialization ids
+
+Shader version: 450
+local_size = (1, 1, 1)
+local_size ids = (1, -1, -1)
+0:? Sequence
+0:10  Function Definition: do_compute(u1; ( global void)
+0:10    Function Parameters: 
+0:10      'index' ( in highp uint)
+0:12    Sequence
+0:12      add second child into first child ( temp highp 4-component vector of float)
+0:12        indirect index (layout( column_major std430) temp highp 4-component vector of float)
+0:12          data: direct index for structure (layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float)
+0:12            'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+0:12            Constant:
+0:12              0 (const int)
+0:12          'index' ( in highp uint)
+0:12        Constant:
+0:12          1.000000
+0:12          1.000000
+0:12          1.000000
+0:12          1.000000
+0:7  Function Definition: main( ( global void)
+0:7    Function Parameters: 
+0:9    Sequence
+0:9      Function Call: do_compute(u1; ( global void)
+0:9        direct index ( temp highp uint)
+0:9          'gl_GlobalInvocationID' ( in highp 3-component vector of uint GlobalInvocationID)
+0:9          Constant:
+0:9            0 (const int)
+0:?   Linker Objects
+0:?     'gl_WorkGroupSize' ( specialization-constant const highp 3-component vector of uint WorkGroupSize)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?       1 (const uint)
+0:?     'dataBuf' (layout( set=0 binding=0 column_major std430) buffer block{layout( column_major std430) buffer runtime-sized array of highp 4-component vector of float data})
+
+Validation failed
+SPIR-V is not generated for failed compile or link

+ 1 - 0
Test/baseResults/validation_fails.txt

@@ -47,6 +47,7 @@ Test/baseResults/link.vk.crossStageIO.1.vert.out
 Test/baseResults/link.vk.differentPC.0.0.frag.out
 Test/baseResults/link.vk.differentPC.1.0.frag.out
 Test/baseResults/link.vk.missingCrossStageIO.0.vert.out
+Test/baseResults/link.vk.multiUnitLayout.2.comp.out
 Test/baseResults/link.vk.pcNamingInvalid.0.0.vert.out
 Test/baseResults/spv.130.frag.out
 Test/baseResults/spv.140.frag.out

+ 11 - 0
Test/link.multiUnitLayout.0.frag

@@ -0,0 +1,11 @@
+#version 450
+
+layout (depth_greater) out float gl_FragDepth;
+
+void outputColor(vec4 color);
+
+void main()
+{
+  outputColor(vec4(1.0, 0.0, 0.0, 1.0));
+  gl_FragDepth = 0.5;
+}

+ 14 - 0
Test/link.multiUnitLayout.0.mesh

@@ -0,0 +1,14 @@
+#version 460
+#extension GL_EXT_mesh_shader : enable
+
+layout(local_size_x = 1) in;
+layout(max_vertices=81) out;
+layout(max_primitives=32) out;
+layout(triangles) out;
+
+void do_process();
+
+void main()
+{
+  do_process();
+}

+ 13 - 0
Test/link.multiUnitLayout.0.tese

@@ -0,0 +1,13 @@
+#version 410
+
+layout(triangles, equal_spacing, cw) in;
+
+vec4 transformPosition(vec4 position);
+
+void main()
+{
+  vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+  vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+  vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+  gl_Position = transformPosition(p0 + p1 + p2);
+}

+ 12 - 0
Test/link.multiUnitLayout.0.vert

@@ -0,0 +1,12 @@
+#version 450
+
+layout(xfb_buffer = 1, xfb_stride = 32) out;
+
+layout(location = 0) in vec4 in_position;
+
+vec4 computePosition(vec4 position);
+
+void main()
+{
+  gl_Position = computePosition(in_position);
+}

+ 8 - 0
Test/link.multiUnitLayout.1.frag

@@ -0,0 +1,8 @@
+#version 450
+
+layout(location=0) out vec4 FragColor;
+
+void outputColor(vec4 color)
+{
+  FragColor = color;
+}

+ 12 - 0
Test/link.multiUnitLayout.1.mesh

@@ -0,0 +1,12 @@
+#version 460
+#extension GL_EXT_mesh_shader : enable
+
+layout(std430) buffer DataBuffer
+{
+  uint data[];
+} dataBuffer;
+
+void do_process()
+{
+  dataBuffer.data[gl_LocalInvocationID.x] = gl_WorkGroupID.x;
+}

+ 6 - 0
Test/link.multiUnitLayout.1.tese

@@ -0,0 +1,6 @@
+#version 410
+
+vec4 transformPosition(vec4 position)
+{
+  return 2.0 * position;
+}

+ 6 - 0
Test/link.multiUnitLayout.1.vert

@@ -0,0 +1,6 @@
+#version 450
+
+vec4 computePosition(vec4 position)
+{
+  return vec4(1.0) + 2.0 * position;
+}

+ 11 - 0
Test/link.multiUnitLayout.2.frag

@@ -0,0 +1,11 @@
+#version 450
+
+// Should generate a contradictory depth layout error
+layout (depth_less) out float gl_FragDepth;
+
+layout(location=0) out vec4 FragColor;
+
+void outputColor(vec4 color)
+{
+  FragColor = color;
+}

+ 15 - 0
Test/link.multiUnitLayout.2.mesh

@@ -0,0 +1,15 @@
+#version 460
+#extension GL_EXT_mesh_shader : enable
+
+// Should generate a contradictory max_primitives value layout error
+layout(max_primitives=34) out;
+
+layout(std430) buffer DataBuffer
+{
+  uint data[];
+} dataBuffer;
+
+void do_process()
+{
+  dataBuffer.data[gl_LocalInvocationID.x] = gl_WorkGroupID.x;
+}

+ 9 - 0
Test/link.multiUnitLayout.2.tese

@@ -0,0 +1,9 @@
+#version 410
+
+// Should generate contradictory input vertex spacing and triangle ordering errors
+layout(triangles, fractional_even_spacing, ccw) in;
+
+vec4 transformPosition(vec4 position)
+{
+  return 2.0 * position;
+}

+ 9 - 0
Test/link.multiUnitLayout.2.vert

@@ -0,0 +1,9 @@
+#version 450
+
+// Should generate a contradictory xfb_stride error
+layout(xfb_buffer = 1, xfb_stride = 34) out;
+
+vec4 computePosition(vec4 position)
+{
+  return vec4(1.0) + 2.0 * position;
+}

+ 10 - 0
Test/link.vk.multiUnitLayout.0.comp

@@ -0,0 +1,10 @@
+#version 450 core
+
+layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
+
+void do_compute(uint index);
+
+void main()
+{
+  do_compute(gl_GlobalInvocationID.x);
+}

+ 10 - 0
Test/link.vk.multiUnitLayout.1.comp

@@ -0,0 +1,10 @@
+#version 450 core
+
+layout(set = 0, binding = 0) buffer DataBuf {
+    vec4 data[];
+} dataBuf;
+
+void do_compute(uint index)
+{
+  dataBuf.data[index] += vec4(1.0);
+}

+ 13 - 0
Test/link.vk.multiUnitLayout.2.comp

@@ -0,0 +1,13 @@
+#version 450 core
+
+// Should generate a contradictory local size specialization ids error
+layout(local_size_x_id = 1, local_size_y = 1, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) buffer DataBuf {
+    vec4 data[];
+} dataBuf;
+
+void do_compute(uint index)
+{
+  dataBuf.data[index] += vec4(1.0);
+}

+ 33 - 6
glslang/MachineIndependent/linkValidate.cpp

@@ -535,6 +535,9 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
             error(infoSink, "number of invocations must match between compilation units");
     }
 
+    // The GLSL specification requires that at least one compilation unit
+    // must declare the vertices layout, but not all units need to do so.
+    // However, all declarations must match.
     if (vertices == TQualifier::layoutNotSet)
         vertices = unit.vertices;
     else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) {
@@ -545,20 +548,30 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
         else
             assert(0);
     }
+
+    // The mesh shader extension requires that at least one compilation unit
+    // must declare the max_primitives layout, but not all units need to do so.
+    // However, all declarations must match.
     if (primitives == TQualifier::layoutNotSet)
         primitives = unit.primitives;
-    else if (primitives != unit.primitives) {
+    else if (unit.primitives != TQualifier::layoutNotSet && primitives != unit.primitives) {
         if (language == EShLangMesh)
             error(infoSink, "Contradictory layout max_primitives values");
         else
             assert(0);
     }
 
+    // The GLSL specification requires that at least one compilation unit
+    // must declare the input primitive layout, but not all units need to do so.
+    // However, all declarations must match.
     if (inputPrimitive == ElgNone)
         inputPrimitive = unit.inputPrimitive;
     else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive)
         error(infoSink, "Contradictory input layout primitives");
 
+    // The GLSL specification requires that at least one compilation unit
+    // must declare the output primitive layout, but not all units need to do so.
+    // However, all declarations must match.
     if (outputPrimitive == ElgNone)
         outputPrimitive = unit.outputPrimitive;
     else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive)
@@ -567,19 +580,27 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
         error(infoSink, "gl_FragCoord redeclarations must match across shaders");
 
+    // The GLSL specification requires that at least one compilation unit
+    // must declare the vertex spacing layout, but not all units need to do so.
+    // However, all declarations must match.
     if (vertexSpacing == EvsNone)
         vertexSpacing = unit.vertexSpacing;
-    else if (vertexSpacing != unit.vertexSpacing)
+    else if (unit.vertexSpacing != EvsNone && vertexSpacing != unit.vertexSpacing)
         error(infoSink, "Contradictory input vertex spacing");
 
+    // The GLSL specification requires that at least one compilation unit
+    // must declare the triangle ordering layout, but not all units need to do so.
+    // However, all declarations must match.
     if (vertexOrder == EvoNone)
         vertexOrder = unit.vertexOrder;
-    else if (vertexOrder != unit.vertexOrder)
+    else if (unit.vertexOrder != EvoNone && vertexOrder != unit.vertexOrder)
         error(infoSink, "Contradictory triangle ordering");
 
     MERGE_TRUE(pointMode);
 
     for (int i = 0; i < 3; ++i) {
+        // The GLSL specification requires that all workgroup size declarations must match
+        // but not all units have to declare the layout.
         if (unit.localSizeNotDefault[i]) {
             if (!localSizeNotDefault[i]) {
                 localSize[i] = unit.localSize[i];
@@ -589,9 +610,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
                 error(infoSink, "Contradictory local size");
         }
 
+        // The GLSL specification requires that all workgroup size specialization
+        // ids declarations must match, but not all units have to declare the layout.
         if (localSizeSpecId[i] == TQualifier::layoutNotSet)
             localSizeSpecId[i] = unit.localSizeSpecId[i];
-        else if (localSizeSpecId[i] != unit.localSizeSpecId[i])
+        else if (unit.localSizeSpecId[i] != TQualifier::layoutNotSet && localSizeSpecId[i] != unit.localSizeSpecId[i])
             error(infoSink, "Contradictory local size specialization ids");
     }
 
@@ -602,9 +625,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_TRUE(nonCoherentStencilAttachmentReadEXT);
     MERGE_TRUE(nonCoherentTileAttachmentReadQCOM);
 
+    // The GLSL specification requires that all depth layout redeclarations must match,
+    // but not all units have to declare the layout.
     if (depthLayout == EldNone)
         depthLayout = unit.depthLayout;
-    else if (depthLayout != unit.depthLayout)
+    else if (unit.depthLayout != EldNone && depthLayout != unit.depthLayout)
         error(infoSink, "Contradictory depth layouts");
 
     MERGE_TRUE(depthReplacing);
@@ -615,9 +640,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
     MERGE_TRUE(xfbMode);
 
     for (size_t b = 0; b < xfbBuffers.size(); ++b) {
+        // The GLSL specification requires that all xfb_stride declarations for
+        // the same buffer must match, but not all units have to declare the layout.
         if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
             xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
-        else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride)
+        else if (unit.xfbBuffers[b].stride != TQualifier::layoutXfbStrideEnd && xfbBuffers[b].stride != unit.xfbBuffers[b].stride)
             error(infoSink, "Contradictory xfb_stride");
         xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride);
         if (unit.xfbBuffers[b].contains64BitType)

+ 2 - 0
gtests/Link.FromFile.Vk.cpp

@@ -121,6 +121,8 @@ INSTANTIATE_TEST_SUITE_P(
         {"link.vk.pcNamingInvalid.0.0.vert", "link.vk.pcNamingInvalid.0.1.vert"},
         {"link.vk.multiBlocksValid.0.0.vert", "link.vk.multiBlocksValid.0.1.vert"},
         {"link.vk.multiBlocksValid.1.0.geom", "link.vk.multiBlocksValid.1.1.geom"},
+        {"link.vk.multiUnitLayout.0.comp", "link.vk.multiUnitLayout.1.comp"},
+        {"link.vk.multiUnitLayout.2.comp", "link.vk.multiUnitLayout.0.comp"},
         {"link.vk.inconsistentGLPerVertex.0.vert", "link.vk.inconsistentGLPerVertex.0.geom"},
         {"link.vk.crossStageIO.0.vert", "link.vk.crossStageIO.0.frag"},
         {"link.vk.crossStageIO.1.vert", "link.vk.crossStageIO.1.geom", "link.vk.crossStageIO.1.frag"},

+ 8 - 0
gtests/Link.FromFile.cpp

@@ -111,6 +111,14 @@ INSTANTIATE_TEST_SUITE_P(
         {"link.multiAnonBlocksValid.0.0.vert", "link.multiAnonBlocksValid.0.1.vert"},
         {"link.multiBlocksInvalid.0.0.vert", "link.multiBlocksInvalid.0.1.vert"},
         {"link.multiBlocksValid.1.0.vert", "link.multiBlocksValid.1.1.vert"},
+        {"link.multiUnitLayout.0.vert", "link.multiUnitLayout.1.vert"},
+        {"link.multiUnitLayout.0.frag", "link.multiUnitLayout.1.frag"},
+        {"link.multiUnitLayout.0.tese", "link.multiUnitLayout.1.tese"},
+        {"link.multiUnitLayout.0.mesh", "link.multiUnitLayout.1.mesh"},
+        {"link.multiUnitLayout.2.vert", "link.multiUnitLayout.0.vert"},
+        {"link.multiUnitLayout.2.frag", "link.multiUnitLayout.0.frag"},
+        {"link.multiUnitLayout.2.tese", "link.multiUnitLayout.0.tese"},
+        {"link.multiUnitLayout.2.mesh", "link.multiUnitLayout.0.mesh"},
         {"link.tesselation.vert", "link.tesselation.frag"},
         {"link.tesselation.tese", "link.tesselation.tesc"},
         {"link.redeclareBuiltin.vert", "link.redeclareBuiltin.geom"},