Implement location overlap error checking.
authorJohn Kessenich <cepheus@frii.com>
Thu, 5 Dec 2013 20:07:56 +0000 (20:07 +0000)
committerJohn Kessenich <cepheus@frii.com>
Thu, 5 Dec 2013 20:07:56 +0000 (20:07 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24376 e7fa87d3-cd2b-0410-9028-fcbf551c1848

13 files changed:
Test/300layout.frag
Test/300layout.vert
Test/400.frag
Test/430.vert
Test/baseResults/300layout.frag.out
Test/baseResults/300layout.vert.out
Test/baseResults/400.frag.out
Test/baseResults/430.vert.out
Test/baseResults/specExamples.frag.out
glslang/Include/revision.h
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/localintermediate.h

index b4b0bba..70cbc9a 100644 (file)
@@ -13,3 +13,7 @@ void main()
     p = pos;
     q[1] = pos;
 }
+
+layout(location = 40) out float ca[4];
+layout(location = 41) out float cb[2];  // ERROR, overlap
+layout(location = 39) out float cc[6];  // ERROR, overlap
index 18f69c3..6a863cf 100644 (file)
@@ -5,7 +5,7 @@ struct s { vec4 v; };
 layout(location = 7) in vec3 c;
 layout(LocatioN = 3) in vec4 p;
 layout(LocatioN = 9) in vec4 q[4]; // ERROR, no array
-layout(LocatioN = 10) in s r[4];   // ERROR, no struct
+layout(LocatioN = 10) in s r[4];   // ERROR, no struct, ERROR, location overlap
 out vec4 pos;
 out vec3 color;
 
@@ -52,3 +52,6 @@ shared vec4 compute_only;  // ERROR
 layout(packed) uniform;
 
 layout(packed) float aoeuntaoeu;
+
+layout(location = 40) in float cd;
+layout(location = 37) in mat4x3 ce; // ERROR, overlap
index c8039f0..6d47138 100644 (file)
@@ -33,7 +33,7 @@ layout(location = 4) in vec4 vl; // ERROR, not supported
 #extension GL_ARB_separate_shader_objects : enable
 #endif
 
-layout(location = 4) in vec4 vl2;
+layout(location = 6) in vec4 vl2;
 
 layout(location = 3) uniform vec3 uv3;
 
index 6912fb4..25c17a2 100644 (file)
@@ -2,7 +2,7 @@
 \r
 layout(location = 3) vec4 v4;  // ERROR\r
 \r
-layout(location = 3) uniform vec4 uv4;\r
+layout(location = 4) uniform vec4 uv4;\r
 \r
 layout(location = 2) in   inb1 { vec4 v; } b1;  // ERROR\r
 layout(location = 2) out outb1 { vec4 v; } b2;  // ERROR\r
@@ -30,4 +30,13 @@ void foo3(invariant vec4 v4,                 // ERROR
           layout(location = 3) vec2 v2,      // ERROR\r
           centroid vec3 cv3)                 // ERROR\r
 {\r
-}
\ No newline at end of file
+}\r
+\r
+struct S {\r
+    mat3x2 m[7];  // needs 7*3 locations\r
+    float f;      // needs 1 location\r
+};                // needs 22 locations\r
+\r
+layout(location = 10) out S cs[2];     // 10 through 10 + 2 * 22 - 1 = 53\r
+layout(location = 54) out float cf;\r
+layout(location = 53) out float cg; // ERROR, collision at 31\r
index 95d3596..ac66569 100644 (file)
@@ -1,6 +1,8 @@
 300layout.frag\r
 ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment\r
-ERROR: 1 compilation errors.  No code generated.\r
+ERROR: 0:18: 'location' : repeated use of location 41\r
+ERROR: 0:19: 'location' : repeated use of location 40\r
+ERROR: 3 compilation errors.  No code generated.\r
 \r
 \r
 ERROR: node is still EOpNull!\r
@@ -25,6 +27,9 @@ ERROR: node is still EOpNull!
 0:?     'c' (layout(location=1 ) out mediump 4-component vector of float)\r
 0:?     'p' (layout(location=3 ) out mediump 4-component vector of float)\r
 0:?     'q' (layout(location=4 ) out 2-element array of mediump 4-component vector of float)\r
+0:?     'ca' (layout(location=40 ) out 4-element array of mediump float)\r
+0:?     'cb' (layout(location=41 ) out 2-element array of mediump float)\r
+0:?     'cc' (layout(location=39 ) out 6-element array of mediump float)\r
 \r
 \r
 Linked fragment stage:\r
index d303b5d..ae183bf 100644 (file)
@@ -2,6 +2,7 @@
 ERROR: 0:7: 'vertex input arrays' : not supported with this profile: es\r
 ERROR: 0:8: 'in' : cannot be a structure or array \r
 ERROR: 0:8: 'vertex input arrays' : not supported with this profile: es\r
