diff --git a/Test/baseResults/440.frag.out b/Test/baseResults/440.frag.out index 7ea19262d..9de029a21 100644 --- a/Test/baseResults/440.frag.out +++ b/Test/baseResults/440.frag.out @@ -1,7 +1,7 @@ 440.frag ERROR: 0:11: 'location' : overlapping use of location 4 ERROR: 0:13: 'component' : type overflows the available 4 components -ERROR: 0:22: 'location' : fragment outputs or tileImageEXTs sharing the same location 30 must be the same basic type +ERROR: 0:22: 'location' : the aliases sharing the location 30 must be the same basic type and interpolation qualification ERROR: 0:24: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) ERROR: 0:25: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) ERROR: 0:26: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) diff --git a/Test/baseResults/440.vert.out b/Test/baseResults/440.vert.out index 6c975c09a..f34154852 100644 --- a/Test/baseResults/440.vert.out +++ b/Test/baseResults/440.vert.out @@ -10,16 +10,21 @@ ERROR: 0:39: 'component' : type overflows the available 4 components ERROR: 0:40: 'component' : type overflows the available 4 components ERROR: 0:42: 'component' : cannot apply to a matrix, structure, or block ERROR: 0:43: 'component' : cannot apply to a matrix, structure, or block +ERROR: 0:43: 'location' : the aliases sharing the location 33 must be the same basic type and interpolation qualification ERROR: 0:44: 'component' : cannot apply to a matrix, structure, or block +ERROR: 0:44: 'location' : the aliases sharing the location 34 must be the same basic type and interpolation qualification ERROR: 0:46: 'component' : must specify 'location' to use 'component' ERROR: 0:52: 'location' : overlapping use of location 40 ERROR: 0:54: 'component' : type overflows the available 4 components 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:58: 'location' : the aliases sharing the location 43 must be the same basic type and interpolation qualification ERROR: 0:61: 'location/component/index' : cannot declare a default, use a full declaration +ERROR: 0:64: 'location' : the aliases sharing the location 50 must be the same basic type and interpolation qualification ERROR: 0:66: 'component' : doubles cannot start on an odd-numbered component ERROR: 0:67: 'component' : type overflows the available 4 components +ERROR: 0:69: 'location' : the aliases sharing the location 53 must be the same basic type and interpolation qualification ERROR: 0:71: 'location' : overlapping use of location 55 ERROR: 0:75: 'location' : overlapping use of location 57 ERROR: 0:78: 'location' : overlapping use of location 59 @@ -56,7 +61,7 @@ ERROR: 0:193: 'assign' : l-value required "gl_BaseVertexARB" (can't modify shad ERROR: 0:194: 'assign' : l-value required "gl_BaseInstanceARB" (can't modify shader input) ERROR: 0:195: 'assign' : l-value required "gl_DrawIDARB" (can't modify shader input) ERROR: 0:196: 'glBaseInstanceARB' : undeclared identifier -ERROR: 57 compilation errors. No code generated. +ERROR: 62 compilation errors. No code generated. Shader version: 440 diff --git a/Test/baseResults/location_aliasing.tesc.out b/Test/baseResults/location_aliasing.tesc.out new file mode 100644 index 000000000..54263d25d --- /dev/null +++ b/Test/baseResults/location_aliasing.tesc.out @@ -0,0 +1,33 @@ +location_aliasing.tesc +ERROR: 0:7: 'location' : the aliases sharing the location 1 must be the same basic type and interpolation qualification +ERROR: 1 compilation errors. No code generated. + + +Shader version: 430 +Requested GL_ARB_enhanced_layouts +vertices = 1 +ERROR: node is still EOpNull! +0:13 Function Definition: main( ( global void) +0:13 Function Parameters: +0:? Linker Objects +0:? 'gohan' (layout( location=1 component=0) in 32-element array of double) +0:? 'goten' (layout( location=1 component=2) in 32-element array of float) +0:? 'vs_tcs' ( in 32-element array of 4-component vector of float) +0:? 'tcs_tes' ( out 1-element array of 4-component vector of float) + + +Linked tessellation control stage: + + +Shader version: 430 +Requested GL_ARB_enhanced_layouts +vertices = 1 +ERROR: node is still EOpNull! +0:13 Function Definition: main( ( global void) +0:13 Function Parameters: +0:? Linker Objects +0:? 'gohan' (layout( location=1 component=0) in 32-element array of double) +0:? 'goten' (layout( location=1 component=2) in 32-element array of float) +0:? 'vs_tcs' ( in 32-element array of 4-component vector of float) +0:? 'tcs_tes' ( out 1-element array of 4-component vector of float) + diff --git a/Test/baseResults/location_aliasing1.frag.out b/Test/baseResults/location_aliasing1.frag.out new file mode 100644 index 000000000..3a1e1a24b --- /dev/null +++ b/Test/baseResults/location_aliasing1.frag.out @@ -0,0 +1,27 @@ +location_aliasing1.frag +ERROR: 0:6: 'location' : the aliases sharing the location 1 must be the same basic type and interpolation qualification +ERROR: 1 compilation errors. No code generated. + + +Shader version: 430 +Requested GL_ARB_enhanced_layouts +ERROR: node is still EOpNull! +0:8 Function Definition: main( ( global void) +0:8 Function Parameters: +0:? Linker Objects +0:? 'in1' (layout( location=1 component=0) smooth in float) +0:? 'in2' (layout( location=1 component=2) flat in float) + + +Linked fragment stage: + + +Shader version: 430 +Requested GL_ARB_enhanced_layouts +ERROR: node is still EOpNull! +0:8 Function Definition: main( ( global void) +0:8 Function Parameters: +0:? Linker Objects +0:? 'in1' (layout( location=1 component=0) smooth in float) +0:? 'in2' (layout( location=1 component=2) flat in float) + diff --git a/Test/baseResults/spv.ext.ShaderTileImage.typemismatch.frag.out b/Test/baseResults/spv.ext.ShaderTileImage.typemismatch.frag.out index e91ffb73f..057e5e1d5 100644 --- a/Test/baseResults/spv.ext.ShaderTileImage.typemismatch.frag.out +++ b/Test/baseResults/spv.ext.ShaderTileImage.typemismatch.frag.out @@ -1,5 +1,5 @@ spv.ext.ShaderTileImage.typemismatch.frag -ERROR: 0:7: 'location' : fragment outputs or tileImageEXTs sharing the same location 0 must be the same basic type +ERROR: 0:7: 'location' : the aliases sharing the location 0 must be the same basic type and interpolation qualification ERROR: 1 compilation errors. No code generated. diff --git a/Test/location_aliasing.tesc b/Test/location_aliasing.tesc new file mode 100644 index 000000000..624396519 --- /dev/null +++ b/Test/location_aliasing.tesc @@ -0,0 +1,15 @@ +#version 430 core +#extension GL_ARB_enhanced_layouts : require + +layout(vertices = 1) out; + +layout (location = 1, component = 0) in double gohan[]; +layout (location = 1, component = 2) in float goten[]; + + +in vec4 vs_tcs[]; +out vec4 tcs_tes[]; + +void main() +{ +} \ No newline at end of file diff --git a/Test/location_aliasing1.frag b/Test/location_aliasing1.frag new file mode 100644 index 000000000..c8c7d264d --- /dev/null +++ b/Test/location_aliasing1.frag @@ -0,0 +1,10 @@ +#version 430 core +#extension GL_ARB_enhanced_layouts : require + + +layout (location = 1, component = 0) in smooth float in1; +layout (location = 1, component = 2) in flat float in2; + +void main() +{ +} \ No newline at end of file diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f157d15b2..cb19b2d43 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -6568,10 +6568,10 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision); if (repeated >= 0 && ! typeCollision) error(loc, "overlapping use of location", "location", "%d", repeated); - // "fragment-shader outputs/tileImageEXT ... if two variables are placed within the same - // location, they must have the same underlying type (floating-point or integer)" - if (typeCollision && language == EShLangFragment && (qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT)) - error(loc, "fragment outputs or tileImageEXTs sharing the same location", "location", "%d must be the same basic type", repeated); + // When location aliasing, the aliases sharing the location must have the same underlying numerical type and bit width( + // floating - point or integer, 32 - bit versus 64 - bit,etc.) + if (typeCollision && (qualifier.isPipeInput() || qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT)) + error(loc, "the aliases sharing the location", "location", "%d must be the same basic type and interpolation qualification", repeated); } if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 3b5add9de..62e24426e 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -1689,7 +1689,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ // First range: TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation); TRange componentRange(0, 3); - TIoRange range(locationRange, componentRange, type.getBasicType(), 0); + TIoRange range(locationRange, componentRange, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat); // check for collisions collision = checkLocationRange(set, range, type, typeCollision); @@ -1699,7 +1699,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ // Second range: TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1); TRange componentRange2(0, 1); - TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0); + TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat); // check for collisions collision = checkLocationRange(set, range2, type, typeCollision); @@ -1725,7 +1725,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ TBasicType basicTy = type.getBasicType(); if (basicTy == EbtSampler && type.getSampler().isAttachmentEXT()) basicTy = type.getSampler().type; - TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0); + TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0, qualifier.centroid, qualifier.smooth, qualifier.flat); // check for collisions, except for vertex inputs on desktop targeting OpenGL if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0) @@ -1748,7 +1748,11 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp if (range.overlap(usedIo[set][r])) { // there is a collision; pick one return std::max(range.location.start, usedIo[set][r].location.start); - } else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) { + } else if (range.location.overlap(usedIo[set][r].location) && + (type.getBasicType() != usedIo[set][r].basicType || + type.getQualifier().centroid != usedIo[set][r].centroid || + type.getQualifier().smooth != usedIo[set][r].smooth || + type.getQualifier().flat != usedIo[set][r].flat)) { // aliased-type mismatch typeCollision = true; return std::max(range.location.start, usedIo[set][r].location.start); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index c9eac27d5..5e9714780 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -123,8 +123,10 @@ struct TRange { // 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, int index) - : location(location), component(component), basicType(basicType), index(index) { } + TIoRange(TRange location, TRange component, TBasicType basicType, int index, bool centroid, bool smooth, bool flat) + : location(location), component(component), basicType(basicType), index(index), centroid(centroid), smooth(smooth), flat(flat) + { + } bool overlap(const TIoRange& rhs) const { return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; @@ -133,6 +135,9 @@ struct TIoRange { TRange component; TBasicType basicType; int index; + bool centroid; + bool smooth; + bool flat; }; // An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp index 7410f6ce1..6067e9b83 100644 --- a/gtests/AST.FromFile.cpp +++ b/gtests/AST.FromFile.cpp @@ -306,6 +306,8 @@ INSTANTIATE_TEST_SUITE_P( "coord_conventions.frag", "gl_FragCoord.frag", "glsl.interpOp.error.frag", + "location_aliasing.tesc", + "location_aliasing1.frag", "GL_EXT_draw_instanced.vert", "overflow_underflow_toinf_0.frag", "GL_EXT_texture_array.frag",