xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/ShaderValidation_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ShaderValidation_test.cpp:
7 //   Tests that malformed shaders fail compilation, and that correct shaders pass compilation.
8 //
9 
10 #include "GLSLANG/ShaderLang.h"
11 #include "angle_gl.h"
12 #include "gtest/gtest.h"
13 #include "tests/test_utils/ShaderCompileTreeTest.h"
14 
15 using namespace sh;
16 
17 // Tests that don't target a specific version of the API spec (sometimes there are minor
18 // differences). They choose the shader spec version with version directives.
19 class FragmentShaderValidationTest : public ShaderCompileTreeTest
20 {
21   public:
FragmentShaderValidationTest()22     FragmentShaderValidationTest() {}
23 
24   protected:
getShaderType() const25     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const26     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
27 };
28 
29 // Tests that don't target a specific version of the API spec (sometimes there are minor
30 // differences). They choose the shader spec version with version directives.
31 class VertexShaderValidationTest : public ShaderCompileTreeTest
32 {
33   public:
VertexShaderValidationTest()34     VertexShaderValidationTest() {}
35 
36   protected:
getShaderType() const37     ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
getShaderSpec() const38     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
39 };
40 
41 class WebGL2FragmentShaderValidationTest : public ShaderCompileTreeTest
42 {
43   public:
WebGL2FragmentShaderValidationTest()44     WebGL2FragmentShaderValidationTest() {}
45 
46   protected:
getShaderType() const47     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const48     ShShaderSpec getShaderSpec() const override { return SH_WEBGL2_SPEC; }
49 };
50 
51 class WebGL1FragmentShaderValidationTest : public ShaderCompileTreeTest
52 {
53   public:
WebGL1FragmentShaderValidationTest()54     WebGL1FragmentShaderValidationTest() {}
55 
56   protected:
getShaderType() const57     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const58     ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; }
59 };
60 
61 class ComputeShaderValidationTest : public ShaderCompileTreeTest
62 {
63   public:
ComputeShaderValidationTest()64     ComputeShaderValidationTest() {}
65 
66   protected:
getShaderType() const67     ::GLenum getShaderType() const override { return GL_COMPUTE_SHADER; }
getShaderSpec() const68     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
69 };
70 
71 class ComputeShaderEnforcePackingValidationTest : public ComputeShaderValidationTest
72 {
73   public:
ComputeShaderEnforcePackingValidationTest()74     ComputeShaderEnforcePackingValidationTest() {}
75 
76   protected:
initResources(ShBuiltInResources * resources)77     void initResources(ShBuiltInResources *resources) override
78     {
79         resources->MaxComputeUniformComponents = kMaxComputeUniformComponents;
80 
81         // We need both MaxFragmentUniformVectors and MaxFragmentUniformVectors smaller than
82         // MaxComputeUniformComponents / 4.
83         resources->MaxVertexUniformVectors   = 16;
84         resources->MaxFragmentUniformVectors = 16;
85     }
86 
SetUp()87     void SetUp() override
88     {
89         mCompileOptions.enforcePackingRestrictions = true;
90         ShaderCompileTreeTest::SetUp();
91     }
92 
93     // It is unnecessary to use a very large MaxComputeUniformComponents in this test.
94     static constexpr GLint kMaxComputeUniformComponents = 128;
95 };
96 
97 class GeometryShaderValidationTest : public ShaderCompileTreeTest
98 {
99   public:
GeometryShaderValidationTest()100     GeometryShaderValidationTest() {}
101 
102   protected:
initResources(ShBuiltInResources * resources)103     void initResources(ShBuiltInResources *resources) override
104     {
105         resources->EXT_geometry_shader = 1;
106     }
getShaderType() const107     ::GLenum getShaderType() const override { return GL_GEOMETRY_SHADER_EXT; }
getShaderSpec() const108     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
109 };
110 
111 class FragmentShaderEXTGeometryShaderValidationTest : public FragmentShaderValidationTest
112 {
113   public:
FragmentShaderEXTGeometryShaderValidationTest()114     FragmentShaderEXTGeometryShaderValidationTest() {}
115 
116   protected:
initResources(ShBuiltInResources * resources)117     void initResources(ShBuiltInResources *resources) override
118     {
119         resources->EXT_geometry_shader = 1;
120     }
121 };
122 
123 // This is a test for a bug that used to exist in ANGLE:
124 // Calling a function with all parameters missing should not succeed.
TEST_F(FragmentShaderValidationTest,FunctionParameterMismatch)125 TEST_F(FragmentShaderValidationTest, FunctionParameterMismatch)
126 {
127     const std::string &shaderString =
128         "precision mediump float;\n"
129         "float fun(float a) {\n"
130         "   return a * 2.0;\n"
131         "}\n"
132         "void main() {\n"
133         "   float ff = fun();\n"
134         "   gl_FragColor = vec4(ff);\n"
135         "}\n";
136     if (compile(shaderString))
137     {
138         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
139     }
140 }
141 
142 // Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7)
TEST_F(FragmentShaderValidationTest,RedeclaringFunctionAsVariable)143 TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsVariable)
144 {
145     const std::string &shaderString =
146         "precision mediump float;\n"
147         "float fun(float a) {\n"
148         "   return a * 2.0;\n"
149         "}\n"
150         "float fun;\n"
151         "void main() {\n"
152         "   gl_FragColor = vec4(0.0);\n"
153         "}\n";
154     if (compile(shaderString))
155     {
156         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
157     }
158 }
159 
160 // Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7)
TEST_F(FragmentShaderValidationTest,RedeclaringFunctionAsStruct)161 TEST_F(FragmentShaderValidationTest, RedeclaringFunctionAsStruct)
162 {
163     const std::string &shaderString =
164         "precision mediump float;\n"
165         "float fun(float a) {\n"
166         "   return a * 2.0;\n"
167         "}\n"
168         "struct fun { float a; };\n"
169         "void main() {\n"
170         "   gl_FragColor = vec4(0.0);\n"
171         "}\n";
172     if (compile(shaderString))
173     {
174         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
175     }
176 }
177 
178 // Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0)
TEST_F(FragmentShaderValidationTest,RedeclaringFunctionWithDifferentQualifiers)179 TEST_F(FragmentShaderValidationTest, RedeclaringFunctionWithDifferentQualifiers)
180 {
181     const std::string &shaderString =
182         "precision mediump float;\n"
183         "float fun(out float a);\n"
184         "float fun(float a) {\n"
185         "   return a * 2.0;\n"
186         "}\n"
187         "void main() {\n"
188         "   gl_FragColor = vec4(0.0);\n"
189         "}\n";
190     if (compile(shaderString))
191     {
192         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
193     }
194 }
195 
196 // Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
TEST_F(FragmentShaderValidationTest,CompareStructsContainingArrays)197 TEST_F(FragmentShaderValidationTest, CompareStructsContainingArrays)
198 {
199     const std::string &shaderString =
200         "precision mediump float;\n"
201         "struct s { float a[3]; };\n"
202         "void main() {\n"
203         "   s a;\n"
204         "   s b;\n"
205         "   bool c = (a == b);\n"
206         "   gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
207         "}\n";
208     if (compile(shaderString))
209     {
210         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
211     }
212 }
213 
214 // Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
TEST_F(FragmentShaderValidationTest,AssignStructsContainingArrays)215 TEST_F(FragmentShaderValidationTest, AssignStructsContainingArrays)
216 {
217     const std::string &shaderString =
218         "precision mediump float;\n"
219         "struct s { float a[3]; };\n"
220         "void main() {\n"
221         "   s a;\n"
222         "   s b;\n"
223         "   b.a[0] = 0.0;\n"
224         "   a = b;\n"
225         "   gl_FragColor = vec4(a.a[0]);\n"
226         "}\n";
227     if (compile(shaderString))
228     {
229         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
230     }
231 }
232 
233 // Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7
234 // and 5.9)
TEST_F(FragmentShaderValidationTest,CompareStructsContainingSamplers)235 TEST_F(FragmentShaderValidationTest, CompareStructsContainingSamplers)
236 {
237     const std::string &shaderString =
238         "precision mediump float;\n"
239         "struct s { sampler2D foo; };\n"
240         "uniform s a;\n"
241         "uniform s b;\n"
242         "void main() {\n"
243         "   bool c = (a == b);\n"
244         "   gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
245         "}\n";
246     if (compile(shaderString))
247     {
248         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
249     }
250 }
251 
252 // Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this
253 // extends to structs containing samplers. ESSL 1.00 spec is clearer about this.
TEST_F(FragmentShaderValidationTest,AssignStructsContainingSamplers)254 TEST_F(FragmentShaderValidationTest, AssignStructsContainingSamplers)
255 {
256     const std::string &shaderString =
257         "#version 300 es\n"
258         "precision mediump float;\n"
259         "struct s { sampler2D foo; };\n"
260         "uniform s a;\n"
261         "out vec4 my_FragColor;\n"
262         "void main() {\n"
263         "   s b;\n"
264         "   b = a;\n"
265         "   my_FragColor = vec4(1.0);\n"
266         "}\n";
267     if (compile(shaderString))
268     {
269         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
270     }
271 }
272 
273 // This is a regression test for a particular bug that was in ANGLE.
274 // It also verifies that ESSL3 functionality doesn't leak to ESSL1.
TEST_F(FragmentShaderValidationTest,ArrayWithNoSizeInInitializerList)275 TEST_F(FragmentShaderValidationTest, ArrayWithNoSizeInInitializerList)
276 {
277     const std::string &shaderString =
278         "precision mediump float;\n"
279         "void main() {\n"
280         "   float a[2], b[];\n"
281         "   gl_FragColor = vec4(1.0);\n"
282         "}\n";
283     if (compile(shaderString))
284     {
285         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
286     }
287 }
288 
289 // Const variables need an initializer.
TEST_F(FragmentShaderValidationTest,ConstVarNotInitialized)290 TEST_F(FragmentShaderValidationTest, ConstVarNotInitialized)
291 {
292     const std::string &shaderString =
293         "#version 300 es\n"
294         "precision mediump float;\n"
295         "out vec4 my_FragColor;\n"
296         "void main() {\n"
297         "   const float a;\n"
298         "   my_FragColor = vec4(1.0);\n"
299         "}\n";
300     if (compile(shaderString))
301     {
302         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
303     }
304 }
305 
306 // Const variables need an initializer. In ESSL1 const structs containing
307 // arrays are not allowed at all since it's impossible to initialize them.
308 // Even though this test is for ESSL3 the only thing that's critical for
309 // ESSL1 is the non-initialization check that's used for both language versions.
310 // Whether ESSL1 compilation generates the most helpful error messages is a
311 // secondary concern.
TEST_F(FragmentShaderValidationTest,ConstStructNotInitialized)312 TEST_F(FragmentShaderValidationTest, ConstStructNotInitialized)
313 {
314     const std::string &shaderString =
315         "#version 300 es\n"
316         "precision mediump float;\n"
317         "struct S {\n"
318         "   float a[3];\n"
319         "};\n"
320         "out vec4 my_FragColor;\n"
321         "void main() {\n"
322         "   const S b;\n"
323         "   my_FragColor = vec4(1.0);\n"
324         "}\n";
325     if (compile(shaderString))
326     {
327         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
328     }
329 }
330 
331 // Const variables need an initializer. In ESSL1 const arrays are not allowed
332 // at all since it's impossible to initialize them.
333 // Even though this test is for ESSL3 the only thing that's critical for
334 // ESSL1 is the non-initialization check that's used for both language versions.
335 // Whether ESSL1 compilation generates the most helpful error messages is a
336 // secondary concern.
TEST_F(FragmentShaderValidationTest,ConstArrayNotInitialized)337 TEST_F(FragmentShaderValidationTest, ConstArrayNotInitialized)
338 {
339     const std::string &shaderString =
340         "#version 300 es\n"
341         "precision mediump float;\n"
342         "out vec4 my_FragColor;\n"
343         "void main() {\n"
344         "   const float a[3];\n"
345         "   my_FragColor = vec4(1.0);\n"
346         "}\n";
347     if (compile(shaderString))
348     {
349         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
350     }
351 }
352 
353 // Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
TEST_F(FragmentShaderValidationTest,BlockLayoutQualifierOnRegularUniform)354 TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnRegularUniform)
355 {
356     const std::string &shaderString =
357         "#version 300 es\n"
358         "precision mediump float;\n"
359         "layout(packed) uniform mat2 x;\n"
360         "out vec4 my_FragColor;\n"
361         "void main() {\n"
362         "   my_FragColor = vec4(1.0);\n"
363         "}\n";
364     if (compile(shaderString))
365     {
366         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
367     }
368 }
369 
370 // Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
TEST_F(FragmentShaderValidationTest,BlockLayoutQualifierOnUniformWithEmptyDecl)371 TEST_F(FragmentShaderValidationTest, BlockLayoutQualifierOnUniformWithEmptyDecl)
372 {
373     // Yes, the comma in the declaration below is not a typo.
374     // Empty declarations are allowed in GLSL.
375     const std::string &shaderString =
376         "#version 300 es\n"
377         "precision mediump float;\n"
378         "layout(packed) uniform mat2, x;\n"
379         "out vec4 my_FragColor;\n"
380         "void main() {\n"
381         "   my_FragColor = vec4(1.0);\n"
382         "}\n";
383     if (compile(shaderString))
384     {
385         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
386     }
387 }
388 
389 // Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
TEST_F(FragmentShaderValidationTest,ArraysOfArrays1)390 TEST_F(FragmentShaderValidationTest, ArraysOfArrays1)
391 {
392     const std::string &shaderString =
393         "#version 300 es\n"
394         "precision mediump float;\n"
395         "out vec4 my_FragColor;\n"
396         "void main() {\n"
397         "   float[5] a[3];\n"
398         "   my_FragColor = vec4(1.0);\n"
399         "}\n";
400     if (compile(shaderString))
401     {
402         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
403     }
404 }
405 
406 // Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
TEST_F(FragmentShaderValidationTest,ArraysOfArrays2)407 TEST_F(FragmentShaderValidationTest, ArraysOfArrays2)
408 {
409     const std::string &shaderString =
410         "#version 300 es\n"
411         "precision mediump float;\n"
412         "out vec4 my_FragColor;\n"
413         "void main() {\n"
414         "   float[2] a, b[3];\n"
415         "   my_FragColor = vec4(1.0);\n"
416         "}\n";
417     if (compile(shaderString))
418     {
419         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
420     }
421 }
422 
423 // Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9). Test this in a struct.
TEST_F(FragmentShaderValidationTest,ArraysOfArraysInStruct)424 TEST_F(FragmentShaderValidationTest, ArraysOfArraysInStruct)
425 {
426     const std::string &shaderString =
427         "#version 300 es\n"
428         "precision mediump float;\n"
429         "out vec4 my_FragColor;\n"
430         "struct S {\n"
431         "    float[2] foo[3];\n"
432         "};\n"
433         "void main() {\n"
434         "    my_FragColor = vec4(1.0);\n"
435         "}\n";
436     if (compile(shaderString))
437     {
438         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
439     }
440 }
441 
442 // Test invalid dimensionality of implicitly sized array constructor arguments.
TEST_F(FragmentShaderValidationTest,TooHighDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments)443 TEST_F(FragmentShaderValidationTest,
444        TooHighDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments)
445 {
446     const std::string &shaderString =
447         "#version 310 es\n"
448         "precision mediump float;\n"
449         "out vec4 my_FragColor;\n"
450         "void main() {\n"
451         "    float[][] a = float[][](float[1][1](float[1](1.0)), float[1][1](float[1](2.0)));\n"
452         "    my_FragColor = vec4(a[0][0]);\n"
453         "}\n";
454     if (compile(shaderString))
455     {
456         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
457     }
458 }
459 
460 // Test invalid dimensionality of implicitly sized array constructor arguments.
TEST_F(FragmentShaderValidationTest,TooLowDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments)461 TEST_F(FragmentShaderValidationTest,
462        TooLowDimensionalityOfImplicitlySizedArrayOfArraysConstructorArguments)
463 {
464     const std::string &shaderString =
465         "#version 310 es\n"
466         "precision mediump float;\n"
467         "out vec4 my_FragColor;\n"
468         "void main() {\n"
469         "    float[][][] a = float[][][](float[2](1.0, 2.0), float[2](3.0, 4.0));\n"
470         "    my_FragColor = vec4(a[0][0][0]);\n"
471         "}\n";
472     if (compile(shaderString))
473     {
474         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
475     }
476 }
477 
478 // Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9)
TEST_F(FragmentShaderValidationTest,UninitializedImplicitArraySize)479 TEST_F(FragmentShaderValidationTest, UninitializedImplicitArraySize)
480 {
481     const std::string &shaderString =
482         "#version 300 es\n"
483         "precision mediump float;\n"
484         "out vec4 my_FragColor;\n"
485         "void main() {\n"
486         "   float[] a;\n"
487         "   my_FragColor = vec4(1.0);\n"
488         "}\n";
489     if (compile(shaderString))
490     {
491         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
492     }
493 }
494 
495 // An operator can only form a constant expression if all the operands are constant expressions
496 // - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3)
TEST_F(FragmentShaderValidationTest,TernaryOperatorNotConstantExpression)497 TEST_F(FragmentShaderValidationTest, TernaryOperatorNotConstantExpression)
498 {
499     const std::string &shaderString =
500         "#version 300 es\n"
501         "precision mediump float;\n"
502         "out vec4 my_FragColor;\n"
503         "uniform bool u;\n"
504         "void main() {\n"
505         "   const bool a = true ? true : u;\n"
506         "   my_FragColor = vec4(1.0);\n"
507         "}\n";
508     if (compile(shaderString))
509     {
510         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
511     }
512 }
513 
514 // Ternary operator can operate on arrays (ESSL 3.00 section 5.7)
TEST_F(FragmentShaderValidationTest,TernaryOperatorOnArrays)515 TEST_F(FragmentShaderValidationTest, TernaryOperatorOnArrays)
516 {
517     const std::string &shaderString =
518         "#version 300 es\n"
519         "precision mediump float;\n"
520         "out vec4 my_FragColor;\n"
521         "void main() {\n"
522         "   float[1] a = float[1](0.0);\n"
523         "   float[1] b = float[1](1.0);\n"
524         "   float[1] c = true ? a : b;\n"
525         "   my_FragColor = vec4(1.0);\n"
526         "}\n";
527     if (!compile(shaderString))
528     {
529         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
530     }
531 }
532 
533 // Ternary operator can operate on structs (ESSL 3.00 section 5.7)
TEST_F(FragmentShaderValidationTest,TernaryOperatorOnStructs)534 TEST_F(FragmentShaderValidationTest, TernaryOperatorOnStructs)
535 {
536     const std::string &shaderString =
537         "#version 300 es\n"
538         "precision mediump float;\n"
539         "out vec4 my_FragColor;\n"
540         "struct S { float foo; };\n"
541         "void main() {\n"
542         "   S a = S(0.0);\n"
543         "   S b = S(1.0);\n"
544         "   S c = true ? a : b;\n"
545         "   my_FragColor = vec4(1.0);\n"
546         "}\n";
547     if (!compile(shaderString))
548     {
549         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
550     }
551 }
552 
553 // Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9)
554 // Assigning it to unsigned should result in an error.
TEST_F(FragmentShaderValidationTest,AssignArrayLengthToUnsigned)555 TEST_F(FragmentShaderValidationTest, AssignArrayLengthToUnsigned)
556 {
557     const std::string &shaderString =
558         "#version 300 es\n"
559         "precision mediump float;\n"
560         "out vec4 my_FragColor;\n"
561         "void main() {\n"
562         "   int[1] arr;\n"
563         "   uint l = arr.length();\n"
564         "   my_FragColor = vec4(float(l));\n"
565         "}\n";
566     if (compile(shaderString))
567     {
568         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
569     }
570 }
571 
572 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
573 // Initializing with a varying should be an error.
TEST_F(FragmentShaderValidationTest,AssignVaryingToGlobal)574 TEST_F(FragmentShaderValidationTest, AssignVaryingToGlobal)
575 {
576     const std::string &shaderString =
577         "precision mediump float;\n"
578         "varying float a;\n"
579         "float b = a * 2.0;\n"
580         "void main() {\n"
581         "   gl_FragColor = vec4(b);\n"
582         "}\n";
583     if (compile(shaderString))
584     {
585         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
586     }
587 }
588 
589 // Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
590 // Initializing with an uniform should be an error.
TEST_F(FragmentShaderValidationTest,AssignUniformToGlobalESSL3)591 TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL3)
592 {
593     const std::string &shaderString =
594         "#version 300 es\n"
595         "precision mediump float;\n"
596         "uniform float a;\n"
597         "float b = a * 2.0;\n"
598         "out vec4 my_FragColor;\n"
599         "void main() {\n"
600         "   my_FragColor = vec4(b);\n"
601         "}\n";
602     if (compile(shaderString))
603     {
604         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
605     }
606 }
607 
608 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
609 // Initializing with an uniform used to generate a warning on ESSL 1.00 because of legacy
610 // compatibility, but that causes dEQP to fail (which expects an error)
TEST_F(FragmentShaderValidationTest,AssignUniformToGlobalESSL1)611 TEST_F(FragmentShaderValidationTest, AssignUniformToGlobalESSL1)
612 {
613     const std::string &shaderString =
614         "precision mediump float;\n"
615         "uniform float a;\n"
616         "float b = a * 2.0;\n"
617         "void main() {\n"
618         "   gl_FragColor = vec4(b);\n"
619         "}\n";
620     if (compile(shaderString))
621     {
622         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
623     }
624 }
625 
626 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
627 // Initializing with an user-defined function call should be an error.
TEST_F(FragmentShaderValidationTest,AssignFunctionCallToGlobal)628 TEST_F(FragmentShaderValidationTest, AssignFunctionCallToGlobal)
629 {
630     const std::string &shaderString =
631         "precision mediump float;\n"
632         "float foo() { return 1.0; }\n"
633         "float b = foo();\n"
634         "void main() {\n"
635         "   gl_FragColor = vec4(b);\n"
636         "}\n";
637     if (compile(shaderString))
638     {
639         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
640     }
641 }
642 
643 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
644 // Initializing with an assignment to another global should be an error.
TEST_F(FragmentShaderValidationTest,AssignAssignmentToGlobal)645 TEST_F(FragmentShaderValidationTest, AssignAssignmentToGlobal)
646 {
647     const std::string &shaderString =
648         "precision mediump float;\n"
649         "float c = 1.0;\n"
650         "float b = (c = 0.0);\n"
651         "void main() {\n"
652         "   gl_FragColor = vec4(b);\n"
653         "}\n";
654     if (compile(shaderString))
655     {
656         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
657     }
658 }
659 
660 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
661 // Initializing with incrementing another global should be an error.
TEST_F(FragmentShaderValidationTest,AssignIncrementToGlobal)662 TEST_F(FragmentShaderValidationTest, AssignIncrementToGlobal)
663 {
664     const std::string &shaderString =
665         "precision mediump float;\n"
666         "float c = 1.0;\n"
667         "float b = (c++);\n"
668         "void main() {\n"
669         "   gl_FragColor = vec4(b);\n"
670         "}\n";
671     if (compile(shaderString))
672     {
673         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
674     }
675 }
676 
677 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
678 // Initializing with a texture lookup function call should be an error.
TEST_F(FragmentShaderValidationTest,AssignTexture2DToGlobal)679 TEST_F(FragmentShaderValidationTest, AssignTexture2DToGlobal)
680 {
681     const std::string &shaderString =
682         "precision mediump float;\n"
683         "uniform mediump sampler2D s;\n"
684         "float b = texture2D(s, vec2(0.5, 0.5)).x;\n"
685         "void main() {\n"
686         "   gl_FragColor = vec4(b);\n"
687         "}\n";
688     if (compile(shaderString))
689     {
690         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
691     }
692 }
693 
694 // Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
695 // Initializing with a non-constant global should be an error.
TEST_F(FragmentShaderValidationTest,AssignNonConstGlobalToGlobal)696 TEST_F(FragmentShaderValidationTest, AssignNonConstGlobalToGlobal)
697 {
698     const std::string &shaderString =
699         "#version 300 es\n"
700         "precision mediump float;\n"
701         "float a = 1.0;\n"
702         "float b = a * 2.0;\n"
703         "out vec4 my_FragColor;\n"
704         "void main() {\n"
705         "   my_FragColor = vec4(b);\n"
706         "}\n";
707     if (compile(shaderString))
708     {
709         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
710     }
711 }
712 
713 // Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
714 // Initializing with a constant global should be fine.
TEST_F(FragmentShaderValidationTest,AssignConstGlobalToGlobal)715 TEST_F(FragmentShaderValidationTest, AssignConstGlobalToGlobal)
716 {
717     const std::string &shaderString =
718         "#version 300 es\n"
719         "precision mediump float;\n"
720         "const float a = 1.0;\n"
721         "float b = a * 2.0;\n"
722         "out vec4 my_FragColor;\n"
723         "void main() {\n"
724         "   my_FragColor = vec4(b);\n"
725         "}\n";
726     if (!compile(shaderString))
727     {
728         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
729     }
730 }
731 
732 // Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2)
TEST_F(FragmentShaderValidationTest,WriteBothFragDataAndFragColor)733 TEST_F(FragmentShaderValidationTest, WriteBothFragDataAndFragColor)
734 {
735     const std::string &shaderString =
736         "precision mediump float;\n"
737         "void foo() {\n"
738         "   gl_FragData[0].a++;\n"
739         "}\n"
740         "void main() {\n"
741         "   gl_FragColor.x += 0.0;\n"
742         "}\n";
743     if (compile(shaderString))
744     {
745         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
746     }
747 }
748 
749 // Version directive must be on the first line (ESSL 3.00 section 3.3)
TEST_F(FragmentShaderValidationTest,VersionOnSecondLine)750 TEST_F(FragmentShaderValidationTest, VersionOnSecondLine)
751 {
752     const std::string &shaderString =
753         "\n"
754         "#version 300 es\n"
755         "precision mediump float;\n"
756         "out vec4 my_FragColor;\n"
757         "void main() {\n"
758         "   my_FragColor = vec4(0.0);\n"
759         "}\n";
760     if (compile(shaderString))
761     {
762         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
763     }
764 }
765 
766 // Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8)
TEST_F(FragmentShaderValidationTest,LayoutQualifierInCondition)767 TEST_F(FragmentShaderValidationTest, LayoutQualifierInCondition)
768 {
769     const std::string &shaderString =
770         "#version 300 es\n"
771         "precision mediump float;\n"
772         "uniform vec4 u;\n"
773         "out vec4 my_FragColor;\n"
774         "void main() {\n"
775         "    int i = 0;\n"
776         "    for (int j = 0; layout(location = 0) bool b = false; ++j) {\n"
777         "        ++i;\n"
778         "    }\n"
779         "    my_FragColor = u;\n"
780         "}\n";
781     if (compile(shaderString))
782     {
783         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
784     }
785 }
786 
787 // Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8)
TEST_F(FragmentShaderValidationTest,LayoutQualifierInFunctionReturnType)788 TEST_F(FragmentShaderValidationTest, LayoutQualifierInFunctionReturnType)
789 {
790     const std::string &shaderString =
791         "#version 300 es\n"
792         "precision mediump float;\n"
793         "uniform vec4 u;\n"
794         "out vec4 my_FragColor;\n"
795         "layout(location = 0) vec4 foo() {\n"
796         "    return u;\n"
797         "}\n"
798         "void main() {\n"
799         "    my_FragColor = foo();\n"
800         "}\n";
801     if (compile(shaderString))
802     {
803         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
804     }
805 }
806 
807 // If there is more than one output, the location must be specified for all outputs.
808 // (ESSL 3.00.04 section 4.3.8.2)
TEST_F(FragmentShaderValidationTest,TwoOutputsNoLayoutQualifiers)809 TEST_F(FragmentShaderValidationTest, TwoOutputsNoLayoutQualifiers)
810 {
811     const std::string &shaderString =
812         "#version 300 es\n"
813         "precision mediump float;\n"
814         "uniform vec4 u;\n"
815         "out vec4 my_FragColor;\n"
816         "out vec4 my_SecondaryFragColor;\n"
817         "void main() {\n"
818         "    my_FragColor = vec4(1.0);\n"
819         "    my_SecondaryFragColor = vec4(0.5);\n"
820         "}\n";
821     if (compile(shaderString))
822     {
823         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
824     }
825 }
826 
827 // (ESSL 3.00.04 section 4.3.8.2)
TEST_F(FragmentShaderValidationTest,TwoOutputsFirstLayoutQualifier)828 TEST_F(FragmentShaderValidationTest, TwoOutputsFirstLayoutQualifier)
829 {
830     const std::string &shaderString =
831         "#version 300 es\n"
832         "precision mediump float;\n"
833         "uniform vec4 u;\n"
834         "layout(location = 0) out vec4 my_FragColor;\n"
835         "out vec4 my_SecondaryFragColor;\n"
836         "void main() {\n"
837         "    my_FragColor = vec4(1.0);\n"
838         "    my_SecondaryFragColor = vec4(0.5);\n"
839         "}\n";
840     if (compile(shaderString))
841     {
842         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
843     }
844 }
845 
846 // (ESSL 3.00.04 section 4.3.8.2)
TEST_F(FragmentShaderValidationTest,TwoOutputsSecondLayoutQualifier)847 TEST_F(FragmentShaderValidationTest, TwoOutputsSecondLayoutQualifier)
848 {
849     const std::string &shaderString =
850         "#version 300 es\n"
851         "precision mediump float;\n"
852         "uniform vec4 u;\n"
853         "out vec4 my_FragColor;\n"
854         "layout(location = 0) out vec4 my_SecondaryFragColor;\n"
855         "void main() {\n"
856         "    my_FragColor = vec4(1.0);\n"
857         "    my_SecondaryFragColor = vec4(0.5);\n"
858         "}\n";
859     if (compile(shaderString))
860     {
861         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
862     }
863 }
864 
865 // Uniforms can be arrays (ESSL 3.00 section 4.3.5)
TEST_F(FragmentShaderValidationTest,UniformArray)866 TEST_F(FragmentShaderValidationTest, UniformArray)
867 {
868     const std::string &shaderString =
869         "#version 300 es\n"
870         "precision mediump float;\n"
871         "uniform vec4[2] u;\n"
872         "out vec4 my_FragColor;\n"
873         "void main() {\n"
874         "    my_FragColor = u[0];\n"
875         "}\n";
876     if (!compile(shaderString))
877     {
878         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
879     }
880 }
881 
882 // Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4)
TEST_F(FragmentShaderValidationTest,FragmentInputArrayOfStructs)883 TEST_F(FragmentShaderValidationTest, FragmentInputArrayOfStructs)
884 {
885     const std::string &shaderString =
886         "#version 300 es\n"
887         "precision mediump float;\n"
888         "struct S {\n"
889         "    vec4 foo;\n"
890         "};\n"
891         "in S i[2];\n"
892         "out vec4 my_FragColor;\n"
893         "void main() {\n"
894         "    my_FragColor = i[0].foo;\n"
895         "}\n";
896     if (compile(shaderString))
897     {
898         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
899     }
900 }
901 
902 // Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
903 // This test is testing the case where the array brackets are after the variable name, so
904 // the arrayness isn't known when the type and qualifiers are initially parsed.
TEST_F(VertexShaderValidationTest,VertexShaderInputArray)905 TEST_F(VertexShaderValidationTest, VertexShaderInputArray)
906 {
907     const std::string &shaderString =
908         "#version 300 es\n"
909         "precision mediump float;\n"
910         "in vec4 i[2];\n"
911         "void main() {\n"
912         "    gl_Position = i[0];\n"
913         "}\n";
914     if (compile(shaderString))
915     {
916         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
917     }
918 }
919 
920 // Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
921 // This test is testing the case where the array brackets are after the type.
TEST_F(VertexShaderValidationTest,VertexShaderInputArrayType)922 TEST_F(VertexShaderValidationTest, VertexShaderInputArrayType)
923 {
924     const std::string &shaderString =
925         "#version 300 es\n"
926         "precision mediump float;\n"
927         "in vec4[2] i;\n"
928         "void main() {\n"
929         "    gl_Position = i[0];\n"
930         "}\n";
931     if (compile(shaderString))
932     {
933         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
934     }
935 }
936 
937 // Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4)
TEST_F(FragmentShaderValidationTest,FragmentShaderInputStructWithBool)938 TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithBool)
939 {
940     const std::string &shaderString =
941         "#version 300 es\n"
942         "precision mediump float;\n"
943         "struct S {\n"
944         "    bool foo;\n"
945         "};\n"
946         "in S s;\n"
947         "out vec4 my_FragColor;\n"
948         "void main() {\n"
949         "    my_FragColor = vec4(0.0);\n"
950         "}\n";
951     if (compile(shaderString))
952     {
953         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
954     }
955 }
956 
957 // Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4)
TEST_F(FragmentShaderValidationTest,FragmentShaderInputStructWithInt)958 TEST_F(FragmentShaderValidationTest, FragmentShaderInputStructWithInt)
959 {
960     const std::string &shaderString =
961         "#version 300 es\n"
962         "precision mediump float;\n"
963         "struct S {\n"
964         "    int foo;\n"
965         "};\n"
966         "in S s;\n"
967         "out vec4 my_FragColor;\n"
968         "void main() {\n"
969         "    my_FragColor = vec4(0.0);\n"
970         "}\n";
971     if (compile(shaderString))
972     {
973         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
974     }
975 }
976 
977 // Selecting a field of a vector that's the result of dynamic indexing a constant array should work.
TEST_F(FragmentShaderValidationTest,ShaderSelectingFieldOfVectorIndexedFromArray)978 TEST_F(FragmentShaderValidationTest, ShaderSelectingFieldOfVectorIndexedFromArray)
979 {
980     const std::string &shaderString =
981         "#version 300 es\n"
982         "precision mediump float;\n"
983         "out vec4 my_FragColor;\n"
984         "uniform int i;\n"
985         "void main() {\n"
986         "    float f = vec2[1](vec2(0.0, 0.1))[i].x;\n"
987         "    my_FragColor = vec4(f);\n"
988         "}\n";
989     if (!compile(shaderString))
990     {
991         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
992     }
993 }
994 
995 // Passing an array into a function and then passing a value from that array into another function
996 // should work. This is a regression test for a bug where the mangled name of a TType was not
997 // properly updated when determining the type resulting from array indexing.
TEST_F(FragmentShaderValidationTest,ArrayValueFromFunctionParameterAsParameter)998 TEST_F(FragmentShaderValidationTest, ArrayValueFromFunctionParameterAsParameter)
999 {
1000     const std::string &shaderString =
1001         "precision mediump float;\n"
1002         "uniform float u;\n"
1003         "float foo(float f) {\n"
1004         "   return f * 2.0;\n"
1005         "}\n"
1006         "float bar(float[2] f) {\n"
1007         "    return foo(f[0]);\n"
1008         "}\n"
1009         "void main()\n"
1010         "{\n"
1011         "    float arr[2];\n"
1012         "    arr[0] = u;\n"
1013         "    gl_FragColor = vec4(bar(arr));\n"
1014         "}\n";
1015     if (!compile(shaderString))
1016     {
1017         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1018     }
1019 }
1020 
1021 // Test that out-of-range integer literal generates an error in ESSL 3.00.
TEST_F(FragmentShaderValidationTest,OutOfRangeIntegerLiteral)1022 TEST_F(FragmentShaderValidationTest, OutOfRangeIntegerLiteral)
1023 {
1024     const std::string &shaderString =
1025         "#version 300 es\n"
1026         "precision mediump float;\n"
1027         "precision highp int;\n"
1028         "out vec4 my_FragColor;\n"
1029         "void main() {\n"
1030         "    my_FragColor = vec4(0x100000000);\n"
1031         "}\n";
1032     if (compile(shaderString))
1033     {
1034         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1035     }
1036 }
1037 
1038 // Test that vector field selection from a value taken from an array constructor is accepted as a
1039 // constant expression.
TEST_F(FragmentShaderValidationTest,FieldSelectionFromVectorArrayConstructorIsConst)1040 TEST_F(FragmentShaderValidationTest, FieldSelectionFromVectorArrayConstructorIsConst)
1041 {
1042     const std::string &shaderString =
1043         "#version 300 es\n"
1044         "precision mediump float;\n"
1045         "out vec4 my_FragColor;\n"
1046         "void main()\n"
1047         "{\n"
1048         "    const float f = vec2[1](vec2(0.0, 1.0))[0].x;\n"
1049         "    my_FragColor = vec4(f);\n"
1050         "}\n";
1051     if (!compile(shaderString))
1052     {
1053         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1054     }
1055 }
1056 
1057 // Test that structure field selection from a value taken from an array constructor is accepted as a
1058 // constant expression.
TEST_F(FragmentShaderValidationTest,FieldSelectionFromStructArrayConstructorIsConst)1059 TEST_F(FragmentShaderValidationTest, FieldSelectionFromStructArrayConstructorIsConst)
1060 {
1061     const std::string &shaderString =
1062         "#version 300 es\n"
1063         "precision mediump float;\n"
1064         "out vec4 my_FragColor;\n"
1065         "struct S { float member; };\n"
1066         "void main()\n"
1067         "{\n"
1068         "    const float f = S[1](S(0.0))[0].member;\n"
1069         "    my_FragColor = vec4(f);\n"
1070         "}\n";
1071     if (!compile(shaderString))
1072     {
1073         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1074     }
1075 }
1076 
1077 // Test that a reference to a const array is accepted as a constant expression.
TEST_F(FragmentShaderValidationTest,ArraySymbolIsConst)1078 TEST_F(FragmentShaderValidationTest, ArraySymbolIsConst)
1079 {
1080     const std::string &shaderString =
1081         "#version 300 es\n"
1082         "precision mediump float;\n"
1083         "out vec4 my_FragColor;\n"
1084         "void main()\n"
1085         "{\n"
1086         "    const float[2] arr = float[2](0.0, 1.0);\n"
1087         "    const float f = arr[0];\n"
1088         "    my_FragColor = vec4(f);\n"
1089         "}\n";
1090     if (!compile(shaderString))
1091     {
1092         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1093     }
1094 }
1095 
1096 // Test that using an array constructor in a parameter to a built-in function is accepted as a
1097 // constant expression.
TEST_F(FragmentShaderValidationTest,BuiltInFunctionAppliedToArrayConstructorIsConst)1098 TEST_F(FragmentShaderValidationTest, BuiltInFunctionAppliedToArrayConstructorIsConst)
1099 {
1100     const std::string &shaderString =
1101         "#version 300 es\n"
1102         "precision mediump float;\n"
1103         "out vec4 my_FragColor;\n"
1104         "void main()\n"
1105         "{\n"
1106         "    const float f = sin(float[2](0.0, 1.0)[0]);\n"
1107         "    my_FragColor = vec4(f);\n"
1108         "}\n";
1109     if (!compile(shaderString))
1110     {
1111         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1112     }
1113 }
1114 
1115 // Test that using an array constructor in a parameter to a built-in function is accepted as a
1116 // constant expression.
TEST_F(FragmentShaderValidationTest,BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst)1117 TEST_F(FragmentShaderValidationTest,
1118        BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst)
1119 {
1120     const std::string &shaderString =
1121         "#version 300 es\n"
1122         "precision mediump float;\n"
1123         "out vec4 my_FragColor;\n"
1124         "void main()\n"
1125         "{\n"
1126         "    const float f = pow(1.0, float[2](0.0, 1.0)[0]);\n"
1127         "    my_FragColor = vec4(f);\n"
1128         "}\n";
1129     if (!compile(shaderString))
1130     {
1131         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1132     }
1133 }
1134 
1135 // Test that using an array constructor in a parameter to a constructor is accepted as a constant
1136 // expression.
TEST_F(FragmentShaderValidationTest,ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst)1137 TEST_F(FragmentShaderValidationTest,
1138        ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst)
1139 {
1140     const std::string &shaderString =
1141         "#version 300 es\n"
1142         "precision mediump float;\n"
1143         "out vec4 my_FragColor;\n"
1144         "void main()\n"
1145         "{\n"
1146         "    const vec2 f = vec2(1.0, float[2](0.0, 1.0)[0]);\n"
1147         "    my_FragColor = vec4(f.x);\n"
1148         "}\n";
1149     if (!compile(shaderString))
1150     {
1151         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1152     }
1153 }
1154 
1155 // Test that using an array constructor in an operand of the ternary selection operator is accepted
1156 // as a constant expression.
TEST_F(FragmentShaderValidationTest,TernaryOperatorAppliedToArrayConstructorIsConst)1157 TEST_F(FragmentShaderValidationTest, TernaryOperatorAppliedToArrayConstructorIsConst)
1158 {
1159     const std::string &shaderString =
1160         "#version 300 es\n"
1161         "precision mediump float;\n"
1162         "out vec4 my_FragColor;\n"
1163         "void main()\n"
1164         "{\n"
1165         "    const float f = true ? float[2](0.0, 1.0)[0] : 1.0;\n"
1166         "    my_FragColor = vec4(f);\n"
1167         "}\n";
1168     if (!compile(shaderString))
1169     {
1170         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1171     }
1172 }
1173 
1174 // Test that a ternary operator with one unevaluated non-constant operand is not a constant
1175 // expression.
TEST_F(FragmentShaderValidationTest,TernaryOperatorNonConstantOperand)1176 TEST_F(FragmentShaderValidationTest, TernaryOperatorNonConstantOperand)
1177 {
1178     const std::string &shaderString =
1179         "precision mediump float;\n"
1180         "uniform float u;\n"
1181         "void main()\n"
1182         "{\n"
1183         "    const float f = true ? 1.0 : u;\n"
1184         "    gl_FragColor = vec4(f);\n"
1185         "}\n";
1186     if (compile(shaderString))
1187     {
1188         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1189     }
1190 }
1191 
1192 // Test that a sampler can't be used in constructor argument list
TEST_F(FragmentShaderValidationTest,SamplerInConstructorArguments)1193 TEST_F(FragmentShaderValidationTest, SamplerInConstructorArguments)
1194 {
1195     const std::string &shaderString =
1196         "precision mediump float;\n"
1197         "uniform sampler2D s;\n"
1198         "void main()\n"
1199         "{\n"
1200         "    vec2 v = vec2(0.0, s);\n"
1201         "    gl_FragColor = vec4(v, 0.0, 0.0);\n"
1202         "}\n";
1203     if (compile(shaderString))
1204     {
1205         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1206     }
1207 }
1208 
1209 // Test that void can't be used in constructor argument list
TEST_F(FragmentShaderValidationTest,VoidInConstructorArguments)1210 TEST_F(FragmentShaderValidationTest, VoidInConstructorArguments)
1211 {
1212     const std::string &shaderString =
1213         "precision mediump float;\n"
1214         "void foo() {}\n"
1215         "void main()\n"
1216         "{\n"
1217         "    vec2 v = vec2(0.0, foo());\n"
1218         "    gl_FragColor = vec4(v, 0.0, 0.0);\n"
1219         "}\n";
1220     if (compile(shaderString))
1221     {
1222         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1223     }
1224 }
1225 
1226 // Test that a shader passing a struct into a constructor of array of structs with 1 element works.
TEST_F(FragmentShaderValidationTest,SingleStructArrayConstructor)1227 TEST_F(FragmentShaderValidationTest, SingleStructArrayConstructor)
1228 {
1229     const std::string &shaderString =
1230         "#version 300 es\n"
1231         "precision mediump float;\n"
1232         "out vec4 my_FragColor;\n"
1233         "uniform float u;\n"
1234         "struct S { float member; };\n"
1235         "void main()\n"
1236         "{\n"
1237         "    S[1] sarr = S[1](S(u));\n"
1238         "    my_FragColor = vec4(sarr[0].member);\n"
1239         "}\n";
1240     if (!compile(shaderString))
1241     {
1242         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1243     }
1244 }
1245 
1246 // Test that a shader with empty constructor parameter list is not accepted.
TEST_F(FragmentShaderValidationTest,EmptyArrayConstructor)1247 TEST_F(FragmentShaderValidationTest, EmptyArrayConstructor)
1248 {
1249     const std::string &shaderString =
1250         "#version 300 es\n"
1251         "precision mediump float;\n"
1252         "out vec4 my_FragColor;\n"
1253         "uniform float u;\n"
1254         "const float[] f = f[]();\n"
1255         "void main()\n"
1256         "{\n"
1257         "    my_FragColor = vec4(0.0);\n"
1258         "}\n";
1259     if (compile(shaderString))
1260     {
1261         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1262     }
1263 }
1264 
1265 // Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE
1266 // is able to constant fold the index expression. ESSL 3.00 section 4.3.6.
TEST_F(FragmentShaderValidationTest,DynamicallyIndexedFragmentOutput)1267 TEST_F(FragmentShaderValidationTest, DynamicallyIndexedFragmentOutput)
1268 {
1269     const std::string &shaderString =
1270         "#version 300 es\n"
1271         "precision mediump float;\n"
1272         "uniform int a;\n"
1273         "out vec4[2] my_FragData;\n"
1274         "void main()\n"
1275         "{\n"
1276         "    my_FragData[true ? 0 : a] = vec4(0.0);\n"
1277         "}\n";
1278     if (compile(shaderString))
1279     {
1280         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1281     }
1282 }
1283 
1284 // Test that indexing a uniform buffer array with a non-constant expression is forbidden, even if
1285 // ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7.
TEST_F(FragmentShaderValidationTest,DynamicallyIndexedUniformBuffer)1286 TEST_F(FragmentShaderValidationTest, DynamicallyIndexedUniformBuffer)
1287 {
1288     const std::string &shaderString =
1289         R"(#version 300 es
1290         precision mediump float;
1291         uniform int a;
1292         uniform B
1293         {
1294             vec4 f;
1295         }
1296         blocks[2];
1297         out vec4 my_FragColor;
1298         void main()
1299         {
1300             my_FragColor = blocks[true ? 0 : a].f;
1301         })";
1302     if (compile(shaderString))
1303     {
1304         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1305     }
1306 }
1307 
1308 // Test that indexing a storage buffer array with a non-constant expression is forbidden, even if
1309 // ANGLE is able to constant fold the index expression. ESSL 3.10 section 4.3.9.
TEST_F(FragmentShaderValidationTest,DynamicallyIndexedStorageBuffer)1310 TEST_F(FragmentShaderValidationTest, DynamicallyIndexedStorageBuffer)
1311 {
1312     const std::string &shaderString =
1313         R"(#version 310 es
1314         precision mediump float;
1315         uniform int a;
1316         layout(std140) buffer B
1317         {
1318             vec4 f;
1319         }
1320         blocks[2];
1321         out vec4 my_FragColor;
1322         void main()
1323         {
1324             my_FragColor = blocks[true ? 0 : a].f;
1325         })";
1326     if (compile(shaderString))
1327     {
1328         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1329     }
1330 }
1331 
1332 // Test that indexing a sampler array with a non-constant expression is forbidden, even if ANGLE is
1333 // able to constant fold the index expression. ESSL 3.00 section 4.1.7.1.
TEST_F(FragmentShaderValidationTest,DynamicallyIndexedSampler)1334 TEST_F(FragmentShaderValidationTest, DynamicallyIndexedSampler)
1335 {
1336     const std::string &shaderString =
1337         R"(#version 300 es
1338         precision mediump float;
1339         uniform int a;
1340         uniform sampler2D s[2];
1341         out vec4 my_FragColor;
1342         void main()
1343         {
1344             my_FragColor = texture(s[true ? 0 : a], vec2(0));
1345         })";
1346     if (compile(shaderString))
1347     {
1348         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1349     }
1350 }
1351 
1352 // Test that indexing an image array with a non-constant expression is forbidden, even if ANGLE is
1353 // able to constant fold the index expression. ESSL 3.10 section 4.1.7.2.
TEST_F(FragmentShaderValidationTest,DynamicallyIndexedImage)1354 TEST_F(FragmentShaderValidationTest, DynamicallyIndexedImage)
1355 {
1356     const std::string &shaderString =
1357         R"(#version 310 es
1358         precision mediump float;
1359         uniform int a;
1360         layout(rgba32f) uniform highp readonly image2D image[2];
1361         out vec4 my_FragColor;
1362         void main()
1363         {
1364             my_FragColor = imageLoad(image[true ? 0 : a], ivec2(0));
1365         })";
1366     if (compile(shaderString))
1367     {
1368         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1369     }
1370 }
1371 
1372 // Test that a shader that uses a struct definition in place of a struct constructor does not
1373 // compile. See GLSL ES 1.00 section 5.4.3.
TEST_F(FragmentShaderValidationTest,StructConstructorWithStructDefinition)1374 TEST_F(FragmentShaderValidationTest, StructConstructorWithStructDefinition)
1375 {
1376     const std::string &shaderString =
1377         "precision mediump float;\n"
1378         "void main()\n"
1379         "{\n"
1380         "    struct s { float f; } (0.0);\n"
1381         "    gl_FragColor = vec4(0.0);\n"
1382         "}\n";
1383     if (compile(shaderString))
1384     {
1385         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1386     }
1387 }
1388 
1389 // Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even
1390 // when ANGLE is able to constant fold the index.
1391 // WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output'
TEST_F(WebGL2FragmentShaderValidationTest,IndexFragDataWithNonConstant)1392 TEST_F(WebGL2FragmentShaderValidationTest, IndexFragDataWithNonConstant)
1393 {
1394     const std::string &shaderString =
1395         "precision mediump float;\n"
1396         "void main()\n"
1397         "{\n"
1398         "    for (int i = 0; i < 2; ++i) {\n"
1399         "        gl_FragData[true ? 0 : i] = vec4(0.0);\n"
1400         "    }\n"
1401         "}\n";
1402     if (compile(shaderString))
1403     {
1404         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1405     }
1406 }
1407 
1408 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
1409 // Initializing with an uniform should generate a warning
1410 // (we don't generate an error on ESSL 1.00 because of WebGL compatibility)
TEST_F(WebGL2FragmentShaderValidationTest,AssignUniformToGlobalESSL1)1411 TEST_F(WebGL2FragmentShaderValidationTest, AssignUniformToGlobalESSL1)
1412 {
1413     const std::string &shaderString =
1414         "precision mediump float;\n"
1415         "uniform float a;\n"
1416         "float b = a * 2.0;\n"
1417         "void main() {\n"
1418         "   gl_FragColor = vec4(b);\n"
1419         "}\n";
1420     if (compile(shaderString))
1421     {
1422         if (!hasWarning())
1423         {
1424             FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
1425                    << mInfoLog;
1426         }
1427     }
1428     else
1429     {
1430         FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
1431     }
1432 }
1433 
1434 // Test that deferring global variable init works with an empty main().
TEST_F(WebGL2FragmentShaderValidationTest,DeferGlobalVariableInitWithEmptyMain)1435 TEST_F(WebGL2FragmentShaderValidationTest, DeferGlobalVariableInitWithEmptyMain)
1436 {
1437     const std::string &shaderString =
1438         "precision mediump float;\n"
1439         "uniform float u;\n"
1440         "float foo = u;\n"
1441         "void main() {}\n";
1442     if (!compile(shaderString))
1443     {
1444         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1445     }
1446 }
1447 
1448 // Test that a non-constant texture offset is not accepted for textureOffset.
1449 // ESSL 3.00 section 8.8
TEST_F(FragmentShaderValidationTest,TextureOffsetNonConst)1450 TEST_F(FragmentShaderValidationTest, TextureOffsetNonConst)
1451 {
1452     const std::string &shaderString =
1453         "#version 300 es\n"
1454         "precision mediump float;\n"
1455         "out vec4 my_FragColor;\n"
1456         "uniform vec3 u_texCoord;\n"
1457         "uniform mediump sampler3D u_sampler;\n"
1458         "uniform int x;\n"
1459         "void main()\n"
1460         "{\n"
1461         "   my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8));\n"
1462         "}\n";
1463     if (compile(shaderString))
1464     {
1465         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1466     }
1467 }
1468 
1469 // Test that a non-constant texture offset is not accepted for textureProjOffset with bias.
1470 // ESSL 3.00 section 8.8
TEST_F(FragmentShaderValidationTest,TextureProjOffsetNonConst)1471 TEST_F(FragmentShaderValidationTest, TextureProjOffsetNonConst)
1472 {
1473     const std::string &shaderString =
1474         "#version 300 es\n"
1475         "precision mediump float;\n"
1476         "out vec4 my_FragColor;\n"
1477         "uniform vec4 u_texCoord;\n"
1478         "uniform mediump sampler3D u_sampler;\n"
1479         "uniform int x;\n"
1480         "void main()\n"
1481         "{\n"
1482         "   my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0);\n"
1483         "}\n";
1484     if (compile(shaderString))
1485     {
1486         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1487     }
1488 }
1489 
1490 // Test that an out-of-range texture offset is not accepted.
1491 // GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior.
TEST_F(FragmentShaderValidationTest,TextureLodOffsetOutOfRange)1492 TEST_F(FragmentShaderValidationTest, TextureLodOffsetOutOfRange)
1493 {
1494     const std::string &shaderString =
1495         "#version 300 es\n"
1496         "precision mediump float;\n"
1497         "out vec4 my_FragColor;\n"
1498         "uniform vec3 u_texCoord;\n"
1499         "uniform mediump sampler3D u_sampler;\n"
1500         "void main()\n"
1501         "{\n"
1502         "   my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, 8));\n"
1503         "}\n";
1504     if (compile(shaderString))
1505     {
1506         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1507     }
1508 }
1509 
1510 // Test that default precision qualifier for uint is not accepted.
1511 // ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types.
TEST_F(FragmentShaderValidationTest,DefaultPrecisionUint)1512 TEST_F(FragmentShaderValidationTest, DefaultPrecisionUint)
1513 {
1514     const std::string &shaderString =
1515         "#version 300 es\n"
1516         "precision mediump float;\n"
1517         "precision mediump uint;\n"
1518         "out vec4 my_FragColor;\n"
1519         "void main()\n"
1520         "{\n"
1521         "   my_FragColor = vec4(0.0);\n"
1522         "}\n";
1523     if (compile(shaderString))
1524     {
1525         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1526     }
1527 }
1528 
1529 // Test that sampler3D needs to be precision qualified.
1530 // ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision.
TEST_F(FragmentShaderValidationTest,NoPrecisionSampler3D)1531 TEST_F(FragmentShaderValidationTest, NoPrecisionSampler3D)
1532 {
1533     const std::string &shaderString =
1534         "#version 300 es\n"
1535         "precision mediump float;\n"
1536         "uniform sampler3D s;\n"
1537         "out vec4 my_FragColor;\n"
1538         "void main()\n"
1539         "{\n"
1540         "   my_FragColor = vec4(0.0);\n"
1541         "}\n";
1542     if (compile(shaderString))
1543     {
1544         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1545     }
1546 }
1547 
1548 // Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0,
1549 // even when ANGLE is able to constant fold the initializer.
1550 // ESSL 1.00 Appendix A.
TEST_F(WebGL1FragmentShaderValidationTest,NonConstantLoopIndex)1551 TEST_F(WebGL1FragmentShaderValidationTest, NonConstantLoopIndex)
1552 {
1553     const std::string &shaderString =
1554         "precision mediump float;\n"
1555         "uniform int u;\n"
1556         "void main()\n"
1557         "{\n"
1558         "    for (int i = (true ? 1 : u); i < 5; ++i) {\n"
1559         "        gl_FragColor = vec4(0.0);\n"
1560         "    }\n"
1561         "}\n";
1562     if (compile(shaderString))
1563     {
1564         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1565     }
1566 }
1567 
1568 // Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
1569 // Initializing with an uniform should generate a warning
1570 // (we don't generate an error on ESSL 1.00 because of WebGL compatibility)
TEST_F(WebGL1FragmentShaderValidationTest,AssignUniformToGlobalESSL1)1571 TEST_F(WebGL1FragmentShaderValidationTest, AssignUniformToGlobalESSL1)
1572 {
1573     const std::string &shaderString =
1574         "precision mediump float;\n"
1575         "uniform float a;\n"
1576         "float b = a * 2.0;\n"
1577         "void main() {\n"
1578         "   gl_FragColor = vec4(b);\n"
1579         "}\n";
1580     if (compile(shaderString))
1581     {
1582         if (!hasWarning())
1583         {
1584             FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
1585                    << mInfoLog;
1586         }
1587     }
1588     else
1589     {
1590         FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
1591     }
1592 }
1593 
1594 // Test that deferring global variable init works with an empty main().
TEST_F(WebGL1FragmentShaderValidationTest,DeferGlobalVariableInitWithEmptyMain)1595 TEST_F(WebGL1FragmentShaderValidationTest, DeferGlobalVariableInitWithEmptyMain)
1596 {
1597     const std::string &shaderString =
1598         "precision mediump float;\n"
1599         "uniform float u;\n"
1600         "float foo = u;\n"
1601         "void main() {}\n";
1602     if (!compile(shaderString))
1603     {
1604         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1605     }
1606 }
1607 
1608 // Check that indices that are not integers are rejected.
1609 // The check should be done even if ESSL 1.00 Appendix A limitations are not applied.
TEST_F(FragmentShaderValidationTest,NonIntegerIndex)1610 TEST_F(FragmentShaderValidationTest, NonIntegerIndex)
1611 {
1612     const std::string &shaderString =
1613         "precision mediump float;\n"
1614         "void main()\n"
1615         "{\n"
1616         "    float f[3];\n"
1617         "    const float i = 2.0;\n"
1618         "    gl_FragColor = vec4(f[i]);\n"
1619         "}\n";
1620     if (compile(shaderString))
1621     {
1622         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1623     }
1624 }
1625 
1626 // ESSL1 shaders with a duplicate function prototype should be rejected.
1627 // ESSL 1.00.17 section 4.2.7.
TEST_F(FragmentShaderValidationTest,DuplicatePrototypeESSL1)1628 TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL1)
1629 {
1630     const std::string &shaderString =
1631         "precision mediump float;\n"
1632         "void foo();\n"
1633         "void foo();\n"
1634         "void foo() {}\n"
1635         "void main()\n"
1636         "{\n"
1637         "    gl_FragColor = vec4(0.0);\n"
1638         "}\n";
1639     if (compile(shaderString))
1640     {
1641         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1642     }
1643 }
1644 
1645 // ESSL3 shaders with a duplicate function prototype should be allowed.
1646 // ESSL 3.00.4 section 4.2.3.
TEST_F(FragmentShaderValidationTest,DuplicatePrototypeESSL3)1647 TEST_F(FragmentShaderValidationTest, DuplicatePrototypeESSL3)
1648 {
1649     const std::string &shaderString =
1650         "#version 300 es\n"
1651         "precision mediump float;\n"
1652         "out vec4 my_FragColor;\n"
1653         "void foo();\n"
1654         "void foo();\n"
1655         "void foo() {}\n"
1656         "void main()\n"
1657         "{\n"
1658         "    my_FragColor = vec4(0.0);\n"
1659         "}\n";
1660     if (!compile(shaderString))
1661     {
1662         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1663     }
1664 }
1665 
1666 // Shaders with a local function prototype should be rejected.
1667 // ESSL 3.00.4 section 4.2.4.
TEST_F(FragmentShaderValidationTest,LocalFunctionPrototype)1668 TEST_F(FragmentShaderValidationTest, LocalFunctionPrototype)
1669 {
1670     const std::string &shaderString =
1671         "#version 300 es\n"
1672         "precision mediump float;\n"
1673         "out vec4 my_FragColor;\n"
1674         "void main()\n"
1675         "{\n"
1676         "    void foo();\n"
1677         "    my_FragColor = vec4(0.0);\n"
1678         "}\n";
1679     if (compile(shaderString))
1680     {
1681         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1682     }
1683 }
1684 
1685 // ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all).
1686 // ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL.
TEST_F(FragmentShaderValidationTest,ESSL300FragmentInvariantAll)1687 TEST_F(FragmentShaderValidationTest, ESSL300FragmentInvariantAll)
1688 {
1689     const std::string &shaderString =
1690         "#version 300 es\n"
1691         "#pragma STDGL invariant(all)\n"
1692         "precision mediump float;\n"
1693         "out vec4 my_FragColor;\n"
1694         "void main()\n"
1695         "{\n"
1696         "    my_FragColor = vec4(0.0);\n"
1697         "}\n";
1698     if (compile(shaderString))
1699     {
1700         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1701     }
1702 }
1703 
1704 // Built-in functions can be overloaded in ESSL 1.00.
TEST_F(FragmentShaderValidationTest,ESSL100BuiltInFunctionOverload)1705 TEST_F(FragmentShaderValidationTest, ESSL100BuiltInFunctionOverload)
1706 {
1707     const std::string &shaderString =
1708         "precision mediump float;\n"
1709         "int sin(int x)\n"
1710         "{\n"
1711         "    return int(sin(float(x)));\n"
1712         "}\n"
1713         "void main()\n"
1714         "{\n"
1715         "   gl_FragColor = vec4(sin(1));"
1716         "}\n";
1717     if (!compile(shaderString))
1718     {
1719         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1720     }
1721 }
1722 
1723 // Built-in functions can not be overloaded in ESSL 3.00.
TEST_F(FragmentShaderValidationTest,ESSL300BuiltInFunctionOverload)1724 TEST_F(FragmentShaderValidationTest, ESSL300BuiltInFunctionOverload)
1725 {
1726     const std::string &shaderString =
1727         "#version 300 es\n"
1728         "precision mediump float;\n"
1729         "out vec4 my_FragColor;\n"
1730         "int sin(int x)\n"
1731         "{\n"
1732         "    return int(sin(float(x)));\n"
1733         "}\n"
1734         "void main()\n"
1735         "{\n"
1736         "   my_FragColor = vec4(sin(1));"
1737         "}\n";
1738     if (compile(shaderString))
1739     {
1740         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1741     }
1742 }
1743 
1744 // Multiplying a 4x2 matrix with a 4x2 matrix should not work.
TEST_F(FragmentShaderValidationTest,CompoundMultiplyMatrixIdenticalNonSquareDimensions)1745 TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixIdenticalNonSquareDimensions)
1746 {
1747     const std::string &shaderString =
1748         "#version 300 es\n"
1749         "precision mediump float;\n"
1750         "out vec4 my_FragColor;\n"
1751         "void main()\n"
1752         "{\n"
1753         "   mat4x2 foo;\n"
1754         "   foo *= mat4x2(4.0);\n"
1755         "   my_FragColor = vec4(0.0);\n"
1756         "}\n";
1757     if (compile(shaderString))
1758     {
1759         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1760     }
1761 }
1762 
1763 // Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work.
TEST_F(FragmentShaderValidationTest,CompoundMultiplyMatrixValidNonSquareDimensions)1764 TEST_F(FragmentShaderValidationTest, CompoundMultiplyMatrixValidNonSquareDimensions)
1765 {
1766     const std::string &shaderString =
1767         "#version 300 es\n"
1768         "precision mediump float;\n"
1769         "out vec4 my_FragColor;\n"
1770         "void main()\n"
1771         "{\n"
1772         "   mat2x4 foo;\n"
1773         "   foo *= mat2x2(4.0);\n"
1774         "   my_FragColor = vec4(0.0);\n"
1775         "}\n";
1776     if (!compile(shaderString))
1777     {
1778         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1779     }
1780 }
1781 
1782 // Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle.
TEST_F(FragmentShaderValidationTest,OutOfBoundsVectorSwizzle)1783 TEST_F(FragmentShaderValidationTest, OutOfBoundsVectorSwizzle)
1784 {
1785     const std::string &shaderString =
1786         "void main() {\n"
1787         "   vec2(0).qq;\n"
1788         "}\n";
1789     if (compile(shaderString))
1790     {
1791         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1792     }
1793 }
1794 
1795 // Covers a bug where strange preprocessor defines could trigger asserts.
TEST_F(FragmentShaderValidationTest,DefineWithSemicolon)1796 TEST_F(FragmentShaderValidationTest, DefineWithSemicolon)
1797 {
1798     const std::string &shaderString =
1799         "#define Def; highp\n"
1800         "uniform Def vec2 a;\n";
1801     if (compile(shaderString))
1802     {
1803         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1804     }
1805 }
1806 
1807 // Covers a bug in our parsing of malformed shift preprocessor expressions.
TEST_F(FragmentShaderValidationTest,LineDirectiveUndefinedShift)1808 TEST_F(FragmentShaderValidationTest, LineDirectiveUndefinedShift)
1809 {
1810     const std::string &shaderString = "#line x << y";
1811     if (compile(shaderString))
1812     {
1813         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1814     }
1815 }
1816 
1817 // Covers a bug in our parsing of malformed shift preprocessor expressions.
TEST_F(FragmentShaderValidationTest,LineDirectiveNegativeShift)1818 TEST_F(FragmentShaderValidationTest, LineDirectiveNegativeShift)
1819 {
1820     const std::string &shaderString = "#line x << -1";
1821     if (compile(shaderString))
1822     {
1823         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1824     }
1825 }
1826 
1827 // gl_MaxImageUnits is only available in ES 3.1 shaders.
TEST_F(FragmentShaderValidationTest,MaxImageUnitsInES3Shader)1828 TEST_F(FragmentShaderValidationTest, MaxImageUnitsInES3Shader)
1829 {
1830     const std::string &shaderString =
1831         "#version 300 es\n"
1832         "precision mediump float;\n"
1833         "out vec4 myOutput;"
1834         "void main() {\n"
1835         "   float ff = float(gl_MaxImageUnits);\n"
1836         "   myOutput = vec4(ff);\n"
1837         "}\n";
1838     if (compile(shaderString))
1839     {
1840         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1841     }
1842 }
1843 
1844 // struct += struct is an invalid operation.
TEST_F(FragmentShaderValidationTest,StructCompoundAssignStruct)1845 TEST_F(FragmentShaderValidationTest, StructCompoundAssignStruct)
1846 {
1847     const std::string &shaderString =
1848         "#version 300 es\n"
1849         "precision mediump float;\n"
1850         "out vec4 myOutput;\n"
1851         "struct S { float foo; };\n"
1852         "void main() {\n"
1853         "   S a, b;\n"
1854         "   a += b;\n"
1855         "   myOutput = vec4(0);\n"
1856         "}\n";
1857     if (compile(shaderString))
1858     {
1859         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1860     }
1861 }
1862 
1863 // struct == different struct is an invalid operation.
TEST_F(FragmentShaderValidationTest,StructEqDifferentStruct)1864 TEST_F(FragmentShaderValidationTest, StructEqDifferentStruct)
1865 {
1866     const std::string &shaderString =
1867         "#version 300 es\n"
1868         "precision mediump float;\n"
1869         "out vec4 myOutput;\n"
1870         "struct S { float foo; };\n"
1871         "struct S2 { float foobar; };\n"
1872         "void main() {\n"
1873         "   S a;\n"
1874         "   S2 b;\n"
1875         "   a == b;\n"
1876         "   myOutput = vec4(0);\n"
1877         "}\n";
1878     if (compile(shaderString))
1879     {
1880         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1881     }
1882 }
1883 
1884 // Compute shaders are not supported in versions lower than 310.
TEST_F(ComputeShaderValidationTest,Version100)1885 TEST_F(ComputeShaderValidationTest, Version100)
1886 {
1887     const std::string &shaderString =
1888         R"(void main()
1889         {
1890         })";
1891     if (compile(shaderString))
1892     {
1893         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1894     }
1895 }
1896 
1897 // Compute shaders are not supported in versions lower than 310.
TEST_F(ComputeShaderValidationTest,Version300)1898 TEST_F(ComputeShaderValidationTest, Version300)
1899 {
1900     const std::string &shaderString =
1901         R"(#version 300 es
1902         void main()
1903         {
1904         })";
1905     if (compile(shaderString))
1906     {
1907         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1908     }
1909 }
1910 
1911 // Compute shaders should have work group size specified. However, it is not a compile time error
1912 // to not have the size specified, but rather a link time one.
1913 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,NoWorkGroupSizeSpecified)1914 TEST_F(ComputeShaderValidationTest, NoWorkGroupSizeSpecified)
1915 {
1916     const std::string &shaderString =
1917         "#version 310 es\n"
1918         "void main()\n"
1919         "{\n"
1920         "}\n";
1921     if (!compile(shaderString))
1922     {
1923         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1924     }
1925 }
1926 
1927 // Test that workgroup size declaration doesn't accept variable declaration.
TEST_F(ComputeShaderValidationTest,NoVariableDeclrationAfterWorkGroupSize)1928 TEST_F(ComputeShaderValidationTest, NoVariableDeclrationAfterWorkGroupSize)
1929 {
1930     constexpr char kShaderString[] =
1931         R"(#version 310 es
1932         layout(local_size_x = 1) in vec4 x;
1933         void main()
1934         {
1935         })";
1936     if (compile(kShaderString))
1937     {
1938         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1939     }
1940 }
1941 
1942 // Work group size is less than 1. It should be at least 1.
1943 // GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
1944 // The spec is not clear whether having a local size qualifier equal zero
1945 // is correct.
1946 // TODO (mradev): Ask people from Khronos to clarify the spec.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeTooSmallXdimension)1947 TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallXdimension)
1948 {
1949     const std::string &shaderString =
1950         "#version 310 es\n"
1951         "layout(local_size_x = 0) in;\n"
1952         "void main()\n"
1953         "{\n"
1954         "}\n";
1955     if (compile(shaderString))
1956     {
1957         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1958     }
1959 }
1960 
1961 // Work group size is correct for the x and y dimensions, but not for the z dimension.
1962 // GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
TEST_F(ComputeShaderValidationTest,WorkGroupSizeTooSmallZDimension)1963 TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooSmallZDimension)
1964 {
1965     const std::string &shaderString =
1966         "#version 310 es\n"
1967         "layout(local_size_x = 4, local_size_y = 6, local_size_z = 0) in;\n"
1968         "void main()\n"
1969         "{\n"
1970         "}\n";
1971     if (compile(shaderString))
1972     {
1973         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1974     }
1975 }
1976 
1977 // Work group size is bigger than the minimum in the x dimension.
1978 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,WorkGroupSizeTooBigXDimension)1979 TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigXDimension)
1980 {
1981     const std::string &shaderString =
1982         "#version 310 es\n"
1983         "layout(local_size_x = 9989899) in;\n"
1984         "void main()\n"
1985         "{\n"
1986         "}\n";
1987     if (compile(shaderString))
1988     {
1989         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1990     }
1991 }
1992 
1993 // Work group size is bigger than the minimum in the y dimension.
1994 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,WorkGroupSizeTooBigYDimension)1995 TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigYDimension)
1996 {
1997     const std::string &shaderString =
1998         "#version 310 es\n"
1999         "layout(local_size_x = 5, local_size_y = 9989899) in;\n"
2000         "void main()\n"
2001         "{\n"
2002         "}\n";
2003     if (compile(shaderString))
2004     {
2005         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2006     }
2007 }
2008 
2009 // Work group size is definitely bigger than the minimum in the z dimension.
2010 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,WorkGroupSizeTooBigZDimension)2011 TEST_F(ComputeShaderValidationTest, WorkGroupSizeTooBigZDimension)
2012 {
2013     const std::string &shaderString =
2014         "#version 310 es\n"
2015         "layout(local_size_x = 5, local_size_y = 5, local_size_z = 9989899) in;\n"
2016         "void main()\n"
2017         "{\n"
2018         "}\n";
2019     if (compile(shaderString))
2020     {
2021         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2022     }
2023 }
2024 
2025 // Work group size specified through macro expansion.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeMacro)2026 TEST_F(ComputeShaderValidationTest, WorkGroupSizeMacro)
2027 {
2028     const std::string &shaderString =
2029         "#version 310 es\n"
2030         "#define MYDEF(x) x"
2031         "layout(local_size_x = MYDEF(127)) in;\n"
2032         "void main()\n"
2033         "{\n"
2034         "}\n";
2035     if (!compile(shaderString))
2036     {
2037         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2038     }
2039 }
2040 
2041 // Work group size specified as an unsigned integer.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeUnsignedInteger)2042 TEST_F(ComputeShaderValidationTest, WorkGroupSizeUnsignedInteger)
2043 {
2044     const std::string &shaderString =
2045         "#version 310 es\n"
2046         "layout(local_size_x = 123u) in;\n"
2047         "void main()\n"
2048         "{\n"
2049         "}\n";
2050     if (!compile(shaderString))
2051     {
2052         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2053     }
2054 }
2055 
2056 // Work group size specified in hexadecimal.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeHexadecimal)2057 TEST_F(ComputeShaderValidationTest, WorkGroupSizeHexadecimal)
2058 {
2059     const std::string &shaderString =
2060         "#version 310 es\n"
2061         "layout(local_size_x = 0x3A) in;\n"
2062         "void main()\n"
2063         "{\n"
2064         "}\n";
2065     if (!compile(shaderString))
2066     {
2067         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2068     }
2069 }
2070 
2071 // local_size_x is -1 in hexadecimal format.
2072 // -1 is used as unspecified value in the TLayoutQualifier structure.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeMinusOneHexadecimal)2073 TEST_F(ComputeShaderValidationTest, WorkGroupSizeMinusOneHexadecimal)
2074 {
2075     const std::string &shaderString =
2076         "#version 310 es\n"
2077         "layout(local_size_x = 0xFFFFFFFF) in;\n"
2078         "void main()\n"
2079         "{\n"
2080         "}\n";
2081     if (compile(shaderString))
2082     {
2083         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2084     }
2085 }
2086 
2087 // Work group size specified in octal.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeOctal)2088 TEST_F(ComputeShaderValidationTest, WorkGroupSizeOctal)
2089 {
2090     const std::string &shaderString =
2091         "#version 310 es\n"
2092         "layout(local_size_x = 013) in;\n"
2093         "void main()\n"
2094         "{\n"
2095         "}\n";
2096     if (!compile(shaderString))
2097     {
2098         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2099     }
2100 }
2101 
2102 // Work group size is negative. It is specified in hexadecimal.
TEST_F(ComputeShaderValidationTest,WorkGroupSizeNegativeHexadecimal)2103 TEST_F(ComputeShaderValidationTest, WorkGroupSizeNegativeHexadecimal)
2104 {
2105     const std::string &shaderString =
2106         "#version 310 es\n"
2107         "layout(local_size_x = 0xFFFFFFEC) in;\n"
2108         "void main()\n"
2109         "{\n"
2110         "}\n";
2111     if (compile(shaderString))
2112     {
2113         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2114     }
2115 }
2116 
2117 // Multiple work group layout qualifiers with differing values.
2118 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,DifferingLayoutQualifiers)2119 TEST_F(ComputeShaderValidationTest, DifferingLayoutQualifiers)
2120 {
2121     const std::string &shaderString =
2122         "#version 310 es\n"
2123         "layout(local_size_x = 5, local_size_x = 6) in;\n"
2124         "void main()\n"
2125         "{\n"
2126         "}\n";
2127     if (compile(shaderString))
2128     {
2129         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2130     }
2131 }
2132 
2133 // Multiple work group input variables with differing local size values.
2134 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,MultipleInputVariablesDifferingLocalSize)2135 TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize)
2136 {
2137     const std::string &shaderString =
2138         "#version 310 es\n"
2139         "layout(local_size_x = 5, local_size_y = 6) in;\n"
2140         "layout(local_size_x = 5, local_size_y = 7) in;\n"
2141         "void main()\n"
2142         "{\n"
2143         "}\n";
2144     if (compile(shaderString))
2145     {
2146         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2147     }
2148 }
2149 
2150 // Multiple work group input variables with differing local size values.
2151 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,MultipleInputVariablesDifferingLocalSize2)2152 TEST_F(ComputeShaderValidationTest, MultipleInputVariablesDifferingLocalSize2)
2153 {
2154     const std::string &shaderString =
2155         "#version 310 es\n"
2156         "layout(local_size_x = 5) in;\n"
2157         "layout(local_size_x = 5, local_size_y = 7) in;\n"
2158         "void main()\n"
2159         "{\n"
2160         "}\n";
2161     if (compile(shaderString))
2162     {
2163         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2164     }
2165 }
2166 
2167 // Multiple work group input variables with the same local size values. It should compile.
2168 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,MultipleInputVariablesSameLocalSize)2169 TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize)
2170 {
2171     const std::string &shaderString =
2172         "#version 310 es\n"
2173         "layout(local_size_x = 5, local_size_y = 6) in;\n"
2174         "layout(local_size_x = 5, local_size_y = 6) in;\n"
2175         "void main()\n"
2176         "{\n"
2177         "}\n";
2178     if (!compile(shaderString))
2179     {
2180         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2181     }
2182 }
2183 
2184 // Multiple work group input variables with the same local size values. It should compile.
2185 // Since the default value is 1, it should compile.
2186 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,MultipleInputVariablesSameLocalSize2)2187 TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize2)
2188 {
2189     const std::string &shaderString =
2190         "#version 310 es\n"
2191         "layout(local_size_x = 5) in;\n"
2192         "layout(local_size_x = 5, local_size_y = 1) in;\n"
2193         "void main()\n"
2194         "{\n"
2195         "}\n";
2196     if (!compile(shaderString))
2197     {
2198         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2199     }
2200 }
2201 
2202 // Multiple work group input variables with the same local size values. It should compile.
2203 // Since the default value is 1, it should compile.
2204 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,MultipleInputVariablesSameLocalSize3)2205 TEST_F(ComputeShaderValidationTest, MultipleInputVariablesSameLocalSize3)
2206 {
2207     const std::string &shaderString =
2208         "#version 310 es\n"
2209         "layout(local_size_x = 5, local_size_y = 1) in;\n"
2210         "layout(local_size_x = 5) in;\n"
2211         "void main()\n"
2212         "{\n"
2213         "}\n";
2214     if (!compile(shaderString))
2215     {
2216         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2217     }
2218 }
2219 
2220 // Specifying row_major qualifier in a work group size layout.
2221 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,RowMajorInComputeInputLayout)2222 TEST_F(ComputeShaderValidationTest, RowMajorInComputeInputLayout)
2223 {
2224     const std::string &shaderString =
2225         "#version 310 es\n"
2226         "layout(local_size_x = 5, row_major) in;\n"
2227         "void main()\n"
2228         "{\n"
2229         "}\n";
2230     if (compile(shaderString))
2231     {
2232         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2233     }
2234 }
2235 
2236 // local size layout can be used only with compute input variables
2237 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,UniformComputeInputLayout)2238 TEST_F(ComputeShaderValidationTest, UniformComputeInputLayout)
2239 {
2240     const std::string &shaderString =
2241         "#version 310 es\n"
2242         "layout(local_size_x = 5) uniform;\n"
2243         "void main()\n"
2244         "{\n"
2245         "}\n";
2246     if (compile(shaderString))
2247     {
2248         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2249     }
2250 }
2251 
2252 // local size layout can be used only with compute input variables
2253 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,UniformBufferComputeInputLayout)2254 TEST_F(ComputeShaderValidationTest, UniformBufferComputeInputLayout)
2255 {
2256     const std::string &shaderString =
2257         "#version 310 es\n"
2258         "layout(local_size_x = 5) uniform SomeBuffer { vec4 something; };\n"
2259         "void main()\n"
2260         "{\n"
2261         "}\n";
2262     if (compile(shaderString))
2263     {
2264         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2265     }
2266 }
2267 
2268 // local size layout can be used only with compute input variables
2269 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,StructComputeInputLayout)2270 TEST_F(ComputeShaderValidationTest, StructComputeInputLayout)
2271 {
2272     const std::string &shaderString =
2273         "#version 310 es\n"
2274         "layout(local_size_x = 5) struct SomeBuffer { vec4 something; };\n"
2275         "void main()\n"
2276         "{\n"
2277         "}\n";
2278     if (compile(shaderString))
2279     {
2280         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2281     }
2282 }
2283 
2284 // local size layout can be used only with compute input variables
2285 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,StructBodyComputeInputLayout)2286 TEST_F(ComputeShaderValidationTest, StructBodyComputeInputLayout)
2287 {
2288     const std::string &shaderString =
2289         "#version 310 es\n"
2290         "struct S {\n"
2291         "   layout(local_size_x = 12) vec4 foo;\n"
2292         "};\n"
2293         "void main()"
2294         "{"
2295         "}";
2296     if (compile(shaderString))
2297     {
2298         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2299     }
2300 }
2301 
2302 // local size layout can be used only with compute input variables
2303 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,TypeComputeInputLayout)2304 TEST_F(ComputeShaderValidationTest, TypeComputeInputLayout)
2305 {
2306     const std::string &shaderString =
2307         "#version 310 es\n"
2308         "layout(local_size_x = 5) vec4;\n"
2309         "void main()\n"
2310         "{\n"
2311         "}\n";
2312     if (compile(shaderString))
2313     {
2314         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2315     }
2316 }
2317 
2318 // Invalid use of the out storage qualifier in a compute shader.
2319 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,InvalidOutStorageQualifier)2320 TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier)
2321 {
2322     const std::string &shaderString =
2323         "#version 310 es\n"
2324         "layout(local_size_x = 15) in;\n"
2325         "out vec4 myOutput;\n"
2326         "void main() {\n"
2327         "}\n";
2328 
2329     if (compile(shaderString))
2330     {
2331         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2332     }
2333 }
2334 
2335 // Invalid use of the out storage qualifier in a compute shader.
2336 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,InvalidOutStorageQualifier2)2337 TEST_F(ComputeShaderValidationTest, InvalidOutStorageQualifier2)
2338 {
2339     const std::string &shaderString =
2340         "#version 310 es\n"
2341         "layout(local_size_x = 15) in;\n"
2342         "out myOutput;\n"
2343         "void main() {\n"
2344         "}\n";
2345 
2346     if (compile(shaderString))
2347     {
2348         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2349     }
2350 }
2351 
2352 // Invalid use of the in storage qualifier. Can be only used to describe the local block size.
2353 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,InvalidInStorageQualifier)2354 TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier)
2355 {
2356     const std::string &shaderString =
2357         "#version 310 es\n"
2358         "layout(local_size_x = 15) in;\n"
2359         "in vec4 myInput;\n"
2360         "void main() {\n"
2361         "}\n";
2362 
2363     if (compile(shaderString))
2364     {
2365         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2366     }
2367 }
2368 
2369 // Invalid use of the in storage qualifier. Can be only used to describe the local block size.
2370 // The test checks a different part of the GLSL grammar than what InvalidInStorageQualifier checks.
2371 // GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs
TEST_F(ComputeShaderValidationTest,InvalidInStorageQualifier2)2372 TEST_F(ComputeShaderValidationTest, InvalidInStorageQualifier2)
2373 {
2374     const std::string &shaderString =
2375         "#version 310 es\n"
2376         "layout(local_size_x = 15) in;\n"
2377         "in myInput;\n"
2378         "void main() {\n"
2379         "}\n";
2380 
2381     if (compile(shaderString))
2382     {
2383         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2384     }
2385 }
2386 
2387 // The local_size layout qualifier is only available in compute shaders.
TEST_F(VertexShaderValidationTest,InvalidUseOfLocalSizeX)2388 TEST_F(VertexShaderValidationTest, InvalidUseOfLocalSizeX)
2389 {
2390     const std::string &shaderString =
2391         "#version 310 es\n"
2392         "precision mediump float;\n"
2393         "layout(local_size_x = 15) in vec4 myInput;\n"
2394         "out vec4 myOutput;\n"
2395         "void main() {\n"
2396         "   myOutput = myInput;\n"
2397         "}\n";
2398 
2399     if (compile(shaderString))
2400     {
2401         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2402     }
2403 }
2404 
2405 // The local_size layout qualifier is only available in compute shaders.
TEST_F(FragmentShaderValidationTest,InvalidUseOfLocalSizeX)2406 TEST_F(FragmentShaderValidationTest, InvalidUseOfLocalSizeX)
2407 {
2408     const std::string &shaderString =
2409         "#version 310 es\n"
2410         "precision mediump float;\n"
2411         "layout(local_size_x = 15) in vec4 myInput;\n"
2412         "out vec4 myOutput;\n"
2413         "void main() {\n"
2414         "   myOutput = myInput;\n"
2415         "}\n";
2416 
2417     if (compile(shaderString))
2418     {
2419         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2420     }
2421 }
2422 
2423 // The local_size layout qualifier is only available in compute shaders.
TEST_F(GeometryShaderValidationTest,InvalidUseOfLocalSizeX)2424 TEST_F(GeometryShaderValidationTest, InvalidUseOfLocalSizeX)
2425 {
2426     const std::string &shaderString1 =
2427         R"(#version 310 es
2428         #extension GL_EXT_geometry_shader : require
2429         layout (points, local_size_x = 15) in;
2430         layout (points, max_vertices = 2) out;
2431         void main()
2432         {
2433         })";
2434 
2435     const std::string &shaderString2 =
2436         R"(#version 310 es
2437         #extension GL_EXT_geometry_shader : require
2438         layout (points) in;
2439         layout (invocations = 2, local_size_x = 15) in;
2440         layout (points, max_vertices = 2) out;
2441         void main()
2442         {
2443         })";
2444 
2445     const std::string &shaderString3 =
2446         R"(#version 310 es
2447         #extension GL_EXT_geometry_shader : require
2448         layout (points) in;
2449         layout (points, local_size_x = 15, max_vertices = 2) out;
2450         void main()
2451         {
2452         })";
2453 
2454     const std::string &shaderString4 =
2455         R"(#version 310 es
2456         #extension GL_EXT_geometry_shader : require
2457         layout (points) in;
2458         layout (points) out;
2459         layout (max_vertices = 2, local_size_x = 15) out;
2460         void main()
2461         {
2462         })";
2463     if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||
2464         compile(shaderString4))
2465     {
2466         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2467     }
2468 }
2469 
2470 // It is a compile time error to use the gl_WorkGroupSize constant if
2471 // the local size has not been declared yet.
2472 // GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
TEST_F(ComputeShaderValidationTest,InvalidUsageOfWorkGroupSize)2473 TEST_F(ComputeShaderValidationTest, InvalidUsageOfWorkGroupSize)
2474 {
2475     const std::string &shaderString =
2476         "#version 310 es\n"
2477         "void main()\n"
2478         "{\n"
2479         "   uvec3 WorkGroupSize = gl_WorkGroupSize;\n"
2480         "}\n"
2481         "layout(local_size_x = 12) in;\n";
2482     if (compile(shaderString))
2483     {
2484         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2485     }
2486 }
2487 
2488 // The test covers the compute shader built-in variables and constants.
TEST_F(ComputeShaderValidationTest,CorrectUsageOfComputeBuiltins)2489 TEST_F(ComputeShaderValidationTest, CorrectUsageOfComputeBuiltins)
2490 {
2491     const std::string &shaderString =
2492         R"(#version 310 es
2493         layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
2494         layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
2495         void main()
2496         {
2497             uvec3 temp1 = gl_NumWorkGroups;
2498             uvec3 temp2 = gl_WorkGroupSize;
2499             uvec3 temp3 = gl_WorkGroupID;
2500             uvec3 temp4 = gl_LocalInvocationID;
2501             uvec3 temp5 = gl_GlobalInvocationID;
2502             uint  temp6 = gl_LocalInvocationIndex;
2503             imageStore(imageOut, ivec2(0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
2504         })";
2505     if (!compile(shaderString))
2506     {
2507         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2508     }
2509 }
2510 
2511 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableNumWorkGroups)2512 TEST_F(ComputeShaderValidationTest, SpecialVariableNumWorkGroups)
2513 {
2514     const std::string &shaderString =
2515         "#version 310 es\n"
2516         "layout(local_size_x = 12) in;\n"
2517         "void main()\n"
2518         "{\n"
2519         "   gl_NumWorkGroups = uvec3(1); \n"
2520         "}\n";
2521     if (compile(shaderString))
2522     {
2523         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2524     }
2525 }
2526 
2527 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableWorkGroupID)2528 TEST_F(ComputeShaderValidationTest, SpecialVariableWorkGroupID)
2529 {
2530     const std::string &shaderString =
2531         "#version 310 es\n"
2532         "layout(local_size_x = 12) in;\n"
2533         "void main()\n"
2534         "{\n"
2535         "   gl_WorkGroupID = uvec3(1); \n"
2536         "}\n";
2537     if (compile(shaderString))
2538     {
2539         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2540     }
2541 }
2542 
2543 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableLocalInvocationID)2544 TEST_F(ComputeShaderValidationTest, SpecialVariableLocalInvocationID)
2545 {
2546     const std::string &shaderString =
2547         "#version 310 es\n"
2548         "layout(local_size_x = 12) in;\n"
2549         "void main()\n"
2550         "{\n"
2551         "   gl_LocalInvocationID = uvec3(1); \n"
2552         "}\n";
2553     if (compile(shaderString))
2554     {
2555         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2556     }
2557 }
2558 
2559 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableGlobalInvocationID)2560 TEST_F(ComputeShaderValidationTest, SpecialVariableGlobalInvocationID)
2561 {
2562     const std::string &shaderString =
2563         "#version 310 es\n"
2564         "layout(local_size_x = 12) in;\n"
2565         "void main()\n"
2566         "{\n"
2567         "   gl_GlobalInvocationID = uvec3(1); \n"
2568         "}\n";
2569     if (compile(shaderString))
2570     {
2571         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2572     }
2573 }
2574 
2575 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableLocalInvocationIndex)2576 TEST_F(ComputeShaderValidationTest, SpecialVariableLocalInvocationIndex)
2577 {
2578     const std::string &shaderString =
2579         "#version 310 es\n"
2580         "layout(local_size_x = 12) in;\n"
2581         "void main()\n"
2582         "{\n"
2583         "   gl_LocalInvocationIndex = 1; \n"
2584         "}\n";
2585     if (compile(shaderString))
2586     {
2587         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2588     }
2589 }
2590 
2591 // It is illegal to write to a special variable.
TEST_F(ComputeShaderValidationTest,SpecialVariableWorkGroupSize)2592 TEST_F(ComputeShaderValidationTest, SpecialVariableWorkGroupSize)
2593 {
2594     const std::string &shaderString =
2595         "#version 310 es\n"
2596         "layout(local_size_x = 12) in;\n"
2597         "void main()\n"
2598         "{\n"
2599         "   gl_WorkGroupSize = uvec3(1); \n"
2600         "}\n";
2601     if (compile(shaderString))
2602     {
2603         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2604     }
2605 }
2606 
2607 // It is illegal to apply an unary operator to a sampler.
TEST_F(FragmentShaderValidationTest,SamplerUnaryOperator)2608 TEST_F(FragmentShaderValidationTest, SamplerUnaryOperator)
2609 {
2610     const std::string &shaderString =
2611         "precision mediump float;\n"
2612         "uniform sampler2D s;\n"
2613         "void main()\n"
2614         "{\n"
2615         "   -s;\n"
2616         "   gl_FragColor = vec4(0);\n"
2617         "}\n";
2618     if (compile(shaderString))
2619     {
2620         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2621     }
2622 }
2623 
2624 // Invariant cannot be used with a work group size declaration.
TEST_F(ComputeShaderValidationTest,InvariantBlockSize)2625 TEST_F(ComputeShaderValidationTest, InvariantBlockSize)
2626 {
2627     const std::string &shaderString =
2628         "#version 310 es\n"
2629         "invariant layout(local_size_x = 15) in;\n"
2630         "void main() {\n"
2631         "}\n";
2632 
2633     if (compile(shaderString))
2634     {
2635         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2636     }
2637 }
2638 
2639 // Invariant cannot be used with a non-output variable in ESSL3.
TEST_F(FragmentShaderValidationTest,InvariantNonOuput)2640 TEST_F(FragmentShaderValidationTest, InvariantNonOuput)
2641 {
2642     const std::string &shaderString =
2643         "#version 300 es\n"
2644         "invariant int value;\n"
2645         "void main() {\n"
2646         "}\n";
2647 
2648     if (compile(shaderString))
2649     {
2650         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2651     }
2652 }
2653 
2654 // Invariant cannot be used with a non-output variable in ESSL3.
2655 // ESSL 3.00.6 section 4.8: This applies even if the declaration is empty.
TEST_F(FragmentShaderValidationTest,InvariantNonOuputEmptyDeclaration)2656 TEST_F(FragmentShaderValidationTest, InvariantNonOuputEmptyDeclaration)
2657 {
2658     const std::string &shaderString =
2659         "#version 300 es\n"
2660         "precision mediump float;\n"
2661         "invariant in float;\n"
2662         "void main() {}\n";
2663 
2664     if (compile(shaderString))
2665     {
2666         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2667     }
2668 }
2669 
2670 // Invariant declaration should follow the following format "invariant <out variable name>".
2671 // Test having an incorrect qualifier in the invariant declaration.
TEST_F(FragmentShaderValidationTest,InvariantDeclarationWithStorageQualifier)2672 TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithStorageQualifier)
2673 {
2674     const std::string &shaderString =
2675         "#version 300 es\n"
2676         "precision mediump float;\n"
2677         "out vec4 foo;\n"
2678         "invariant centroid foo;\n"
2679         "void main() {\n"
2680         "}\n";
2681     if (compile(shaderString))
2682     {
2683         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2684     }
2685 }
2686 
2687 // Invariant declaration should follow the following format "invariant <out variable name>".
2688 // Test having an incorrect precision qualifier in the invariant declaration.
TEST_F(FragmentShaderValidationTest,InvariantDeclarationWithPrecisionQualifier)2689 TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithPrecisionQualifier)
2690 {
2691     const std::string &shaderString =
2692         "#version 300 es\n"
2693         "precision mediump float;\n"
2694         "out vec4 foo;\n"
2695         "invariant highp foo;\n"
2696         "void main() {\n"
2697         "}\n";
2698     if (compile(shaderString))
2699     {
2700         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2701     }
2702 }
2703 
2704 // Invariant declaration should follow the following format "invariant <out variable name>".
2705 // Test having an incorrect layout qualifier in the invariant declaration.
TEST_F(FragmentShaderValidationTest,InvariantDeclarationWithLayoutQualifier)2706 TEST_F(FragmentShaderValidationTest, InvariantDeclarationWithLayoutQualifier)
2707 {
2708     const std::string &shaderString =
2709         "#version 300 es\n"
2710         "precision mediump float;\n"
2711         "out vec4 foo;\n"
2712         "invariant layout(location=0) foo;\n"
2713         "void main() {\n"
2714         "}\n";
2715     if (compile(shaderString))
2716     {
2717         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2718     }
2719 }
2720 
2721 // Variable declaration with both invariant and layout qualifiers is not valid in the formal grammar
2722 // provided in the ESSL 3.00 spec. ESSL 3.10 starts allowing this combination, but ESSL 3.00 should
2723 // still disallow it.
TEST_F(FragmentShaderValidationTest,VariableDeclarationWithInvariantAndLayoutQualifierESSL300)2724 TEST_F(FragmentShaderValidationTest, VariableDeclarationWithInvariantAndLayoutQualifierESSL300)
2725 {
2726     const std::string &shaderString =
2727         "#version 300 es\n"
2728         "precision mediump float;\n"
2729         "invariant layout(location = 0) out vec4 my_FragColor;\n"
2730         "void main() {\n"
2731         "}\n";
2732     if (compile(shaderString))
2733     {
2734         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2735     }
2736 }
2737 
2738 // Bit shift with a rhs value > 31 has an undefined result in the GLSL spec. Detecting an undefined
2739 // result at compile time should not generate an error either way.
2740 // ESSL 3.00.6 section 5.9.
TEST_F(FragmentShaderValidationTest,ShiftBy32)2741 TEST_F(FragmentShaderValidationTest, ShiftBy32)
2742 {
2743     const std::string &shaderString =
2744         R"(#version 300 es
2745         precision mediump float;
2746         out uint my_out;
2747         void main() {
2748            my_out = 1u << 32u;
2749         })";
2750     if (compile(shaderString))
2751     {
2752         if (!hasWarning())
2753         {
2754             FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
2755                    << mInfoLog;
2756         }
2757     }
2758     else
2759     {
2760         FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
2761     }
2762 }
2763 
2764 // Bit shift with a rhs value < 0 has an undefined result in the GLSL spec. Detecting an undefined
2765 // result at compile time should not generate an error either way.
2766 // ESSL 3.00.6 section 5.9.
TEST_F(FragmentShaderValidationTest,ShiftByNegative)2767 TEST_F(FragmentShaderValidationTest, ShiftByNegative)
2768 {
2769     const std::string &shaderString =
2770         R"(#version 300 es
2771         precision mediump float;
2772         out uint my_out;
2773         void main() {
2774            my_out = 1u << (-1);
2775         })";
2776     if (compile(shaderString))
2777     {
2778         if (!hasWarning())
2779         {
2780             FAIL() << "Shader compilation succeeded without warnings, expecting warning:\n"
2781                    << mInfoLog;
2782         }
2783     }
2784     else
2785     {
2786         FAIL() << "Shader compilation failed, expecting success with warning:\n" << mInfoLog;
2787     }
2788 }
2789 
2790 // Test that pruning empty declarations from loop init expression works.
TEST_F(FragmentShaderValidationTest,EmptyDeclarationAsLoopInit)2791 TEST_F(FragmentShaderValidationTest, EmptyDeclarationAsLoopInit)
2792 {
2793     const std::string &shaderString =
2794         "#version 300 es\n"
2795         "precision mediump float;\n"
2796         "out vec4 my_FragColor;\n"
2797         "void main()\n"
2798         "{\n"
2799         "    int i = 0;\n"
2800         "    for (int; i < 3; i++)\n"
2801         "    {\n"
2802         "        my_FragColor = vec4(i);\n"
2803         "    }\n"
2804         "}\n";
2805     if (!compile(shaderString))
2806     {
2807         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2808     }
2809 }
2810 // r32f, r32i, r32ui do not require either the writeonly or readonly memory qualifiers.
2811 // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,ImageR32FNoMemoryQualifier)2812 TEST_F(FragmentShaderValidationTest, ImageR32FNoMemoryQualifier)
2813 {
2814     const std::string &shaderString =
2815         "#version 310 es\n"
2816         "precision mediump float;\n"
2817         "precision mediump image2D;\n"
2818         "in vec4 myInput;\n"
2819         "layout(r32f) uniform image2D myImage;\n"
2820         "void main() {\n"
2821         "}\n";
2822 
2823     if (!compile(shaderString))
2824     {
2825         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2826     }
2827 }
2828 
2829 // Images which do not have r32f, r32i or r32ui as internal format, must have readonly or writeonly
2830 // specified.
2831 // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,ImageRGBA32FWithIncorrectMemoryQualifier)2832 TEST_F(FragmentShaderValidationTest, ImageRGBA32FWithIncorrectMemoryQualifier)
2833 {
2834     const std::string &shaderString =
2835         "#version 310 es\n"
2836         "precision mediump float;\n"
2837         "precision mediump image2D;\n"
2838         "in vec4 myInput;\n"
2839         "layout(rgba32f) uniform image2D myImage;\n"
2840         "void main() {\n"
2841         "}\n";
2842 
2843     if (compile(shaderString))
2844     {
2845         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2846     }
2847 }
2848 
2849 // It is a compile-time error to call imageStore when the image is qualified as readonly.
2850 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,StoreInReadOnlyImage)2851 TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImage)
2852 {
2853     const std::string &shaderString =
2854         "#version 310 es\n"
2855         "precision mediump float;\n"
2856         "precision mediump image2D;\n"
2857         "in vec4 myInput;\n"
2858         "layout(r32f) uniform readonly image2D myImage;\n"
2859         "void main() {\n"
2860         "   imageStore(myImage, ivec2(0), vec4(1.0));\n"
2861         "}\n";
2862 
2863     if (compile(shaderString))
2864     {
2865         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2866     }
2867 }
2868 
2869 // It is a compile-time error to call imageLoad when the image is qualified as writeonly.
2870 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,LoadFromWriteOnlyImage)2871 TEST_F(FragmentShaderValidationTest, LoadFromWriteOnlyImage)
2872 {
2873     const std::string &shaderString =
2874         "#version 310 es\n"
2875         "precision mediump float;\n"
2876         "precision mediump image2D;\n"
2877         "in vec4 myInput;\n"
2878         "layout(r32f) uniform writeonly image2D myImage;\n"
2879         "void main() {\n"
2880         "   imageLoad(myImage, ivec2(0));\n"
2881         "}\n";
2882 
2883     if (compile(shaderString))
2884     {
2885         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2886     }
2887 }
2888 
2889 // It is a compile-time error to call imageStore when the image is qualified as readonly.
2890 // Test to make sure this is validated correctly for images in arrays.
2891 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,StoreInReadOnlyImageArray)2892 TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImageArray)
2893 {
2894     const std::string &shaderString =
2895         "#version 310 es\n"
2896         "precision mediump float;\n"
2897         "precision mediump image2D;\n"
2898         "in vec4 myInput;\n"
2899         "layout(r32f) uniform readonly image2D myImage[2];\n"
2900         "void main() {\n"
2901         "   imageStore(myImage[0], ivec2(0), vec4(1.0));\n"
2902         "}\n";
2903 
2904     if (compile(shaderString))
2905     {
2906         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2907     }
2908 }
2909 
2910 // It is a compile-time error to call imageStore when the image is qualified as readonly.
2911 // Test to make sure that checking this doesn't crash when validating an image in a struct.
2912 // Image in a struct in itself isn't accepted by the parser, but error recovery still results in
2913 // an image in the struct.
2914 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,StoreInReadOnlyImageInStruct)2915 TEST_F(FragmentShaderValidationTest, StoreInReadOnlyImageInStruct)
2916 {
2917     const std::string &shaderString =
2918         "#version 310 es\n"
2919         "precision mediump float;\n"
2920         "precision mediump image2D;\n"
2921         "in vec4 myInput;\n"
2922         "uniform struct S {\n"
2923         "    layout(r32f) readonly image2D myImage;\n"
2924         "} s;\n"
2925         "void main() {\n"
2926         "   imageStore(s.myImage, ivec2(0), vec4(1.0));\n"
2927         "}\n";
2928 
2929     if (compile(shaderString))
2930     {
2931         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
2932     }
2933 }
2934 
2935 // A valid declaration and usage of an image3D.
TEST_F(FragmentShaderValidationTest,ValidImage3D)2936 TEST_F(FragmentShaderValidationTest, ValidImage3D)
2937 {
2938     const std::string &shaderString =
2939         "#version 310 es\n"
2940         "precision mediump float;\n"
2941         "precision mediump image3D;\n"
2942         "in vec4 myInput;\n"
2943         "layout(rgba32f) uniform readonly image3D myImage;\n"
2944         "void main() {\n"
2945         "   imageLoad(myImage, ivec3(0));\n"
2946         "}\n";
2947 
2948     if (!compile(shaderString))
2949     {
2950         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2951     }
2952 }
2953 
2954 // A valid declaration and usage of an imageCube.
TEST_F(FragmentShaderValidationTest,ValidImageCube)2955 TEST_F(FragmentShaderValidationTest, ValidImageCube)
2956 {
2957     const std::string &shaderString =
2958         "#version 310 es\n"
2959         "precision mediump float;\n"
2960         "precision mediump imageCube;\n"
2961         "in vec4 myInput;\n"
2962         "layout(rgba32f) uniform readonly imageCube myImage;\n"
2963         "void main() {\n"
2964         "   imageLoad(myImage, ivec3(0));\n"
2965         "}\n";
2966 
2967     if (!compile(shaderString))
2968     {
2969         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2970     }
2971 }
2972 
2973 // A valid declaration and usage of an image2DArray.
TEST_F(FragmentShaderValidationTest,ValidImage2DArray)2974 TEST_F(FragmentShaderValidationTest, ValidImage2DArray)
2975 {
2976     const std::string &shaderString =
2977         "#version 310 es\n"
2978         "precision mediump float;\n"
2979         "precision mediump image2DArray;\n"
2980         "in vec4 myInput;\n"
2981         "layout(rgba32f) uniform readonly image2DArray myImage;\n"
2982         "void main() {\n"
2983         "   imageLoad(myImage, ivec3(0));\n"
2984         "}\n";
2985 
2986     if (!compile(shaderString))
2987     {
2988         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
2989     }
2990 }
2991 
2992 // Images cannot be l-values.
2993 // GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types
TEST_F(FragmentShaderValidationTest,ImageLValueFunctionDefinitionInOut)2994 TEST_F(FragmentShaderValidationTest, ImageLValueFunctionDefinitionInOut)
2995 {
2996     const std::string &shaderString =
2997         "#version 310 es\n"
2998         "precision mediump float;\n"
2999         "precision mediump image2D;\n"
3000         "void myFunc(inout image2D someImage) {}\n"
3001         "void main() {\n"
3002         "}\n";
3003 
3004     if (compile(shaderString))
3005     {
3006         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3007     }
3008 }
3009 
3010 // Cannot assign to images.
3011 // GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types
TEST_F(FragmentShaderValidationTest,ImageAssignment)3012 TEST_F(FragmentShaderValidationTest, ImageAssignment)
3013 {
3014     const std::string &shaderString =
3015         "#version 310 es\n"
3016         "precision mediump float;\n"
3017         "precision mediump image2D;\n"
3018         "layout(rgba32f) uniform readonly image2D myImage;\n"
3019         "layout(rgba32f) uniform readonly image2D myImage2;\n"
3020         "void main() {\n"
3021         "   myImage = myImage2;\n"
3022         "}\n";
3023 
3024     if (compile(shaderString))
3025     {
3026         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3027     }
3028 }
3029 
3030 // Passing an image qualifier to a function should not be able to discard the readonly qualifier.
3031 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,ReadOnlyQualifierMissingInFunctionArgument)3032 TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgument)
3033 {
3034     const std::string &shaderString =
3035         "#version 310 es\n"
3036         "precision mediump float;\n"
3037         "precision mediump image2D;\n"
3038         "layout(rgba32f) uniform readonly image2D myImage;\n"
3039         "void myFunc(in image2D someImage) {}\n"
3040         "void main() {\n"
3041         "   myFunc(myImage);\n"
3042         "}\n";
3043 
3044     if (compile(shaderString))
3045     {
3046         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3047     }
3048 }
3049 
3050 // Passing an image qualifier to a function should not be able to discard the readonly qualifier.
3051 // Test with an image from an array.
3052 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,ReadOnlyQualifierMissingInFunctionArgumentArray)3053 TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgumentArray)
3054 {
3055     const std::string &shaderString =
3056         "#version 310 es\n"
3057         "precision mediump float;\n"
3058         "precision mediump image2D;\n"
3059         "layout(rgba32f) uniform readonly image2D myImage[2];\n"
3060         "void myFunc(in image2D someImage) {}\n"
3061         "void main() {\n"
3062         "   myFunc(myImage[0]);\n"
3063         "}\n";
3064 
3065     if (compile(shaderString))
3066     {
3067         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3068     }
3069 }
3070 
3071 // Passing an image qualifier to a function should not be able to discard the readonly qualifier.
3072 // Test that validation doesn't crash on this for an image in a struct.
3073 // Image in a struct in itself isn't accepted by the parser, but error recovery still results in
3074 // an image in the struct.
3075 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,ReadOnlyQualifierMissingInFunctionArgumentStruct)3076 TEST_F(FragmentShaderValidationTest, ReadOnlyQualifierMissingInFunctionArgumentStruct)
3077 {
3078     const std::string &shaderString =
3079         "#version 310 es\n"
3080         "precision mediump float;\n"
3081         "precision mediump image2D;\n"
3082         "uniform struct S {\n"
3083         "    layout(r32f) readonly image2D myImage;\n"
3084         "} s;\n"
3085         "void myFunc(in image2D someImage) {}\n"
3086         "void main() {\n"
3087         "   myFunc(s.myImage);\n"
3088         "}\n";
3089 
3090     if (compile(shaderString))
3091     {
3092         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3093     }
3094 }
3095 
3096 // Passing an image qualifier to a function should not be able to discard the writeonly qualifier.
3097 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,WriteOnlyQualifierMissingInFunctionArgument)3098 TEST_F(FragmentShaderValidationTest, WriteOnlyQualifierMissingInFunctionArgument)
3099 {
3100     const std::string &shaderString =
3101         "#version 310 es\n"
3102         "precision mediump float;\n"
3103         "precision mediump image2D;\n"
3104         "layout(rgba32f) uniform writeonly image2D myImage;\n"
3105         "void myFunc(in image2D someImage) {}\n"
3106         "void main() {\n"
3107         "   myFunc(myImage);\n"
3108         "}\n";
3109 
3110     if (compile(shaderString))
3111     {
3112         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3113     }
3114 }
3115 
3116 // Passing an image parameter as an argument to another function should not be able to discard the
3117 // writeonly qualifier.
3118 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,DiscardWriteonlyInFunctionBody)3119 TEST_F(FragmentShaderValidationTest, DiscardWriteonlyInFunctionBody)
3120 {
3121     const std::string &shaderString =
3122         "#version 310 es\n"
3123         "precision mediump float;\n"
3124         "precision mediump image2D;\n"
3125         "layout(rgba32f) uniform writeonly image2D myImage;\n"
3126         "void myFunc1(in image2D someImage) {}\n"
3127         "void myFunc2(in writeonly image2D someImage) { myFunc1(someImage); }\n"
3128         "void main() {\n"
3129         "   myFunc2(myImage);\n"
3130         "}\n";
3131 
3132     if (compile(shaderString))
3133     {
3134         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3135     }
3136 }
3137 
3138 // The memory qualifiers for the image declaration and function argument match and the test should
3139 // pass.
TEST_F(FragmentShaderValidationTest,CorrectImageMemoryQualifierSpecified)3140 TEST_F(FragmentShaderValidationTest, CorrectImageMemoryQualifierSpecified)
3141 {
3142     const std::string &shaderString =
3143         "#version 310 es\n"
3144         "precision mediump float;\n"
3145         "precision mediump image2D;\n"
3146         "layout(r32f) uniform image2D myImage;\n"
3147         "void myFunc(in image2D someImage) {}\n"
3148         "void main() {\n"
3149         "   myFunc(myImage);\n"
3150         "}\n";
3151 
3152     if (!compile(shaderString))
3153     {
3154         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3155     }
3156 }
3157 
3158 // The test adds additional qualifiers to the argument in the function header.
3159 // This is correct since no memory qualifiers are discarded upon the function call.
3160 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,CorrectImageMemoryQualifierSpecified2)3161 TEST_F(FragmentShaderValidationTest, CorrectImageMemoryQualifierSpecified2)
3162 {
3163     const std::string &shaderString =
3164         "#version 310 es\n"
3165         "precision mediump float;\n"
3166         "precision mediump image2D;\n"
3167         "layout(r32f) uniform image2D myImage;\n"
3168         "void myFunc(in readonly writeonly image2D someImage) {}\n"
3169         "void main() {\n"
3170         "   myFunc(myImage);\n"
3171         "}\n";
3172 
3173     if (!compile(shaderString))
3174     {
3175         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3176     }
3177 }
3178 
3179 // Images are not allowed in structs.
3180 // GLSL ES 3.10 Revision 4, 4.1.8 Structures
TEST_F(FragmentShaderValidationTest,ImageInStruct)3181 TEST_F(FragmentShaderValidationTest, ImageInStruct)
3182 {
3183     const std::string &shaderString =
3184         "#version 310 es\n"
3185         "precision mediump float;\n"
3186         "precision mediump image2D;\n"
3187         "struct myStruct { layout(r32f) image2D myImage; };\n"
3188         "void main() {\n"
3189         "}\n";
3190 
3191     if (compile(shaderString))
3192     {
3193         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3194     }
3195 }
3196 
3197 // Images are not allowed in interface blocks.
3198 // GLSL ES 3.10 Revision 4, 4.3.9 Interface Blocks
TEST_F(FragmentShaderValidationTest,ImageInInterfaceBlock)3199 TEST_F(FragmentShaderValidationTest, ImageInInterfaceBlock)
3200 {
3201     const std::string &shaderString =
3202         "#version 310 es\n"
3203         "precision mediump float;\n"
3204         "precision mediump image2D;\n"
3205         "uniform myBlock { layout(r32f) image2D myImage; };\n"
3206         "void main() {\n"
3207         "}\n";
3208 
3209     if (compile(shaderString))
3210     {
3211         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3212     }
3213 }
3214 
3215 // Readonly used with an interface block.
TEST_F(FragmentShaderValidationTest,ReadonlyWithInterfaceBlock)3216 TEST_F(FragmentShaderValidationTest, ReadonlyWithInterfaceBlock)
3217 {
3218     const std::string &shaderString =
3219         "#version 310 es\n"
3220         "precision mediump float;\n"
3221         "uniform readonly myBlock { float something; };\n"
3222         "void main() {\n"
3223         "}\n";
3224 
3225     if (compile(shaderString))
3226     {
3227         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3228     }
3229 }
3230 
3231 // Readonly used with an invariant.
TEST_F(FragmentShaderValidationTest,ReadonlyWithInvariant)3232 TEST_F(FragmentShaderValidationTest, ReadonlyWithInvariant)
3233 {
3234     const std::string &shaderString =
3235         "#version 310 es\n"
3236         "precision mediump float;\n"
3237         "out vec4 something;\n"
3238         "invariant readonly something;\n"
3239         "void main() {\n"
3240         "}\n";
3241 
3242     if (compile(shaderString))
3243     {
3244         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3245     }
3246 }
3247 
3248 // Readonly used with a member of a structure.
TEST_F(FragmentShaderValidationTest,ReadonlyWithStructMember)3249 TEST_F(FragmentShaderValidationTest, ReadonlyWithStructMember)
3250 {
3251     const std::string &shaderString =
3252         "#version 310 es\n"
3253         "precision mediump float;\n"
3254         "out vec4 something;\n"
3255         "struct MyStruct { readonly float myMember; };\n"
3256         "void main() {\n"
3257         "}\n";
3258 
3259     if (compile(shaderString))
3260     {
3261         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3262     }
3263 }
3264 
3265 // It should not be possible to use an internal format layout qualifier with an interface block.
TEST_F(FragmentShaderValidationTest,ImageInternalFormatWithInterfaceBlock)3266 TEST_F(FragmentShaderValidationTest, ImageInternalFormatWithInterfaceBlock)
3267 {
3268     const std::string &shaderString =
3269         "#version 310 es\n"
3270         "precision mediump float;\n"
3271         "out vec4 something;\n"
3272         "layout(rgba32f) uniform MyStruct { float myMember; };\n"
3273         "void main() {\n"
3274         "}\n";
3275 
3276     if (compile(shaderString))
3277     {
3278         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3279     }
3280 }
3281 
3282 // It should not be possible to use an internal format layout qualifier with a uniform without a
3283 // type.
TEST_F(FragmentShaderValidationTest,ImageInternalFormatInGlobalLayoutQualifier)3284 TEST_F(FragmentShaderValidationTest, ImageInternalFormatInGlobalLayoutQualifier)
3285 {
3286     const std::string &shaderString =
3287         "#version 310 es\n"
3288         "precision mediump float;\n"
3289         "out vec4 something;\n"
3290         "layout(rgba32f) uniform;\n"
3291         "void main() {\n"
3292         "}\n";
3293 
3294     if (compile(shaderString))
3295     {
3296         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3297     }
3298 }
3299 
3300 // ESSL 1.00 section 4.1.7.
3301 // Samplers are not allowed as operands for most operations. Test this for ternary operator.
TEST_F(FragmentShaderValidationTest,SamplerAsTernaryOperand)3302 TEST_F(FragmentShaderValidationTest, SamplerAsTernaryOperand)
3303 {
3304     const std::string &shaderString =
3305         "precision mediump float;\n"
3306         "uniform bool u;\n"
3307         "uniform sampler2D s1;\n"
3308         "uniform sampler2D s2;\n"
3309         "void main() {\n"
3310         "    gl_FragColor = texture2D(u ? s1 : s2, vec2(0, 0));\n"
3311         "}\n";
3312 
3313     if (compile(shaderString))
3314     {
3315         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3316     }
3317 }
3318 
3319 // ESSL 1.00.17 section 4.5.2.
3320 // ESSL 3.00.6 section 4.5.3.
3321 // Precision must be specified for floats. Test this with a declaration with no qualifiers.
TEST_F(FragmentShaderValidationTest,FloatDeclarationNoQualifiersNoPrecision)3322 TEST_F(FragmentShaderValidationTest, FloatDeclarationNoQualifiersNoPrecision)
3323 {
3324     const std::string &shaderString =
3325         "vec4 foo = vec4(0.0);\n"
3326         "void main()\n"
3327         "{\n"
3328         "    gl_FragColor = foo;\n"
3329         "}\n";
3330 
3331     if (compile(shaderString))
3332     {
3333         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3334     }
3335 }
3336 
3337 // Precision must be specified for floats. Test this with a function argument no qualifiers.
TEST_F(FragmentShaderValidationTest,FloatDeclarationNoQualifiersNoPrecisionFunctionArg)3338 TEST_F(FragmentShaderValidationTest, FloatDeclarationNoQualifiersNoPrecisionFunctionArg)
3339 {
3340     const std::string &shaderString = R"(
3341 int c(float x)
3342 {
3343     return int(x);
3344 }
3345 void main()
3346 {
3347     c(5.0);
3348 })";
3349 
3350     if (compile(shaderString))
3351     {
3352         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3353     }
3354 }
3355 
3356 // Check compiler doesn't crash on incorrect unsized array declarations.
TEST_F(FragmentShaderValidationTest,IncorrectUnsizedArray)3357 TEST_F(FragmentShaderValidationTest, IncorrectUnsizedArray)
3358 {
3359     const std::string &shaderString =
3360         "#version 300 es\n"
3361         "precision mediump float;\n"
3362         "float foo[] = 0.0;\n"
3363         "out vec4 my_FragColor;\n"
3364         "void main()\n"
3365         "{\n"
3366         "    foo[0] = 1.0;\n"
3367         "    my_FragColor = vec4(foo[0]);\n"
3368         "}\n";
3369 
3370     if (compile(shaderString))
3371     {
3372         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3373     }
3374 }
3375 
3376 // Check compiler doesn't crash when a bvec is on the right hand side of a logical operator.
3377 // ESSL 3.00.6 section 5.9.
TEST_F(FragmentShaderValidationTest,LogicalOpRHSIsBVec)3378 TEST_F(FragmentShaderValidationTest, LogicalOpRHSIsBVec)
3379 {
3380     const std::string &shaderString =
3381         "#version 300 es\n"
3382         "void main()\n"
3383         "{\n"
3384         "    bool b;\n"
3385         "    bvec3 b3;\n"
3386         "    b && b3;\n"
3387         "}\n";
3388 
3389     if (compile(shaderString))
3390     {
3391         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3392     }
3393 }
3394 
3395 // Check compiler doesn't crash when there's an unsized array constructor with no parameters.
3396 // ESSL 3.00.6 section 4.1.9: Array size must be greater than zero.
TEST_F(FragmentShaderValidationTest,UnsizedArrayConstructorNoParameters)3397 TEST_F(FragmentShaderValidationTest, UnsizedArrayConstructorNoParameters)
3398 {
3399     const std::string &shaderString =
3400         "#version 300 es\n"
3401         "void main()\n"
3402         "{\n"
3403         "    int[]();\n"
3404         "}\n";
3405 
3406     if (compile(shaderString))
3407     {
3408         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3409     }
3410 }
3411 
3412 // Passing an image parameter as an argument to another function should not be able to discard the
3413 // coherent qualifier.
TEST_F(FragmentShaderValidationTest,CoherentQualifierMissingInFunctionArgument)3414 TEST_F(FragmentShaderValidationTest, CoherentQualifierMissingInFunctionArgument)
3415 {
3416     const std::string &shaderString =
3417         "#version 310 es\n"
3418         "precision mediump float;\n"
3419         "precision mediump image2D;\n"
3420         "layout(r32f) uniform coherent image2D myImage;\n"
3421         "void myFunc(in image2D someImage) {}\n"
3422         "void main() {\n"
3423         "   myFunc(myImage);\n"
3424         "}\n";
3425 
3426     if (compile(shaderString))
3427     {
3428         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3429     }
3430 }
3431 
3432 // Passing an image parameter as an argument to another function should not be able to discard the
3433 // volatile qualifier.
TEST_F(FragmentShaderValidationTest,VolatileQualifierMissingInFunctionArgument)3434 TEST_F(FragmentShaderValidationTest, VolatileQualifierMissingInFunctionArgument)
3435 {
3436     const std::string &shaderString =
3437         "#version 310 es\n"
3438         "precision mediump float;\n"
3439         "precision mediump image2D;\n"
3440         "layout(r32f) uniform volatile image2D myImage;\n"
3441         "void myFunc(in image2D someImage) {}\n"
3442         "void main() {\n"
3443         "   myFunc(myImage);\n"
3444         "}\n";
3445 
3446     if (compile(shaderString))
3447     {
3448         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3449     }
3450 }
3451 
3452 // The restrict qualifier can be discarded from a function argument.
3453 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,RestrictQualifierDiscardedInFunctionArgument)3454 TEST_F(FragmentShaderValidationTest, RestrictQualifierDiscardedInFunctionArgument)
3455 {
3456     const std::string &shaderString =
3457         "#version 310 es\n"
3458         "precision mediump float;\n"
3459         "precision mediump image2D;\n"
3460         "layout(r32f) uniform restrict image2D myImage;\n"
3461         "void myFunc(in image2D someImage) {}\n"
3462         "void main() {\n"
3463         "   myFunc(myImage);\n"
3464         "}\n";
3465 
3466     if (!compile(shaderString))
3467     {
3468         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3469     }
3470 }
3471 
3472 // Function image arguments can be overqualified.
3473 // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
TEST_F(FragmentShaderValidationTest,OverqualifyingImageParameter)3474 TEST_F(FragmentShaderValidationTest, OverqualifyingImageParameter)
3475 {
3476     const std::string &shaderString =
3477         "#version 310 es\n"
3478         "precision mediump float;\n"
3479         "precision mediump image2D;\n"
3480         "layout(r32f) uniform image2D myImage;\n"
3481         "void myFunc(in coherent volatile image2D someImage) {}\n"
3482         "void main() {\n"
3483         "   myFunc(myImage);\n"
3484         "}\n";
3485 
3486     if (!compile(shaderString))
3487     {
3488         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3489     }
3490 }
3491 
3492 // Test that work group size can be used to size arrays.
3493 // GLSL ES 3.10.4 section 7.1.3 Compute Shader Special Variables
TEST_F(ComputeShaderValidationTest,WorkGroupSizeAsArraySize)3494 TEST_F(ComputeShaderValidationTest, WorkGroupSizeAsArraySize)
3495 {
3496     const std::string &shaderString =
3497         "#version 310 es\n"
3498         "layout(local_size_x = 5, local_size_y = 3, local_size_z = 1) in;\n"
3499         "void main()\n"
3500         "{\n"
3501         "    int[gl_WorkGroupSize.x] a = int[5](0, 0, 0, 0, 0);\n"
3502         "    int[gl_WorkGroupSize.y] b = int[3](0, 0, 0);\n"
3503         "    int[gl_WorkGroupSize.z] c = int[1](0);\n"
3504         "}\n";
3505     if (!compile(shaderString))
3506     {
3507         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3508     }
3509 }
3510 
3511 // Shared memory variables cannot be used inside a vertex shader.
3512 // GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(VertexShaderValidationTest,VertexShaderSharedMemory)3513 TEST_F(VertexShaderValidationTest, VertexShaderSharedMemory)
3514 {
3515     const std::string &shaderString =
3516         "#version 310 es\n"
3517         "precision mediump float;\n"
3518         "in vec4 i;\n"
3519         "shared float myShared[10];\n"
3520         "void main() {\n"
3521         "    gl_Position = i;\n"
3522         "}\n";
3523     if (compile(shaderString))
3524     {
3525         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3526     }
3527 }
3528 
3529 // Shared memory variables cannot be used inside a fragment shader.
3530 // GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(FragmentShaderValidationTest,FragmentShaderSharedMemory)3531 TEST_F(FragmentShaderValidationTest, FragmentShaderSharedMemory)
3532 {
3533     const std::string &shaderString =
3534         "#version 310 es\n"
3535         "precision mediump float;\n"
3536         "shared float myShared[10];\n"
3537         "out vec4 color;\n"
3538         "void main() {\n"
3539         "   color = vec4(1.0);\n"
3540         "}\n";
3541     if (compile(shaderString))
3542     {
3543         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3544     }
3545 }
3546 
3547 // Shared memory cannot be combined with any other storage qualifier.
TEST_F(ComputeShaderValidationTest,UniformSharedMemory)3548 TEST_F(ComputeShaderValidationTest, UniformSharedMemory)
3549 {
3550     const std::string &shaderString =
3551         "#version 310 es\n"
3552         "precision mediump float;\n"
3553         "layout(local_size_x = 5) in;\n"
3554         "uniform shared float myShared[100];\n"
3555         "void main() {\n"
3556         "}\n";
3557 
3558     if (compile(shaderString))
3559     {
3560         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3561     }
3562 }
3563 
3564 // Correct usage of shared memory variables.
TEST_F(ComputeShaderValidationTest,CorrectUsageOfSharedMemory)3565 TEST_F(ComputeShaderValidationTest, CorrectUsageOfSharedMemory)
3566 {
3567     const std::string &shaderString =
3568         "#version 310 es\n"
3569         "precision mediump float;\n"
3570         "layout(local_size_x = 5) in;\n"
3571         "shared float myShared[100];\n"
3572         "void main() {\n"
3573         "   myShared[gl_LocalInvocationID.x] = 1.0;\n"
3574         "}\n";
3575 
3576     if (!compile(shaderString))
3577     {
3578         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3579     }
3580 }
3581 
3582 // Shared memory variables cannot be initialized.
3583 // GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(ComputeShaderValidationTest,SharedVariableInitialization)3584 TEST_F(ComputeShaderValidationTest, SharedVariableInitialization)
3585 {
3586     const std::string &shaderString =
3587         "#version 310 es\n"
3588         "precision mediump float;\n"
3589         "layout(local_size_x = 5) in;\n"
3590         "shared int myShared = 0;\n"
3591         "void main() {\n"
3592         "}\n";
3593 
3594     if (compile(shaderString))
3595     {
3596         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3597     }
3598 }
3599 
3600 // Local variables cannot be qualified as shared.
3601 // GLSL ES 3.10 Revision 4, 4.3 Storage Qualifiers
TEST_F(ComputeShaderValidationTest,SharedMemoryInFunctionBody)3602 TEST_F(ComputeShaderValidationTest, SharedMemoryInFunctionBody)
3603 {
3604     const std::string &shaderString =
3605         "#version 310 es\n"
3606         "precision mediump float;\n"
3607         "layout(local_size_x = 5) in;\n"
3608         "void func() {\n"
3609         "   shared int myShared;\n"
3610         "}\n"
3611         "void main() {\n"
3612         "   func();\n"
3613         "}\n";
3614 
3615     if (compile(shaderString))
3616     {
3617         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3618     }
3619 }
3620 
3621 // Struct members cannot be qualified as shared.
TEST_F(ComputeShaderValidationTest,SharedMemoryInStruct)3622 TEST_F(ComputeShaderValidationTest, SharedMemoryInStruct)
3623 {
3624     const std::string &shaderString =
3625         "#version 310 es\n"
3626         "precision mediump float;\n"
3627         "layout(local_size_x = 5) in;\n"
3628         "struct MyStruct {\n"
3629         "   shared int myShared;\n"
3630         "};\n"
3631         "void main() {\n"
3632         "}\n";
3633 
3634     if (compile(shaderString))
3635     {
3636         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3637     }
3638 }
3639 
3640 // Interface block members cannot be qualified as shared.
TEST_F(ComputeShaderValidationTest,SharedMemoryInInterfaceBlock)3641 TEST_F(ComputeShaderValidationTest, SharedMemoryInInterfaceBlock)
3642 {
3643     const std::string &shaderString =
3644         "#version 310 es\n"
3645         "precision mediump float;\n"
3646         "layout(local_size_x = 5) in;\n"
3647         "uniform Myblock {\n"
3648         "   shared int myShared;\n"
3649         "};\n"
3650         "void main() {\n"
3651         "}\n";
3652 
3653     if (compile(shaderString))
3654     {
3655         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3656     }
3657 }
3658 
3659 // The shared qualifier cannot be used with any other qualifier.
TEST_F(ComputeShaderValidationTest,SharedWithInvariant)3660 TEST_F(ComputeShaderValidationTest, SharedWithInvariant)
3661 {
3662     const std::string &shaderString =
3663         "#version 310 es\n"
3664         "precision mediump float;\n"
3665         "layout(local_size_x = 5) in;\n"
3666         "invariant shared int myShared;\n"
3667         "void main() {\n"
3668         "}\n";
3669 
3670     if (compile(shaderString))
3671     {
3672         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3673     }
3674 }
3675 
3676 // The shared qualifier cannot be used with any other qualifier.
TEST_F(ComputeShaderValidationTest,SharedWithMemoryQualifier)3677 TEST_F(ComputeShaderValidationTest, SharedWithMemoryQualifier)
3678 {
3679     const std::string &shaderString =
3680         "#version 310 es\n"
3681         "precision mediump float;\n"
3682         "layout(local_size_x = 5) in;\n"
3683         "readonly shared int myShared;\n"
3684         "void main() {\n"
3685         "}\n";
3686 
3687     if (compile(shaderString))
3688     {
3689         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3690     }
3691 }
3692 
3693 // The shared qualifier cannot be used with any other qualifier.
TEST_F(ComputeShaderValidationTest,SharedGlobalLayoutDeclaration)3694 TEST_F(ComputeShaderValidationTest, SharedGlobalLayoutDeclaration)
3695 {
3696     const std::string &shaderString =
3697         "#version 310 es\n"
3698         "precision mediump float;\n"
3699         "layout(local_size_x = 5) in;\n"
3700         "layout(row_major) shared mat4;\n"
3701         "void main() {\n"
3702         "}\n";
3703 
3704     if (compile(shaderString))
3705     {
3706         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3707     }
3708 }
3709 
3710 // Declaring a function with the same name as a built-in from a higher ESSL version should not cause
3711 // a redeclaration error.
TEST_F(FragmentShaderValidationTest,BuiltinESSL31FunctionDeclaredInESSL30Shader)3712 TEST_F(FragmentShaderValidationTest, BuiltinESSL31FunctionDeclaredInESSL30Shader)
3713 {
3714     const std::string &shaderString =
3715         "#version 300 es\n"
3716         "precision mediump float;\n"
3717         "void imageSize() {}\n"
3718         "void main() {\n"
3719         "   imageSize();\n"
3720         "}\n";
3721 
3722     if (!compile(shaderString))
3723     {
3724         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
3725     }
3726 }
3727 
3728 // Attempting to declare num_views without enabling OVR_multiview.
TEST_F(VertexShaderValidationTest,InvalidNumViews)3729 TEST_F(VertexShaderValidationTest, InvalidNumViews)
3730 {
3731     const std::string &shaderString =
3732         "#version 300 es\n"
3733         "precision mediump float;\n"
3734         "layout (num_views = 2) in;\n"
3735         "void main() {\n"
3736         "}\n";
3737 
3738     if (compile(shaderString))
3739     {
3740         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
3741     }
3742 }
3743 
3744 // memoryBarrierShared is only available in a compute shader.
3745 // GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
TEST_F(FragmentShaderValidationTest,InvalidUseOfMemoryBarrierShared)3746 TEST_F(FragmentShaderValidationTest, InvalidUseOfMemoryBarrierShared)
3747 {
3748     const std::string &shaderString =
3749         "#version 310 es\n"
3750         "precision mediump float;\n"
3751         "void main() {\n"
3752         "    memoryBarrierShared();\n"
3753         "}\n";
3754 
3755     if (compile(shaderString))
3756     {
3757         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3758     }
3759 }
3760 
3761 // groupMemoryBarrier is only available in a compute shader.
3762 // GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
TEST_F(FragmentShaderValidationTest,InvalidUseOfGroupMemoryBarrier)3763 TEST_F(FragmentShaderValidationTest, InvalidUseOfGroupMemoryBarrier)
3764 {
3765     const std::string &shaderString =
3766         "#version 310 es\n"
3767         "precision mediump float;\n"
3768         "void main() {\n"
3769         "    groupMemoryBarrier();\n"
3770         "}\n";
3771 
3772     if (compile(shaderString))
3773     {
3774         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3775     }
3776 }
3777 
3778 // barrier can be used in a compute shader.
3779 // GLSL ES 3.10 Revision 4, 8.14 Shader Invocation Control Functions
TEST_F(ComputeShaderValidationTest,ValidUseOfBarrier)3780 TEST_F(ComputeShaderValidationTest, ValidUseOfBarrier)
3781 {
3782     const std::string &shaderString =
3783         "#version 310 es\n"
3784         "layout(local_size_x = 15) in;\n"
3785         "void main() {\n"
3786         "   barrier();\n"
3787         "}\n";
3788 
3789     if (!compile(shaderString))
3790     {
3791         FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
3792     }
3793 }
3794 
3795 // memoryBarrierImage() can be used in all GLSL ES 3.10 shaders.
3796 // GLSL ES 3.10 Revision 4, 8.15 Shader Memory Control Functions
TEST_F(FragmentShaderValidationTest,ValidUseOfMemoryBarrierImageInFragmentShader)3797 TEST_F(FragmentShaderValidationTest, ValidUseOfMemoryBarrierImageInFragmentShader)
3798 {
3799     const std::string &shaderString =
3800         "#version 310 es\n"
3801         "precision mediump float;\n"
3802         "precision highp image2D;\n"
3803         "layout(r32f) uniform image2D myImage;\n"
3804         "void main() {\n"
3805         "    imageStore(myImage, ivec2(0), vec4(1.0));\n"
3806         "    memoryBarrierImage();\n"
3807         "}\n";
3808 
3809     if (!compile(shaderString))
3810     {
3811         FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
3812     }
3813 }
3814 
3815 // checks that gsampler2DMS is not supported in version lower than 310
TEST_F(FragmentShaderValidationTest,Sampler2DMSInESSL300Shader)3816 TEST_F(FragmentShaderValidationTest, Sampler2DMSInESSL300Shader)
3817 {
3818     const std::string &shaderString =
3819         "#version 300 es\n"
3820         "uniform highp sampler2DMS s;\n"
3821         "void main() {}\n";
3822 
3823     if (compile(shaderString))
3824     {
3825         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3826     }
3827 }
3828 
3829 // Declare main() with incorrect parameters.
3830 // ESSL 3.00.6 section 6.1 Function Definitions.
TEST_F(FragmentShaderValidationTest,InvalidMainPrototypeParameters)3831 TEST_F(FragmentShaderValidationTest, InvalidMainPrototypeParameters)
3832 {
3833     const std::string &shaderString =
3834         "#version 300 es\n"
3835         "void main(int a);\n"
3836         "void main() {}\n";
3837 
3838     if (compile(shaderString))
3839     {
3840         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3841     }
3842 }
3843 
3844 // Regression test for a crash in the empty constructor of unsized array
3845 // of a structure with non-basic fields fields. Test with "void".
TEST_F(FragmentShaderValidationTest,VoidFieldStructUnsizedArrayEmptyConstructor)3846 TEST_F(FragmentShaderValidationTest, VoidFieldStructUnsizedArrayEmptyConstructor)
3847 {
3848     const std::string &shaderString =
3849         "#version 300 es\n"
3850         "struct S {void a;};"
3851         "void main() {S s[] = S[]();}\n";
3852     if (compile(shaderString))
3853     {
3854         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3855     }
3856 }
3857 
3858 // Regression test for a crash in the empty constructor of unsized array
3859 // of a structure with non-basic fields fields. Test with something other than "void".
TEST_F(FragmentShaderValidationTest,SamplerFieldStructUnsizedArrayEmptyConstructor)3860 TEST_F(FragmentShaderValidationTest, SamplerFieldStructUnsizedArrayEmptyConstructor)
3861 {
3862     const std::string &shaderString =
3863         "#version 300 es\n"
3864         "struct S {sampler2D a;};"
3865         "void main() {S s[] = S[]();}\n";
3866     if (compile(shaderString))
3867     {
3868         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3869     }
3870 }
3871 
3872 // Checks that odd array initialization syntax is an error, and does not produce
3873 // an ASSERT failure.
TEST_F(VertexShaderValidationTest,InvalidArrayConstruction)3874 TEST_F(VertexShaderValidationTest, InvalidArrayConstruction)
3875 {
3876     const std::string &shaderString =
3877         "struct S { mediump float i; mediump int ggb; };\n"
3878         "void main() {\n"
3879         "  S s[2];\n"
3880         "  s = S[](s.x, 0.0);\n"
3881         "  gl_Position = vec4(1, 0, 0, 1);\n"
3882         "}";
3883     if (compile(shaderString))
3884     {
3885         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3886     }
3887 }
3888 
3889 // Correct usage of image binding layout qualifier.
TEST_F(ComputeShaderValidationTest,CorrectImageBindingLayoutQualifier)3890 TEST_F(ComputeShaderValidationTest, CorrectImageBindingLayoutQualifier)
3891 {
3892     const std::string &shaderString =
3893         "#version 310 es\n"
3894         "precision mediump float;\n"
3895         "precision mediump image2D;\n"
3896         "layout(local_size_x = 5) in;\n"
3897         "layout(binding = 1, rgba32f) writeonly uniform image2D myImage;\n"
3898         "void main()\n"
3899         "{\n"
3900         "   imageStore(myImage, ivec2(gl_LocalInvocationID.xy), vec4(1.0));\n"
3901         "}\n";
3902 
3903     if (!compile(shaderString))
3904     {
3905         FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
3906     }
3907 }
3908 
3909 // Incorrect use of "binding" on a global layout qualifier.
TEST_F(ComputeShaderValidationTest,IncorrectGlobalBindingLayoutQualifier)3910 TEST_F(ComputeShaderValidationTest, IncorrectGlobalBindingLayoutQualifier)
3911 {
3912     const std::string &shaderString =
3913         "#version 310 es\n"
3914         "layout(local_size_x = 5, binding = 0) in;\n"
3915         "void main() {}\n";
3916 
3917     if (compile(shaderString))
3918     {
3919         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3920     }
3921 }
3922 
3923 // Incorrect use of "binding" on a struct field layout qualifier.
TEST_F(ComputeShaderValidationTest,IncorrectStructFieldBindingLayoutQualifier)3924 TEST_F(ComputeShaderValidationTest, IncorrectStructFieldBindingLayoutQualifier)
3925 {
3926     const std::string &shaderString =
3927         "#version 310 es\n"
3928         "precision mediump float;\n"
3929         "layout(local_size_x = 1) in;\n"
3930         "struct S\n"
3931         "{\n"
3932         "  layout(binding = 0) float f;\n"
3933         "};\n"
3934         "void main() {}\n";
3935 
3936     if (compile(shaderString))
3937     {
3938         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3939     }
3940 }
3941 
3942 // Variable binding layout qualifier is set to a negative value. 0xffffffff wraps around to -1
3943 // according to the integer parsing rules.
TEST_F(FragmentShaderValidationTest,ImageBindingUnitNegative)3944 TEST_F(FragmentShaderValidationTest, ImageBindingUnitNegative)
3945 {
3946     const std::string &shaderString =
3947         "#version 310 es\n"
3948         "precision mediump float;\n"
3949         "layout(rgba32f, binding = 0xffffffff) writeonly uniform mediump image2D myImage;\n"
3950         "out vec4 outFrag;\n"
3951         "void main()\n"
3952         "{\n"
3953         "   outFrag = vec4(0.0);\n"
3954         "}\n";
3955 
3956     if (compile(shaderString))
3957     {
3958         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3959     }
3960 }
3961 
3962 // Image binding layout qualifier value is greater than the maximum image binding.
TEST_F(FragmentShaderValidationTest,ImageBindingUnitTooBig)3963 TEST_F(FragmentShaderValidationTest, ImageBindingUnitTooBig)
3964 {
3965     const std::string &shaderString =
3966         "#version 310 es\n"
3967         "precision mediump float;\n"
3968         "layout(rgba32f, binding = 9999) writeonly uniform mediump image2D myImage;\n"
3969         "out vec4 outFrag;\n"
3970         "void main()\n"
3971         "{\n"
3972         "   outFrag = vec4(0.0);\n"
3973         "}\n";
3974 
3975     if (compile(shaderString))
3976     {
3977         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3978     }
3979 }
3980 
3981 // Uniform variable binding is set on a non-opaque type.
TEST_F(FragmentShaderValidationTest,NonOpaqueUniformBinding)3982 TEST_F(FragmentShaderValidationTest, NonOpaqueUniformBinding)
3983 {
3984     const std::string &shaderString =
3985         "#version 310 es\n"
3986         "precision mediump float;\n"
3987         "layout(binding = 0) uniform float myFloat;\n"
3988         "out vec4 outFrag;\n"
3989         "void main()\n"
3990         "{\n"
3991         "   outFrag = vec4(myFloat);\n"
3992         "}\n";
3993 
3994     if (compile(shaderString))
3995     {
3996         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
3997     }
3998 }
3999 
4000 // Uniform variable binding is set on a sampler type.
4001 // ESSL 3.10 section 4.4.5 Opaque Uniform Layout Qualifiers.
TEST_F(FragmentShaderValidationTest,SamplerUniformBinding)4002 TEST_F(FragmentShaderValidationTest, SamplerUniformBinding)
4003 {
4004     const std::string &shaderString =
4005         "#version 310 es\n"
4006         "precision mediump float;\n"
4007         "layout(binding = 0) uniform mediump sampler2D mySampler;\n"
4008         "out vec4 outFrag;\n"
4009         "void main()\n"
4010         "{\n"
4011         "   outFrag = vec4(0.0);\n"
4012         "}\n";
4013 
4014     if (!compile(shaderString))
4015     {
4016         FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
4017     }
4018 }
4019 
4020 // Uniform variable binding is set on a sampler type in an ESSL 3.00 shader.
4021 // The binding layout qualifier was added in ESSL 3.10, so this is incorrect.
TEST_F(FragmentShaderValidationTest,SamplerUniformBindingESSL300)4022 TEST_F(FragmentShaderValidationTest, SamplerUniformBindingESSL300)
4023 {
4024     const std::string &shaderString =
4025         "#version 300 es\n"
4026         "precision mediump float;\n"
4027         "layout(binding = 0) uniform mediump sampler2D mySampler;\n"
4028         "out vec4 outFrag;\n"
4029         "void main()\n"
4030         "{\n"
4031         "   outFrag = vec4(0.0);\n"
4032         "}\n";
4033 
4034     if (compile(shaderString))
4035     {
4036         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
4037     }
4038 }
4039 
4040 // Attempting to construct a struct containing a void array should fail without asserting.
TEST_F(FragmentShaderValidationTest,ConstructStructContainingVoidArray)4041 TEST_F(FragmentShaderValidationTest, ConstructStructContainingVoidArray)
4042 {
4043     const std::string &shaderString =
4044         "#version 300 es\n"
4045         "precision mediump float;\n"
4046         "out vec4 outFrag;\n"
4047         "struct S\n"
4048         "{\n"
4049         "    void A[1];\n"
4050         "} s = S();\n"
4051         "void main()\n"
4052         "{\n"
4053         "    outFrag = vec4(0.0);\n"
4054         "}\n";
4055 
4056     if (compile(shaderString))
4057     {
4058         FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
4059     }
4060 }
4061 
4062 // Uniforms can't have location in ESSL 3.00.
4063 // Test this with an empty declaration (ESSL 3.00.6 section 4.8: The combinations of qualifiers that
4064 // cause compile-time or link-time errors are the same whether or not the declaration is empty).
TEST_F(FragmentShaderValidationTest,UniformLocationEmptyDeclaration)4065 TEST_F(FragmentShaderValidationTest, UniformLocationEmptyDeclaration)
4066 {
4067     const std::string &shaderString =
4068         "#version 300 es\n"
4069         "precision mediump float;\n"
4070         "layout(location=0) uniform float;\n"
4071         "void main() {}\n";
4072 
4073     if (compile(shaderString))
4074     {
4075         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4076     }
4077 }
4078 
4079 // Test function parameters of opaque type can't be l-value too.
TEST_F(FragmentShaderValidationTest,OpaqueParameterCanNotBeLValue)4080 TEST_F(FragmentShaderValidationTest, OpaqueParameterCanNotBeLValue)
4081 {
4082     const std::string &shaderString =
4083         "#version 310 es\n"
4084         "uniform sampler2D s;\n"
4085         "void foo(sampler2D as) {\n"
4086         "    as = s;\n"
4087         "}\n"
4088         "void main() {}\n";
4089 
4090     if (compile(shaderString))
4091     {
4092         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4093     }
4094 }
4095 
4096 // Test samplers must not be operands in expressions, except for array indexing, structure field
4097 // selection and parentheses(ESSL 3.00 Secion 4.1.7).
TEST_F(FragmentShaderValidationTest,InvalidExpressionForSamplerOperands)4098 TEST_F(FragmentShaderValidationTest, InvalidExpressionForSamplerOperands)
4099 {
4100     const std::string &shaderString =
4101         "#version 300 es\n"
4102         "uniform sampler2D s;\n"
4103         "uniform sampler2D s2;\n"
4104         "void main() {\n"
4105         "    s + s2;\n"
4106         "}\n";
4107 
4108     if (compile(shaderString))
4109     {
4110         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4111     }
4112 }
4113 
4114 // Test interface blocks as invalid operands to a binary expression.
TEST_F(FragmentShaderValidationTest,InvalidInterfaceBlockBinaryExpression)4115 TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockBinaryExpression)
4116 {
4117     const std::string &shaderString =
4118         "#version 300 es\n"
4119         "uniform U\n"
4120         "{\n"
4121         "    int foo; \n"
4122         "} u;\n"
4123         "void main()\n"
4124         "{\n"
4125         "    u + u;\n"
4126         "}\n";
4127 
4128     if (compile(shaderString))
4129     {
4130         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4131     }
4132 }
4133 
4134 // Test interface block as an invalid operand to an unary expression.
TEST_F(FragmentShaderValidationTest,InvalidInterfaceBlockUnaryExpression)4135 TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockUnaryExpression)
4136 {
4137     const std::string &shaderString =
4138         "#version 300 es\n"
4139         "uniform U\n"
4140         "{\n"
4141         "    int foo; \n"
4142         "} u;\n"
4143         "void main()\n"
4144         "{\n"
4145         "    +u;\n"
4146         "}\n";
4147 
4148     if (compile(shaderString))
4149     {
4150         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4151     }
4152 }
4153 
4154 // Test interface block as an invalid operand to a ternary expression.
4155 // Note that the spec is not very explicit on this, but it makes sense to forbid this.
TEST_F(FragmentShaderValidationTest,InvalidInterfaceBlockTernaryExpression)4156 TEST_F(FragmentShaderValidationTest, InvalidInterfaceBlockTernaryExpression)
4157 {
4158     const std::string &shaderString =
4159         "#version 300 es\n"
4160         "uniform U\n"
4161         "{\n"
4162         "    int foo; \n"
4163         "} u;\n"
4164         "void main()\n"
4165         "{\n"
4166         "    true ? u : u;\n"
4167         "}\n";
4168 
4169     if (compile(shaderString))
4170     {
4171         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4172     }
4173 }
4174 
4175 // Test that "buffer" and "shared" are valid identifiers in version lower than GLSL ES 3.10.
TEST_F(FragmentShaderValidationTest,BufferAndSharedAsIdentifierOnES3)4176 TEST_F(FragmentShaderValidationTest, BufferAndSharedAsIdentifierOnES3)
4177 {
4178     const std::string &shaderString =
4179         R"(#version 300 es
4180         precision highp float;
4181         out vec4 my_out;
4182         void main()
4183         {
4184             int buffer = 1;
4185             int shared = 2;
4186             my_out = vec4(buffer + shared);
4187         })";
4188 
4189     if (!compile(shaderString))
4190     {
4191         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
4192     }
4193 }
4194 
4195 // Test that a struct can not be used as a constructor argument for a scalar.
TEST_F(FragmentShaderValidationTest,StructAsBoolConstructorArgument)4196 TEST_F(FragmentShaderValidationTest, StructAsBoolConstructorArgument)
4197 {
4198     const std::string &shaderString =
4199         "precision mediump float;\n"
4200         "struct my_struct\n"
4201         "{\n"
4202         "    float f;\n"
4203         "};\n"
4204         "my_struct a = my_struct(1.0);\n"
4205         "void main(void)\n"
4206         "{\n"
4207         "    bool test = bool(a);\n"
4208         "}\n";
4209 
4210     if (compile(shaderString))
4211     {
4212         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4213     }
4214 }
4215 
4216 // Test that a compute shader can be compiled with MAX_COMPUTE_UNIFORM_COMPONENTS uniform
4217 // components.
TEST_F(ComputeShaderEnforcePackingValidationTest,MaxComputeUniformComponents)4218 TEST_F(ComputeShaderEnforcePackingValidationTest, MaxComputeUniformComponents)
4219 {
4220     GLint uniformVectorCount = kMaxComputeUniformComponents / 4;
4221 
4222     std::ostringstream ostream;
4223     ostream << "#version 310 es\n"
4224                "layout(local_size_x = 1) in;\n";
4225 
4226     for (GLint i = 0; i < uniformVectorCount; ++i)
4227     {
4228         ostream << "uniform vec4 u_value" << i << ";\n";
4229     }
4230 
4231     ostream << "void main()\n"
4232                "{\n";
4233 
4234     for (GLint i = 0; i < uniformVectorCount; ++i)
4235     {
4236         ostream << "    vec4 v" << i << " = u_value" << i << ";\n";
4237     }
4238 
4239     ostream << "}\n";
4240 
4241     if (!compile(ostream.str()))
4242     {
4243         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
4244     }
4245 }
4246 
4247 // Test that a function can't be declared with a name starting with "gl_". Note that it's important
4248 // that the function is not being called.
TEST_F(FragmentShaderValidationTest,FunctionDeclaredWithReservedName)4249 TEST_F(FragmentShaderValidationTest, FunctionDeclaredWithReservedName)
4250 {
4251     const std::string &shaderString =
4252         "precision mediump float;\n"
4253         "void gl_();\n"
4254         "void main()\n"
4255         "{\n"
4256         "    gl_FragColor = vec4(0.0);\n"
4257         "}\n";
4258 
4259     if (compile(shaderString))
4260     {
4261         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4262     }
4263 }
4264 
4265 // Test that a function can't be defined with a name starting with "gl_". Note that it's important
4266 // that the function is not being called.
TEST_F(FragmentShaderValidationTest,FunctionDefinedWithReservedName)4267 TEST_F(FragmentShaderValidationTest, FunctionDefinedWithReservedName)
4268 {
4269     const std::string &shaderString =
4270         "precision mediump float;\n"
4271         "void gl_()\n"
4272         "{\n"
4273         "}\n"
4274         "void main()\n"
4275         "{\n"
4276         "    gl_FragColor = vec4(0.0);\n"
4277         "}\n";
4278 
4279     if (compile(shaderString))
4280     {
4281         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4282     }
4283 }
4284 
4285 // Test that ops with mismatching operand types are disallowed and don't result in an assert.
4286 // This makes sure that constant folding doesn't fetch invalid union values in case operand types
4287 // mismatch.
TEST_F(FragmentShaderValidationTest,InvalidOpsWithConstantOperandsDontAssert)4288 TEST_F(FragmentShaderValidationTest, InvalidOpsWithConstantOperandsDontAssert)
4289 {
4290     const std::string &shaderString =
4291         "#version 300 es\n"
4292         "precision mediump float;\n"
4293         "out vec4 my_FragColor;\n"
4294         "void main()\n"
4295         "{\n"
4296         "    float f1 = 0.5 / 2;\n"
4297         "    float f2 = true + 0.5;\n"
4298         "    float f3 = float[2](0.0, 1.0)[1.0];\n"
4299         "    float f4 = float[2](0.0, 1.0)[true];\n"
4300         "    float f5 = true ? 1.0 : 0;\n"
4301         "    float f6 = 1.0 ? 1.0 : 2.0;\n"
4302         "    my_FragColor = vec4(0.0);\n"
4303         "}\n";
4304 
4305     if (compile(shaderString))
4306     {
4307         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4308     }
4309 }
4310 
4311 // Test that case labels with invalid types don't assert
TEST_F(FragmentShaderValidationTest,CaseLabelsWithInvalidTypesDontAssert)4312 TEST_F(FragmentShaderValidationTest, CaseLabelsWithInvalidTypesDontAssert)
4313 {
4314     const std::string &shaderString =
4315         "#version 300 es\n"
4316         "precision mediump float;\n"
4317         "out vec4 my_FragColor;\n"
4318         "uniform int i;\n"
4319         "void main()\n"
4320         "{\n"
4321         "    float f = 0.0;\n"
4322         "    switch (i)\n"
4323         "    {\n"
4324         "        case 0u:\n"
4325         "            f = 0.0;\n"
4326         "        case true:\n"
4327         "            f = 1.0;\n"
4328         "        case 2.0:\n"
4329         "            f = 2.0;\n"
4330         "    }\n"
4331         "    my_FragColor = vec4(0.0);\n"
4332         "}\n";
4333 
4334     if (compile(shaderString))
4335     {
4336         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4337     }
4338 }
4339 
4340 // Test that using an array as an index is not allowed.
TEST_F(FragmentShaderValidationTest,ArrayAsIndex)4341 TEST_F(FragmentShaderValidationTest, ArrayAsIndex)
4342 {
4343     const std::string &shaderString =
4344         "#version 300 es\n"
4345         "precision mediump float;\n"
4346         "out vec4 my_FragColor;\n"
4347         "void main()\n"
4348         "{\n"
4349         "    int i[2] = int[2](0, 1);\n"
4350         "    float f[2] = float[2](2.0, 3.0);\n"
4351         "    my_FragColor = vec4(f[i]);\n"
4352         "}\n";
4353 
4354     if (compile(shaderString))
4355     {
4356         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4357     }
4358 }
4359 
4360 // Test that using an array as an array size is not allowed.
TEST_F(FragmentShaderValidationTest,ArrayAsArraySize)4361 TEST_F(FragmentShaderValidationTest, ArrayAsArraySize)
4362 {
4363     const std::string &shaderString =
4364         "#version 300 es\n"
4365         "precision mediump float;\n"
4366         "out vec4 my_FragColor;\n"
4367         "void main()\n"
4368         "{\n"
4369         "    const int i[2] = int[2](1, 2);\n"
4370         "    float f[i];\n"
4371         "    my_FragColor = vec4(f[0]);\n"
4372         "}\n";
4373 
4374     if (compile(shaderString))
4375     {
4376         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4377     }
4378 }
4379 
4380 // The input primitive layout qualifier is only available in geometry shaders.
TEST_F(VertexShaderValidationTest,InvalidUseOfInputPrimitives)4381 TEST_F(VertexShaderValidationTest, InvalidUseOfInputPrimitives)
4382 {
4383     const std::string &shaderString =
4384         "#version 310 es\n"
4385         "precision mediump float;\n"
4386         "layout(points) in vec4 myInput;\n"
4387         "out vec4 myOutput;\n"
4388         "void main() {\n"
4389         "   myOutput = myInput;\n"
4390         "}\n";
4391 
4392     if (compile(shaderString))
4393     {
4394         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4395     }
4396 }
4397 
4398 // The input primitive layout qualifier is only available in geometry shaders.
TEST_F(FragmentShaderValidationTest,InvalidUseOfInputPrimitives)4399 TEST_F(FragmentShaderValidationTest, InvalidUseOfInputPrimitives)
4400 {
4401     const std::string &shaderString =
4402         "#version 310 es\n"
4403         "precision mediump float;\n"
4404         "layout(points) in vec4 myInput;\n"
4405         "out vec4 myOutput;\n"
4406         "void main() {\n"
4407         "   myOutput = myInput;\n"
4408         "}\n";
4409 
4410     if (compile(shaderString))
4411     {
4412         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4413     }
4414 }
4415 
4416 // The input primitive layout qualifier is only available in geometry shaders.
TEST_F(ComputeShaderValidationTest,InvalidUseOfInputPrimitives)4417 TEST_F(ComputeShaderValidationTest, InvalidUseOfInputPrimitives)
4418 {
4419     const std::string &shaderString =
4420         "#version 310 es\n"
4421         "layout(points, local_size_x = 12) in;\n"
4422         "void main()\n"
4423         "{\n"
4424         "   uvec3 WorkGroupSize = gl_WorkGroupSize;\n"
4425         "}\n";
4426 
4427     if (compile(shaderString))
4428     {
4429         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4430     }
4431 }
4432 
4433 // The output primitive layout qualifier is only available in geometry shaders.
TEST_F(VertexShaderValidationTest,InvalidUseOfOutputPrimitives)4434 TEST_F(VertexShaderValidationTest, InvalidUseOfOutputPrimitives)
4435 {
4436     const std::string &shaderString =
4437         "#version 310 es\n"
4438         "precision mediump float;\n"
4439         "in vec4 myInput;\n"
4440         "layout(points) out vec4 myOutput;\n"
4441         "void main() {\n"
4442         "   myOutput = myInput;\n"
4443         "}\n";
4444 
4445     if (compile(shaderString))
4446     {
4447         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4448     }
4449 }
4450 
4451 // The output primitive layout qualifier is only available in geometry shaders.
TEST_F(FragmentShaderValidationTest,InvalidUseOfOutputPrimitives)4452 TEST_F(FragmentShaderValidationTest, InvalidUseOfOutputPrimitives)
4453 {
4454     const std::string &shaderString =
4455         "#version 310 es\n"
4456         "precision mediump float;\n"
4457         "in vec4 myInput;\n"
4458         "layout(points) out vec4 myOutput;\n"
4459         "void main() {\n"
4460         "   myOutput = myInput;\n"
4461         "}\n";
4462 
4463     if (compile(shaderString))
4464     {
4465         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4466     }
4467 }
4468 
4469 // The 'invocations' layout qualifier is only available in geometry shaders.
TEST_F(VertexShaderValidationTest,InvalidUseOfInvocations)4470 TEST_F(VertexShaderValidationTest, InvalidUseOfInvocations)
4471 {
4472     const std::string &shaderString =
4473         "#version 310 es\n"
4474         "precision mediump float;\n"
4475         "layout (invocations = 3) in vec4 myInput;\n"
4476         "out vec4 myOutput;\n"
4477         "void main() {\n"
4478         "   myOutput = myInput;\n"
4479         "}\n";
4480 
4481     if (compile(shaderString))
4482     {
4483         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4484     }
4485 }
4486 
4487 // The 'invocations' layout qualifier is only available in geometry shaders.
TEST_F(FragmentShaderValidationTest,InvalidUseOfInvocations)4488 TEST_F(FragmentShaderValidationTest, InvalidUseOfInvocations)
4489 {
4490     const std::string &shaderString =
4491         "#version 310 es\n"
4492         "precision mediump float;\n"
4493         "layout (invocations = 3) in vec4 myInput;\n"
4494         "out vec4 myOutput;\n"
4495         "void main() {\n"
4496         "   myOutput = myInput;\n"
4497         "}\n";
4498 
4499     if (compile(shaderString))
4500     {
4501         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4502     }
4503 }
4504 
4505 // The 'invocations' layout qualifier is only available in geometry shaders.
TEST_F(ComputeShaderValidationTest,InvalidUseOfInvocations)4506 TEST_F(ComputeShaderValidationTest, InvalidUseOfInvocations)
4507 {
4508     const std::string &shaderString =
4509         "#version 310 es\n"
4510         "layout(invocations = 3, local_size_x = 12) in;\n"
4511         "void main()\n"
4512         "{\n"
4513         "   uvec3 WorkGroupSize = gl_WorkGroupSize;\n"
4514         "}\n";
4515     if (compile(shaderString))
4516     {
4517         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4518     }
4519 }
4520 
4521 // The 'max_vertices' layout qualifier is only available in geometry shaders.
TEST_F(VertexShaderValidationTest,InvalidUseOfMaxVertices)4522 TEST_F(VertexShaderValidationTest, InvalidUseOfMaxVertices)
4523 {
4524     const std::string &shaderString =
4525         "#version 310 es\n"
4526         "precision mediump float;\n"
4527         "in vec4 myInput;\n"
4528         "layout(max_vertices = 3) out vec4 myOutput;\n"
4529         "void main() {\n"
4530         "   myOutput = myInput;\n"
4531         "}\n";
4532 
4533     if (compile(shaderString))
4534     {
4535         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4536     }
4537 }
4538 
4539 // The 'max_vertices' layout qualifier is only available in geometry shaders.
TEST_F(FragmentShaderValidationTest,InvalidUseOfMaxVertices)4540 TEST_F(FragmentShaderValidationTest, InvalidUseOfMaxVertices)
4541 {
4542     const std::string &shaderString =
4543         "#version 310 es\n"
4544         "precision mediump float;\n"
4545         "in vec4 myInput;\n"
4546         "layout(max_vertices = 3) out vec4 myOutput;\n"
4547         "void main() {\n"
4548         "   myOutput = myInput;\n"
4549         "}\n";
4550 
4551     if (compile(shaderString))
4552     {
4553         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4554     }
4555 }
4556 
4557 // Test that using the same variable name twice in function parameters fails without crashing.
TEST_F(FragmentShaderValidationTest,RedefinedParamInFunctionHeader)4558 TEST_F(FragmentShaderValidationTest, RedefinedParamInFunctionHeader)
4559 {
4560     const std::string &shaderString =
4561         "#version 300 es\n"
4562         "precision mediump float;\n"
4563         "out vec4 my_FragColor;\n"
4564         "void foo(int a, float a)\n"
4565         "{\n"
4566         "    return;\n"
4567         "}\n"
4568         "void main()\n"
4569         "{\n"
4570         "    my_FragColor = vec4(0.0);\n"
4571         "}\n";
4572 
4573     if (compile(shaderString))
4574     {
4575         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4576     }
4577 }
4578 
4579 // Test that using gl_ViewportIndex is not allowed in an ESSL 3.10 shader.
TEST_F(VertexShaderValidationTest,ViewportIndexInESSL310)4580 TEST_F(VertexShaderValidationTest, ViewportIndexInESSL310)
4581 {
4582     const std::string &shaderString =
4583         "#version 310 es\n"
4584         "precision mediump float;\n"
4585         "void main()\n"
4586         "{\n"
4587         "    gl_Position = vec4(gl_ViewportIndex);\n"
4588         "}\n";
4589 
4590     if (compile(shaderString))
4591     {
4592         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4593     }
4594 }
4595 
4596 // Test that gl_PrimitiveID is valid in fragment shader with 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,PrimitiveIDWithExtension)4597 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, PrimitiveIDWithExtension)
4598 {
4599     const std::string &shaderString =
4600         R"(#version 310 es
4601         #extension GL_EXT_geometry_shader : require
4602         precision mediump float;
4603         layout(location = 0) out mediump vec4 fragColor;
4604         void main(void)
4605         {
4606             vec4 data = vec4(0.1, 0.2, 0.3, 0.4);
4607             float value = data[gl_PrimitiveID % 4];
4608             fragColor = vec4(value, 0, 0, 1);
4609         })";
4610 
4611     if (!compile(shaderString))
4612     {
4613         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
4614     }
4615 }
4616 
4617 // Test that gl_PrimitiveID is invalid in fragment shader without 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,PrimitiveIDWithoutExtension)4618 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, PrimitiveIDWithoutExtension)
4619 {
4620     const std::string &shaderString =
4621         R"(#version 310 es
4622         precision mediump float;
4623         layout(location = 0) out mediump vec4 fragColor;
4624         void main(void)
4625         {
4626             vec4 data = vec4(0.1, 0.2, 0.3, 0.4);
4627             float value = data[gl_PrimitiveID % 4];
4628             fragColor = vec4(value, 0, 0, 1);
4629         })";
4630 
4631     if (compile(shaderString))
4632     {
4633         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4634     }
4635 }
4636 
4637 // Test that gl_PrimitiveID cannot be l-value in fragment shader.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,AssignValueToPrimitiveID)4638 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, AssignValueToPrimitiveID)
4639 {
4640     const std::string &shaderString =
4641         R"(#version 310 es
4642         #extension GL_EXT_geometry_shader : require
4643         precision mediump float;
4644         layout(location = 0) out mediump vec4 fragColor;
4645         void main(void)
4646         {
4647             gl_PrimitiveID = 1;
4648             fragColor = vec4(1.0, 0.0, 0.0, 1.0);
4649         })";
4650 
4651     if (compile(shaderString))
4652     {
4653         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4654     }
4655 }
4656 
4657 // Test that gl_Layer is valid in fragment shader with 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,LayerWithExtension)4658 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, LayerWithExtension)
4659 {
4660     const std::string &shaderString =
4661         R"(#version 310 es
4662         #extension GL_EXT_geometry_shader : require
4663         precision mediump float;
4664         layout(location = 0) out mediump vec4 fragColor;
4665         void main(void)
4666         {
4667             vec4 data = vec4(0.1, 0.2, 0.3, 0.4);
4668             float value = data[gl_Layer % 4];
4669             fragColor = vec4(value, 0, 0, 1);
4670         })";
4671 
4672     if (!compile(shaderString))
4673     {
4674         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
4675     }
4676 }
4677 
4678 // Test that gl_Layer is invalid in fragment shader without 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,LayerWithoutExtension)4679 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, LayerWithoutExtension)
4680 {
4681     const std::string &shaderString =
4682         R"(#version 310 es
4683         precision mediump float;
4684         layout(location = 0) out mediump vec4 fragColor;
4685         void main(void)
4686         {
4687             vec4 data = vec4(0.1, 0.2, 0.3, 0.4);
4688             float value = data[gl_Layer % 4];
4689             fragColor = vec4(value, 0, 0, 1);
4690         })";
4691 
4692     if (compile(shaderString))
4693     {
4694         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4695     }
4696 }
4697 
4698 // Test that gl_Layer cannot be l-value in fragment shader.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,AssignValueToLayer)4699 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, AssignValueToLayer)
4700 {
4701     const std::string &shaderString =
4702         R"(#version 310 es
4703         #extension GL_EXT_geometry_shader : require
4704         precision mediump float;
4705         layout(location = 0) out mediump vec4 fragColor;
4706         void main(void)
4707         {
4708             gl_Layer = 1;
4709             fragColor = vec4(1.0, 0.0, 0.0, 1.0);
4710         })";
4711 
4712     if (compile(shaderString))
4713     {
4714         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4715     }
4716 }
4717 
4718 // Test that all built-in constants defined in GL_EXT_geometry_shader can be used in fragment shader
4719 // with 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,GeometryShaderBuiltInConstants)4720 TEST_F(FragmentShaderEXTGeometryShaderValidationTest, GeometryShaderBuiltInConstants)
4721 {
4722     const std::string &kShaderHeader =
4723         R"(#version 310 es
4724         #extension GL_EXT_geometry_shader : require
4725         precision mediump float;
4726         layout(location = 0) out mediump vec4 fragColor;
4727         void main(void)
4728         {
4729             int val = )";
4730 
4731     const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
4732         "gl_MaxGeometryInputComponents",
4733         "gl_MaxGeometryOutputComponents",
4734         "gl_MaxGeometryImageUniforms",
4735         "gl_MaxGeometryTextureImageUnits",
4736         "gl_MaxGeometryOutputVertices",
4737         "gl_MaxGeometryTotalOutputComponents",
4738         "gl_MaxGeometryUniformComponents",
4739         "gl_MaxGeometryAtomicCounters",
4740         "gl_MaxGeometryAtomicCounterBuffers",
4741     }};
4742 
4743     const std::string &kShaderTail =
4744         R"(;
4745             fragColor = vec4(val, 0, 0, 1);
4746         })";
4747 
4748     for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
4749     {
4750         std::ostringstream ostream;
4751         ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
4752         if (!compile(ostream.str()))
4753         {
4754             FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;
4755         }
4756     }
4757 }
4758 
4759 // Test that any built-in constants defined in GL_EXT_geometry_shader cannot be used in fragment
4760 // shader without 'GL_EXT_geometry_shader' declared.
TEST_F(FragmentShaderEXTGeometryShaderValidationTest,GeometryShaderBuiltInConstantsWithoutExtension)4761 TEST_F(FragmentShaderEXTGeometryShaderValidationTest,
4762        GeometryShaderBuiltInConstantsWithoutExtension)
4763 {
4764     const std::string &kShaderHeader =
4765         "#version 310 es\n"
4766         "precision mediump float;\n"
4767         "layout(location = 0) out mediump vec4 fragColor;\n"
4768         "void main(void)\n"
4769         "{\n"
4770         "    int val = ";
4771 
4772     const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
4773         "gl_MaxGeometryInputComponents",
4774         "gl_MaxGeometryOutputComponents",
4775         "gl_MaxGeometryImageUniforms",
4776         "gl_MaxGeometryTextureImageUnits",
4777         "gl_MaxGeometryOutputVertices",
4778         "gl_MaxGeometryTotalOutputComponents",
4779         "gl_MaxGeometryUniformComponents",
4780         "gl_MaxGeometryAtomicCounters",
4781         "gl_MaxGeometryAtomicCounterBuffers",
4782     }};
4783 
4784     const std::string &kShaderTail =
4785         ";\n"
4786         "    fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4787         "}\n";
4788 
4789     for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
4790     {
4791         std::ostringstream ostream;
4792         ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
4793         if (compile(ostream.str()))
4794         {
4795             FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4796         }
4797     }
4798 }
4799 
4800 // Test that declaring and using an interface block with 'const' qualifier is not allowed.
TEST_F(VertexShaderValidationTest,InterfaceBlockUsingConstQualifier)4801 TEST_F(VertexShaderValidationTest, InterfaceBlockUsingConstQualifier)
4802 {
4803     const std::string &shaderString =
4804         "#version 310 es\n"
4805         "const block\n"
4806         "{\n"
4807         "    vec2 value;\n"
4808         "} ConstBlock[2];\n"
4809         "void main()\n"
4810         "{\n"
4811         "    int i = 0;\n"
4812         "    vec2 value1 = ConstBlock[i].value;\n"
4813         "}\n";
4814 
4815     if (compile(shaderString))
4816     {
4817         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4818     }
4819 }
4820 
4821 // Test that using shader io blocks without declaration of GL_EXT_shader_io_block is not allowed.
TEST_F(VertexShaderValidationTest,IOBlockWithoutExtension)4822 TEST_F(VertexShaderValidationTest, IOBlockWithoutExtension)
4823 {
4824     const std::string &shaderString =
4825         R"(#version 310 es
4826         out block
4827         {
4828             vec2 value;
4829         } VSOutput[2];
4830         void main()
4831         {
4832             int i = 0;
4833             vec2 value1 = VSOutput[i].value;
4834         })";
4835 
4836     if (compile(shaderString))
4837     {
4838         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4839     }
4840 }
4841 
4842 // Test that using shader io blocks without declaration of GL_EXT_shader_io_block is not allowed.
TEST_F(FragmentShaderValidationTest,IOBlockWithoutExtension)4843 TEST_F(FragmentShaderValidationTest, IOBlockWithoutExtension)
4844 {
4845     const std::string &shaderString =
4846         R"(#version 310 es
4847         precision mediump float;
4848         in block
4849         {
4850             vec4 i_color;
4851         } FSInput[2];
4852         out vec4 o_color;
4853         void main()
4854         {
4855             int i = 0;
4856             o_color = FSInput[i].i_color;
4857         })";
4858 
4859     if (compile(shaderString))
4860     {
4861         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4862     }
4863 }
4864 
4865 // Test that a shader input with 'flat' qualifier cannot be used as l-value.
TEST_F(FragmentShaderValidationTest,AssignValueToFlatIn)4866 TEST_F(FragmentShaderValidationTest, AssignValueToFlatIn)
4867 {
4868     const std::string &shaderString =
4869         "#version 310 es\n"
4870         "precision mediump float;\n"
4871         "flat in float value;\n"
4872         "out vec4 o_color;\n"
4873         "void main()\n"
4874         "{\n"
4875         "    value = 1.0;\n"
4876         "    o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4877         "}\n";
4878 
4879     if (compile(shaderString))
4880     {
4881         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4882     }
4883 }
4884 
4885 // Test that a shader input with 'smooth' qualifier cannot be used as l-value.
TEST_F(FragmentShaderValidationTest,AssignValueToSmoothIn)4886 TEST_F(FragmentShaderValidationTest, AssignValueToSmoothIn)
4887 {
4888     const std::string &shaderString =
4889         "#version 310 es\n"
4890         "precision mediump float;\n"
4891         "smooth in float value;\n"
4892         "out vec4 o_color;\n"
4893         "void main()\n"
4894         "{\n"
4895         "    value = 1.0;\n"
4896         "    o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4897         "}\n";
4898 
4899     if (compile(shaderString))
4900     {
4901         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4902     }
4903 }
4904 
4905 // Test that a shader input with 'centroid' qualifier cannot be used as l-value.
TEST_F(FragmentShaderValidationTest,AssignValueToCentroidIn)4906 TEST_F(FragmentShaderValidationTest, AssignValueToCentroidIn)
4907 {
4908     const std::string &shaderString =
4909         "#version 310 es\n"
4910         "precision mediump float;\n"
4911         "centroid in float value;\n"
4912         "out vec4 o_color;\n"
4913         "void main()\n"
4914         "{\n"
4915         "    value = 1.0;\n"
4916         "    o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4917         "}\n";
4918 
4919     if (compile(shaderString))
4920     {
4921         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4922     }
4923 }
4924 
4925 // Test that shader compilation fails if the component argument is dynamic.
TEST_F(FragmentShaderValidationTest,DynamicComponentTextureGather)4926 TEST_F(FragmentShaderValidationTest, DynamicComponentTextureGather)
4927 {
4928     const std::string &shaderString =
4929         "#version 310 es\n"
4930         "precision mediump float;\n"
4931         "precision mediump sampler2D;\n"
4932         "uniform sampler2D tex;\n"
4933         "out vec4 o_color;\n"
4934         "uniform int uComp;\n"
4935         "void main()\n"
4936         "{\n"
4937         "    o_color = textureGather(tex, vec2(0), uComp);"
4938         "}\n";
4939 
4940     if (compile(shaderString))
4941     {
4942         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4943     }
4944 }
4945 
4946 // Test that shader compilation fails if the component argument to textureGather has a negative
4947 // value.
TEST_F(FragmentShaderValidationTest,TextureGatherNegativeComponent)4948 TEST_F(FragmentShaderValidationTest, TextureGatherNegativeComponent)
4949 {
4950     const std::string &shaderString =
4951         "#version 310 es\n"
4952         "precision mediump float;\n"
4953         "precision mediump sampler2D;\n"
4954         "uniform sampler2D tex;\n"
4955         "out vec4 o_color;\n"
4956         "void main()\n"
4957         "{\n"
4958         "    o_color = textureGather(tex, vec2(0), -1);"
4959         "}\n";
4960 
4961     if (compile(shaderString))
4962     {
4963         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4964     }
4965 }
4966 
4967 // Test that shader compilation fails if the component argument to textureGather has a value greater
4968 // than 3.
TEST_F(FragmentShaderValidationTest,TextureGatherTooGreatComponent)4969 TEST_F(FragmentShaderValidationTest, TextureGatherTooGreatComponent)
4970 {
4971     const std::string &shaderString =
4972         "#version 310 es\n"
4973         "precision mediump float;\n"
4974         "precision mediump sampler2D;\n"
4975         "uniform sampler2D tex;\n"
4976         "out vec4 o_color;\n"
4977         "void main()\n"
4978         "{\n"
4979         "    o_color = textureGather(tex, vec2(0), 4);"
4980         "}\n";
4981 
4982     if (compile(shaderString))
4983     {
4984         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
4985     }
4986 }
4987 
4988 // Test that shader compilation fails if the offset is less than the minimum value.
TEST_F(FragmentShaderValidationTest,TextureGatherTooGreatOffset)4989 TEST_F(FragmentShaderValidationTest, TextureGatherTooGreatOffset)
4990 {
4991     const std::string &shaderString =
4992         "#version 310 es\n"
4993         "precision mediump float;\n"
4994         "precision mediump sampler2D;\n"
4995         "uniform sampler2D tex;\n"
4996         "out vec4 o_color;\n"
4997         "void main()\n"
4998         "{\n"
4999         "    o_color = textureGatherOffset(tex, vec2(0), ivec2(-100), 2);"
5000         "}\n";
5001 
5002     if (compile(shaderString))
5003     {
5004         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5005     }
5006 }
5007 
5008 // Test that it isn't allowed to use 'location' layout qualifier on GLSL ES 3.0 vertex shader
5009 // outputs.
TEST_F(VertexShaderValidationTest,UseLocationOnVertexOutES30)5010 TEST_F(VertexShaderValidationTest, UseLocationOnVertexOutES30)
5011 {
5012     const std::string &shaderString =
5013         "#version 300 es\n"
5014         "in vec4 v1;\n"
5015         "layout (location = 1) out vec4 o_color;\n"
5016         "void main()\n"
5017         "{\n"
5018         "}\n";
5019 
5020     if (compile(shaderString))
5021     {
5022         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5023     }
5024 }
5025 
5026 // Test that using 'location' layout qualifier on vertex shader outputs is legal in GLSL ES 3.1
5027 // shaders.
TEST_F(VertexShaderValidationTest,UseLocationOnVertexOutES31)5028 TEST_F(VertexShaderValidationTest, UseLocationOnVertexOutES31)
5029 {
5030     const std::string &shaderString =
5031         "#version 310 es\n"
5032         "in vec4 v1;\n"
5033         "layout (location = 1) out vec4 o_color1;\n"
5034         "layout (location = 2) out vec4 o_color2;\n"
5035         "out vec3 v3;\n"
5036         "void main()\n"
5037         "{\n"
5038         "}\n";
5039 
5040     if (!compile(shaderString))
5041     {
5042         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5043     }
5044 }
5045 
5046 // Test that it isn't allowed to use 'location' layout qualifier on GLSL ES 3.0 fragment shader
5047 // inputs.
TEST_F(FragmentShaderValidationTest,UseLocationOnFragmentInES30)5048 TEST_F(FragmentShaderValidationTest, UseLocationOnFragmentInES30)
5049 {
5050     const std::string &shaderString =
5051         "#version 300 es\n"
5052         "precision mediump float;\n"
5053         "layout (location = 0) in vec4 v_color1;\n"
5054         "layout (location = 0) out vec4 o_color;\n"
5055         "void main()\n"
5056         "{\n"
5057         "}\n";
5058 
5059     if (compile(shaderString))
5060     {
5061         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5062     }
5063 }
5064 
5065 // Test that using 'location' layout qualifier on fragment shader inputs is legal in GLSL ES 3.1
5066 // shaders.
TEST_F(FragmentShaderValidationTest,UseLocationOnFragmentInES31)5067 TEST_F(FragmentShaderValidationTest, UseLocationOnFragmentInES31)
5068 {
5069     const std::string &shaderString =
5070         "#version 310 es\n"
5071         "precision mediump float;\n"
5072         "layout (location = 0) in mat4 v_mat;\n"
5073         "layout (location = 4) in vec4 v_color1;\n"
5074         "in vec2 v_color2;\n"
5075         "layout (location = 0) out vec4 o_color;\n"
5076         "void main()\n"
5077         "{\n"
5078         "}\n";
5079 
5080     if (!compile(shaderString))
5081     {
5082         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5083     }
5084 }
5085 
5086 // Test that declaring outputs of a vertex shader with same location causes a compile error.
TEST_F(VertexShaderValidationTest,DeclareSameLocationOnVertexOut)5087 TEST_F(VertexShaderValidationTest, DeclareSameLocationOnVertexOut)
5088 {
5089     const std::string &shaderString =
5090         "#version 310 es\n"
5091         "in float i_value;\n"
5092         "layout (location = 1) out vec4 o_color1;\n"
5093         "layout (location = 1) out vec4 o_color2;\n"
5094         "void main()\n"
5095         "{\n"
5096         "}\n";
5097 
5098     if (compile(shaderString))
5099     {
5100         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5101     }
5102 }
5103 
5104 // Test that declaring inputs of a fragment shader with same location causes a compile error.
TEST_F(FragmentShaderValidationTest,DeclareSameLocationOnFragmentIn)5105 TEST_F(FragmentShaderValidationTest, DeclareSameLocationOnFragmentIn)
5106 {
5107     const std::string &shaderString =
5108         "#version 310 es\n"
5109         "precision mediump float;\n"
5110         "in float i_value;\n"
5111         "layout (location = 1) in vec4 i_color1;\n"
5112         "layout (location = 1) in vec4 i_color2;\n"
5113         "layout (location = 0) out vec4 o_color;\n"
5114         "void main()\n"
5115         "{\n"
5116         "}\n";
5117 
5118     if (compile(shaderString))
5119     {
5120         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5121     }
5122 }
5123 
5124 // Test that the location of an element of an array conflicting with other output varyings in a
5125 // vertex shader causes a compile error.
TEST_F(VertexShaderValidationTest,LocationConflictsnOnArrayElement)5126 TEST_F(VertexShaderValidationTest, LocationConflictsnOnArrayElement)
5127 {
5128     const std::string &shaderString =
5129         "#version 310 es\n"
5130         "in float i_value;\n"
5131         "layout (location = 0) out vec4 o_color1[3];\n"
5132         "layout (location = 1) out vec4 o_color2;\n"
5133         "void main()\n"
5134         "{\n"
5135         "}\n";
5136 
5137     if (compile(shaderString))
5138     {
5139         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5140     }
5141 }
5142 
5143 // Test that the location of an element of a matrix conflicting with other output varyings in a
5144 // vertex shader causes a compile error.
TEST_F(VertexShaderValidationTest,LocationConflictsOnMatrixElement)5145 TEST_F(VertexShaderValidationTest, LocationConflictsOnMatrixElement)
5146 {
5147     const std::string &shaderString =
5148         "#version 310 es\n"
5149         "in float i_value;\n"
5150         "layout (location = 0) out mat4 o_mvp;\n"
5151         "layout (location = 2) out vec4 o_color;\n"
5152         "void main()\n"
5153         "{\n"
5154         "}\n";
5155 
5156     if (compile(shaderString))
5157     {
5158         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5159     }
5160 }
5161 
5162 // Test that the location of an element of a struct conflicting with other output varyings in a
5163 // vertex shader causes a compile error.
TEST_F(VertexShaderValidationTest,LocationConflictsOnStructElement)5164 TEST_F(VertexShaderValidationTest, LocationConflictsOnStructElement)
5165 {
5166     const std::string &shaderString =
5167         "#version 310 es\n"
5168         "in float i_value;\n"
5169         "struct S\n"
5170         "{\n"
5171         "    float value1;\n"
5172         "    vec3 value2;\n"
5173         "};\n"
5174         "layout (location = 0) out S s_in;"
5175         "layout (location = 1) out vec4 o_color;\n"
5176         "void main()\n"
5177         "{\n"
5178         "}\n";
5179 
5180     if (compile(shaderString))
5181     {
5182         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5183     }
5184 }
5185 
5186 // Test that declaring inputs of a vertex shader with a location larger than GL_MAX_VERTEX_ATTRIBS
5187 // causes a compile error.
TEST_F(VertexShaderValidationTest,AttributeLocationOutOfRange)5188 TEST_F(VertexShaderValidationTest, AttributeLocationOutOfRange)
5189 {
5190     // Assumes 1000 >= GL_MAX_VERTEX_ATTRIBS.
5191     // Current OpenGL and Direct3D implementations support up to 32.
5192 
5193     const std::string &shaderString =
5194         "#version 300 es\n"
5195         "layout (location = 1000) in float i_value;\n"
5196         "void main()\n"
5197         "{\n"
5198         "}\n";
5199 
5200     if (compile(shaderString))
5201     {
5202         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5203     }
5204 }
5205 
5206 // Test that a block can follow the final case in a switch statement.
5207 // GLSL ES 3.00.5 section 6 and the grammar suggest that an empty block is a statement.
TEST_F(FragmentShaderValidationTest,SwitchFinalCaseHasEmptyBlock)5208 TEST_F(FragmentShaderValidationTest, SwitchFinalCaseHasEmptyBlock)
5209 {
5210     const std::string &shaderString =
5211         R"(#version 300 es
5212 
5213         precision mediump float;
5214         uniform int i;
5215         void main()
5216         {
5217             switch (i)
5218             {
5219                 case 0:
5220                     break;
5221                 default:
5222                     {}
5223             }
5224         })";
5225 
5226     if (!compile(shaderString))
5227     {
5228         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5229     }
5230 }
5231 
5232 // Test that an empty declaration can follow the final case in a switch statement.
TEST_F(FragmentShaderValidationTest,SwitchFinalCaseHasEmptyDeclaration)5233 TEST_F(FragmentShaderValidationTest, SwitchFinalCaseHasEmptyDeclaration)
5234 {
5235     const std::string &shaderString =
5236         R"(#version 300 es
5237 
5238         precision mediump float;
5239         uniform int i;
5240         void main()
5241         {
5242             switch (i)
5243             {
5244                 case 0:
5245                     break;
5246                 default:
5247                     float;
5248             }
5249         })";
5250 
5251     if (!compile(shaderString))
5252     {
5253         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5254     }
5255 }
5256 
5257 // The final case in a switch statement can't be empty in ESSL 3.10 either. This is the intent of
5258 // the spec though public spec in early 2018 didn't reflect this yet.
TEST_F(FragmentShaderValidationTest,SwitchFinalCaseEmptyESSL310)5259 TEST_F(FragmentShaderValidationTest, SwitchFinalCaseEmptyESSL310)
5260 {
5261     const std::string &shaderString =
5262         R"(#version 310 es
5263 
5264         precision mediump float;
5265         uniform int i;
5266         void main()
5267         {
5268             switch (i)
5269             {
5270                 case 0:
5271                     break;
5272                 default:
5273             }
5274         })";
5275 
5276     if (compile(shaderString))
5277     {
5278         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5279     }
5280 }
5281 
5282 // Test that fragment shader cannot declare unsized inputs.
TEST_F(FragmentShaderValidationTest,UnsizedInputs)5283 TEST_F(FragmentShaderValidationTest, UnsizedInputs)
5284 {
5285     const std::string &shaderString =
5286         "#version 310 es\n"
5287         "precision mediump float;\n"
5288         "in float i_value[];\n"
5289         "void main()\n"
5290         "{\n"
5291         "}\n";
5292 
5293     if (compile(shaderString))
5294     {
5295         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5296     }
5297 }
5298 
5299 // Test that unsized struct members are not allowed.
TEST_F(FragmentShaderValidationTest,UnsizedStructMember)5300 TEST_F(FragmentShaderValidationTest, UnsizedStructMember)
5301 {
5302     const std::string &shaderString =
5303         R"(#version 300 es
5304 
5305         precision highp float;
5306         out vec4 color;
5307 
5308         struct S
5309         {
5310             int[] foo;
5311         };
5312 
5313         void main()
5314         {
5315             color = vec4(1.0);
5316         })";
5317 
5318     if (compile(shaderString))
5319     {
5320         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5321     }
5322 }
5323 
5324 // Test that unsized parameters without a name are not allowed.
5325 // GLSL ES 3.10 section 6.1 Function Definitions.
TEST_F(FragmentShaderValidationTest,UnsizedNamelessParameter)5326 TEST_F(FragmentShaderValidationTest, UnsizedNamelessParameter)
5327 {
5328     const std::string &shaderString =
5329         R"(#version 300 es
5330 
5331         precision highp float;
5332         out vec4 color;
5333 
5334         void foo(int[]);
5335 
5336         void main()
5337         {
5338             color = vec4(1.0);
5339         })";
5340 
5341     if (compile(shaderString))
5342     {
5343         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5344     }
5345 }
5346 
5347 // Test that partially unsized array of arrays constructor sizes are validated.
TEST_F(FragmentShaderValidationTest,PartiallyUnsizedArrayOfArraysConstructor)5348 TEST_F(FragmentShaderValidationTest, PartiallyUnsizedArrayOfArraysConstructor)
5349 {
5350     const std::string &shaderString =
5351         R"(#version 310 es
5352 
5353         precision highp float;
5354         out vec4 color;
5355 
5356         void main()
5357         {
5358             int a[][] = int[2][](int[1](1));
5359             color = vec4(a[0][0]);
5360         })";
5361 
5362     if (compile(shaderString))
5363     {
5364         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5365     }
5366 }
5367 
5368 // Test that duplicate field names in a struct declarator list are validated.
TEST_F(FragmentShaderValidationTest,DuplicateFieldNamesInStructDeclaratorList)5369 TEST_F(FragmentShaderValidationTest, DuplicateFieldNamesInStructDeclaratorList)
5370 {
5371     const std::string &shaderString =
5372         R"(precision mediump float;
5373 
5374         struct S {
5375             float f, f;
5376         };
5377 
5378         void main()
5379         {
5380             gl_FragColor = vec4(1.0);
5381         })";
5382 
5383     if (compile(shaderString))
5384     {
5385         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5386     }
5387 }
5388 
5389 // Test that an empty statement is not allowed in switch before the first case.
TEST_F(FragmentShaderValidationTest,EmptyStatementInSwitchBeforeFirstCase)5390 TEST_F(FragmentShaderValidationTest, EmptyStatementInSwitchBeforeFirstCase)
5391 {
5392     const std::string &shaderString =
5393         R"(#version 300 es
5394 
5395         precision mediump float;
5396         uniform int u_zero;
5397         out vec4 my_FragColor;
5398 
5399         void main()
5400         {
5401             switch(u_zero)
5402             {
5403                     ;
5404                 case 0:
5405                     my_FragColor = vec4(0.0);
5406                 default:
5407                     my_FragColor = vec4(1.0);
5408             }
5409         })";
5410 
5411     if (compile(shaderString))
5412     {
5413         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5414     }
5415 }
5416 
5417 // Test that a nameless struct definition is not allowed as a function parameter type.
5418 // ESSL 3.00.6 section 12.10. ESSL 3.10 January 2016 section 13.10.
TEST_F(FragmentShaderValidationTest,NamelessStructDefinitionAsParameterType)5419 TEST_F(FragmentShaderValidationTest, NamelessStructDefinitionAsParameterType)
5420 {
5421     const std::string &shaderString =
5422         R"(#version 300 es
5423 
5424         precision highp float;
5425         out vec4 my_FragColor;
5426 
5427         float foo(struct { float field; } f)
5428         {
5429             return f.field;
5430         }
5431 
5432         void main()
5433         {
5434             my_FragColor = vec4(0, 1, 0, 1);
5435         })";
5436 
5437     if (compile(shaderString))
5438     {
5439         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5440     }
5441 }
5442 
5443 // Test that a named struct definition is not allowed as a function parameter type.
5444 // ESSL 3.00.6 section 12.10. ESSL 3.10 January 2016 section 13.10.
TEST_F(FragmentShaderValidationTest,NamedStructDefinitionAsParameterType)5445 TEST_F(FragmentShaderValidationTest, NamedStructDefinitionAsParameterType)
5446 {
5447     const std::string &shaderString =
5448         R"(#version 300 es
5449 
5450         precision highp float;
5451         out vec4 my_FragColor;
5452 
5453         float foo(struct S { float field; } f)
5454         {
5455             return f.field;
5456         }
5457 
5458         void main()
5459         {
5460             my_FragColor = vec4(0, 1, 0, 1);
5461         })";
5462 
5463     if (compile(shaderString))
5464     {
5465         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5466     }
5467 }
5468 
5469 // Test that a named struct definition is not allowed as a function parameter type.
5470 // ESSL 3.00.6 section 12.10. ESSL 3.10 January 2016 section 13.10.
TEST_F(FragmentShaderValidationTest,StructDefinitionAsTypeOfParameterWithoutName)5471 TEST_F(FragmentShaderValidationTest, StructDefinitionAsTypeOfParameterWithoutName)
5472 {
5473     const std::string &shaderString =
5474         R"(#version 300 es
5475 
5476         precision highp float;
5477         out vec4 my_FragColor;
5478 
5479         float foo(struct S { float field; } /* no parameter name */)
5480         {
5481             return 1.0;
5482         }
5483 
5484         void main()
5485         {
5486             my_FragColor = vec4(0, 1, 0, 1);
5487         })";
5488 
5489     if (compile(shaderString))
5490     {
5491         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5492     }
5493 }
5494 
5495 // Test that an unsized const array doesn't assert.
TEST_F(FragmentShaderValidationTest,UnsizedConstArray)5496 TEST_F(FragmentShaderValidationTest, UnsizedConstArray)
5497 {
5498     const std::string &shaderString =
5499         R"(#version 300 es
5500 
5501         void main()
5502         {
5503             const int t[];
5504             t[0];
5505         })";
5506 
5507     if (compile(shaderString))
5508     {
5509         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5510     }
5511 }
5512 
5513 // Test that the value passed to the mem argument of an atomic memory function can be a shared
5514 // variable.
TEST_F(ComputeShaderValidationTest,AtomicAddWithSharedVariable)5515 TEST_F(ComputeShaderValidationTest, AtomicAddWithSharedVariable)
5516 {
5517     const std::string &shaderString =
5518         R"(#version 310 es
5519 
5520         layout(local_size_x = 5) in;
5521         shared uint myShared;
5522 
5523         void main() {
5524             atomicAdd(myShared, 2u);
5525         })";
5526 
5527     if (!compile(shaderString))
5528     {
5529         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5530     }
5531 }
5532 
5533 // Test that it is acceptable to pass an element of an array to the mem argument of an atomic memory
5534 // function, as long as the underlying array is a buffer or shared variable.
TEST_F(ComputeShaderValidationTest,AtomicAddWithSharedVariableArray)5535 TEST_F(ComputeShaderValidationTest, AtomicAddWithSharedVariableArray)
5536 {
5537     const std::string &shaderString =
5538         R"(#version 310 es
5539 
5540         layout(local_size_x = 5) in;
5541         shared uint myShared[2];
5542 
5543         void main() {
5544             atomicAdd(myShared[0], 2u);
5545         })";
5546 
5547     if (!compile(shaderString))
5548     {
5549         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5550     }
5551 }
5552 
5553 // Test that it is acceptable to pass a single component of a vector to the mem argument of an
5554 // atomic memory function, as long as the underlying vector is a buffer or shared variable.
TEST_F(ComputeShaderValidationTest,AtomicAddWithSharedVariableVector)5555 TEST_F(ComputeShaderValidationTest, AtomicAddWithSharedVariableVector)
5556 {
5557     const std::string &shaderString =
5558         R"(#version 310 es
5559 
5560         layout(local_size_x = 5) in;
5561         shared uvec4 myShared;
5562 
5563         void main() {
5564             atomicAdd(myShared[0], 2u);
5565         })";
5566 
5567     if (!compile(shaderString))
5568     {
5569         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5570     }
5571 }
5572 
5573 // Test that the value passed to the mem argument of an atomic memory function can be a buffer
5574 // variable.
TEST_F(FragmentShaderValidationTest,AtomicAddWithBufferVariable)5575 TEST_F(FragmentShaderValidationTest, AtomicAddWithBufferVariable)
5576 {
5577     const std::string &shaderString =
5578         R"(#version 310 es
5579 
5580         layout(std140) buffer bufferName1{
5581             uint u1;
5582         };
5583 
5584         void main()
5585         {
5586             atomicAdd(u1, 2u);
5587         })";
5588 
5589     if (!compile(shaderString))
5590     {
5591         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5592     }
5593 }
5594 
5595 // Test that it is acceptable to pass an element of an array to the mem argument of an atomic memory
5596 // function, as long as the underlying array is a buffer or shared variable.
TEST_F(FragmentShaderValidationTest,AtomicAddWithBufferVariableArrayElement)5597 TEST_F(FragmentShaderValidationTest, AtomicAddWithBufferVariableArrayElement)
5598 {
5599     const std::string &shaderString =
5600         R"(#version 310 es
5601 
5602         layout(std140) buffer bufferName1{
5603             uint u1[2];
5604         };
5605 
5606         void main()
5607         {
5608             atomicAdd(u1[0], 2u);
5609         })";
5610 
5611     if (!compile(shaderString))
5612     {
5613         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5614     }
5615 }
5616 
5617 // Test that it is acceptable to pass a member of a shader storage block instance to the mem
5618 // argument of an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithBufferVariableInBlockInstance)5619 TEST_F(FragmentShaderValidationTest, AtomicAddWithBufferVariableInBlockInstance)
5620 {
5621     const std::string &shaderString =
5622         R"(#version 310 es
5623 
5624         layout(std140) buffer bufferName{
5625             uint u1;
5626         } instanceName;
5627 
5628         void main()
5629         {
5630             atomicAdd(instanceName.u1, 2u);
5631         })";
5632 
5633     if (!compile(shaderString))
5634     {
5635         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5636     }
5637 }
5638 
5639 // Test that it is acceptable to pass a member of a shader storage block instance array to the mem
5640 // argument of an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithBufferVariableInBlockInstanceArray)5641 TEST_F(FragmentShaderValidationTest, AtomicAddWithBufferVariableInBlockInstanceArray)
5642 {
5643     const std::string &shaderString =
5644         R"(#version 310 es
5645 
5646         layout(std140) buffer bufferName{
5647             uint u1;
5648         } instanceName[1];
5649 
5650         void main()
5651         {
5652             atomicAdd(instanceName[0].u1, 2u);
5653         })";
5654 
5655     if (!compile(shaderString))
5656     {
5657         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5658     }
5659 }
5660 
5661 // Test that it is acceptable to pass an element of an array  of a shader storage block instance to
5662 // the mem argument of an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithElementOfArrayInBlockInstance)5663 TEST_F(FragmentShaderValidationTest, AtomicAddWithElementOfArrayInBlockInstance)
5664 {
5665     const std::string &shaderString =
5666         R"(#version 310 es
5667 
5668         layout(std140) buffer blockName {
5669             uint data[2];
5670         } instanceName;
5671 
5672         void main()
5673         {
5674             atomicAdd(instanceName.data[0], 2u);
5675         })";
5676 
5677     if (!compile(shaderString))
5678     {
5679         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5680     }
5681 }
5682 
5683 // Test that it is not allowed to pass an atomic counter variable to the mem argument of an atomic
5684 // memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithAtomicCounter)5685 TEST_F(FragmentShaderValidationTest, AtomicAddWithAtomicCounter)
5686 {
5687     const std::string &shaderString =
5688         R"(#version 310 es
5689 
5690         layout(binding = 0, offset = 4) uniform atomic_uint ac;
5691 
5692         void main()
5693         {
5694             atomicAdd(ac, 2u);
5695         })";
5696 
5697     if (compile(shaderString))
5698     {
5699         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5700     }
5701 }
5702 
5703 // Test that it is not allowed to pass an element of an atomic counter array to the mem argument of
5704 // an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithAtomicCounterArray)5705 TEST_F(FragmentShaderValidationTest, AtomicAddWithAtomicCounterArray)
5706 {
5707     const std::string &shaderString =
5708         R"(#version 310 es
5709 
5710         layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
5711 
5712         void main()
5713         {
5714             atomicAdd(ac[0], 2u);
5715         })";
5716 
5717     if (compile(shaderString))
5718     {
5719         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5720     }
5721 }
5722 
5723 // Test that it is not allowed to pass a local uint value to the mem argument of an atomic memory
5724 // function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithNonStorageVariable)5725 TEST_F(FragmentShaderValidationTest, AtomicAddWithNonStorageVariable)
5726 {
5727     const std::string &shaderString =
5728         R"(#version 310 es
5729 
5730         void main()
5731         {
5732             uint test = 1u;
5733             atomicAdd(test, 2u);
5734         })";
5735 
5736     if (compile(shaderString))
5737     {
5738         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5739     }
5740 }
5741 
5742 // Test that it is acceptable to pass a swizzle of a member of a shader storage block to the mem
5743 // argument of an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithSwizzle)5744 TEST_F(FragmentShaderValidationTest, AtomicAddWithSwizzle)
5745 {
5746     const std::string &shaderString =
5747         R"(#version 310 es
5748 
5749         layout(std140) buffer bufferName{
5750             uvec4 u1[2];
5751         } instanceName[3];
5752 
5753         void main()
5754         {
5755             atomicAdd(instanceName[2].u1[1].y, 2u);
5756         })";
5757 
5758     if (!compile(shaderString))
5759     {
5760         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5761     }
5762 }
5763 
5764 // Test that it is not allowed to pass an expression that does not constitute of indexing, field
5765 // selection or swizzle to the mem argument of an atomic memory function.
TEST_F(FragmentShaderValidationTest,AtomicAddWithNonIndexNonSwizzleExpression)5766 TEST_F(FragmentShaderValidationTest, AtomicAddWithNonIndexNonSwizzleExpression)
5767 {
5768     const std::string &shaderString =
5769         R"(#version 310 es
5770 
5771         layout(std140) buffer bufferName{
5772             uint u1[2];
5773         } instanceName[3];
5774 
5775         void main()
5776         {
5777             atomicAdd(instanceName[2].u1[1] + 1u, 2u);
5778         })";
5779 
5780     if (compile(shaderString))
5781     {
5782         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5783     }
5784 }
5785 
5786 // Test that negative indexing of a matrix doesn't result in an assert.
TEST_F(FragmentShaderValidationTest,MatrixNegativeIndex)5787 TEST_F(FragmentShaderValidationTest, MatrixNegativeIndex)
5788 {
5789     const std::string &shaderString =
5790         R"(
5791         precision mediump float;
5792 
5793         void main()
5794         {
5795             gl_FragColor = mat4(1.0)[-1];
5796         })";
5797 
5798     if (compile(shaderString))
5799     {
5800         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5801     }
5802 }
5803 
5804 // Global variable initializers need to be constant expressions. Test with assigning a ternary
5805 // expression that ANGLE can fold.
TEST_F(FragmentShaderValidationTest,AssignConstantFoldedFromNonConstantTernaryToGlobal)5806 TEST_F(FragmentShaderValidationTest, AssignConstantFoldedFromNonConstantTernaryToGlobal)
5807 {
5808     const std::string &shaderString =
5809         R"(#version 300 es
5810         precision mediump float;
5811 
5812         uniform float u;
5813         float f = true ? 1.0 : u;
5814 
5815         out vec4 my_FragColor;
5816 
5817         void main()
5818         {
5819            my_FragColor = vec4(f);
5820         })";
5821     if (compile(shaderString))
5822     {
5823         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5824     }
5825 }
5826 
5827 // Global variable initializers need to be constant expressions. Test with assigning a ternary
5828 // expression that ANGLE can fold.
TEST_F(FragmentShaderValidationTest,AssignConstantArrayVariableFoldedFromNonConstantTernaryToGlobal)5829 TEST_F(FragmentShaderValidationTest,
5830        AssignConstantArrayVariableFoldedFromNonConstantTernaryToGlobal)
5831 {
5832     const std::string &shaderString =
5833         R"(#version 300 es
5834         precision mediump float;
5835 
5836         uniform float u[2];
5837         const float c[2] = float[2](1.0, 2.0);
5838         float f[2] = true ? c : u;
5839 
5840         out vec4 my_FragColor;
5841 
5842         void main()
5843         {
5844            my_FragColor = vec4(f[0], f[1], 0.0, 1.0);
5845         })";
5846     if (compile(shaderString))
5847     {
5848         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5849     }
5850 }
5851 
5852 // Test going past the struct nesting limit while simultaneously using invalid nested struct
5853 // definitions. This makes sure that the code generating an error message about going past the
5854 // struct nesting limit does not access the name of a nameless struct definition.
TEST_F(WebGL1FragmentShaderValidationTest,StructNestingLimitWithNestedStructDefinitions)5855 TEST_F(WebGL1FragmentShaderValidationTest, StructNestingLimitWithNestedStructDefinitions)
5856 {
5857     const std::string &shaderString =
5858         R"(
5859         precision mediump float;
5860 
5861         struct
5862         {
5863             struct
5864             {
5865                 struct
5866                 {
5867                     struct
5868                     {
5869                         struct
5870                         {
5871                             struct
5872                             {
5873                                 float f;
5874                             } s5;
5875                         } s4;
5876                     } s3;
5877                 } s2;
5878             } s1;
5879         } s0;
5880 
5881         void main(void)
5882         {
5883             gl_FragColor = vec4(s0.s1.s2.s3.s4.s5.f);
5884         })";
5885     if (compile(shaderString))
5886     {
5887         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5888     }
5889 }
5890 
5891 // Test that the result of a sequence operator is not a constant-expression.
5892 // ESSL 3.00 section 12.43.
TEST_F(FragmentShaderValidationTest,CommaReturnsNonConstant)5893 TEST_F(FragmentShaderValidationTest, CommaReturnsNonConstant)
5894 {
5895     const std::string &shaderString =
5896         R"(#version 300 es
5897 
5898         precision highp float;
5899         out vec4 my_FragColor;
5900 
5901         void main(void)
5902         {
5903             const int i = (0, 0);
5904             my_FragColor = vec4(i);
5905         })";
5906     if (compile(shaderString))
5907     {
5908         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5909     }
5910 }
5911 
5912 // Test that the result of indexing into an array constructor with some non-constant arguments is
5913 // not a constant expression.
TEST_F(FragmentShaderValidationTest,IndexingIntoArrayConstructorWithNonConstantArgumentsIsNotConstantExpression)5914 TEST_F(FragmentShaderValidationTest,
5915        IndexingIntoArrayConstructorWithNonConstantArgumentsIsNotConstantExpression)
5916 {
5917     const std::string &shaderString =
5918         R"(#version 310 es
5919         precision highp float;
5920         uniform float u;
5921         out float my_FragColor;
5922         void main()
5923         {
5924             const float f = float[2](u, 1.0)[1];
5925             my_FragColor = f;
5926         })";
5927     if (compile(shaderString))
5928     {
5929         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5930     }
5931 }
5932 
5933 // Test that the type of an initializer of a constant variable needs to match.
TEST_F(FragmentShaderValidationTest,ConstantInitializerTypeMismatch)5934 TEST_F(FragmentShaderValidationTest, ConstantInitializerTypeMismatch)
5935 {
5936     const std::string &shaderString =
5937         R"(
5938         precision mediump float;
5939         const float f = 0;
5940 
5941         void main()
5942         {
5943             gl_FragColor = vec4(f);
5944         })";
5945     if (compile(shaderString))
5946     {
5947         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5948     }
5949 }
5950 
5951 // Test that redeclaring a built-in is an error in ESSL 1.00. ESSL 1.00.17 section 4.2.6 disallows
5952 // "redefinition" of built-ins - it's not very explicit about redeclaring them, but we treat this as
5953 // an error. The redeclaration cannot serve any purpose since it can't be accompanied by a
5954 // definition.
TEST_F(FragmentShaderValidationTest,RedeclaringBuiltIn)5955 TEST_F(FragmentShaderValidationTest, RedeclaringBuiltIn)
5956 {
5957     const std::string &shaderString =
5958         R"(
5959         precision mediump float;
5960         float sin(float x);
5961 
5962         void main()
5963         {
5964             gl_FragColor = vec4(0.0);
5965         })";
5966     if (compile(shaderString))
5967     {
5968         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
5969     }
5970 }
5971 
5972 // Redefining a built-in that is not available in the current shader stage is assumed to be not an
5973 // error. Test with redefining groupMemoryBarrier() in fragment shader. The built-in
5974 // groupMemoryBarrier() is only available in compute shaders.
TEST_F(FragmentShaderValidationTest,RedeclaringBuiltInFromAnotherShaderStage)5975 TEST_F(FragmentShaderValidationTest, RedeclaringBuiltInFromAnotherShaderStage)
5976 {
5977     const std::string &shaderString =
5978         R"(#version 310 es
5979         precision mediump float;
5980         out vec4 my_FragColor;
5981         float groupMemoryBarrier() { return 1.0; }
5982 
5983         void main()
5984         {
5985             my_FragColor = vec4(groupMemoryBarrier());
5986         })";
5987     if (!compile(shaderString))
5988     {
5989         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
5990     }
5991 }
5992 
5993 // Test that standard derivative functions that are in core ESSL 3.00 compile successfully.
TEST_F(FragmentShaderValidationTest,ESSL300StandardDerivatives)5994 TEST_F(FragmentShaderValidationTest, ESSL300StandardDerivatives)
5995 {
5996     const std::string &shaderString =
5997         R"(#version 300 es
5998         precision mediump float;
5999         in vec4 iv;
6000         out vec4 my_FragColor;
6001 
6002         void main()
6003         {
6004             vec4 v4 = vec4(0.0);
6005             v4 += fwidth(iv);
6006             v4 += dFdx(iv);
6007             v4 += dFdy(iv);
6008             my_FragColor = v4;
6009         })";
6010     if (!compile(shaderString))
6011     {
6012         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6013     }
6014 }
6015 
6016 // Test that vertex shader built-in gl_Position is not accessible in fragment shader.
TEST_F(FragmentShaderValidationTest,GlPosition)6017 TEST_F(FragmentShaderValidationTest, GlPosition)
6018 {
6019     const std::string &shaderString =
6020         R"(#version 300 es
6021         precision mediump float;
6022         in vec4 iv;
6023         out vec4 my_FragColor;
6024 
6025         void main()
6026         {
6027             gl_Position = iv;
6028             my_FragColor = iv;
6029         })";
6030     if (compile(shaderString))
6031     {
6032         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6033     }
6034 }
6035 
6036 // Test that compute shader built-in gl_LocalInvocationID is not accessible in fragment shader.
TEST_F(FragmentShaderValidationTest,GlLocalInvocationID)6037 TEST_F(FragmentShaderValidationTest, GlLocalInvocationID)
6038 {
6039     const std::string &shaderString =
6040         R"(#version 310 es
6041         precision mediump float;
6042         out vec3 my_FragColor;
6043 
6044         void main()
6045         {
6046             my_FragColor = vec3(gl_LocalInvocationID);
6047         })";
6048     if (compile(shaderString))
6049     {
6050         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6051     }
6052 }
6053 
6054 // Test that fragment shader built-in gl_FragCoord is not accessible in vertex shader.
TEST_F(VertexShaderValidationTest,GlFragCoord)6055 TEST_F(VertexShaderValidationTest, GlFragCoord)
6056 {
6057     const std::string &shaderString =
6058         R"(#version 300 es
6059         precision mediump float;
6060 
6061         void main()
6062         {
6063             gl_Position = vec4(gl_FragCoord);
6064         })";
6065     if (compile(shaderString))
6066     {
6067         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6068     }
6069 }
6070 
6071 // Test that a long sequence of repeated swizzling on an l-value does not cause a stack overflow.
TEST_F(VertexShaderValidationTest,LValueRepeatedSwizzle)6072 TEST_F(VertexShaderValidationTest, LValueRepeatedSwizzle)
6073 {
6074     std::stringstream shaderString;
6075     shaderString << R"(#version 300 es
6076         precision mediump float;
6077 
6078         uniform vec2 u;
6079 
6080         void main()
6081         {
6082             vec2 f;
6083             f)";
6084     for (int i = 0; i < 1000; ++i)
6085     {
6086         shaderString << ".yx.yx";
6087     }
6088     shaderString << R"( = vec2(0.0);
6089         })";
6090 
6091     if (!compile(shaderString.str()))
6092     {
6093         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6094     }
6095 }
6096 
6097 // Test that swizzling that contains duplicate components can't form an l-value, even if it is
6098 // swizzled again so that the final result does not contain duplicate components.
TEST_F(VertexShaderValidationTest,LValueSwizzleDuplicateComponents)6099 TEST_F(VertexShaderValidationTest, LValueSwizzleDuplicateComponents)
6100 {
6101 
6102     const std::string &shaderString = R"(#version 300 es
6103         precision mediump float;
6104 
6105         void main()
6106         {
6107             vec2 f;
6108             (f.xxyy).xz = vec2(0.0);
6109         })";
6110 
6111     if (compile(shaderString))
6112     {
6113         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6114     }
6115 }
6116 
6117 // Test that a fragment shader with nested if statements without braces compiles successfully.
TEST_F(FragmentShaderValidationTest,HandleIfInnerIfStatementAlwaysTriviallyPruned)6118 TEST_F(FragmentShaderValidationTest, HandleIfInnerIfStatementAlwaysTriviallyPruned)
6119 {
6120     const std::string &shaderString =
6121         R"(precision mediump float;
6122         void main()
6123         {
6124             if (true)
6125                 if (false)
6126                     gl_FragColor = vec4(0.0);
6127         })";
6128     if (!compile(shaderString))
6129     {
6130         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6131     }
6132 }
6133 
6134 // Test that a fragment shader with an if statement nested in a loop without braces compiles
6135 // successfully.
TEST_F(FragmentShaderValidationTest,HandleLoopInnerIfStatementAlwaysTriviallyPruned)6136 TEST_F(FragmentShaderValidationTest, HandleLoopInnerIfStatementAlwaysTriviallyPruned)
6137 {
6138     const std::string &shaderString =
6139         R"(precision mediump float;
6140         void main()
6141         {
6142             while (false)
6143                 if (false)
6144                     gl_FragColor = vec4(0.0);
6145         })";
6146     if (!compile(shaderString))
6147     {
6148         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6149     }
6150 }
6151 
6152 // Test that declaring both gl_FragColor and gl_FragData invariant is not an error. The GLSL ES 1.00
6153 // spec only disallows writing to both of them. ANGLE extends this validation to also cover reads,
6154 // but it makes sense not to treat declaring them both invariant as an error.
TEST_F(FragmentShaderValidationTest,DeclareBothBuiltInFragmentOutputsInvariant)6155 TEST_F(FragmentShaderValidationTest, DeclareBothBuiltInFragmentOutputsInvariant)
6156 {
6157     const std::string &shaderString =
6158         R"(
6159         invariant gl_FragColor;
6160         invariant gl_FragData;
6161         precision mediump float;
6162         void main()
6163         {
6164             gl_FragColor = vec4(0.0);
6165         })";
6166     if (!compile(shaderString))
6167     {
6168         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6169     }
6170 }
6171 
6172 // Test that a case cannot be placed inside a block nested inside a switch statement. GLSL ES 3.10
6173 // section 6.2.
TEST_F(FragmentShaderValidationTest,CaseInsideBlock)6174 TEST_F(FragmentShaderValidationTest, CaseInsideBlock)
6175 {
6176     const std::string &shaderString =
6177         R"(#version 300 es
6178         precision mediump float;
6179         uniform int u;
6180         out vec4 my_FragColor;
6181         void main()
6182         {
6183             switch (u)
6184             {
6185                 case 1:
6186                 {
6187                     case 0:
6188                         my_FragColor = vec4(0.0);
6189                 }
6190                 default:
6191                     my_FragColor = vec4(1.0);
6192             }
6193         })";
6194     if (compile(shaderString))
6195     {
6196         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6197     }
6198 }
6199 
6200 // Test using a value from a constant array as a case label.
TEST_F(FragmentShaderValidationTest,ValueFromConstantArrayAsCaseLabel)6201 TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsCaseLabel)
6202 {
6203     const std::string &shaderString =
6204         R"(#version 300 es
6205         precision mediump float;
6206         uniform int u;
6207         const int[3] arr = int[3](2, 1, 0);
6208         out vec4 my_FragColor;
6209         void main()
6210         {
6211             switch (u)
6212             {
6213                 case arr[1]:
6214                     my_FragColor = vec4(0.0);
6215                 case 2:
6216                 case 0:
6217                 default:
6218                     my_FragColor = vec4(1.0);
6219             }
6220         })";
6221     if (!compile(shaderString))
6222     {
6223         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6224     }
6225 }
6226 
6227 // Test using a value from a constant array as a fragment output index.
TEST_F(FragmentShaderValidationTest,ValueFromConstantArrayAsFragmentOutputIndex)6228 TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsFragmentOutputIndex)
6229 {
6230     const std::string &shaderString =
6231         R"(#version 300 es
6232         precision mediump float;
6233         uniform int u;
6234         const int[3] arr = int[3](4, 1, 0);
6235         out vec4 my_FragData[2];
6236         void main()
6237         {
6238             my_FragData[arr[1]] = vec4(0.0);
6239             my_FragData[arr[2]] = vec4(0.0);
6240         })";
6241     if (!compile(shaderString))
6242     {
6243         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6244     }
6245 }
6246 
6247 // Test using a value from a constant array as an array size.
TEST_F(FragmentShaderValidationTest,ValueFromConstantArrayAsArraySize)6248 TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsArraySize)
6249 {
6250     const std::string &shaderString =
6251         R"(#version 300 es
6252         precision mediump float;
6253         uniform int u;
6254         const int[3] arr = int[3](0, 2, 0);
6255         const int[arr[1]] arr2 = int[2](2, 1);
6256         out vec4 my_FragColor;
6257         void main()
6258         {
6259             my_FragColor = vec4(arr2[1]);
6260         })";
6261     if (!compile(shaderString))
6262     {
6263         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6264     }
6265 }
6266 
6267 // Test that an invalid struct with void fields doesn't crash or assert when used in a comma
6268 // operator. This is a regression test.
TEST_F(FragmentShaderValidationTest,InvalidStructWithVoidFieldsInComma)6269 TEST_F(FragmentShaderValidationTest, InvalidStructWithVoidFieldsInComma)
6270 {
6271     // The struct needed the two fields for the bug to repro.
6272     const std::string &shaderString =
6273         R"(#version 300 es
6274 precision highp float;
6275 
6276 struct T { void a[8], c; };
6277 
6278 void main() {
6279     0.0, T();
6280 })";
6281     if (compile(shaderString))
6282     {
6283         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6284     }
6285 }
6286 
6287 // Test that layout(early_fragment_tests) in; is valid in fragment shader
TEST_F(FragmentShaderValidationTest,ValidEarlyFragmentTests)6288 TEST_F(FragmentShaderValidationTest, ValidEarlyFragmentTests)
6289 {
6290     constexpr char kShaderString[] =
6291         R"(#version 310 es
6292         precision mediump float;
6293         layout(early_fragment_tests) in;
6294         out vec4 color;
6295         void main()
6296         {
6297             color = vec4(0.0);
6298         })";
6299     if (!compile(kShaderString))
6300     {
6301         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6302     }
6303 }
6304 
6305 // Test that layout(early_fragment_tests=x) in; is invalid
TEST_F(FragmentShaderValidationTest,InvalidValueForEarlyFragmentTests)6306 TEST_F(FragmentShaderValidationTest, InvalidValueForEarlyFragmentTests)
6307 {
6308     constexpr char kShaderString[] =
6309         R"(#version 310 es
6310         precision mediump float;
6311         layout(early_fragment_tests=1) in;
6312         out vec4 color;
6313         void main()
6314         {
6315             color = vec4(0.0);
6316         })";
6317     if (compile(kShaderString))
6318     {
6319         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6320     }
6321 }
6322 
6323 // Test that layout(early_fragment_tests) in varying; is invalid
TEST_F(FragmentShaderValidationTest,InvalidEarlyFragmentTestsOnVariableDecl)6324 TEST_F(FragmentShaderValidationTest, InvalidEarlyFragmentTestsOnVariableDecl)
6325 {
6326     constexpr char kShaderString[] =
6327         R"(#version 310 es
6328         precision mediump float;
6329         layout(early_fragment_tests) in vec4 v;
6330         out vec4 color;
6331         void main()
6332         {
6333             color = v;
6334         })";
6335     if (compile(kShaderString))
6336     {
6337         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6338     }
6339 }
6340 
6341 // Test that layout(early_fragment_tests) in; is invalid in vertex shader
TEST_F(VertexShaderValidationTest,InvalidEarlyFragmentTests)6342 TEST_F(VertexShaderValidationTest, InvalidEarlyFragmentTests)
6343 {
6344     constexpr char kShaderString[] =
6345         R"(#version 310 es
6346         layout(early_fragment_tests) in;
6347         void main()
6348         {
6349             gl_Position = vec4(0.0);
6350         })";
6351     if (compile(kShaderString))
6352     {
6353         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6354     }
6355 }
6356 
6357 // Test that layout(early_fragment_tests) in; is invalid in compute shader
TEST_F(ComputeShaderValidationTest,InvalidEarlyFragmentTests)6358 TEST_F(ComputeShaderValidationTest, InvalidEarlyFragmentTests)
6359 {
6360     constexpr char kShaderString[] =
6361         R"(#version 310 es
6362         layout(local_size_x = 1) in;
6363         layout(early_fragment_tests) in;
6364         void main() {})";
6365     if (compile(kShaderString))
6366     {
6367         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6368     }
6369 }
6370 
6371 // Test that layout(x) in; only accepts x=early_fragment_tests.
TEST_F(FragmentShaderValidationTest,NothingButEarlyFragmentTestsWithInWithoutVariableDecl)6372 TEST_F(FragmentShaderValidationTest, NothingButEarlyFragmentTestsWithInWithoutVariableDecl)
6373 {
6374     const char *noValueQualifiers[] = {
6375         "shared",      "packed",
6376         "std140",      "std430",
6377         "row_major",   "col_major",
6378         "location",    "yuv",
6379         "rgba32f",     "rgba16f",
6380         "r32f",        "rgba8",
6381         "rgba8_snorm", "rgba32i",
6382         "rgba16i",     "rgba8i",
6383         "r32i",        "rgba32ui",
6384         "rgba16ui",    "rgba8ui",
6385         "r32ui",       "points",
6386         "lines",       "lines_adjacency",
6387         "triangles",   "triangles_adjacency",
6388         "line_strip",  "triangle_strip",
6389     };
6390 
6391     const char *withValueQualifiers[] = {
6392         "location",     "binding",   "offset",      "local_size_x", "local_size_y",
6393         "local_size_z", "num_views", "invocations", "max_vertices", "index",
6394     };
6395 
6396     constexpr char kShaderStringPre[] =
6397         R"(#version 310 es
6398         precision mediump float;
6399         layout()";
6400     constexpr char kShaderStringPost[] =
6401         R"() in;
6402         out vec4 color;
6403         void main()
6404         {
6405             color = vec4(0.0);
6406         })";
6407 
6408     // Make sure the method of constructing shaders is valid.
6409     const std::string validShaderString =
6410         kShaderStringPre + std::string("early_fragment_tests") + kShaderStringPost;
6411     if (!compile(validShaderString))
6412     {
6413         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
6414     }
6415 
6416     for (size_t i = 0; i < ArraySize(noValueQualifiers); ++i)
6417     {
6418         const std::string shaderString =
6419             kShaderStringPre + std::string(noValueQualifiers[i]) + kShaderStringPost;
6420 
6421         if (compile(shaderString))
6422         {
6423             FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6424         }
6425     }
6426 
6427     for (size_t i = 0; i < ArraySize(withValueQualifiers); ++i)
6428     {
6429         const std::string shaderString =
6430             kShaderStringPre + std::string(withValueQualifiers[i]) + "=1" + kShaderStringPost;
6431 
6432         if (compile(shaderString))
6433         {
6434             FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
6435         }
6436     }
6437 }
6438