Implement 'index' layout qualifier for fragment outputs.  Based partly on a submission.


git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27759 e7fa87d3-cd2b-0410-9028-fcbf551c1848
diff --git a/Test/330.frag b/Test/330.frag
index d6083c0..a23ab66 100644
--- a/Test/330.frag
+++ b/Test/330.frag
@@ -1,7 +1,7 @@
 #version 330 compatibility
 
 in vec4 inVar;
-out vec4 outVar;
+layout(location=0, index=0) out vec4 outVar;
 
 varying vec4 varyingVar;
 
@@ -118,3 +118,11 @@
     vec4 j; // gets location 43
     vec4 k; // ERROR, location 44 already used
 };
+
+layout(index=0) out vec4 outVar2; // ERROR: missing explicit location
+layout(location=0, index=1) out vec4 outVar3; // no error even though location is overlapping
+layout(location=0, index=1) out vec4 outVar4; // ERROR overlapping
+layout(location=27, index=0) in vec4 indexIn; // ERROR, not on in
+layout(location=0, index=0) in; // ERROR, not just on in
+layout(location=0, index=0) out; // ERROR, need a variable
+layout(location=26, index=0) out indexBlock { int a; } indexBlockI; // ERROR, not on a block
\ No newline at end of file
diff --git a/Test/400.geom b/Test/400.geom
index 34a3fb9..7fe9fc1 100644
--- a/Test/400.geom
+++ b/Test/400.geom
@@ -99,3 +99,5 @@
     i1 = findMSB(i1);

     i2 = findMSB(u2);

 }

+

+layout(location = 7, index = 1) out vec4 indexedOut;

diff --git a/Test/430.vert b/Test/430.vert
index 0722823..64dd42f 100644
--- a/Test/430.vert
+++ b/Test/430.vert
@@ -114,13 +114,13 @@
 const int start2 = 5;

 layout(location = start2 * start2 - 2 - 4) in vec4 v6;

 

