Clean up/resolve a bunch of TODO, which included implementing pixel_center_integer...
authorJohn Kessenich <cepheus@frii.com>
Tue, 5 Nov 2013 18:07:25 +0000 (18:07 +0000)
committerJohn Kessenich <cepheus@frii.com>
Tue, 5 Nov 2013 18:07:25 +0000 (18:07 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23874 e7fa87d3-cd2b-0410-9028-fcbf551c1848

28 files changed:
Install/Windows/glslangValidator.exe
Test/130.frag
Test/150.frag [new file with mode: 0644]
Test/300.frag
Test/400.frag
Test/baseResults/130.frag.out
Test/baseResults/150.frag.out [new file with mode: 0644]
Test/baseResults/150.geom.out
Test/baseResults/300.frag.out
Test/baseResults/400.frag.out
Test/baseResults/410.geom.out
Test/baseResults/specExamples.frag.out
Test/baseResults/specExamples.vert.out
Test/testlist
Todo.txt
glslang/Include/Types.h
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/Initialize.cpp
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/glslang.y
glslang/MachineIndependent/intermOut.cpp
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/localintermediate.h
glslang/MachineIndependent/preprocessor/PpScanner.cpp
glslang/MachineIndependent/preprocessor/PpTokens.cpp
glslang/OSDependent/Linux/ossource.cpp

index 248a1e4..24272a3 100644 (file)
Binary files a/Install/Windows/glslangValidator.exe and b/Install/Windows/glslangValidator.exe differ
index c65cd0e..3099a47 100644 (file)
@@ -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 (file)
index 0000000..fb15a00
--- /dev/null
@@ -0,0 +1,14 @@
+#version 150 core\r
+\r
+in vec4 gl_FragCoord;\r
+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;  // ERROR\r
+layout(pixel_center_integer) in vec4 gl_FragCoord;  // ERROR\r
+layout(origin_upper_left) in vec4 foo;  // ERROR\r
+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;\r
+\r
+void main()\r
+{\r
+    vec4 c = gl_FragCoord;\r
+}\r
+\r
+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;\r
index 88539cb..d63c81e 100644 (file)
@@ -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
index b2d8398..82cd3ab 100644 (file)
@@ -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;
index f6120e9..55d7e52 100644 (file)
@@ -1,6 +1,9 @@
 Warning, version 130 is not yet complete; most features are present, but a few are missing.\r
 ERROR: 0:25: 'texture gather function' : not supported for this version or the enabled extensions \r
-ERROR: 1 compilation errors.  No code generated.\r
+ERROR: 0:35: 'redeclaration' : cannot change the type of gl_Color\r
+ERROR: 0:38: 'gl_Color' : redeclaring non-array as array \r
+ERROR: 0:39: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_Color\r
+ERROR: 4 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
 0:16  Function Definition: main( (void)\r
@@ -48,4 +51,6 @@ ERROR: node is still EOpNull!
 0:?     'fnop' (noperspective in float)\r
 0:?     'gl_ClipDistance' (smooth in unsized array of float)\r
 0:?     'sampC' (uniform samplerCube)\r
+0:?     'gl_Color' (smooth in 4-component vector of float)\r
+0:?     'gl_Color' (flat in 4-component vector of float)\r
 \r
diff --git a/Test/baseResults/150.frag.out b/Test/baseResults/150.frag.out
new file mode 100644 (file)
index 0000000..9d98ddf
--- /dev/null
@@ -0,0 +1,21 @@
+Warning, version 150 is not yet complete; some version-specific features are present, but many are missing.\r
+ERROR: 0:4: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord\r
+ERROR: 0:5: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord\r
+ERROR: 0:6: 'layout qualifier' : can only apply origin_upper_left and pixel_center_origin to gl_FragCoord \r
+ERROR: 3 compilation errors.  No code generated.\r
+\r
+gl_FragCoord pixel center is integer\r
+gl_FragCoord origin is upper left\r
+ERROR: node is still EOpNull!\r
+0:9  Function Definition: main( (void)\r
+0:9    Function Parameters: \r
+0:11    Sequence\r
+0:11      Sequence\r
+0:11        move second child to first child (4-component vector of float)\r
+0:11          'c' (4-component vector of float)\r
+0:11          'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
+0:?   Linker Objects\r
+0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
+0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
+0:?     'foo' (smooth in 4-component vector of float)\r
+\r
index 186e4a4..0da9b61 100644 (file)
@@ -71,7 +71,7 @@ ERROR: node is still EOpNull!
 0:33          Constant:\r
 0:33            2 (const int)\r
 0:34      move second child to first child (4-component vector of float)\r
-0:34        gl_Position: direct index for structure (layout(stream=0 ) 4-component vector of float)\r
+0:34        gl_Position: direct index for structure (layout(stream=0 ) gl_Position 4-component vector of float)\r
 0:34          '__anon__1' (layout(stream=0 ) out block{gl_Position,gl_PointSize,gl_ClipDistance})\r
 0:34          Constant:\r
 0:34            0 (const uint)\r
@@ -83,7 +83,7 @@ ERROR: node is still EOpNull!
 0:34          Constant:\r
 0:34            0 (const int)\r
 0:35      move second child to first child (float)\r
-0:35        gl_PointSize: direct index for structure (layout(stream=0 ) float)\r
+0:35        gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float)\r
 0:35          '__anon__1' (layout(stream=0 ) out block{gl_Position,gl_PointSize,gl_ClipDistance})\r
 0:35          Constant:\r
 0:35            1 (const uint)\r
index 670ce24..2e0d657 100644 (file)
@@ -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\r
 ERROR: 0:103: 'arrays of arrays' : not supported with this profile: es\r
 ERROR: 0:100: 'arrays of arrays' : not supported with this profile: es\r
-ERROR: 0:106: 'imageBuffer' : Reserved word. \r
-ERROR: 0:106: '' :  syntax error\r
-ERROR: 21 compilation errors.  No code generated.\r
+ERROR: 0:111: 'variable indexing fragment shader ouput array' : not supported with this profile: es\r
+ERROR: 0:114: 'imageBuffer' : Reserved word. \r
+ERROR: 0:114: '' :  syntax error\r
+ERROR: 22 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
 0:53  Function Definition: main( (void)\r
@@ -208,6 +209,20 @@ ERROR: node is still EOpNull!
 0:96          'c4D' (smooth lowp 4-component vector of float)\r
 0:97      arc hyp. tangent (lowp 3-component vector of float)\r
 0:97        'c3D' (smooth in lowp 3-component vector of float)\r
+0:108  Function Definition: foo( (void)\r
+0:108    Function Parameters: \r
+0:110    Sequence\r
+0:110      move second child to first child (lowp 4-component vector of float)\r
+0:110        direct index (lowp 4-component vector of float)\r
+0:110          'colors' (out 4-element array of lowp 4-component vector of float)\r
+0:110          Constant:\r
+0:110            2 (const int)\r
+0:110        'c4D' (smooth lowp 4-component vector of float)\r
+0:111      move second child to first child (lowp 4-component vector of float)\r
+0:111        indirect index (lowp 4-component vector of float)\r
+0:111          'colors' (out 4-element array of lowp 4-component vector of float)\r
+0:111          'ic1D' (flat in mediump int)\r
+0:111        'c4D' (smooth lowp 4-component vector of float)\r
 0:?   Linker Objects\r
 0:?     's2D' (uniform lowp sampler2D)\r
 0:?     's3D' (uniform lowp sampler3D)\r
@@ -240,4 +255,5 @@ ERROR: node is still EOpNull!
 0:?     'sf' (out lowp float)\r
 0:?     'arrayedSampler' (uniform 5-element array of lowp sampler2D)\r
 0:?     'multiInst' (layout(column_major shared ) uniform 2-element array of block{a,b,c})\r
+0:?     'colors' (out 4-element array of lowp 4-component vector of float)\r
 \r
index 89396d2..6f478f6 100644 (file)
@@ -1,10 +1,15 @@
 Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.\r
 ERROR: 0:20: 'texture gather component' : must be a constant \r
 ERROR: 0:21: 'texture gather component' : must be 0, 1, 2, or 3 \r
-ERROR: 0:26: 'location qualifier on input' : not supported for this version or the enabled extensions \r
-ERROR: 0:34: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions \r
-ERROR: 4 compilation errors.  No code generated.\r
+ERROR: 0:28: 'location qualifier on input' : not supported for this version or the enabled extensions \r
+ERROR: 0:36: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions \r
+ERROR: 0:38: 'redeclaration' : cannot apply layout qualifier to gl_Color\r
+ERROR: 0:39: 'redeclaration' : cannot change qualification of gl_ClipDistance\r
+ERROR: 0:41: 'gl_FragCoord' : cannot redeclare after use \r
+ERROR: 7 compilation errors.  No code generated.\r
 \r
+gl_FragCoord pixel center is integer\r
+gl_FragCoord origin is upper left\r
 ERROR: node is still EOpNull!\r
 0:10  Function Definition: main( (void)\r
 0:10    Function Parameters: \r
@@ -105,6 +110,10 @@ ERROR: node is still EOpNull!
 0:23            0.100000\r
 0:23          Construct ivec2 (2-component vector of int)\r
 0:23            'i' (flat in int)\r
+0:25      Sequence\r
+0:25        move second child to first child (4-component vector of float)\r
+0:25          'c' (4-component vector of float)\r
+0:25          'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
 0:?   Linker Objects\r
 0:?     'c2D' (smooth in 2-component vector of float)\r
 0:?     'i' (flat in int)\r
@@ -112,8 +121,12 @@ ERROR: node is still EOpNull!
 0:?     'arrayedSampler' (uniform 5-element array of sampler2D)\r
 0:?     'samp2dr' (uniform usampler2DRect)\r
 0:?     'isamp2DA' (uniform isampler2DArray)\r
-0:?     'gl_ClipDistance' (smooth in unsized array of float)\r
+0:?     'gl_ClipDistance' (smooth in 4-element array of float)\r
 0:?     'vl' (layout(location=4 ) smooth in 4-component vector of float)\r
 0:?     'vl2' (layout(location=4 ) smooth in 4-component vector of float)\r
 0:?     'uv3' (layout(location=3 ) uniform 3-component vector of float)\r
+0:?     '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})\r
+0:?     '__anon__0' (in block{gl_FogFragCoord,gl_TexCoord,gl_Color,gl_SecondaryColor})\r
+0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
+0:?     'gl_FragCoord' (gl_FragCoord 4-component vector of float)\r
 \r
index 5a01691..0b3acd8 100644 (file)
@@ -32,7 +32,7 @@ ERROR: node is still EOpNull!
 0:30            Constant:\r
 0:30              0 (const int)\r
 0:31      move second child to first child (float)\r
-0:31        gl_PointSize: direct index for structure (layout(stream=0 ) float)\r
+0:31        gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float)\r
 0:31          '__anon__0' (layout(stream=0 ) out block{gl_PointSize})\r
 0:31          Constant:\r
 0:31            0 (const uint)\r
index de312ae..19a1c15 100644 (file)
@@ -6,10 +6,8 @@ ERROR: 0:37: 'view' : redefinition
 ERROR: 0:68: 'lightPosition' : redefinition \r
 ERROR: 0:75: 'Atten' : member storage qualifier cannot contradict block storage qualifier \r
 ERROR: 0:87: 'Color' : redefinition \r
-ERROR: 0:92: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
-ERROR: 0:93: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
-ERROR: 0:94: 'origin_upper_left' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
-ERROR: 0:94: 'pixel_center_integer' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
+ERROR: 0:92: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord\r
+ERROR: 0:93: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord\r
 ERROR: 0:96: 'early_fragment_tests' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) \r
 ERROR: 0:99: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value \r
 ERROR: 0:99: 'local_size_y' : there is no such layout identifier for this stage taking an assigned value \r
@@ -48,8 +46,10 @@ ERROR: 0:226: 'in' : not allowed in nested scope
 ERROR: 0:227: 'in' : not allowed in nested scope \r
 ERROR: 0:228: 'in' : not allowed in nested scope \r
 ERROR: 0:232: 'out' : not allowed in nested scope \r
-ERROR: 49 compilation errors.  No code generated.\r
+ERROR: 47 compilation errors.  No code generated.\r
 \r
+gl_FragCoord pixel center is integer\r
+gl_FragCoord origin is upper left\r
 ERROR: node is still EOpNull!\r
 0:5  Sequence\r
 0:5    move second child to first child (int)\r
index 030d42e..2803903 100644 (file)
@@ -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 \r
 ERROR: 0:97: 'binding' : requires block, or sampler/image, or atomic-counter type \r
 ERROR: 0:106: '' : vertex input cannot be further qualified \r
+ERROR: 0:106: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_FrontColor\r
+ERROR: 0:107: 'redeclaration' : cannot change storage, memory, or auxiliary qualification of gl_FrontColor\r
 ERROR: 0:112: 'ColorIvn' : identifier not previously declared \r
 ERROR: 0:132: 'shared' : not supported in this stage: vertex\r
 ERROR: 0:134: '' : function does not return a value: funcA\r
@@ -40,7 +42,7 @@ ERROR: 0:153: '' : function does not return a value: func3
 ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array \r
 ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array \r
 ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array \r
-ERROR: 40 compilation errors.  No code generated.\r
+ERROR: 42 compilation errors.  No code generated.\r
 \r
 ERROR: node is still EOpNull!\r
 0:134  Function Definition: funcA(I21; (4-component vector of float)\r
index aebde4a..74d5d84 100644 (file)
@@ -14,6 +14,7 @@ versionsErrors.vert
 140.frag
 150.vert
 150.geom
+150.frag
 precision.frag
 precision.vert
 nonSquare.vert
index f3ce5b4..29ed8c1 100644 (file)
--- 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.
+
index 9ca4407..8edf8bd 100644 (file)
@@ -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;
     }
index 3559a92..67b90c8 100644 (file)
@@ -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:
index f59a1df..0231115 100644 (file)
@@ -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:
index d217945..de1280d 100644 (file)
@@ -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");
     //}
index a9fc2e2..d21d95d 100644 (file)
@@ -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 \96 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) {
index 7e499e7..7ff225d 100644 (file)
@@ -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:
index 56bb3a5..cd1966a 100644 (file)
@@ -779,13 +779,13 @@ declaration
     }\r
     | type_qualifier IDENTIFIER SEMICOLON {\r
         parseContext.pipeInOutFix($1.loc, $1.qualifier);\r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string);\r
         $$ = 0;\r
     }\r
     | type_qualifier IDENTIFIER identifier_list SEMICOLON {\r
         parseContext.pipeInOutFix($1.loc, $1.qualifier);\r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         $3->push_back($2.string);\r
         parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3);\r
         $$ = 0;\r
@@ -797,7 +797,7 @@ block_structure
         --parseContext.structNestingLevel;\r
         parseContext.blockName = $2.string;\r
         parseContext.pipeInOutFix($1.loc, $1.qualifier);\r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         parseContext.currentBlockQualifier = $1.qualifier;\r
         $$.loc = $1.loc;\r
         $$.typeList = $5;\r
@@ -919,7 +919,7 @@ parameter_declaration
         if ($1.qualifier.precision != EpqNone)\r
             $$.param.type->getQualifier().precision = $1.qualifier.precision;\r
         \r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type);\r
         parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type);\r
     }\r