+ERROR: 0:8: 'location' : repeated use of location 10\r
 ERROR: 0:12: 'badm4' : cannot specify matrix layout on a variable declaration \r
 ERROR: 0:12: 'badm4' : cannot specify packing on a variable declaration \r
 ERROR: 0:19: 'badf' : member of uniform block cannot have an auxiliary or interpolation qualifier \r
@@ -15,7 +16,8 @@ ERROR: 0:42: 'location qualifier on output' : not supported in this stage: verte
 ERROR: 0:50: 'shared' : not supported with this profile: es\r
 ERROR: 0:50: 'shared' : not supported in this stage: vertex\r
 ERROR: 0:54: 'aoeuntaoeu' : layout qualifiers for matrix layout and packing only apply to uniform or buffer blocks \r
-ERROR: 16 compilation errors.  No code generated.\r
+ERROR: 0:57: 'location' : repeated use of location 40\r
+ERROR: 18 compilation errors.  No code generated.\r
 \r
 \r
 ERROR: node is still EOpNull!\r
@@ -72,6 +74,8 @@ ERROR: node is still EOpNull!
 0:?     'badoutA' (layout(location=10 ) smooth out highp 4-component vector of float)\r
 0:?     'compute_only' (shared highp 4-component vector of float)\r
 0:?     'aoeuntaoeu' (layout(packed ) highp float)\r
+0:?     'cd' (layout(location=40 ) in highp float)\r
+0:?     'ce' (layout(location=37 ) in highp 4X3 matrix of float)\r
 0:?     'gl_VertexID' (gl_VertexId highp int)\r
 0:?     'gl_InstanceID' (gl_InstanceId highp int)\r
 \r
index e6e3368..936cf2b 100644 (file)
@@ -197,7 +197,7 @@ ERROR: node is still EOpNull!
 0:?     'isamp2DA' (uniform isampler2DArray)\r
 0:?     'gl_ClipDistance' (smooth in 4-element array of float)\r
 0:?     'vl' (layout(location=4 ) smooth in 4-component vector of float)\r
-0:?     'vl2' (layout(location=4 ) smooth in 4-component vector of float)\r
+0:?     'vl2' (layout(location=6 ) smooth in 4-component vector of float)\r
 0:?     'uv3' (layout(location=3 ) uniform 3-component vector of float)\r
 0:?     '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})\r
 0:?     '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})\r
index 54d8060..5b7a5aa 100644 (file)
@@ -11,7 +11,8 @@ ERROR: 0:25: 'm3' : cannot use layout qualifiers on structure members
 ERROR: 0:28: '' : cannot use invariant qualifier on a function parameter \r
 ERROR: 0:30: '' : cannot use layout qualifiers on a function parameter \r
 ERROR: 0:31: '' : cannot use auxiliary or interpolation qualifiers on a function parameter \r
-ERROR: 11 compilation errors.  No code generated.\r
+ERROR: 0:42: 'location' : repeated use of location 53\r
+ERROR: 12 compilation errors.  No code generated.\r
 \r
 \r
 ERROR: node is still EOpNull!\r
@@ -36,10 +37,13 @@ ERROR: node is still EOpNull!
 0:31      'cv3' (in 3-component vector of float)\r
 0:?   Linker Objects\r
 0:?     'v4' (layout(location=3 ) 4-component vector of float)\r
-0:?     'uv4' (layout(location=3 ) uniform 4-component vector of float)\r
+0:?     'uv4' (layout(location=4 ) uniform 4-component vector of float)\r
 0:?     'b1' (layout(location=2 ) in block{v})\r
 0:?     'b2' (layout(location=2 ) out block{v})\r
 0:?     '__anon__0' (out block{gl_ClipDistance})\r
+0:?     'cs' (layout(location=10 ) smooth out 2-element array of structure{m,f})\r
+0:?     'cf' (layout(location=54 ) smooth out float)\r
+0:?     'cg' (layout(location=53 ) smooth out float)\r
 0:?     'gl_VertexID' (gl_VertexId int)\r
 0:?     'gl_InstanceID' (gl_InstanceId int)\r
 \r
index 4668014..2629e78 100644 (file)
@@ -16,6 +16,7 @@ ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage
 ERROR: 0:100: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value \r
 ERROR: 0:102: 'color' : redefinition \r
 ERROR: 0:103: 'index' : there is no such layout identifier for this stage taking an assigned value \r
+ERROR: 0:104: 'location' : repeated use of location 3\r
 ERROR: 0:106: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
 ERROR: 0:112: 'depth_any' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
 ERROR: 0:115: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
@@ -48,7 +49,7 @@ ERROR: 0:226: 'in' : not allowed in nested scope
 ERROR: 0:227: 'in' : not allowed in nested scope \r
 ERROR: 0:228: 'in' : not allowed in nested scope \r
 ERROR: 0:232: 'out' : not allowed in nested scope \r
-ERROR: 48 compilation errors.  No code generated.\r
+ERROR: 49 compilation errors.  No code generated.\r
 \r
 \r
 gl_FragCoord pixel center is integer\r