-layout(location = 28) in inblock2 {

+layout(location = 28) in inblock2 {  // ERROR, input block in vertex shader, other errors are valid checks still...

     bool b1;

     float f1;

     layout(location = 25) float f2;

 } ininst2;

 

-in ublock4 {

+in ublock4 {                         // ERROR, input block in vertex shader, other errors are valid checks still...

     layout(location = 50) float f1;

     layout(location = 51) float f2;

 } in4;

diff --git a/Test/baseResults/140.frag.out b/Test/baseResults/140.frag.out
index 8600e92..ebb4e56 100644
--- a/Test/baseResults/140.frag.out
+++ b/Test/baseResults/140.frag.out
@@ -6,7 +6,6 @@
 ERROR: 0:24: 'location qualifier on input' : not supported for this version or the enabled extensions 

 ERROR: 0:26: 'location' : not supported for this version or the enabled extensions 

 ERROR: 0:26: 'location qualifier on output' : not supported for this version or the enabled extensions 

-WARNING: 0:28: '#extension' : extension is only partially supported: GL_ARB_explicit_attrib_location

 ERROR: 0:38: 'assign' :  l-value required "v" (can't modify shader input)

 ERROR: 0:38: 'out' : Non-L-value cannot be passed for 'out' or 'inout' parameters. 

 ERROR: 8 compilation errors.  No code generated.

diff --git a/Test/baseResults/140.vert.out b/Test/baseResults/140.vert.out
index 2fa9191..0b0799f 100644
--- a/Test/baseResults/140.vert.out
+++ b/Test/baseResults/140.vert.out
@@ -2,7 +2,6 @@
 ERROR: 0:23: 'gl_Position' : identifiers starting with "gl_" are reserved 

 ERROR: 0:25: 'location' : not supported for this version or the enabled extensions 

 ERROR: 0:25: 'location qualifier on input' : not supported for this version or the enabled extensions 

-WARNING: 0:27: '#extension' : extension is only partially supported: GL_ARB_explicit_attrib_location

 ERROR: 0:34: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_Position

 ERROR: 0:34: 'redeclaration' : cannot change interpolation qualification of gl_Position

 ERROR: 0:35: 'redeclaration' : cannot change the type of gl_Position

diff --git a/Test/baseResults/330.frag.out b/Test/baseResults/330.frag.out
index e56026b..e2c4540 100644
--- a/Test/baseResults/330.frag.out
+++ b/Test/baseResults/330.frag.out
@@ -26,7 +26,14 @@
 ERROR: 0:94: 'location' : either the block needs a location, or all members need a location, or no members have a location 

 ERROR: 0:108: 'A' : cannot use layout qualifiers on structure members 

 ERROR: 0:119: 'location' : overlapping use of location 44

-ERROR: 27 compilation errors.  No code generated.

+ERROR: 0:122: 'index' : can only be used with an explicit location 

+ERROR: 0:124: 'location' : overlapping use of location 0

+ERROR: 0:125: 'index' : can only be used on an output 

+ERROR: 0:126: 'index' : can only be used on an output 

+ERROR: 0:126: 'location/component/index' : cannot declare a default, use a full declaration 

+ERROR: 0:127: 'location/component/index' : cannot declare a default, use a full declaration 

+ERROR: 0:128: 'out' : cannot declare an output block in a fragment shader 

+ERROR: 34 compilation errors.  No code generated.

 

 

 Shader version: 330

@@ -61,11 +68,11 @@
 0:23            Constant:

 0:23              2 (const uint)

 0:24      move second child to first child (4-component vector of float)

-0:24        'outVar' (out 4-component vector of float)

+0:24        'outVar' (layout(location=0 index=0 ) out 4-component vector of float)

 0:24        'inVar' (smooth in 4-component vector of float)

 0:?   Linker Objects

 0:?     'inVar' (smooth in 4-component vector of float)

-0:?     'outVar' (out 4-component vector of float)

+0:?     'outVar' (layout(location=0 index=0 ) out 4-component vector of float)

 0:?     'varyingVar' (smooth in 4-component vector of float)

 0:?     'anon@0' (in block{in 4-component vector of float gl_Color, })

 0:?     'gl_name' (in block{in int gl_i})

@@ -90,6 +97,11 @@
 0:?     'in4' (in block{layout(location=50 ) in float f1, layout(location=51 ) in float f2})

 0:?     's' (layout(location=33 ) smooth in structure{3-component vector of float a, 2X2 matrix of float b, 2-element array of 4-component vector of float c, 2-component vector of float A})

 0:?     'anon@2' (in block{layout(location=44 component=0 ) in 4-component vector of float d, layout(location=45 component=0 ) in 4-component vector of float e, layout(location=47 ) in 4-component vector of float f, layout(location=48 component=0 ) in 4-component vector of float g, layout(location=41 ) in 4-component vector of float h, layout(location=42 component=0 ) in 4-component vector of float i, layout(location=43 component=0 ) in 4-component vector of float j, layout(location=44 component=0 ) in 4-component vector of float k})

+0:?     'outVar2' (layout(location=63 index=0 ) out 4-component vector of float)

+0:?     'outVar3' (layout(location=0 index=1 ) out 4-component vector of float)

+0:?     'outVar4' (layout(location=0 index=1 ) out 4-component vector of float)

+0:?     'indexIn' (layout(location=27 index=0 ) smooth in 4-component vector of float)

+0:?     'indexBlockI' (layout(location=26 index=0 ) out block{out int a})

 

 

 Linked fragment stage:

@@ -129,11 +141,11 @@
 0:23            Constant:

 0:23              2 (const uint)

 0:24      move second child to first child (4-component vector of float)

-0:24        'outVar' (out 4-component vector of float)

+0:24        'outVar' (layout(location=0 index=0 ) out 4-component vector of float)

 0:24        'inVar' (smooth in 4-component vector of float)

 0:?   Linker Objects

 0:?     'inVar' (smooth in 4-component vector of float)

-0:?     'outVar' (out 4-component vector of float)

+0:?     'outVar' (layout(location=0 index=0 ) out 4-component vector of float)

 0:?     'varyingVar' (smooth in 4-component vector of float)

 0:?     'anon@0' (in block{in 4-component vector of float gl_Color, })

 0:?     'gl_name' (in block{in int gl_i})

@@ -158,4 +170,9 @@
 0:?     'in4' (in block{layout(location=50 ) in float f1, layout(location=51 ) in float f2})

 0:?     's' (layout(location=33 ) smooth in structure{3-component vector of float a, 2X2 matrix of float b, 2-element array of 4-component vector of float c, 2-component vector of float A})

 0:?     'anon@2' (in block{layout(location=44 component=0 ) in 4-component vector of float d, layout(location=45 component=0 ) in 4-component vector of float e, layout(location=47 ) in 4-component vector of float f, layout(location=48 component=0 ) in 4-component vector of float g, layout(location=41 ) in 4-component vector of float h, layout(location=42 component=0 ) in 4-component vector of float i, layout(location=43 component=0 ) in 4-component vector of float j, layout(location=44 component=0 ) in 4-component vector of float k})

+0:?     'outVar2' (layout(location=63 index=0 ) out 4-component vector of float)

+0:?     'outVar3' (layout(location=0 index=1 ) out 4-component vector of float)

+0:?     'outVar4' (layout(location=0 index=1 ) out 4-component vector of float)

+0:?     'indexIn' (layout(location=27 index=0 ) smooth in 4-component vector of float)

+0:?     'indexBlockI' (layout(location=26 index=0 ) out block{out int a})

 

diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out
index b05fd2f..65895a6 100644
--- a/Test/baseResults/400.geom.out
+++ b/Test/baseResults/400.geom.out
@@ -18,7 +18,8 @@
 ERROR: 0:65: 'invocations' : can only apply to 'in' 

 ERROR: 0:67: 'in' : type must be an array: inbls

 ERROR: 0:71: 'triangles' : inconsistent input primitive for array size of inbla

-ERROR: 18 compilation errors.  No code generated.

+ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value 

+ERROR: 19 compilation errors.  No code generated.

 

 

 Shader version: 400

@@ -180,6 +181,7 @@
 0:?     'scalar' (in float)

 0:?     'inbls' (in block{in int a})

 0:?     'inbla' (in 17-element array of block{in int a})

+0:?     'indexedOut' (layout(location=7 stream=0 ) out 4-component vector of float)

 

 

 Linked geometry stage:

@@ -345,4 +347,5 @@
 0:?     'scalar' (in float)

 0:?     'inbls' (in block{in int a})

 0:?     'inbla' (in 17-element array of block{in int a})

+0:?     'indexedOut' (layout(location=7 stream=0 ) out 4-component vector of float)

 

diff --git a/Test/baseResults/420.vert.out b/Test/baseResults/420.vert.out
index ca3c81e..fd58f68 100644
--- a/Test/baseResults/420.vert.out
+++ b/Test/baseResults/420.vert.out
@@ -23,7 +23,8 @@
 ERROR: 0:62: 'xxxxx' : illegal vector field selection 

 ERROR: 0:63: 'xxy' : vector field selection out of range 

 ERROR: 0:66: 'binding' : cannot declare a default, include a type or full declaration 

-ERROR: 0:69: 'location' : cannot declare a default, use a full declaration 

+ERROR: 0:69: 'location/component/index' : cannot declare a default, use a full declaration 

+ERROR: 0:70: 'in' : cannot declare an input block in a vertex shader 

 ERROR: 0:70: 'binding' : requires uniform or buffer storage qualifier 

 ERROR: 0:71: 'binding' : binding is too large 

 ERROR: 0:74: 'binding' : sampler binding not less than gl_MaxCombinedTextureImageUnits 

@@ -48,7 +49,7 @@
 ERROR: 0:143: 'rgba32ui' : does not apply to signed integer images 

 ERROR: 0:144: 'r8ui' : does not apply to signed integer images 

 ERROR: 0:147: 'offset on block member' : not supported for this version or the enabled extensions 

-ERROR: 47 compilation errors.  No code generated.

+ERROR: 48 compilation errors.  No code generated.

 

 

 Shader version: 420

diff --git a/Test/baseResults/430.vert.out b/Test/baseResults/430.vert.out
index 3f6515b..b3cb9b2 100644
--- a/Test/baseResults/430.vert.out
+++ b/Test/baseResults/430.vert.out
@@ -1,6 +1,7 @@
 430.vert

 Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.

 ERROR: 0:3: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers 

+ERROR: 0:7: 'in' : cannot declare an input block in a vertex shader 

 ERROR: 0:7: 'location qualifier on in/out block' : not supported for this version or the enabled extensions 

 ERROR: 0:8: 'location qualifier on in/out block' : not supported for this version or the enabled extensions 

 ERROR: 0:21: 'g' : cannot use storage or interpolation qualifiers on structure members 

@@ -16,7 +17,9 @@
 ERROR: 0:51: 'start' : undeclared identifier 

 ERROR: 0:51: '' : constant expression required 

 ERROR: 0:51: 'layout-id value' : scalar integer expression required 

+ERROR: 0:53: 'in' : cannot declare an input block in a vertex shader 

 ERROR: 0:54: 'location on block member' : not supported for this version or the enabled extensions 

+ERROR: 0:57: 'in' : cannot declare an input block in a vertex shader 

 ERROR: 0:58: 'location on block member' : not supported for this version or the enabled extensions 

 ERROR: 0:59: 'location on block member' : not supported for this version or the enabled extensions 

 ERROR: 0:62: 'uniform buffer-member align' : not supported for this version or the enabled extensions 

@@ -44,6 +47,8 @@
 ERROR: 0:93: 'transform feedback qualifier' : not supported for this version or the enabled extensions 

 ERROR: 0:93: 'transform feedback qualifier' : not supported for this version or the enabled extensions 

 ERROR: 0:93: 'transform feedback qualifier' : not supported for this version or the enabled extensions 

+ERROR: 0:117: 'in' : cannot declare an input block in a vertex shader 

+ERROR: 0:123: 'in' : cannot declare an input block in a vertex shader 

 ERROR: 0:146: 'shared' : not supported in this stage: vertex

 ERROR: 0:150: 'barrier' : no matching overloaded function found 

 ERROR: 0:154: 'memoryBarrierShared' : no matching overloaded function found 

@@ -53,7 +58,7 @@
 ERROR: 0:169: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions 

 ERROR: 0:170: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions 

 ERROR: 0:171: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions 

-ERROR: 53 compilation errors.  No code generated.

+ERROR: 58 compilation errors.  No code generated.

 

 

 Shader version: 430

diff --git a/Test/baseResults/440.frag.out b/Test/baseResults/440.frag.out
index eb5632a..d872949 100644
--- a/Test/baseResults/440.frag.out
+++ b/Test/baseResults/440.frag.out
@@ -19,11 +19,13 @@
 ERROR: 0:37: 'offset' : only applies to block members, not blocks 

 ERROR: 0:38: 'layout' : offset/align can only be used on a uniform or buffer 

 ERROR: 0:38: 'offset' : only applies to block members, not blocks 

+ERROR: 0:39: 'out' : cannot declare an output block in a fragment shader 

 ERROR: 0:39: 'layout' : offset/align can only be used on a uniform or buffer 

 ERROR: 0:39: 'offset' : only applies to block members, not blocks 

 ERROR: 0:42: 'offset/align' : can only be used with std140 or std430 layout packing 

 ERROR: 0:43: 'offset/align' : can only be used with std140 or std430 layout packing 

 ERROR: 0:43: 'layout' : offset/align can only be used on a uniform or buffer 

+ERROR: 0:44: 'out' : cannot declare an output block in a fragment shader 

 ERROR: 0:44: 'offset/align' : can only be used with std140 or std430 layout packing 

 ERROR: 0:44: 'layout' : offset/align can only be used on a uniform or buffer 

 ERROR: 0:46: 'offset' : cannot specify on a variable declaration 

@@ -45,7 +47,7 @@
 ERROR: 0:103: 'align' : must be a power of 2 

 ERROR: 0:102: 'offset' : cannot lie in previous members 

 ERROR: 0:104: 'offset' : must be a multiple of the member's alignment 

-ERROR: 45 compilation errors.  No code generated.

+ERROR: 47 compilation errors.  No code generated.

 

 

 Shader version: 440

diff --git a/Test/baseResults/440.vert.out b/Test/baseResults/440.vert.out
index 5bf7670..12814f2 100644
--- a/Test/baseResults/440.vert.out
+++ b/Test/baseResults/440.vert.out
@@ -18,7 +18,7 @@
 ERROR: 0:55: 'component' : type overflows the available 4 components 

 ERROR: 0:57: 'component' : cannot apply to a matrix, structure, or block 

 ERROR: 0:58: 'component' : cannot apply to a matrix, structure, or block 

-ERROR: 0:61: 'location' : cannot declare a default, use a full declaration 

+ERROR: 0:61: 'location/component/index' : cannot declare a default, use a full declaration 

 ERROR: 0:81: 'xfb layout qualifier' : can only be used on an output 

 ERROR: 0:87: 'xfb_offset' : cannot declare a default, use a full declaration 

 ERROR: 0:97: 'xfb_buffer' : member cannot contradict block (or what block inherited from global) 

diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out
index 7e0b41d..6dfa4b8 100644
--- a/Test/baseResults/specExamples.frag.out
+++ b/Test/baseResults/specExamples.frag.out
@@ -14,8 +14,6 @@
 ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage taking an assigned value 

 ERROR: 0:100: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value 

 ERROR: 0:102: 'color' : redefinition 

-ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value 

-ERROR: 0:104: 'location' : overlapping use of location 3

 ERROR: 0:112: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth

 ERROR: 0:118: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth

 ERROR: 0:121: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth

@@ -43,7 +41,7 @@
 ERROR: 0:227: 'in' : not allowed in nested scope 

 ERROR: 0:228: 'in' : not allowed in nested scope 

 ERROR: 0:232: 'out' : not allowed in nested scope 

-ERROR: 43 compilation errors.  No code generated.

+ERROR: 41 compilation errors.  No code generated.

 

 

 Shader version: 430

@@ -289,7 +287,7 @@
 0:?     'Materiala' (in block{in 4-component vector of float Color, in 2-component vector of float TexCoord})

 0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)

 0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)

-0:?     'factor' (layout(location=3 ) out 4-component vector of float)

+0:?     'factor' (layout(location=3 index=1 ) out 4-component vector of float)

 0:?     'colors' (layout(location=2 ) out 3-element array of 4-component vector of float)

 0:?     'gl_FragDepth' (gl_FragDepth float)

 0:?     'gl_FragDepth' (gl_FragDepth float)

@@ -543,7 +541,7 @@
 0:?     'Materiala' (in block{in 4-component vector of float Color, in 2-component vector of float TexCoord})

 0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)

 0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)

