{
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
--- /dev/null
+#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
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
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
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;
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
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
--- /dev/null
+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
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
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
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
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
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
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
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
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
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
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
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
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
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
140.frag
150.vert
150.geom
+150.frag
precision.frag
precision.vert
nonSquare.vert
- 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)
+ 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
- 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.
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.
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.
+
}
};
+// 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
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;
initType(loc);
sampler.clear();
initQualifiers(global);
- geometry = ElgNone;
- invocations = 0; // 0 means no declaration
- maxVertices = 0;
+ shaderQualifiers.init();
}
void setVector(int s)
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;
}
// 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:
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:
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:
// (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);"
"\n");
}
- if (profile != EEsProfile &&
- (profile == ECompatibilityProfile || version < 150)) {
+ if ( profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
commonBuiltins.append(
"vec4 texture1D(sampler1D, float);"
"vec4 shadow2DProj(sampler2DShadow, vec4);"
"\n");
-
- // TODO: functionality: non-ES legacy texturing for Lod, others?
}
//
//============================================================================
//
// Prototypes for built-in functions seen by vertex shaders only.
+ // (Except legacy lod functions, where it depends which release they are
+ // vertex only.)
//
//============================================================================
//
// 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);"
"\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);"
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;"
//============================================================================
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;"
);
//============================================================================
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;"
);
//
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);
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);
break;
case EShLangCompute:
- // TODO: desktop functionality: support new stages
+ // TODO: 4.3 desktop functionality: compute special variables
break;
default:
//
//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");
//}
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;
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);
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);
}
// 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);
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)
}
// 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);
//
// 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;
}
// 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;
}
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
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);
}
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(), "");
// 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");
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") {
}
}
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;
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
// 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
}
}
}
// 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", "");
}
// 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);
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);
// 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
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());
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());
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) {
//
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;
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.
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) {
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);
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);
TIdSetType inductiveLoopIds;
bool anyIndexLimits;
TVector<TIntermTyped*> needsIndexLimitationChecking;
- // TODO: desktop functionality: track use of gl_FragDepth before redeclaration
+ bool fragCoordUsedBeforeRedeclaration;
//
// Geometry shader input arrays:
}\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
--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
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
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
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
}\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
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
$$.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
\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
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;
(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
//\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
//\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
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
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; }
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&);
int maxVertices;
TLayoutGeometry inputPrimitive;
TLayoutGeometry outputPrimitive;
+ bool pixelCenterInteger;
+ bool originUpperLeft;
// for detecting recursion: pair is <caller, callee>
struct TCall {
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 {
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;
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() { }