index 1c7db6b..9efa61a 100644 (file)
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build\r
 // going.  However, if it is not updated, it can be a version behind.\r
 \r
-#define GLSLANG_REVISION "24355"\r
-#define GLSLANG_DATE     "2013/12/04 14:48:20"\r
+#define GLSLANG_REVISION "24356"\r
+#define GLSLANG_DATE     "2013/12/04 14:50:38"\r
index c3febee..9d80e3e 100644 (file)
@@ -2649,6 +2649,10 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol)
         default:
             break;
         }
+
+        int repeated = intermediate.addUsedLocation(qualifier, type);
+        if (repeated >= 0)
+            error(loc, "repeated use of location", "location", "%d", repeated);
     }
 
     if (qualifier.hasBinding()) {
index b066912..bacf444 100644 (file)
@@ -443,4 +443,95 @@ bool TIntermediate::userOutputUsed() const
     return found;\r
 }\r
 \r
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions\r
+// as the accumulation is done.\r
+//\r
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.\r
+int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type)\r
+{\r
+    int set;\r
+    if (qualifier.isPipeInput())\r
+        set = 0;\r
+    else if (qualifier.isPipeOutput())\r
+        set = 1;\r
+    else if (qualifier.isUniform())\r
+        set = 2;\r
+    else\r
+        return -1;\r
+\r
+    int size;\r
+    if (qualifier.isUniform()) {\r
+        if (type.isArray())\r
+            size = type.getArraySize();\r
+        else\r
+            size = 1;\r
+    } else\r
+        size = computeTypeLocationSize(type);\r
+\r
+    TRange range = { qualifier.layoutSlotLocation, qualifier.layoutSlotLocation + size - 1 };\r
+\r
+    // check for collisions\r
+    for (size_t r = 0; r < usedLocations[set].size(); ++r) {\r
+        if (range.last  >= usedLocations[set][r].start &&\r
+            range.start <= usedLocations[set][r].last) {\r
+            // there is a collision; pick one\r
+            return std::max(range.start, usedLocations[set][r].start);\r
+        }\r
+    }\r
+\r
+    usedLocations[set].push_back(range);\r
+\r
+    return -1;\r
+}\r
+\r
+// Recursively figure out how many locations are used up by an input or output type.\r
+// Return the size of type, as measured by "locations".\r
+int TIntermediate::computeTypeLocationSize(const TType& type)\r
+{\r
+    // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n \r
+    // consecutive locations..."\r
+    if (type.isArray()) {\r
+        TType elementType(type, 0);\r
+        return type.getArraySize() * computeTypeLocationSize(elementType);\r
+    }\r
+\r
+    // "The locations consumed by block and structure members are determined by applying the rules above \r
+    // recursively..."    \r
+    if (type.isStruct()) {\r
+        // TODO: 440 functionality: input/output block locations when members also have locations\r
+        int size = 0;\r
+        for (size_t member = 0; member < type.getStruct()->size(); ++member) {\r
+            TType memberType(type, member);\r
+            size += computeTypeLocationSize(memberType);\r
+        }\r
+        return size;\r
+    }\r
+\r
+    // "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex \r
+    // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while \r
+    // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will \r
+    // consume only a single location, in all stages."\r
+    if (type.isScalar())\r
+        return 1;\r
+    if (type.isVector()) {\r
+        if (language == EShLangVertex && type.getQualifier().isPipeInput())\r
+            return 1;\r
+        if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)\r
+            return 2;\r
+        else\r
+            return 1;\r
+    }\r
+\r
+    // "If the declared input is an n x m single- or double-precision matrix, ...\r
+    // The number of locations assigned for each matrix will be the same as \r
+    // for an n-element array of m-component vectors..."\r
+    if (type.isMatrix()) {\r
+        TType columnType(type, 0);\r
+        return type.getMatrixCols() * computeTypeLocationSize(columnType);\r
+    }\r
+\r
+    assert(0);\r
+    return 1;\r
+}\r
+\r
 } // end namespace glslang\r
index 5eb9d8b..52a4aa6 100644 (file)
@@ -155,6 +155,8 @@ public:
     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
 
+    int addUsedLocation(const TQualifier&, const TType&);
+
 protected:
     void error(TInfoSink& infoSink, const char*);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
@@ -164,6 +166,7 @@ protected:
     void inOutLocationCheck(TInfoSink&);
     TIntermSequence& findLinkerObjects() const;
     bool userOutputUsed() const;
+    int computeTypeLocationSize(const TType&);
 
 protected:
     const EShLanguage language;
@@ -194,6 +197,12 @@ protected:
 
     std::set<TString> ioAccessed;  // set of names of statically read/written I/O that might need extra checking
 
+    struct TRange {
+        int start;
+        int last;
+    };
+    std::vector<TRange> usedLocations[3];    // sets of used locations, one for each of in, out, and uniform
+
 private:
     void operator=(TIntermediate&); // prevent assignments
 };