-0:?     'factor' (layout(location=3 ) out 4-component vector of float)

+0:?     'factor' (layout(location=3 index=1 ) out 4-component vector of float)

 0:?     'colors' (layout(location=2 ) out 3-element array of 4-component vector of float)

 0:?     'gl_FragDepth' (gl_FragDepth float)

 0:?     'gl_FragDepth' (gl_FragDepth float)

diff --git a/Todo.txt b/Todo.txt
index 6d03f46..9be6445 100644
--- a/Todo.txt
+++ b/Todo.txt
@@ -206,7 +206,7 @@
       + Add built-in functions to pack/unpack 16 bit floating-point numbers (ARB_shading_language_pack2f).
         + packHalf2x16 and unpackHalf2x16
         + packSnorm2x16and unpackSnorm2x16
-      - Add gl_FragDepth layout qualifiers to communicate what kind of changes will be made to gl_FragDepth (GL_AMD_conservative depth).
+      + Add gl_FragDepth layout qualifiers to communicate what kind of changes will be made to gl_FragDepth (GL_AMD_conservative depth).
       + Add C-style curly brace initializer lists syntax for initializers. Full initialization of aggregates is required when these are used.
       + Allow .length() to be applied to vectors and matrices, returning the number of components or columns.
       + Clarify that .length() returns an int type and can be used as a constant integer expression.
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 6efc3f1..4ac3a02 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -483,6 +483,8 @@
         layoutLocation = layoutLocationEnd;
         layoutComponent = layoutComponentEnd;
         layoutBinding = layoutBindingEnd;