@@ -937,7 +937,7 @@ parameter_declaration
         if ($1.qualifier.precision != EpqNone)\r
             $$.param.type->getQualifier().precision = $1.qualifier.precision;\r
         \r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         parseContext.parameterSamplerCheck($2.loc, $1.qualifier.storage, *$$.param.type);\r
         parseContext.paramCheck($1.loc, $1.qualifier.storage, $$.param.type);\r
     }\r
@@ -1038,7 +1038,8 @@ fully_specified_type
         if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier))\r
             $2.arraySizes = 0;\r
         \r
-        parseContext.checkNoShaderLayouts($2.loc, $1);\r
+        parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers);\r
+        parseContext.mergeShaderLayoutQualifiers($2.loc, $2.shaderQualifiers, $1.shaderQualifiers);\r
         parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);\r
         parseContext.precisionQualifierCheck($2.loc, $2);\r
 \r
@@ -1095,7 +1096,7 @@ layout_qualifier_id_list
     }\r
     | layout_qualifier_id_list COMMA layout_qualifier_id {\r
         $$ = $1;\r
-        parseContext.mergeShaderLayoutQualifiers($2.loc, $$, $3);\r
+        parseContext.mergeShaderLayoutQualifiers($2.loc, $$.shaderQualifiers, $3.shaderQualifiers);\r
         parseContext.mergeObjectLayoutQualifiers($2.loc, $$.qualifier, $3.qualifier);\r
     }\r
 \r
