From aa657c117ee90f070eb0a0a40882775920470e6b Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Tue, 19 Aug 2014 02:12:44 +0000 Subject: [PATCH] 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 --- Test/330.frag | 10 +++- Test/400.geom | 2 + Test/430.vert | 4 +- Test/baseResults/140.frag.out | 1 - Test/baseResults/140.vert.out | 1 - Test/baseResults/330.frag.out | 27 +++++++-- Test/baseResults/400.geom.out | 5 +- Test/baseResults/420.vert.out | 5 +- Test/baseResults/430.vert.out | 7 ++- Test/baseResults/440.frag.out | 4 +- Test/baseResults/440.vert.out | 2 +- Test/baseResults/specExamples.frag.out | 8 +-- Todo.txt | 2 +- glslang/Include/Types.h | 26 +++++++-- glslang/MachineIndependent/ParseHelper.cpp | 57 +++++++++++++------ glslang/MachineIndependent/Versions.cpp | 2 +- glslang/MachineIndependent/linkValidate.cpp | 18 +++--- .../MachineIndependent/localintermediate.h | 12 ++-- 18 files changed, 135 insertions(+), 58 deletions(-) diff --git a/Test/330.frag b/Test/330.frag index d6083c062..a23ab6644 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 @@ layout(location = 44) in block { 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 34a3fb960..7fe9fc1c3 100644 --- a/Test/400.geom +++ b/Test/400.geom @@ -99,3 +99,5 @@ void bits() 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 07228236b..64dd42f23 100644 --- a/Test/430.vert +++ b/Test/430.vert @@ -114,13 +114,13 @@ int bconst[gl_MaxTransformFeedbackInterleavedComponents]; 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 8600e929e..ebb4e5648 100644 --- a/Test/baseResults/140.frag.out +++ b/Test/baseResults/140.frag.out @@ -6,7 +6,6 @@ ERROR: 0:24: 'location' : not supported for this version or the enabled extensio 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 2fa91916f..0b0799fc1 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 e56026b4c..e2c454033 100644 --- a/Test/baseResults/330.frag.out +++ b/Test/baseResults/330.frag.out @@ -26,7 +26,14 @@ ERROR: 0:89: 'location qualifier on uniform or buffer' : not supported for this 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 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 b05fd2fb0..65895a6ea 100644 --- a/Test/baseResults/400.geom.out +++ b/Test/baseResults/400.geom.out @@ -18,7 +18,8 @@ ERROR: 0:65: 'max_vertices' : can only apply to 'out' 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 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 ca3c81e71..fd58f68bf 100644 --- a/Test/baseResults/420.vert.out +++ b/Test/baseResults/420.vert.out @@ -23,7 +23,8 @@ ERROR: 0:54: 'y' : vector field selection out of range 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:142: 'r8_snorm' : does not apply to signed integer images 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 3f6515ba6..b3cb9b2d7 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:47: 'gl_ClipDistance array size' : must be less than gl_MaxClipDistance 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:92: 'transform feedback qualifier' : not supported for this version or 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:168: 'textureSamples and imageSamples' : not supported for this version 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 eb5632ab1..d87294938 100644 --- a/Test/baseResults/440.frag.out +++ b/Test/baseResults/440.frag.out @@ -19,11 +19,13 @@ ERROR: 0:35: 'layout' : offset/align can only be used on a uniform or buffer 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:85: 'offset' : must be a multiple of the member's alignment 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 5bf767033..12814f21e 100644 --- a/Test/baseResults/440.vert.out +++ b/Test/baseResults/440.vert.out @@ -18,7 +18,7 @@ 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: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 7e0b41d8d..6dfa4b850 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -14,8 +14,6 @@ ERROR: 0:99: 'local_size_x' : there is no such layout identifier for this stage 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: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: 43 compilation errors. No code generated. +ERROR: 41 compilation errors. No code generated. Shader version: 430 @@ -289,7 +287,7 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 6d03f468c..9be6445f3 100644 --- a/Todo.txt +++ b/Todo.txt @@ -206,7 +206,7 @@ Shader Functionality to Implement/Finish + 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 6efc3f13d..4ac3a0211 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -483,6 +483,8 @@ public: layoutLocation = layoutLocationEnd; layoutComponent = layoutComponentEnd; layoutBinding = layoutBindingEnd; + layoutIndex = layoutIndexEnd; + layoutStream = layoutStreamEnd; layoutXfbBuffer = layoutXfbBufferEnd; @@ -494,7 +496,7 @@ public: bool hasLayout() const { return hasUniformLayout() || - hasLocation() || + hasAnyLocation() || hasBinding() || hasStream() || hasXfb() || @@ -514,6 +516,9 @@ public: 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 @@ public: { 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 @@ public: 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 b4393de33..9abd95805 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -3266,6 +3266,13 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, 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 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst, 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 @@ void TParseContext::layoutObjectCheck(TSourceLoc loc, const TSymbol& symbol) // 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 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type) // 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 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type) 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 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali 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 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali 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 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr 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 @@ void TParseContext::fixBlockLocations(TSourceLoc loc, TQualifier& qualifier, TTy 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 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub 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 5add18c72..cf4e7504b 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -165,7 +165,7 @@ void TParseContext::initializeExtensionBehavior() 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 8efe22410..d183a65f2 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -313,13 +313,15 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy } // 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 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink) if (language == EShLangFragment) { if (qualifier.storage == EvqVaryingOut) { ++numFragOut; - if (qualifier.hasLocation()) + if (qualifier.hasAnyLocation()) fragOutHasLocation = true; else fragOutWithNoLocation = true; @@ -634,11 +636,11 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ 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 8fdc0e836..d762efec8 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -77,18 +77,20 @@ struct TRange { 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. -- GitLab