+        layoutIndex = layoutIndexEnd;
+
         layoutStream = layoutStreamEnd;
 
         layoutXfbBuffer = layoutXfbBufferEnd;
@@ -494,7 +496,7 @@
     bool hasLayout() const
     {
         return hasUniformLayout() || 
-               hasLocation() ||
+               hasAnyLocation() ||
                hasBinding() ||
                hasStream() ||
                hasXfb() ||
@@ -514,6 +516,9 @@
                  unsigned int layoutBinding          : 8;
     static const unsigned int layoutBindingEnd =    0xFF;
 
+                 unsigned int layoutIndex           :  8;
+    static const unsigned int layoutIndexEnd =      0xFF;
+
                  unsigned int layoutStream           : 8;
     static const unsigned int layoutStreamEnd =     0xFF;
 
@@ -552,15 +557,24 @@
     {
         return layoutAlign != -1;
     }
+    bool hasAnyLocation() const
+    {
+        return hasLocation() ||
+               hasComponent() ||
+               hasIndex();
+    }
     bool hasLocation() const
     {
-        return layoutLocation  != layoutLocationEnd ||
-               layoutComponent != layoutComponentEnd;
+        return layoutLocation  != layoutLocationEnd;
     }
     bool hasComponent() const
     {
         return layoutComponent != layoutComponentEnd;
     }
+    bool hasIndex() const
+    {
+        return layoutIndex != layoutIndexEnd;
+    }
     bool hasBinding() const
     {
         return layoutBinding != layoutBindingEnd;
@@ -1167,10 +1181,12 @@
             noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
             if (noXfbBuffer.hasLayout()) {
                 p += snprintf(p, end - p, "layout(");
-                if (qualifier.hasLocation()) {
+                if (qualifier.hasAnyLocation()) {
                     p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
-                    if (qualifier.layoutComponent != qualifier.layoutComponentEnd)
+                    if (qualifier.hasComponent())
                         p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
+                    if (qualifier.hasIndex())
+                        p += snprintf(p, end - p, "index=%d ", qualifier.layoutIndex);
                 }
                 if (qualifier.hasBinding())
                     p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index b4393de..9abd958 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -3266,6 +3266,13 @@
         break;
 
     case EShLangFragment:
+        if (id == "index") {
+            requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
+            const char* exts[2] = { GL_ARB_separate_shader_objects, GL_ARB_explicit_attrib_location };
+            profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
+            publicType.qualifier.layoutIndex = value;
+            return;
+        }
         break;
 
     case EShLangCompute:
@@ -3325,11 +3332,13 @@
         dst.layoutAlign = src.layoutAlign;
 
     if (! inheritOnly) {
-        if (src.layoutLocation != TQualifier::layoutLocationEnd)
+        if (src.hasLocation())
             dst.layoutLocation = src.layoutLocation;
-        if (src.layoutComponent != TQualifier::layoutComponentEnd)
+        if (src.hasComponent())
             dst.layoutComponent = src.layoutComponent;
-        
+        if (src.hasIndex())
+            dst.layoutIndex = src.layoutIndex;
+
         if (src.hasOffset())
             dst.layoutOffset = src.layoutOffset;
 
@@ -3354,7 +3363,7 @@
 
     // now, any remaining error checking based on the object itself
 
-    if (qualifier.hasLocation()) {
+    if (qualifier.hasAnyLocation()) {
         switch (qualifier.storage) {
         case EvqUniform:
         case EvqBuffer:
@@ -3405,8 +3414,14 @@
 
     // now, error checking combining type and qualifier
 
-    if (qualifier.hasLocation()) {
-        if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {
+    if (qualifier.hasAnyLocation()) {
+        if (qualifier.hasLocation()) {
+            if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) {
+                if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers)
+                    error(loc, "too large for fragment output", "location", "");
+            }
+        }
+        if (qualifier.hasComponent()) {
             // "It is a compile-time error if this sequence of components gets larger than 3."
             if (qualifier.layoutComponent + type.getVectorSize() > 4)
                 error(loc, "type overflows the available 4 components", "component", "");
@@ -3416,11 +3431,6 @@
                 error(loc, "cannot apply to a matrix, structure, or block", "component", "");
         }
 
-        if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) {
-            if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers)
-                error(loc, "too large for fragment output", "location", "");
-        }
-
         switch (qualifier.storage) {
         case EvqVaryingIn:
         case EvqVaryingOut:
@@ -3514,10 +3524,10 @@
         error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
 
     // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
-    if (qualifier.layoutComponent != TQualifier::layoutComponentEnd && qualifier.layoutLocation == TQualifier::layoutLocationEnd)
+    if (qualifier.hasComponent() && ! qualifier.hasLocation())
         error(loc, "must specify 'location' to use 'component'", "component", "");
 
-    if (qualifier.hasLocation()) {
+    if (qualifier.hasAnyLocation()) {
 
         // "As with input layout qualifiers, all shaders except compute shaders 
         // allow *location* layout qualifiers on output variable declarations, 
@@ -3570,6 +3580,12 @@
         default:
             break;
         }
+        if (qualifier.hasIndex()) {
+            if (qualifier.storage != EvqVaryingOut)
+                error(loc, "can only be used on an output", "index", "");
+            if (! qualifier.hasLocation())
+                error(loc, "can only be used with an explicit location", "index", "");
+        }
     }
 
     if (qualifier.hasBinding()) {
@@ -4240,10 +4256,14 @@
     case EvqVaryingIn:
         requireProfile(loc, ~EEsProfile, "input block");
         profileRequires(loc, ~EEsProfile, 150, GL_ARB_separate_shader_objects, "input block");
+        if (language == EShLangVertex)
+            error(loc, "cannot declare an input block in a vertex shader", "in", "");
         break;
     case EvqVaryingOut:
         requireProfile(loc, ~EEsProfile, "output block");
         profileRequires(loc, ~EEsProfile, 150, GL_ARB_separate_shader_objects, "output block");
+        if (language == EShLangFragment)
+            error(loc, "cannot declare an output block in a fragment shader", "out", "");
         break;
     default:
         error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
@@ -4455,13 +4475,16 @@
         if (memberWithLocation) {
             // remove any block-level location and make it per *every* member
             int nextLocation;  // by the rule above, initial value is not relevant
-            if (qualifier.hasLocation()) {
+            if (qualifier.hasAnyLocation()) {
                 nextLocation = qualifier.layoutLocation;
                 qualifier.layoutLocation = TQualifier::layoutLocationEnd;
-                if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {
+                if (qualifier.hasComponent()) {
                     // "It is a compile-time error to apply the *component* qualifier to a ... block"
                     error(loc, "cannot apply to a block", "component", "");
                 }
+                if (qualifier.hasIndex()) {
+                    error(loc, "cannot apply to a block", "index", "");
+                }
             }
             for (unsigned int member = 0; member < typeList.size(); ++member) {
                 TQualifier& memberQualifier = typeList[member].type->getQualifier();
@@ -4781,8 +4804,8 @@
 
     if (qualifier.hasBinding())
         error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
-    if (qualifier.hasLocation())
-        error(loc, "cannot declare a default, use a full declaration", "location", "");
+    if (qualifier.hasAnyLocation())
+        error(loc, "cannot declare a default, use a full declaration", "location/component/index", "");
     if (qualifier.hasXfbOffset())
         error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
 }
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 5add18c..cf4e750 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -165,7 +165,7 @@
     extensionBehavior[GL_ARB_enhanced_layouts]             = EBhDisable;
     extensionBehavior[GL_ARB_texture_cube_map_array]       = EBhDisable;
     extensionBehavior[GL_ARB_shader_texture_lod]           = EBhDisable;
-    extensionBehavior[GL_ARB_explicit_attrib_location]     = EBhDisablePartial; // "index" for fragment outputs is missing
+    extensionBehavior[GL_ARB_explicit_attrib_location]     = EBhDisable;
     extensionBehavior[GL_ARB_shader_image_load_store]      = EBhDisable;
     extensionBehavior[GL_ARB_shader_atomic_counters]       = EBhDisable;
     extensionBehavior[GL_ARB_derivative_control]           = EBhDisable;
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 8efe224..d183a65 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -313,13 +313,15 @@
     }

 

     // Layouts... 

-    // TODO: 4.4 enhanced layouts: Generalize to include offset/align: currrent spec 

+    // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec 

     //       requires separate user-supplied offset from actual computed offset, but 

     //       current implementation only has one offset.

-    if (symbol.getQualifier().layoutMatrix   != unitSymbol.getQualifier().layoutMatrix ||

-        symbol.getQualifier().layoutPacking  != unitSymbol.getQualifier().layoutPacking ||

-        symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation ||

-        symbol.getQualifier().layoutBinding  != unitSymbol.getQualifier().layoutBinding) {

+    if (symbol.getQualifier().layoutMatrix    != unitSymbol.getQualifier().layoutMatrix ||

+        symbol.getQualifier().layoutPacking   != unitSymbol.getQualifier().layoutPacking ||

+        symbol.getQualifier().layoutLocation  != unitSymbol.getQualifier().layoutLocation ||

+        symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent ||

+        symbol.getQualifier().layoutIndex     != unitSymbol.getQualifier().layoutIndex ||

+        symbol.getQualifier().layoutBinding   != unitSymbol.getQualifier().layoutBinding) {

         error(infoSink, "Layout qualification must match:");

         writeTypeComparison = true;

     }

@@ -547,7 +549,7 @@
         if (language == EShLangFragment) {

             if (qualifier.storage == EvqVaryingOut) {

                 ++numFragOut;

-                if (qualifier.hasLocation())

+                if (qualifier.hasAnyLocation())

                     fragOutHasLocation = true;

                 else

                     fragOutWithNoLocation = true;

@@ -634,11 +636,11 @@
 

     TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1);

     TRange componentRange(0, 3);

-    if (qualifier.layoutComponent != TQualifier::layoutComponentEnd) {

+    if (qualifier.hasComponent()) {

         componentRange.start = qualifier.layoutComponent;

         componentRange.last = componentRange.start + type.getVectorSize() - 1;

     }

-    TIoRange range(locationRange, componentRange, type.getBasicType());

+    TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);

 

     // check for collisions, except for vertex inputs on desktop

     if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput())) {

diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 8fdc0e8..d762efe 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -77,18 +77,20 @@
     int last;
 };
 
-// A *location* range is a 2-D rectangle; the set of (location, component) pairs all lying
-// both within the location range and the component range.  Locations don't alias unless
-// both dimensions of their range overlap.
+// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
+// within the same location range, component range, and index value.  Locations don't alias unless
+// all other dimensions of their range overlap.
 struct TIoRange {
-    TIoRange(TRange location, TRange component, TBasicType basicType) : location(location), component(component), basicType(basicType) { }
+    TIoRange(TRange location, TRange component, TBasicType basicType, int index)
+        : location(location), component(component), basicType(basicType), index(index) { }
     bool overlap(const TIoRange& rhs) const
     {
-        return location.overlap(rhs.location) && component.overlap(rhs.component);
+        return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
     }
     TRange location;
     TRange component;
     TBasicType basicType;
+    int index;
 };
 
 // Things that need to be tracked per xfb buffer.