@@ -1134,7 +1135,7 @@ type_qualifier
         if ($$.basicType == EbtVoid)\r
             $$.basicType = $2.basicType;\r
 \r
-        parseContext.mergeShaderLayoutQualifiers($$.loc, $$, $2);\r
+        parseContext.mergeShaderLayoutQualifiers($$.loc, $$.shaderQualifiers, $2.shaderQualifiers);\r
         parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false);\r
     }\r
     ;\r
@@ -1569,7 +1570,7 @@ type_specifier_nonarray
         $$.setMatrix(4, 4);\r
     }\r
     | ATOMIC_UINT {\r
-        // TODO: 4.2 functionality: add type\r
+        // TODO: 4.2 functionality: add atomic_uint type\r
         $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());\r
         $$.basicType = EbtInt;\r
     }\r
@@ -2051,7 +2052,7 @@ struct_declaration
 \r
         $$ = $3;\r
 \r
-        parseContext.checkNoShaderLayouts($1.loc, $1);\r
+        parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);\r
         parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType);\r
         parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);\r
         parseContext.precisionQualifierCheck($2.loc, $2);\r
index e16d970..e5543c9 100644 (file)
@@ -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;
index 47d8cb1..0c1fb7b 100644 (file)
@@ -73,6 +73,9 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
         (profile == EEsProfile && unit.profile != EEsProfile))\r
         error(infoSink, "Cannot mix ES profile with non-ES profile shaders\n");\r
 \r
