diff --git a/Install/Windows/glslangValidator.exe b/Install/Windows/glslangValidator.exe index 248a1e4ffc51d0c8599c60ae77c5b9afb6118d37..24272a3983d2c18fbde74f02f0de81d3ab33e40c 100644 Binary files a/Install/Windows/glslangValidator.exe and b/Install/Windows/glslangValidator.exe differ diff --git a/Test/130.frag b/Test/130.frag index c65cd0efd2efe00627839a655c0504b56eae4396..3099a47bf408ea25df4713826bca743ea8c5fe46 100644 --- a/Test/130.frag +++ b/Test/130.frag @@ -31,3 +31,9 @@ void bar() { vec4 s = textureGather(sampC, vec3(0.2)); } + +flat in vec3 gl_Color; // ERROR, type +in vec4 gl_Color; +flat in vec4 gl_Color; +flat in vec4 gl_Color[2]; // ERROR, array +vec4 gl_Color; // ERROR, storage diff --git a/Test/150.frag b/Test/150.frag new file mode 100644 index 0000000000000000000000000000000000000000..fb15a00f4792936c4f88272080c8934e13d27242 --- /dev/null +++ b/Test/150.frag @@ -0,0 +1,14 @@ +#version 150 core + +in vec4 gl_FragCoord; +layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; // ERROR +layout(pixel_center_integer) in vec4 gl_FragCoord; // ERROR +layout(origin_upper_left) in vec4 foo; // ERROR +layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; + +void main() +{ + vec4 c = gl_FragCoord; +} + +layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; diff --git a/Test/300.frag b/Test/300.frag index 88539cb5954e5798b3ec57a72367b387a622f1fd..d63c81e26bd326ec85cd11193566a8cf5520319c 100644 --- a/Test/300.frag +++ b/Test/300.frag @@ -103,5 +103,13 @@ uniform multi { int c[2][3]; // ERROR } multiInst[2][3]; // ERROR +out vec4 colors[4]; + +void foo() +{ + colors[2] = c4D; + colors[ic1D] = c4D; +} + float imageBuffer; // ERROR, reserved float uimage2DRect; // ERROR, reserved diff --git a/Test/400.frag b/Test/400.frag index b2d8398963d0d4f4a278e5f069e660646054098a..82cd3ab05ba1280189161b29228dcee4b1f66055 100644 --- a/Test/400.frag +++ b/Test/400.frag @@ -21,6 +21,8 @@ void main() iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 4); // ERROR, last argument out of range iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 1+2); iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i)); + + vec4 c = gl_FragCoord; } layout(location = 4) in vec4 vl; // ERROR, not supported @@ -32,3 +34,8 @@ layout(location = 4) in vec4 vl; // ERROR, not supported layout(location = 4) in vec4 vl2; layout(location = 3) uniform vec3 uv3; + +layout(location = 5) in vec4 gl_Color; // ERROR, layout +noperspective in float gl_ClipDistance[4]; // ERROR, can't change qualifier + +layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; diff --git a/Test/baseResults/130.frag.out b/Test/baseResults/130.frag.out index f6120e9b4e7477fbc55e8e4edb1ae9d6a1facead..55d7e528a8504e670eb689b9d88234246dbea87b 100644 --- a/Test/baseResults/130.frag.out +++ b/Test/baseResults/130.frag.out @@ -1,6 +1,9 @@ Warning, version 130 is not yet complete; most features are present, but a few are missing. ERROR: 0:25: 'texture gather function' : not supported for this version or the enabled extensions -ERROR: 1 compilation errors. No code generated. +ERROR: 0:35: 'redeclaration' : cannot change the type of gl_Color +ERROR: 0:38: 'gl_Color' : redeclaring non-array as array +ERROR: 0:39: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_Color +ERROR: 4 compilation errors. No code generated. ERROR: node is still EOpNull! 0:16 Function Definition: main( (void) @@ -48,4 +51,6 @@ ERROR: node is still EOpNull! 0:? 'fnop' (noperspective in float) 0:? 'gl_ClipDistance' (smooth in unsized array of float) 0:? 'sampC' (uniform samplerCube) +0:? 'gl_Color' (smooth in 4-component vector of float) +0:? 'gl_Color' (flat in 4-component vector of float) diff --git a/Test/baseResults/150.frag.out b/Test/baseResults/150.frag.out new file mode 100644 index 0000000000000000000000000000000000000000..9d98ddfa3f41660973a163fdf7e5312401338b15 --- /dev/null +++ b/Test/baseResults/150.frag.out @@ -0,0 +1,21 @@ +Warning, version 150 is not yet complete; some version-specific features are present, but many are missing. +ERROR: 0:4: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord +ERROR: 0:5: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord +ERROR: 0:6: 'layout qualifier' : can only apply origin_upper_left and pixel_center_origin to gl_FragCoord +ERROR: 3 compilation errors. No code generated. + +gl_FragCoord pixel center is integer +gl_FragCoord origin is upper left +ERROR: node is still EOpNull! +0:9 Function Definition: main( (void) +0:9 Function Parameters: +0:11 Sequence +0:11 Sequence +0:11 move second child to first child (4-component vector of float) +0:11 'c' (4-component vector of float) +0:11 'gl_FragCoord' (gl_FragCoord 4-component vector of float) +0:? Linker Objects +0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float) +0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float) +0:? 'foo' (smooth in 4-component vector of float) + diff --git a/Test/baseResults/150.geom.out b/Test/baseResults/150.geom.out index 186e4a492753af4f888e407104f8491b1b7297e7..0da9b61ddc7ff1dd392b80804676d226b93c89b6 100644 --- a/Test/baseResults/150.geom.out +++ b/Test/baseResults/150.geom.out @@ -71,7 +71,7 @@ ERROR: node is still EOpNull! 0:33 Constant: 0:33 2 (const int) 0:34 move second child to first child (4-component vector of float) -0:34 gl_Position: direct index for structure (layout(stream=0 ) 4-component vector of float) +0:34 gl_Position: direct index for structure (layout(stream=0 ) gl_Position 4-component vector of float) 0:34 '__anon__1' (layout(stream=0 ) out block{gl_Position,gl_PointSize,gl_ClipDistance}) 0:34 Constant: 0:34 0 (const uint) @@ -83,7 +83,7 @@ ERROR: node is still EOpNull! 0:34 Constant: 0:34 0 (const int) 0:35 move second child to first child (float) -0:35 gl_PointSize: direct index for structure (layout(stream=0 ) float) +0:35 gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float) 0:35 '__anon__1' (layout(stream=0 ) out block{gl_Position,gl_PointSize,gl_ClipDistance}) 0:35 Constant: 0:35 1 (const uint) diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out index 670ce24daf1f3216063f00126c2caa555c18262c..2e0d6575e19b19eb62fae6652ad40f19b962128a 100644 --- a/Test/baseResults/300.frag.out +++ b/Test/baseResults/300.frag.out @@ -17,9 +17,10 @@ ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es ERROR: 0:103: 'arrays of arrays' : not supported with this profile: es ERROR: 0:100: 'arrays of arrays' : not supported with this profile: es -ERROR: 0:106: 'imageBuffer' : Reserved word. -ERROR: 0:106: '' : syntax error -ERROR: 21 compilation errors. No code generated. +ERROR: 0:111: 'variable indexing fragment shader ouput array' : not supported with this profile: es +ERROR: 0:114: 'imageBuffer' : Reserved word. +ERROR: 0:114: '' : syntax error +ERROR: 22 compilation errors. No code generated. ERROR: node is still EOpNull! 0:53 Function Definition: main( (void) @@ -208,6 +209,20 @@ ERROR: node is still EOpNull! 0:96 'c4D' (smooth lowp 4-component vector of float) 0:97 arc hyp. tangent (lowp 3-component vector of float) 0:97 'c3D' (smooth in lowp 3-component vector of float) +0:108 Function Definition: foo( (void) +0:108 Function Parameters: +0:110 Sequence +0:110 move second child to first child (lowp 4-component vector of float) +0:110 direct index (lowp 4-component vector of float) +0:110 'colors' (out 4-element array of lowp 4-component vector of float) +0:110 Constant: +0:110 2 (const int) +0:110 'c4D' (smooth lowp 4-component vector of float) +0:111 move second child to first child (lowp 4-component vector of float) +0:111 indirect index (lowp 4-component vector of float) +0:111 'colors' (out 4-element array of lowp 4-component vector of float) +0:111 'ic1D' (flat in mediump int) +0:111 'c4D' (smooth lowp 4-component vector of float) 0:? Linker Objects 0:? 's2D' (uniform lowp sampler2D) 0:? 's3D' (uniform lowp sampler3D) @@ -240,4 +255,5 @@ ERROR: node is still EOpNull! 0:? 'sf' (out lowp float) 0:? 'arrayedSampler' (uniform 5-element array of lowp sampler2D) 0:? 'multiInst' (layout(column_major shared ) uniform 2-element array of block{a,b,c}) +0:? 'colors' (out 4-element array of lowp 4-component vector of float) diff --git a/Test/baseResults/400.frag.out b/Test/baseResults/400.frag.out index 89396d2728a5c4461950c975f68280ce909ef238..6f478f6414827da42c3ef9974d7e0a3ff64c4fdc 100644 --- a/Test/baseResults/400.frag.out +++ b/Test/baseResults/400.frag.out @@ -1,10 +1,15 @@ Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. ERROR: 0:20: 'texture gather component' : must be a constant ERROR: 0:21: 'texture gather component' : must be 0, 1, 2, or 3 -ERROR: 0:26: 'location qualifier on input' : not supported for this version or the enabled extensions -ERROR: 0:34: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions -ERROR: 4 compilation errors. No code generated. +ERROR: 0:28: 'location qualifier on input' : not supported for this version or the enabled extensions +ERROR: 0:36: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions +ERROR: 0:38: 'redeclaration' : cannot apply layout qualifier to gl_Color +ERROR: 0:39: 'redeclaration' : cannot change qualification of gl_ClipDistance +ERROR: 0:41: 'gl_FragCoord' : cannot redeclare after use +ERROR: 7 compilation errors. No code generated. +gl_FragCoord pixel center is integer +gl_FragCoord origin is upper left ERROR: node is still EOpNull! 0:10 Function Definition: main( (void) 0:10 Function Parameters: @@ -105,6 +110,10 @@ ERROR: node is still EOpNull! 0:23 0.100000 0:23 Construct ivec2 (2-component vector of int) 0:23 'i' (flat in int) +0:25 Sequence +0:25 move second child to first child (4-component vector of float) +0:25 'c' (4-component vector of float) +0:25 'gl_FragCoord' (gl_FragCoord 4-component vector of float) 0:? Linker Objects 0:? 'c2D' (smooth in 2-component vector of float) 0:? 'i' (flat in int) @@ -112,8 +121,12 @@ ERROR: node is still EOpNull! 0:? 'arrayedSampler' (uniform 5-element array of sampler2D) 0:? 'samp2dr' (uniform usampler2DRect) 0:? 'isamp2DA' (uniform isampler2DArray) -0:? 'gl_ClipDistance' (smooth in unsized array of float) +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:? '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}) +0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float) +0:? 'gl_FragCoord' (gl_FragCoord 4-component vector of float) diff --git a/Test/baseResults/410.geom.out b/Test/baseResults/410.geom.out index 5a01691c79ca2fc810a76cece61c1f5c7fe19ddd..0b3acd853c43b1abfdff93681303b94fad2ae3c2 100644 --- a/Test/baseResults/410.geom.out +++ b/Test/baseResults/410.geom.out @@ -32,7 +32,7 @@ ERROR: node is still EOpNull! 0:30 Constant: 0:30 0 (const int) 0:31 move second child to first child (float) -0:31 gl_PointSize: direct index for structure (layout(stream=0 ) float) +0:31 gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float) 0:31 '__anon__0' (layout(stream=0 ) out block{gl_PointSize}) 0:31 Constant: 0:31 0 (const uint) diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index de312ae814f786f590c482ed938017e6a2c6017f..19a1c155abe53f71b17e87bc807595e71e9689d8 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -6,10 +6,8 @@ ERROR: 0:37: 'view' : redefinition ERROR: 0:68: 'lightPosition' : redefinition ERROR: 0:75: 'Atten' : member storage qualifier cannot contradict block storage qualifier ERROR: 0:87: 'Color' : redefinition -ERROR: 0:92: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) -ERROR: 0:93: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) -ERROR: 0:94: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) -ERROR: 0:94: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) +ERROR: 0:92: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord +ERROR: 0:93: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord ERROR: 0:96: 'early_fragment_tests' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) ERROR: 0:99: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage taking an assigned value @@ -48,8 +46,10 @@ 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: 49 compilation errors. No code generated. +ERROR: 47 compilation errors. No code generated. +gl_FragCoord pixel center is integer +gl_FragCoord origin is upper left ERROR: node is still EOpNull! 0:5 Sequence 0:5 move second child to first child (int) diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out index 030d42ef4bd4cefd3cfd267ad67aa5098d34c6b3..280390337bf17e0bfc1b3f437e1f60ae448e2132 100644 --- a/Test/baseResults/specExamples.vert.out +++ b/Test/baseResults/specExamples.vert.out @@ -30,6 +30,8 @@ ERROR: 0:95: 'binding' : requires block, or sampler/image, or atomic-counter typ ERROR: 0:96: 'binding' : requires block, or sampler/image, or atomic-counter type ERROR: 0:97: 'binding' : requires block, or sampler/image, or atomic-counter type ERROR: 0:106: '' : vertex input cannot be further qualified +ERROR: 0:106: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_FrontColor +ERROR: 0:107: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_FrontColor ERROR: 0:112: 'ColorIvn' : identifier not previously declared ERROR: 0:132: 'shared' : not supported in this stage: vertex ERROR: 0:134: '' : function does not return a value: funcA @@ -40,7 +42,7 @@ ERROR: 0:153: '' : function does not return a value: func3 ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array -ERROR: 40 compilation errors. No code generated. +ERROR: 42 compilation errors. No code generated. ERROR: node is still EOpNull! 0:134 Function Definition: funcA(I21; (4-component vector of float) diff --git a/Test/testlist b/Test/testlist index aebde4a53cb38c84250357880224826f3cc42e89..74d5d84b7ef928d3b1a6caf4b5c982d97efc9d76 100644 --- a/Test/testlist +++ b/Test/testlist @@ -14,6 +14,7 @@ versionsErrors.vert 140.frag 150.vert 150.geom +150.frag precision.frag precision.vert nonSquare.vert diff --git a/Todo.txt b/Todo.txt index f3ce5b4919b9bea45e6aa4c6560d3afbed928503..29ed8c1cc52bf167f8593b1e9d492a97d7066690 100644 --- a/Todo.txt +++ b/Todo.txt @@ -12,40 +12,49 @@ Link Validation - statically consumed input not produced by previous stage - give error for sharing a packed block - 1.2: matching initializers for uniforms + - 1.3: only statically used built-ins have to be redeclared as flat - 1.5: matching between gl_PerVertex blocks and gl_PerFragment blocks - 1.3: deprecated mixing fixed vertex/fragment stage with programmable fragment/vertex stage. - 4.3: compute shader not combined with any other stages - 4.3: remove cross-version linking restrictions. - 4.3: Allow mismatches in interpolation and auxiliary qualification across stages. - 4.4: A stage contains two different blocks, each with no instance name, where the blocks contain a member with the same name. - Intra-stage linking - - ES 3.0: location aliasing/overlap (except desktop vertex shader inputs) - + ES 3.0: fragment outputs all have locations, if more than one + Intra-stage linking, single shader + - limits checking: + - number of texture image units + - texel offsets (or compile-time?) + - number of input/output compononents + - tessellation limits + - ... + exactly one main + + ES 3.0: fragment outputs all have locations, if more than one + - ES 3.0: location aliasing/overlap (except desktop vertex shader inputs) + - Non ES: binding overlap? + - Non ES: gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords + + Non ES: geometry shader input array sizes and input layout qualifier declaration + - Non ES: read or write to both gl_ClipVertex and gl_ClipDistance + - Non ES: write to only one of gl_FragColor, gl_FragData, or user-declared + - 1.50: at least one geometry shader says input primitive and at least one says output primitive... + - 1.50: at least one geometry shader says max_vertices... + - 4.4: An interface contains two different blocks, each with no instance name, where the blocks contain a member with the same name. + - 4.4: component aliasing (except desktop vertex shader inputs) + Intra-stage linking, multiple shader + Non ES: type consistency check of uniforms, globals, ins, and outs + Non ES: value checking of global const initializers + Non ES: value checking of uniform initializers + Non ES: location match - - Non ES: gl_TexCoord can only have a max array size of up to gl_MaxTextureCoords + recursion for functions - Non ES: block matching - Non ES: component/binding/index/offset match check - - Non ES: geometry shader input array sizes and input layout qualifier declaration - Non ES: compute shader layout(local_size_*) matching + mixed es/non-es profiles are an error - Non ES: Even the potential for recursion through subroutine uniforms is an error. - Non ES: matching redeclarations of interface blocks - - Non ES: read or write to both gl_ClipVertex and gl_ClipDistance - - Non ES: write to only one of gl_FragColor, gl_FragData, or user-declared - - 1.50: at least one geometry shader says input primitive and at least one says output primitive... - - 1.50: at least one geometry shader says max_vertices... - 1.50: match between all explicit input array sizes and input primitive - - 4.3: Be clear that early_fragment_tests is only needed in one fragment-stage compilation unit. - - 4.3: Be clear that implicit array sizing is only within a stage, not cross stage. + - 4.3: early_fragment_tests contradictions + - 4.3: implicit array sizing is cross shader within a stage - 4.4: overlapping transform/feedback offsets, offset/stride overflow checks, and stride matching - 4.4: If gl_FragCoord is redeclared in any fragment shader in a program, it must be redeclared in all the fragment shaders in that program that have a static use gl_FragCoord - - 4.4: An interface contains two different blocks, each with no instance name, where the blocks contain a member with the same name. - - 4.4: component aliasing (except desktop vertex shader inputs) Shader Functionality to Implement/Finish ESSL 2.0 (#version 100) @@ -53,19 +62,16 @@ Shader Functionality to Implement/Finish + implement non-inductive array accesses limitation detection ESSL 3.0 - "const" compile-time constant propagation in the front-end has to be complete, for all built-in functions - - add limitation around #define GL_FRAGMENT_PRECISION_HIGH 1 ? GLSL 1.2 + Handle multiple compilation units per stage + Allow initializers on uniform declarations + signature matching takes type conversions into account, ambiguity is an error - - allow constructors to contain non-dereferenced arrays? + - bug: allow constructors to contain non-dereferenced arrays? GLSL 1.3 - . flat is for both user and predeclared built-in in/out variables - GLSL 1.3 (Non-ES) + + flat redeclaration of built-in variables - Preprocessor token pasting (##), ## does macro expansion after pasting not before - - non-perspective (linear) interpolation (noperspective) + + non-perspective (linear) interpolation (noperspective) + add gl_ClipDistance[] to both vertex and fragment shaders - - only statically used built-ins have to be redeclared as flat + Deprecated gl_ClipVertex + deprecate almost all built-in state + ftransform() is deprecated @@ -163,7 +169,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_FragDepthlayout 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. @@ -188,7 +194,7 @@ Shader Functionality to Implement/Finish member, so that must a have valid index. - Arrays of other objects (uniform blocks) containing implicitly sized arrays will have the same implicit size for all elements of the array. - - Arrays of arrays are now supported, as per the GL_ARB_arrays_of_arraysextension. + - Arrays of arrays are now supported, as per the GL_ARB_arrays_of_arrays extension. - Compute shaders are now supported, as per the GL_ARB_compute_shader extension. - Added imageSize() built-ins to query the dimensions of an image. - Define robust out-of-bounds access behavior when enabled, as per the GL_ARB_robust_buffer_access_behavior extension. @@ -232,3 +238,4 @@ Shader Functionality to Implement/Finish transform feedback buffering. + Bug 10530: To be consistent with ES, include sample types as valid in a precision statement. Note the defaults are irrelevant, as precision qualifiers are not required or have any meaning. + diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 9ca44076c9b13906154e3004acc16978cac615df..8edf8bd9d9f9fa2c6ad4fcdab008a0690ee45a68 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -386,6 +386,25 @@ public: } }; +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; // 0 means no declaration + int maxVertices; + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = 0; // 0 means no declaration + maxVertices = 0; + } +}; + // // TPublicType is just temporarily used while parsing and not quite the same // information kept per node in TType. Due to the bison stack, it can't have @@ -399,9 +418,7 @@ public: TBasicType basicType; TSampler sampler; TQualifier qualifier; - TLayoutGeometry geometry; // don't keep this in the qualifier; it's more a per shader than per type - int invocations; // 0 means no declaration - int maxVertices; + TShaderQualifiers shaderQualifiers; int vectorSize : 4; int matrixCols : 4; int matrixRows : 4; @@ -432,9 +449,7 @@ public: initType(loc); sampler.clear(); initQualifiers(global); - geometry = ElgNone; - invocations = 0; // 0 means no declaration - maxVertices = 0; + shaderQualifiers.init(); } void setVector(int s) @@ -793,10 +808,11 @@ public: else totalSize = vectorSize; - if (isArray()) - totalSize *= Max(getArraySize(), getMaxArraySize()); - - // TODO: desktop arrays: it should be ill-defined to get object size if the array is not sized, so the max() above maybe should be an assert + if (isArray()) { + // this function can only be used in paths that don't allow unsized arrays + assert(getArraySize() > 0); + totalSize *= getArraySize(); + } return totalSize; } diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 3559a921ec5ac99ce05b1a0ce008af51f26dd035..67b90c8e304baeead736101d849554f506d59cd7 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -297,7 +297,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) // but not always. int resultSize; switch (op) { - // TODO: functionality: constant folding: finish listing exceptions to size here + // TODO: 3.0 functionality: constant folding: finish listing exceptions to size here case EOpDeterminant: case EOpAny: case EOpAll: @@ -481,7 +481,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) break; } - // TODO: Functionality: constant folding: the rest of the ops have to be fleshed out + // TODO: 3.0 Functionality: constant folding: the rest of the ops have to be fleshed out case EOpSinh: case EOpCosh: @@ -665,7 +665,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) switch (aggrNode->getOp()) { - // TODO: Functionality: constant folding: the rest of the ops have to be fleshed out + // TODO: 3.0 Functionality: constant folding: the rest of the ops have to be fleshed out case EOpModf: case EOpDistance: diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index f59a1dfc6f5cfe43e64f8c3cef12f36474ab76a8..02311151338fe5de11056f8f905b1ec329f3a38d 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -621,8 +621,9 @@ void TBuiltIns::initialize(int version, EProfile profile) // (Per-stage functions below.) // if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || - version < 150) { + profile == ECompatibilityProfile || + (profile == ECoreProfile && version < 420) || + profile == ENoProfile) { commonBuiltins.append( "vec4 texture2D(sampler2D, vec2);" @@ -634,8 +635,9 @@ void TBuiltIns::initialize(int version, EProfile profile) "\n"); } - if (profile != EEsProfile && - (profile == ECompatibilityProfile || version < 150)) { + if ( profile == ECompatibilityProfile || + (profile == ECoreProfile && version < 420) || + profile == ENoProfile) { commonBuiltins.append( "vec4 texture1D(sampler1D, float);" @@ -651,8 +653,6 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 shadow2DProj(sampler2DShadow, vec4);" "\n"); - - // TODO: functionality: non-ES legacy texturing for Lod, others? } // @@ -686,6 +686,8 @@ void TBuiltIns::initialize(int version, EProfile profile) //============================================================================ // // Prototypes for built-in functions seen by vertex shaders only. + // (Except legacy lod functions, where it depends which release they are + // vertex only.) // //============================================================================ @@ -698,8 +700,16 @@ void TBuiltIns::initialize(int version, EProfile profile) // // Original-style texture Functions with lod. // - if (profile != EEsProfile || version == 100) { - stageBuiltins[EShLangVertex].append( + TString* s; + if (version < 130) + s = &stageBuiltins[EShLangVertex]; + else + s = &commonBuiltins; + if ((profile == EEsProfile && version == 100) || + profile == ECompatibilityProfile || + (profile == ECoreProfile && version < 420) || + profile == ENoProfile) { + s->append( "vec4 texture2DLod(sampler2D, vec2, float);" "vec4 texture2DProjLod(sampler2D, vec3, float);" "vec4 texture2DProjLod(sampler2D, vec4, float);" @@ -707,8 +717,10 @@ void TBuiltIns::initialize(int version, EProfile profile) "\n"); } - if (profile != EEsProfile && version > 100) { - stageBuiltins[EShLangVertex].append( + if ( profile == ECompatibilityProfile || + (profile == ECoreProfile && version < 420) || + profile == ENoProfile) { + s->append( "vec4 texture1DLod(sampler1D, float, float);" "vec4 texture1DProjLod(sampler1D, vec2, float);" "vec4 texture1DProjLod(sampler1D, vec4, float);" @@ -982,7 +994,7 @@ void TBuiltIns::initialize(int version, EProfile profile) if (version >= 430) { stageBuiltins[EShLangCompute].append( "in uvec3 gl_NumWorkGroups;" - // TODO: compute shader: constant with no initializer "const uvec3 gl_WorkGroupSize;" + // TODO: 4.3 functionality: compute shader: constant with no initializer "const uvec3 gl_WorkGroupSize;" "in uvec3 gl_WorkGroupID;" "in uvec3 gl_LocalInvocationID;" @@ -1184,7 +1196,7 @@ void TBuiltIns::initialize(int version, EProfile profile) //============================================================================ if (version >= 400) { - // TODO: tessellation: gl_MaxPatchVertices below needs to move to resources mechanism + // TODO: 4.0 tessellation: gl_MaxPatchVertices below needs to move to resources mechanism stageBuiltins[EShLangTessControl].append( "const int gl_MaxPatchVertices = 32;" ); @@ -1242,7 +1254,7 @@ void TBuiltIns::initialize(int version, EProfile profile) //============================================================================ if (version >= 400) { - // TODO: tessellation: gl_MaxPatchVertices below needs to move to resources mechanism + // TODO: 4.0 tessellation: gl_MaxPatchVertices below needs to move to resources mechanism stageBuiltins[EShLangTessEvaluation].append( "const int gl_MaxPatchVertices = 32;" ); @@ -2084,6 +2096,9 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb // switch(language) { case EShLangVertex: + case EShLangTessControl: + case EShLangTessEvaluation: + case EShLangGeometry: SpecialQualifier("gl_Position", EvqPosition, symbolTable); SpecialQualifier("gl_PointSize", EvqPointSize, symbolTable); SpecialQualifier("gl_ClipVertex", EvqClipVertex, symbolTable); @@ -2091,12 +2106,6 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb SpecialQualifier("gl_InstanceID", EvqInstanceId, symbolTable); break; - case EShLangTessControl: - case EShLangTessEvaluation: - case EShLangGeometry: - // TODO: desktop functionality: support new stages: note it is probably best to stop adding/using special qualifiers, given the passthrough nature of these stages - break; - case EShLangFragment: SpecialQualifier("gl_FrontFacing", EvqFace, symbolTable); SpecialQualifier("gl_FragCoord", EvqFragCoord, symbolTable); @@ -2106,7 +2115,7 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb break; case EShLangCompute: - // TODO: desktop functionality: support new stages + // TODO: 4.3 desktop functionality: compute special variables break; default: diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index d21794518148a86f85cbae33a388c17df08beef4..de1280da628ba8287bfc3dc2098b834f72f71e64 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -867,7 +867,7 @@ void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguag // //if (ftransformUsed) { - // TODO: desktop: track ftransform() usage + // TODO: 1.1 lowering functionality: track ftransform() usage // addSymbolLinkageNode(root, symbolTable, "gl_Vertex"); // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix"); //} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index a9fc2e2d0b4dcbe155e91571cf6e9d17eee73273..d21d95dde0bf2329490c636de258668d5aa0cbdc 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -54,7 +54,7 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), tokensBeforeEOF(false), currentScanner(0), numErrors(0), parsingBuiltins(pb), afterEOF(false), - anyIndexLimits(false) + anyIndexLimits(false), fragCoordUsedBeforeRedeclaration(false) { // ensure we always have a linkage node, even if empty, to simplify tree topology algorithms linkage = new TIntermAggregate; @@ -412,11 +412,15 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt if (variable->getType().getQualifier().storage == EvqConst) node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); else { - // break sharing with built-ins TType* type; if (variable->isReadOnly()) { type = new TType; + // break sharing with built-ins type->deepCopy(variable->getType()); + + // track use of unredeclared gl_FragCoord + if (variable->getName() == "gl_FragCoord") + fragCoordUsedBeforeRedeclaration = true; } else type = &variable->getWritableType(); node = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), *type, loc); @@ -473,6 +477,8 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); if (base->getBasicType() == EbtBlock) requireProfile(base->getLoc(), ~EEsProfile, "variable indexing block array"); + else if (language == EShLangFragment && base->getQualifier().storage == EvqVaryingOut) + requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader ouput array"); else if (base->getBasicType() == EbtSampler && version >= 130) { const char* explanation = "variable indexing sampler array"; requireProfile(base->getLoc(), ECoreProfile | ECompatibilityProfile, explanation); @@ -923,7 +929,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal } // generic error recovery - // TODO: coding: localize all the error recoveries that look like this + // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades if (result == 0) { TConstUnionArray unionArray(1); unionArray[0].setDConst(0.0); @@ -1895,19 +1901,18 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int index) { - TIntermSymbol* symbolNode = node->getAsSymbolNode(); - if (! symbolNode) { - // TODO: functionality: unsized arrays: handle members of blocks - return; - } - // maybe there is nothing to do... - // TODO: functionality: unsized arrays: is the node sharing the array type with the symbol table? - if (symbolNode->getType().getMaxArraySize() > index) + TIntermTyped* typedNode = node->getAsTyped(); + if (typedNode->getType().getMaxArraySize() > index) return; // something to do... + // TODO: 1.50 linker: unsized block member array: 'node' could be an expression for a dereference + TIntermSymbol* symbolNode = node->getAsSymbolNode(); + if (! symbolNode) + return; + TSymbol* symbol = symbolTable.find(symbolNode->getName()); assert(symbol); if (symbol == 0) @@ -1919,7 +1924,7 @@ void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int in } // For read-only built-ins, add a new variable for holding the maximum array size of an implicitly-sized shared array. - // TODO: functionality: unsized arrays: is this new array type shared with the node? + // TODO: desktop linker: unsized arrays: is this new array type shared with the node? if (symbol->isReadOnly()) { symbol = symbolTable.copyUp(symbol); @@ -1959,7 +1964,7 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TType // // Returns a redeclared and type-modified variable if a redeclarated occurred. // -TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& identifier, bool& newDeclaration) +TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& identifier, const TQualifier& qualifier, const TShaderQualifiers& publicType, bool& newDeclaration) { if (profile == EEsProfile || ! builtInName(identifier) || symbolTable.atBuiltInLevel()) return 0; @@ -2003,7 +2008,53 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& } // Now, modify the type of the copy, as per the type of the current redeclaration. - // TODO: functionality: verify type change is allowed and make the change in type + + TQualifier& symbolQualifier = symbol->getWritableType().getQualifier(); + if (identifier == "gl_FrontColor" || + identifier == "gl_BackColor" || + identifier == "gl_FrontSecondaryColor" || + identifier == "gl_BackSecondaryColor" || + identifier == "gl_SecondaryColor" || + identifier == "gl_Color") { + symbolQualifier.flat = qualifier.flat; + symbolQualifier.smooth = qualifier.smooth; + symbolQualifier.nopersp = qualifier.nopersp; + if (qualifier.hasLayout()) + error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); + if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage) + error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); + } else if (identifier == "gl_TexCoord" || + identifier == "gl_ClipDistance") { + if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() || + qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || + symbolQualifier.storage != qualifier.storage) + error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); + } else if (identifier == "gl_FragCoord") { + if (fragCoordUsedBeforeRedeclaration) + error(loc, "cannot redeclare after use", "gl_FragCoord", ""); + // Note: this did not catch the case of 1) declare, 2) use, 3) declare again, because the "use" was of a redeclaration, and so didn't set fragCoordUsedBeforeRedeclaration. + // (and that's what the rules are too, as long as #3 matches #1) + if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || + qualifier.isMemory() || qualifier.isAuxiliary()) + error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); + if (identifier == "gl_FragCoord" && qualifier.storage != EvqVaryingIn) + error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str()); + if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || + publicType.originUpperLeft != intermediate.getOriginUpperLeft())) + error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); + if (publicType.pixelCenterInteger) + intermediate.setPixelCenterInteger(); + if (publicType.originUpperLeft) + intermediate.setOriginUpperLeft(); + } else if (identifier == "gl_FragDepth") { + if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || + qualifier.isMemory() || qualifier.isAuxiliary()) + error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); + if (qualifier.storage != EvqVaryingOut) + error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); + // TODO 4.2: gl_FragDepth redeclaration + } + // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above return symbol; } @@ -2062,7 +2113,7 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c if (language == EShLangGeometry && block->getType().isArray() && block->getType().getQualifier().storage == EvqVaryingIn) inputArraySymbolResizeList.push_back(block); - // TODO: semantics: block redeclaration: instance array size matching? + // TODO: SSO/4.10 semantics: block redeclaration: instance array size matching // Edit and error check the container against the redeclaration // - remove unused members @@ -2085,7 +2136,7 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c else member = type.getStruct()->erase(member); - // TODO: semantics: block redeclaration: member type/qualifier matching + // TODO: SSO/4.10 semantics: block redeclaration: member type/qualifier matching } symbolTable.insert(*block); @@ -2306,36 +2357,48 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, } if (language == EShLangGeometry || language == EShLangTessEvaluation) { if (id == TQualifier::getGeometryString(ElgTriangles)) { - publicType.geometry = ElgTriangles; + publicType.shaderQualifiers.geometry = ElgTriangles; return; } if (language == EShLangGeometry) { if (id == TQualifier::getGeometryString(ElgPoints)) { - publicType.geometry = ElgPoints; + publicType.shaderQualifiers.geometry = ElgPoints; return; } if (id == TQualifier::getGeometryString(ElgLineStrip)) { - publicType.geometry = ElgLineStrip; + publicType.shaderQualifiers.geometry = ElgLineStrip; return; } if (id == TQualifier::getGeometryString(ElgLines)) { - publicType.geometry = ElgLines; + publicType.shaderQualifiers.geometry = ElgLines; return; } if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { - publicType.geometry = ElgLinesAdjacency; + publicType.shaderQualifiers.geometry = ElgLinesAdjacency; return; } if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { - publicType.geometry = ElgTrianglesAdjacency; + publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; return; } if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { - publicType.geometry = ElgTriangleStrip; + publicType.shaderQualifiers.geometry = ElgTriangleStrip; return; } } else { - // TODO: tessellation evaluation + // TODO: 4.0 tessellation evaluation + } + } + if (language == EShLangFragment) { + if (id == "origin_upper_left") { + requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left"); + publicType.shaderQualifiers.originUpperLeft = true; + return; + } + if (id == "pixel_center_integer") { + requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer"); + publicType.shaderQualifiers.pixelCenterInteger = true; + return; } } error(loc, "unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4)", id.c_str(), ""); @@ -2345,6 +2408,12 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, // type information for error checking. void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, int value) { + if (value < 0) { + error(loc, "cannot be negative", "layout qualifier value", ""); + return; + // TODO: 4.4: test the above, once expressions are allowed; until then, can't even express a negative location + } + std::transform(id.begin(), id.end(), id.begin(), ::tolower); if (id == "location") { requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "location"); @@ -2367,11 +2436,11 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, if (language == EShLangGeometry) { if (id == "invocations") { profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, 0, "invocations"); - publicType.invocations = value; + publicType.shaderQualifiers.invocations = value; return; } if (id == "max_vertices") { - publicType.maxVertices = value; + publicType.shaderQualifiers.maxVertices = value; return; } if (id == "stream") { @@ -2380,16 +2449,13 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, } } error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); - - // TODO: semantics: error check: make sure locations are non-overlapping across the whole stage - // TODO: semantics: error check: output arrays can only be indexed with a constant (es 300) } // // Merge characteristics of the 'src' qualifier into the 'dst', at the TPublicType level, // which means for layout-qualifier information not kept per qualifier. // -void TParseContext::mergeShaderLayoutQualifiers(TSourceLoc loc, TPublicType& dst, const TPublicType& src) +void TParseContext::mergeShaderLayoutQualifiers(TSourceLoc loc, TShaderQualifiers& dst, const TShaderQualifiers& src) { if (src.geometry != ElgNone) dst.geometry = src.geometry; @@ -2397,6 +2463,10 @@ void TParseContext::mergeShaderLayoutQualifiers(TSourceLoc loc, TPublicType& dst dst.invocations = src.invocations; if (src.maxVertices != 0) dst.maxVertices = src.maxVertices; + if (src.pixelCenterInteger) + dst.pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + dst.originUpperLeft = src.originUpperLeft; } // Merge any layout qualifier information from src into dst, leaving everything else in dst alone @@ -2464,11 +2534,11 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TSymbol& symbol) // an array of size N, all elements of the array from binding through binding + N – 1 must be within this // range." // - // TODO: binding error checking against limits, arrays + // TODO: 4.2 binding limits: binding error checking against limits, arrays // if (type.getBasicType() != EbtSampler && type.getBasicType() != EbtBlock) error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); - // TODO: atomic counter functionality: include in test above + // TODO: 4.2 functionality: atomic counter: include in test above } } @@ -2527,15 +2597,15 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali } // For places that can't have shader-level layout qualifiers -void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TPublicType& publicType) +void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TShaderQualifiers& shaderQualifiers) { const char* message = "can only apply to a standalone qualifier"; - if (publicType.geometry != ElgNone) - error(loc, message, TQualifier::getGeometryString(publicType.geometry), ""); - if (publicType.invocations > 0) + if (shaderQualifiers.geometry != ElgNone) + error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), ""); + if (shaderQualifiers.invocations > 0) error(loc, message, "invocations", ""); - if (publicType.maxVertices > 0) + if (shaderQualifiers.maxVertices > 0) error(loc, message, "max_vertices", ""); } @@ -2658,7 +2728,7 @@ const TFunction* TParseContext::findFunction400(TSourceLoc loc, const TFunction& // Returns a subtree node that computes an initializer, if needed. // Returns 0 if there is no code to execute for initialization. // -TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, TPublicType& publicType, TArraySizes* arraySizes, TIntermTyped* initializer) +TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, const TPublicType& publicType, TArraySizes* arraySizes, TIntermTyped* initializer) { TType type(publicType); @@ -2672,9 +2742,12 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut) type.getQualifier().layoutStream = globalOutputDefaults.layoutStream; + if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) + error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); + // Check for redeclaration of built-ins and/or attempting to declare a reserved name bool newDeclaration = false; // true if a new entry gets added to the symbol table - TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, newDeclaration); + TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers, newDeclaration); if (! symbol) reservedErrorCheck(loc, identifier); @@ -2698,6 +2771,8 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, // non-array case if (! symbol) symbol = declareNonArray(loc, identifier, type, newDeclaration); + else if (type != symbol->getType()) + error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); } // Deal with initializer @@ -2859,7 +2934,7 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType& arrayType.setArraySizes(type); arrayType.changeArraySize(initList->getSequence().size()); TType elementType; - elementType.shallowCopy(arrayType); // TODO: arrays of arrays: combine this with deref. + elementType.shallowCopy(arrayType); // TODO: 4.3 simplification: arrays of arrays: combine this with deref. elementType.dereference(); for (size_t i = 0; i < initList->getSequence().size(); ++i) { initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); @@ -2884,7 +2959,7 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType& return 0; } TType vectorType; - vectorType.shallowCopy(type); // TODO: arrays of arrays: combine this with deref. + vectorType.shallowCopy(type); // TODO: 4.3 simplification: arrays of arrays: combine this with deref. vectorType.dereference(); for (int i = 0; i < type.getMatrixCols(); ++i) { initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped()); @@ -2925,7 +3000,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c TType elementType; elementType.shallowCopy(type); if (type.isArray()) - elementType.dereference(); // TODO: arrays of arrays: combine this with shallowCopy + elementType.dereference(); // TODO: 4.3 simplification: arrays of arrays: combine this with deref. bool singleArg; if (aggrNode) { @@ -3280,43 +3355,43 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, // void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPublicType& publicType) { - if (publicType.maxVertices) { - if (! intermediate.setMaxVertices(publicType.maxVertices)) + if (publicType.shaderQualifiers.maxVertices) { + if (! intermediate.setMaxVertices(publicType.shaderQualifiers.maxVertices)) error(loc, "cannot change previously set layout value", "max_vertices", ""); } - if (publicType.invocations) { - if (! intermediate.setInvocations(publicType.invocations)) + if (publicType.shaderQualifiers.invocations) { + if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) error(loc, "cannot change previously set layout value", "invocations", ""); } - if (publicType.geometry != ElgNone) { + if (publicType.shaderQualifiers.geometry != ElgNone) { if (publicType.qualifier.storage == EvqVaryingIn) { - switch (publicType.geometry) { + switch (publicType.shaderQualifiers.geometry) { case ElgPoints: case ElgLines: case ElgLinesAdjacency: case ElgTriangles: case ElgTrianglesAdjacency: - if (intermediate.setInputPrimitive(publicType.geometry)) + if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) checkInputArrayConsistency(loc); else - error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.geometry), ""); + error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; default: - error(loc, "does not apply to input", TQualifier::getGeometryString(publicType.geometry), ""); + error(loc, "does not apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); } } else if (publicType.qualifier.storage == EvqVaryingOut) { - switch (publicType.geometry) { + switch (publicType.shaderQualifiers.geometry) { case ElgPoints: case ElgLineStrip: case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(publicType.geometry)) - error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.geometry), ""); + if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) + error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; default: - error(loc, "does not only apply to output", TQualifier::getGeometryString(publicType.geometry), ""); + error(loc, "does not only apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); } } else - error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.geometry), ""); + error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); } const TQualifier& qualifier = publicType.qualifier; @@ -3472,7 +3547,7 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, return switchNode; } -// TODO: constant folding: these should use a follow a fully folded model now, and probably move to Constant.cpp scheme. +// TODO: simplification: constant folding: these should use a follow a fully folded model now, and probably move to Constant.cpp scheme. // // This function returns the tree representation for the vector field(s) being accessed from a constant vector. @@ -3552,7 +3627,7 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); TType arrayElementType; - arrayElementType.shallowCopy(node->getType()); // TODO: arrays of arrays: combine this with deref. + arrayElementType.shallowCopy(node->getType()); // TODO: 4.3 simplification: arrays of arrays: combine this with deref. arrayElementType.dereference(); if (index >= node->getType().getArraySize() || index < 0) { diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 7e499e7da8747a3dc89b31c33dab9d03ee3f4292..7ff225d73054961a6354758956855183b0aa479c 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -122,7 +122,7 @@ public: void precisionQualifierCheck(TSourceLoc, TPublicType&); void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type); bool containsSampler(const TType& type); - TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, bool& newDeclaration); + TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration); bool redeclareBuiltinBlock(TSourceLoc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); void paramCheck(TSourceLoc, const TStorageQualifier&, TType* type); void nestedBlockCheck(TSourceLoc); @@ -134,17 +134,17 @@ public: void setLayoutQualifier(TSourceLoc, TPublicType&, TString&); void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int); - void mergeShaderLayoutQualifiers(TSourceLoc, TPublicType& dst, const TPublicType& src); + void mergeShaderLayoutQualifiers(TSourceLoc, TShaderQualifiers& dst, const TShaderQualifiers& src); void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src); void layoutTypeCheck(TSourceLoc, const TSymbol&); void layoutQualifierCheck(TSourceLoc, const TQualifier&); - void checkNoShaderLayouts(TSourceLoc, const TPublicType&); + void checkNoShaderLayouts(TSourceLoc, const TShaderQualifiers&); const TFunction* findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn); const TFunction* findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn); const TFunction* findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn); const TFunction* findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn); - TIntermNode* declareVariable(TSourceLoc, TString& identifier, TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermNode* declareVariable(TSourceLoc, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator); TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset); @@ -241,7 +241,7 @@ protected: TIdSetType inductiveLoopIds; bool anyIndexLimits; TVector<TIntermTyped*> needsIndexLimitationChecking; - // TODO: desktop functionality: track use of gl_FragDepth before redeclaration + bool fragCoordUsedBeforeRedeclaration; // // Geometry shader input arrays: diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 56bb3a5106d195d78e85653226d8dec4fe2c3aa5..cd1966a27043c8e528f8ca5c65744f84293f6fa5 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -779,13 +779,13 @@ declaration } | type_qualifier IDENTIFIER SEMICOLON { parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); $$ = 0; } | type_qualifier IDENTIFIER identifier_list SEMICOLON { parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); $3->push_back($2.string); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); $$ = 0; @@ -797,7 +797,7 @@ block_structure --parseContext.structNestingLevel; parseContext.blockName = $2.string; parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.currentBlockQualifier = $1.qualifier; $$.loc = $1.loc; $$.typeList = $5; @@ -919,7 +919,7 @@ parameter_declaration if ($1.qualifier.precision != EpqNone) $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type); parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type); } @@ -937,7 +937,7 @@ parameter_declaration if ($1.qualifier.precision != EpqNone) $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type); parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type); } @@ -1038,7 +1038,8 @@ fully_specified_type if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier)) $2.arraySizes = 0; - parseContext.checkNoShaderLayouts($2.loc, $1); + parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers); + parseContext.mergeShaderLayoutQualifiers($2.loc, $2.shaderQualifiers, $1.shaderQualifiers); parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); parseContext.precisionQualifierCheck($2.loc, $2); @@ -1095,7 +1096,7 @@ layout_qualifier_id_list } | layout_qualifier_id_list COMMA layout_qualifier_id { $$ = $1; - parseContext.mergeShaderLayoutQualifiers($2.loc, $$, $3); + parseContext.mergeShaderLayoutQualifiers($2.loc, $$.shaderQualifiers, $3.shaderQualifiers); parseContext.mergeObjectLayoutQualifiers($2.loc, $$.qualifier, $3.qualifier); } @@ -1134,7 +1135,7 @@ type_qualifier if ($$.basicType == EbtVoid) $$.basicType = $2.basicType; - parseContext.mergeShaderLayoutQualifiers($$.loc, $$, $2); + parseContext.mergeShaderLayoutQualifiers($$.loc, $$.shaderQualifiers, $2.shaderQualifiers); parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false); } ; @@ -1569,7 +1570,7 @@ type_specifier_nonarray $$.setMatrix(4, 4); } | ATOMIC_UINT { - // TODO: 4.2 functionality: add type + // TODO: 4.2 functionality: add atomic_uint type $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtInt; } @@ -2051,7 +2052,7 @@ struct_declaration $$ = $3; - parseContext.checkNoShaderLayouts($1.loc, $1); + parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType); parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); parseContext.precisionQualifierCheck($2.loc, $2); diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index e16d9705fa5738fb4845cb52391b055cb0587fd0..e5543c96921a8d5f1529fe1d3e0653a9263d0a82 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -585,6 +585,12 @@ void TIntermediate::outputTree(TInfoSink& infoSink) infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n"; } + if (language == EShLangFragment) { + if (pixelCenterInteger) + infoSink.debug << "gl_FragCoord pixel center is integer\n"; + if (originUpperLeft) + infoSink.debug << "gl_FragCoord origin is upper left\n"; + } if (treeRoot == 0) return; diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 47d8cb1e27bcd717448e5ee8c32d24af1f1855b7..0c1fb7bb76d84a2507b5e8e2451e86c28bce2441 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -73,6 +73,9 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) (profile == EEsProfile && unit.profile != EEsProfile)) error(infoSink, "Cannot mix ES profile with non-ES profile shaders\n"); + if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) + error(infoSink, "gl_FragCoord redeclarations must match across shaders\n"); + if (unit.treeRoot == 0) return; @@ -101,7 +104,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) // void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals) { - // TODO: Performance: Processing in alphabetical order will be faster + // TODO: link-time performance: Processing in alphabetical order will be faster // Error check the global objects, not including the linker objects for (unsigned int child = 0; child < globals.size() - 1; ++child) { @@ -157,8 +160,6 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin // // This function only does one of intra- or cross-stage matching per call. // -// TODO: Linker Functionality: this function is under active development -// void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage) { bool writeTypeComparison = false; @@ -340,7 +341,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink) bool fragOutWithNoLocation = false; int numFragOut = 0; - // TODO: maps for location collision checking + // TODO: linker functionality: location collision checking TIntermSequence& linkObjects = findLinkerObjects(); for (size_t i = 0; i < linkObjects.size(); ++i) { diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 7617d9e3b39df68bebbbe5fe2c3c70b4a1a6142f..5657fca1ef5668f3807aab6208d9555bf61f6638 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -57,7 +57,7 @@ class TSymbol; class TIntermediate { public: explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0), - invocations(0), maxVertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone) { } + invocations(0), maxVertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false) { } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -129,6 +129,10 @@ public: outputPrimitive = p; return true; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); void merge(TInfoSink&, TIntermediate&); @@ -157,6 +161,8 @@ protected: int maxVertices; TLayoutGeometry inputPrimitive; TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; // for detecting recursion: pair is <caller, callee> struct TCall { diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp index 1352deb3029aafd7cfe219dfcae2903a4cc6330e..b241ff13f53f6258207215aae1ab47427624798c 100644 --- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -627,7 +627,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * ppToken) return '.'; } case '/': - // TODO: preprocessor: use the Scan.cpp comment scanner + // TODO: preprocessor simplification: use the Scan.cpp comment scanner ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); if (ch == '/') { do { diff --git a/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/glslang/MachineIndependent/preprocessor/PpTokens.cpp index 00a47a2b7d5e2c8c7d9676b2760ab2dd92f03ed1..6451e3eb71bf2b326d7c5128cd018be2610f629f 100644 --- a/glslang/MachineIndependent/preprocessor/PpTokens.cpp +++ b/glslang/MachineIndependent/preprocessor/PpTokens.cpp @@ -299,7 +299,7 @@ void TPpContext::RewindTokenStream(TokenStream *pTok) int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken) { - //TODO: PP: why is this different than byte_scan + //TODO: preprocessor simplification: why is this different than byte_scan char tokenText[TPpToken::maxTokenLength + 1]; int ltoken, len; diff --git a/glslang/OSDependent/Linux/ossource.cpp b/glslang/OSDependent/Linux/ossource.cpp index 03e7b05bfc61a15ede41937e0d0cf2eaa18adf65..0cef0d1e72e3fa5e83a459151124225f116d52ea 100644 --- a/glslang/OSDependent/Linux/ossource.cpp +++ b/glslang/OSDependent/Linux/ossource.cpp @@ -137,7 +137,7 @@ bool OS_FreeTLSIndex(OS_TLSIndex nIndex) return false; } -// TODO: if we need these on linux, flesh them out +// TODO: non-windows: if we need these on linux, flesh them out void InitGlobalLock() { } void GetGlobalLock() { } void ReleaseGlobalLock() { }