diff --git a/Test/300layout.frag b/Test/300layout.frag index b4b0bba5..70cbc9a5 100644 --- a/Test/300layout.frag +++ b/Test/300layout.frag @@ -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 diff --git a/Test/300layout.vert b/Test/300layout.vert index 18f69c3e..6a863cf5 100644 --- a/Test/300layout.vert +++ b/Test/300layout.vert @@ -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 diff --git a/Test/400.frag b/Test/400.frag index c8039f0f..6d471389 100644 --- a/Test/400.frag +++ b/Test/400.frag @@ -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; diff --git a/Test/430.vert b/Test/430.vert index 6912fb4e..25c17a26 100644 --- a/Test/430.vert +++ b/Test/430.vert @@ -2,7 +2,7 @@ layout(location = 3) vec4 v4; // ERROR -layout(location = 3) uniform vec4 uv4; +layout(location = 4) uniform vec4 uv4; layout(location = 2) in inb1 { vec4 v; } b1; // ERROR layout(location = 2) out outb1 { vec4 v; } b2; // ERROR @@ -30,4 +30,13 @@ void foo3(invariant vec4 v4, // ERROR layout(location = 3) vec2 v2, // ERROR centroid vec3 cv3) // ERROR { -} \ No newline at end of file +} + +struct S { + mat3x2 m[7]; // needs 7*3 locations + float f; // needs 1 location +}; // needs 22 locations + +layout(location = 10) out S cs[2]; // 10 through 10 + 2 * 22 - 1 = 53 +layout(location = 54) out float cf; +layout(location = 53) out float cg; // ERROR, collision at 31 diff --git a/Test/baseResults/300layout.frag.out b/Test/baseResults/300layout.frag.out index 95d35963..ac665696 100644 --- a/Test/baseResults/300layout.frag.out +++ b/Test/baseResults/300layout.frag.out @@ -1,6 +1,8 @@ 300layout.frag ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment -ERROR: 1 compilation errors. No code generated. +ERROR: 0:18: 'location' : repeated use of location 41 +ERROR: 0:19: 'location' : repeated use of location 40 +ERROR: 3 compilation errors. No code generated. ERROR: node is still EOpNull! @@ -25,6 +27,9 @@ ERROR: node is still EOpNull! 0:? 'c' (layout(location=1 ) out mediump 4-component vector of float) 0:? 'p' (layout(location=3 ) out mediump 4-component vector of float) 0:? 'q' (layout(location=4 ) out 2-element array of mediump 4-component vector of float) +0:? 'ca' (layout(location=40 ) out 4-element array of mediump float) +0:? 'cb' (layout(location=41 ) out 2-element array of mediump float) +0:? 'cc' (layout(location=39 ) out 6-element array of mediump float) Linked fragment stage: diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out index d303b5db..ae183bfc 100644 --- a/Test/baseResults/300layout.vert.out +++ b/Test/baseResults/300layout.vert.out @@ -2,6 +2,7 @@ ERROR: 0:7: 'vertex input arrays' : not supported with this profile: es ERROR: 0:8: 'in' : cannot be a structure or array ERROR: 0:8: 'vertex input arrays' : not supported with this profile: es +ERROR: 0:8: 'location' : repeated use of location 10 ERROR: 0:12: 'badm4' : cannot specify matrix layout on a variable declaration ERROR: 0:12: 'badm4' : cannot specify packing on a variable declaration ERROR: 0:19: 'badf' : member of uniform block cannot have an auxiliary or interpolation qualifier @@ -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 ERROR: 0:50: 'shared' : not supported in this stage: vertex ERROR: 0:54: 'aoeuntaoeu' : layout qualifiers for matrix layout and packing only apply to uniform or buffer blocks -ERROR: 16 compilation errors. No code generated. +ERROR: 0:57: 'location' : repeated use of location 40 +ERROR: 18 compilation errors. No code generated. ERROR: node is still EOpNull! @@ -72,6 +74,8 @@ ERROR: node is still EOpNull! 0:? 'badoutA' (layout(location=10 ) smooth out highp 4-component vector of float) 0:? 'compute_only' (shared highp 4-component vector of float) 0:? 'aoeuntaoeu' (layout(packed ) highp float) +0:? 'cd' (layout(location=40 ) in highp float) +0:? 'ce' (layout(location=37 ) in highp 4X3 matrix of float) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/400.frag.out b/Test/baseResults/400.frag.out index e6e33689..936cf2b2 100644 --- a/Test/baseResults/400.frag.out +++ b/Test/baseResults/400.frag.out @@ -197,7 +197,7 @@ ERROR: node is still EOpNull! 0:? 'isamp2DA' (uniform isampler2DArray) 0:? 'gl_ClipDistance' (smooth in 4-element array of float) 0:? 'vl' (layout(location=4 ) smooth in 4-component vector of float) -0:? 'vl2' (layout(location=4 ) smooth in 4-component vector of float) +0:? 'vl2' (layout(location=6 ) smooth in 4-component vector of float) 0:? 'uv3' (layout(location=3 ) uniform 3-component vector of float) 0:? '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor}) 0:? '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor}) diff --git a/Test/baseResults/430.vert.out b/Test/baseResults/430.vert.out index 54d80601..5b7a5aa2 100644 --- a/Test/baseResults/430.vert.out +++ b/Test/baseResults/430.vert.out @@ -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 ERROR: 0:30: '' : cannot use layout qualifiers on a function parameter ERROR: 0:31: '' : cannot use auxiliary or interpolation qualifiers on a function parameter -ERROR: 11 compilation errors. No code generated. +ERROR: 0:42: 'location' : repeated use of location 53 +ERROR: 12 compilation errors. No code generated. ERROR: node is still EOpNull! @@ -36,10 +37,13 @@ ERROR: node is still EOpNull! 0:31 'cv3' (in 3-component vector of float) 0:? Linker Objects 0:? 'v4' (layout(location=3 ) 4-component vector of float) -0:? 'uv4' (layout(location=3 ) uniform 4-component vector of float) +0:? 'uv4' (layout(location=4 ) uniform 4-component vector of float) 0:? 'b1' (layout(location=2 ) in block{v}) 0:? 'b2' (layout(location=2 ) out block{v}) 0:? '__anon__0' (out block{gl_ClipDistance}) +0:? 'cs' (layout(location=10 ) smooth out 2-element array of structure{m,f}) +0:? 'cf' (layout(location=54 ) smooth out float) +0:? 'cg' (layout(location=53 ) smooth out float) 0:? 'gl_VertexID' (gl_VertexId int) 0:? 'gl_InstanceID' (gl_InstanceId int) diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index 4668014b..2629e783 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -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 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' : repeated use of location 3 ERROR: 0:106: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) ERROR: 0:112: 'depth_any' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) ERROR: 0:115: 'depth_greater' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) @@ -48,7 +49,7 @@ ERROR: 0:226: 'in' : not allowed in nested scope 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: 48 compilation errors. No code generated. +ERROR: 49 compilation errors. No code generated. gl_FragCoord pixel center is integer diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 1c7db6ba..9efa61a7 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -9,5 +9,5 @@ // source have to figure out how to create revision.h just to get a build // going. However, if it is not updated, it can be a version behind. -#define GLSLANG_REVISION "24355" -#define GLSLANG_DATE "2013/12/04 14:48:20" +#define GLSLANG_REVISION "24356" +#define GLSLANG_DATE "2013/12/04 14:50:38" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index c3febee0..9d80e3ea 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -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()) { diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index b0669128..bacf4449 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -443,4 +443,95 @@ bool TIntermediate::userOutputUsed() const return found; } +// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions +// as the accumulation is done. +// +// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. +int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type) +{ + int set; + if (qualifier.isPipeInput()) + set = 0; + else if (qualifier.isPipeOutput()) + set = 1; + else if (qualifier.isUniform()) + set = 2; + else + return -1; + + int size; + if (qualifier.isUniform()) { + if (type.isArray()) + size = type.getArraySize(); + else + size = 1; + } else + size = computeTypeLocationSize(type); + + TRange range = { qualifier.layoutSlotLocation, qualifier.layoutSlotLocation + size - 1 }; + + // check for collisions + for (size_t r = 0; r < usedLocations[set].size(); ++r) { + if (range.last >= usedLocations[set][r].start && + range.start <= usedLocations[set][r].last) { + // there is a collision; pick one + return std::max(range.start, usedLocations[set][r].start); + } + } + + usedLocations[set].push_back(range); + + return -1; +} + +// Recursively figure out how many locations are used up by an input or output type. +// Return the size of type, as measured by "locations". +int TIntermediate::computeTypeLocationSize(const TType& type) +{ + // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n + // consecutive locations..." + if (type.isArray()) { + TType elementType(type, 0); + return type.getArraySize() * computeTypeLocationSize(elementType); + } + + // "The locations consumed by block and structure members are determined by applying the rules above + // recursively..." + if (type.isStruct()) { + // TODO: 440 functionality: input/output block locations when members also have locations + int size = 0; + for (size_t member = 0; member < type.getStruct()->size(); ++member) { + TType memberType(type, member); + size += computeTypeLocationSize(memberType); + } + return size; + } + + // "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex + // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while + // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will + // consume only a single location, in all stages." + if (type.isScalar()) + return 1; + if (type.isVector()) { + if (language == EShLangVertex && type.getQualifier().isPipeInput()) + return 1; + if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2) + return 2; + else + return 1; + } + + // "If the declared input is an n x m single- or double-precision matrix, ... + // The number of locations assigned for each matrix will be the same as + // for an n-element array of m-component vectors..." + if (type.isMatrix()) { + TType columnType(type, 0); + return type.getMatrixCols() * computeTypeLocationSize(columnType); + } + + assert(0); + return 1; +} + } // end namespace glslang diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 5eb9d8bc..52a4aa66 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -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 ioAccessed; // set of names of statically read/written I/O that might need extra checking + struct TRange { + int start; + int last; + }; + std::vector usedLocations[3]; // sets of used locations, one for each of in, out, and uniform + private: void operator=(TIntermediate&); // prevent assignments };