+    if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)\r
+        error(infoSink, "gl_FragCoord redeclarations must match across shaders\n");\r
+\r
     if (unit.treeRoot == 0)\r
         return;\r
 \r
@@ -101,7 +104,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
 //\r
 void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals)\r
 {\r
-    // TODO: Performance: Processing in alphabetical order will be faster\r
+    // TODO: link-time performance: Processing in alphabetical order will be faster\r
 \r
     // Error check the global objects, not including the linker objects\r
     for (unsigned int child = 0; child < globals.size() - 1; ++child) {\r
@@ -157,8 +160,6 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
 //\r
 // This function only does one of intra- or cross-stage matching per call.\r
 //\r
-// TODO: Linker Functionality: this function is under active development\r
-//\r
 void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)\r
 {\r
     bool writeTypeComparison = false;\r
@@ -340,7 +341,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
     bool fragOutWithNoLocation = false;\r
     int numFragOut = 0;\r
 \r
-    // TODO: maps for location collision checking\r
+    // TODO: linker functionality: location collision checking\r
 \r
     TIntermSequence& linkObjects = findLinkerObjects();\r
     for (size_t i = 0; i < linkObjects.size(); ++i) {\r
index 7617d9e..5657fca 100644 (file)
@@ -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 {
index 1352deb..b241ff1 100644 (file)
@@ -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 {
index 00a47a2..6451e3e 100644 (file)
@@ -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;
index 03e7b05..0cef0d1 100644 (file)
@@ -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() { }