From 8de7e7bf1483adf2047870543ca4b9d00b99fc8a Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Sun, 4 Jun 2017 13:05:50 -0600 Subject: [PATCH] GLSL: Error when using location on an arrayed block. This implements a recent change to the GLSL specification to enforce this ill-defined situation. --- Test/450.frag | 9 +++++++++ Test/450.tesc | 9 +++++++++ Test/baseResults/450.frag.out | 11 +++++++++-- Test/baseResults/450.tesc.out | 11 +++++++++-- glslang/MachineIndependent/ParseHelper.cpp | 18 ++++++++++++++++++ glslang/MachineIndependent/ParseHelper.h | 1 + 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Test/450.frag b/Test/450.frag index 04f3aa1ca..19772552d 100644 --- a/Test/450.frag +++ b/Test/450.frag @@ -54,3 +54,12 @@ float cull(int i) { return (i >= 6) ? gl_CullDistance[5] : gl_CullDistance[i]; } + +layout(location = 6) in bName1 { + float f; + layout(location = 7) float g; +} bInst1; +layout(location = 8) in bName2 { + float f; + layout(location = 9) float g; // ERROR, location on array +} bInst2[3]; diff --git a/Test/450.tesc b/Test/450.tesc index 75a9bf469..bf5c08373 100644 --- a/Test/450.tesc +++ b/Test/450.tesc @@ -12,3 +12,12 @@ void main() { gl_out[gl_InvocationID].gl_CullDistance[2] = gl_in[1].gl_CullDistance[2]; } + +layout(location = 4) out bName1 { + float f; + layout(location = 5) float g; +} bInst1[2]; +layout(location = 6) out bName2 { + float f; + layout(location = 7) float g; // ERROR, location on array +} bInst2[2][3]; diff --git a/Test/baseResults/450.frag.out b/Test/baseResults/450.frag.out index 297ae63fb..3e4ed5f96 100644 --- a/Test/baseResults/450.frag.out +++ b/Test/baseResults/450.frag.out @@ -1,8 +1,11 @@ 450.frag Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. +ERROR: 0:62: 'location' : cannot use in a block array where new locations are needed for each block element +ERROR: 1 compilation errors. No code generated. + Shader version: 450 -0:? Sequence +ERROR: node is still EOpNull! 0:8 Function Definition: main( ( global void) 0:8 Function Parameters: 0:10 Sequence @@ -160,13 +163,15 @@ Shader version: 450 0:? 'us2dmsa' ( uniform usampler2DMSArray) 0:? 'ii2dms' (layout( rgba32i) uniform iimage2DMS) 0:? 'i2dmsa' (layout( rgba32f) uniform image2DMSArray) +0:? 'bInst1' ( in block{layout( location=6 component=0) in float f, layout( location=7) in float g}) +0:? 'bInst2' ( in 3-element array of block{layout( location=8 component=0) in float f, layout( location=9) in float g}) Linked fragment stage: Shader version: 450 -0:? Sequence +ERROR: node is still EOpNull! 0:8 Function Definition: main( ( global void) 0:8 Function Parameters: 0:10 Sequence @@ -273,4 +278,6 @@ Shader version: 450 0:? 'us2dmsa' ( uniform usampler2DMSArray) 0:? 'ii2dms' (layout( rgba32i) uniform iimage2DMS) 0:? 'i2dmsa' (layout( rgba32f) uniform image2DMSArray) +0:? 'bInst1' ( in block{layout( location=6 component=0) in float f, layout( location=7) in float g}) +0:? 'bInst2' ( in 3-element array of block{layout( location=8 component=0) in float f, layout( location=9) in float g}) diff --git a/Test/baseResults/450.tesc.out b/Test/baseResults/450.tesc.out index 29da425ec..7e0918f6f 100644 --- a/Test/baseResults/450.tesc.out +++ b/Test/baseResults/450.tesc.out @@ -1,9 +1,12 @@ 450.tesc Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. +ERROR: 0:20: 'location' : cannot use in a block array where new locations are needed for each block element +ERROR: 1 compilation errors. No code generated. + Shader version: 450 vertices = -1 -0:? Sequence +ERROR: node is still EOpNull! 0:11 Function Definition: main( ( global void) 0:11 Function Parameters: 0:13 Sequence @@ -30,6 +33,8 @@ vertices = -1 0:? Linker Objects 0:? 'gl_in' ( in 32-element array of block{ in 3-element array of float CullDistance gl_CullDistance}) 0:? 'gl_out' ( out 4-element array of block{ out 3-element array of float CullDistance gl_CullDistance}) +0:? 'bInst1' ( out 2-element array of block{layout( location=4 component=0) out float f, layout( location=5) out float g}) +0:? 'bInst2' ( out 2-element array of 3-element array of block{layout( location=6 component=0) out float f, layout( location=7) out float g}) Linked tessellation control stage: @@ -38,7 +43,7 @@ ERROR: Linking tessellation control stage: At least one shader must specify an o Shader version: 450 vertices = -1 -0:? Sequence +ERROR: node is still EOpNull! 0:11 Function Definition: main( ( global void) 0:11 Function Parameters: 0:13 Sequence @@ -65,4 +70,6 @@ vertices = -1 0:? Linker Objects 0:? 'gl_in' ( in 32-element array of block{ in 3-element array of float CullDistance gl_CullDistance}) 0:? 'gl_out' ( out 4-element array of block{ out 3-element array of float CullDistance gl_CullDistance}) +0:? 'bInst1' ( out 2-element array of block{layout( location=4 component=0) out float f, layout( location=5) out float g}) +0:? 'bInst2' ( out 2-element array of 3-element array of block{layout( location=6 component=0) out float f, layout( location=7) out float g}) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 91b14adff..5446a789f 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -4391,6 +4391,22 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb } } +// "For some blocks declared as arrays, the location can only be applied at the block level: +// When a block is declared as an array where additional locations are needed for each member +// for each block array element, it is a compile-time error to specify locations on the block +// members. That is, when locations would be under specified by applying them on block members, +// they are not allowed on block members. For arrayed interfaces (those generally having an +// extra level of arrayness due to interface expansion), the outer array is stripped before +// applying this rule." +void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, TArraySizes* arraySizes) +{ + if (memberWithLocation && arraySizes != nullptr) { + if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0)) + error(loc, "cannot use in a block array where new locations are needed for each block element", + "location", ""); + } +} + // Do layout error checking with respect to a type. void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) { @@ -5693,6 +5709,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con memberQualifier = newMemberQualification; } + layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes); + // Process the members fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); fixBlockXfbOffsets(currentBlockQualifier, typeList); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index dc9dc6a04..17acf5d78 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -338,6 +338,7 @@ public: void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); void layoutTypeCheck(const TSourceLoc&, const TType&); void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); -- GitLab