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