1 //
2 // Copyright 2016 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 // QualificationOrder_test.cpp:
7 // OpenGL ES 3.1 removes the strict order of qualifiers imposed by the grammar.
8 // This file contains tests for invalid order and usage of qualifiers.
9
10 #include "tests/test_utils/ShaderCompileTreeTest.h"
11
12 using namespace sh;
13
14 class QualificationOrderFragmentShaderTest : public ShaderCompileTreeTest
15 {
16 public:
QualificationOrderFragmentShaderTest()17 QualificationOrderFragmentShaderTest() {}
18
19 protected:
initResources(ShBuiltInResources * resources)20 void initResources(ShBuiltInResources *resources) override
21 {
22 resources->MaxDrawBuffers = (getShaderSpec() == SH_GLES2_SPEC) ? 1 : 8;
23 }
24
getShaderType() const25 ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
26
getShaderSpec() const27 ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
28 };
29
30 class QualificationOrderVertexShaderTest : public QualificationOrderFragmentShaderTest
31 {
32 public:
QualificationOrderVertexShaderTest()33 QualificationOrderVertexShaderTest() {}
34
35 protected:
getShaderType() const36 ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
37 };
38
39 // Repeating centroid qualifier is invalid.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingCentroid)40 TEST_F(QualificationOrderFragmentShaderTest, RepeatingCentroid)
41 {
42 const std::string &shaderString =
43 "#version 300 es\n"
44 "precision mediump float;\n"
45 "flat centroid centroid in float myValue;\n"
46 "void main() {\n"
47 "}\n";
48
49 if (compile(shaderString))
50 {
51 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
52 }
53 }
54
55 // Repeating uniform storage qualifiers is invalid.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingUniforms)56 TEST_F(QualificationOrderFragmentShaderTest, RepeatingUniforms)
57 {
58 const std::string &shaderString =
59 "#version 300 es\n"
60 "precision mediump float;\n"
61 "uniform uniform float myValue;\n"
62 "void main() {\n"
63 "}\n";
64
65 if (compile(shaderString))
66 {
67 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
68 }
69 }
70
71 // Repeating varying storage qualifiers is invalid.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingVaryings)72 TEST_F(QualificationOrderFragmentShaderTest, RepeatingVaryings)
73 {
74 const std::string &shaderString =
75 "precision mediump float;\n"
76 "varying varying vec4 myColor;\n"
77 "void main() {\n"
78 "}\n";
79
80 if (compile(shaderString))
81 {
82 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
83 }
84 }
85
86 // Layout qualifier should be before the storage qualifiers.
TEST_F(QualificationOrderFragmentShaderTest,WrongOrderQualifiers)87 TEST_F(QualificationOrderFragmentShaderTest, WrongOrderQualifiers)
88 {
89 const std::string &shaderString =
90 "#version 300 es\n"
91 "precision mediump float;\n"
92 "out layout(location=1) vec4 myColor;\n"
93 "void main() {\n"
94 "}\n";
95
96 if (compile(shaderString))
97 {
98 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
99 }
100 }
101
102 // Centroid out is the correct order. Out centroid is incorrect.
TEST_F(QualificationOrderVertexShaderTest,WrongOrderCentroidOut)103 TEST_F(QualificationOrderVertexShaderTest, WrongOrderCentroidOut)
104 {
105 const std::string &shaderString =
106 "#version 300 es\n"
107 "precision mediump float;\n"
108 "in vec4 uv;\n"
109 "out centroid vec4 position;\n"
110 "void main() {\n"
111 "position = uv;\n"
112 "gl_Position = uv;\n"
113 "}\n";
114
115 if (compile(shaderString))
116 {
117 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
118 }
119 }
120
121 // Centroid in is the correct order. In centroid is incorrect.
TEST_F(QualificationOrderFragmentShaderTest,WrongOrderCentroidIn)122 TEST_F(QualificationOrderFragmentShaderTest, WrongOrderCentroidIn)
123 {
124 const std::string &shaderString =
125 "#version 300 es\n"
126 "precision mediump float;\n"
127 "in centroid vec4 colorIN;\n"
128 "out vec4 colorOUT;\n"
129 "void main() {\n"
130 "colorOUT = colorIN;\n"
131 "}\n";
132
133 if (compile(shaderString))
134 {
135 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
136 }
137 }
138
139 // Type cannot be before the storage qualifier.
TEST_F(QualificationOrderFragmentShaderTest,WrongOrderTypeStorage)140 TEST_F(QualificationOrderFragmentShaderTest, WrongOrderTypeStorage)
141 {
142 const std::string &shaderString =
143 "#version 300 es\n"
144 "precision mediump float;\n"
145 "centroid in vec4 colorIN;\n"
146 "vec4 out colorOUT;\n"
147 "void main() {\n"
148 "colorOUT = colorIN;\n"
149 "}\n";
150
151 if (compile(shaderString))
152 {
153 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
154 }
155 }
156
157 // A variable cannot have two conflicting storage qualifiers.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingDifferentStorageQualifiers)158 TEST_F(QualificationOrderFragmentShaderTest, RepeatingDifferentStorageQualifiers)
159 {
160 const std::string &shaderString =
161 "#version 300 es\n"
162 "precision mediump float;\n"
163 "centroid in vec4 colorIN;\n"
164 "uniform out vec4 colorOUT;\n"
165 "void main() {\n"
166 "colorOUT = colorIN;\n"
167 "}\n";
168
169 if (compile(shaderString))
170 {
171 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
172 }
173 }
174
175 // A variable cannot have two different layout qualifiers.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingLayoutQualifiers)176 TEST_F(QualificationOrderFragmentShaderTest, RepeatingLayoutQualifiers)
177 {
178 const std::string &shaderString =
179 "#version 300 es\n"
180 "precision mediump float;\n"
181 "in vec4 colorIN;\n"
182 "layout(location=0) layout(location=0) out vec4 colorOUT;\n"
183 "void main() {\n"
184 "colorOUT = colorIN;\n"
185 "}\n";
186
187 if (compile(shaderString))
188 {
189 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
190 }
191 }
192
193 // A variable cannot have repeating invariant qualifiers.
TEST_F(QualificationOrderFragmentShaderTest,RepeatingInvariantQualifiers)194 TEST_F(QualificationOrderFragmentShaderTest, RepeatingInvariantQualifiers)
195 {
196 const std::string &shaderString =
197 "#version 300 es\n"
198 "precision mediump float;\n"
199 "in vec4 colorIN;\n"
200 "invariant invariant out vec4 colorOUT;\n"
201 "void main() {\n"
202 "colorOUT = colorIN;\n"
203 "}\n";
204
205 if (compile(shaderString))
206 {
207 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
208 }
209 }
210
211 // A variable cannot have repeating storage qualifiers.
TEST_F(QualificationOrderVertexShaderTest,RepeatingAttributes)212 TEST_F(QualificationOrderVertexShaderTest, RepeatingAttributes)
213 {
214 const std::string &shaderString =
215 "precision mediump float;\n"
216 "attribute attribute vec4 positionIN;\n"
217 "void main() {\n"
218 "gl_Position = positionIN;\n"
219 "}\n";
220
221 if (compile(shaderString))
222 {
223 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
224 }
225 }
226
227 // Wrong order for invariant varying. It should be 'invariant varying', not 'varying invariant'.
TEST_F(QualificationOrderVertexShaderTest,VaryingInvariantWrongOrder)228 TEST_F(QualificationOrderVertexShaderTest, VaryingInvariantWrongOrder)
229 {
230 const std::string &shaderString =
231 "precision mediump float;\n"
232 "attribute vec4 positionIN;\n"
233 "varying invariant vec4 dataOUT;\n"
234 "void main() {\n"
235 "gl_Position = positionIN;\n"
236 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
237 "}\n";
238
239 if (compile(shaderString))
240 {
241 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
242 }
243 }
244
245 // A variable cannot have repeating storage qualifiers.
TEST_F(QualificationOrderVertexShaderTest,AttributeVaryingMix)246 TEST_F(QualificationOrderVertexShaderTest, AttributeVaryingMix)
247 {
248 const std::string &shaderString =
249 "precision mediump float;\n"
250 "attribute varying vec4 positionIN;\n"
251 "void main() {\n"
252 "gl_Position = positionIN;\n"
253 "}\n";
254
255 if (compile(shaderString))
256 {
257 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
258 }
259 }
260
261 // A variable cannot have repeating storage qualifiers.
TEST_F(QualificationOrderVertexShaderTest,VaryingAttributeMix)262 TEST_F(QualificationOrderVertexShaderTest, VaryingAttributeMix)
263 {
264 const std::string &shaderString =
265 "precision mediump float;\n"
266 "varying attribute vec4 positionIN;\n"
267 "void main() {\n"
268 "gl_Position = positionIN;\n"
269 "}\n";
270 if (compile(shaderString))
271 {
272 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
273 }
274 }
275
276 // A variable cannot have repeating interpolation qualifiers.
TEST_F(QualificationOrderVertexShaderTest,RepeatingInterpolationQualifiers)277 TEST_F(QualificationOrderVertexShaderTest, RepeatingInterpolationQualifiers)
278 {
279 const std::string &shaderString =
280 "#version 300 es\n"
281 "precision mediump float;\n"
282 "in vec4 positionIN;\n"
283 "flat flat out vec4 dataOUT;\n"
284 "void main() {\n"
285 "gl_Position = positionIN;\n"
286 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
287 "}\n";
288
289 if (compile(shaderString))
290 {
291 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
292 }
293 }
294
295 // Wrong order for the interpolation and storage qualifier. The correct order is interpolation
296 // qualifier and then storage qualifier.
TEST_F(QualificationOrderVertexShaderTest,WrongOrderInterpolationStorageQualifiers)297 TEST_F(QualificationOrderVertexShaderTest, WrongOrderInterpolationStorageQualifiers)
298 {
299 const std::string &shaderString =
300 "#version 300 es\n"
301 "precision mediump float;\n"
302 "in vec4 positionIN;\n"
303 "out flat vec4 dataOUT;\n"
304 "void main() {\n"
305 "gl_Position = positionIN;\n"
306 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
307 "}\n";
308
309 if (compile(shaderString))
310 {
311 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
312 }
313 }
314
315 // The correct order is invariant, interpolation, storage.
TEST_F(QualificationOrderVertexShaderTest,WrongOrderInvariantInterpolationStorageQualifiers)316 TEST_F(QualificationOrderVertexShaderTest, WrongOrderInvariantInterpolationStorageQualifiers)
317 {
318 const std::string &shaderString =
319 "#version 300 es\n"
320 "precision mediump float;\n"
321 "in vec4 positionIN;\n"
322 "flat invariant out vec4 dataOUT;\n"
323 "void main() {\n"
324 "gl_Position = positionIN;\n"
325 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
326 "}\n";
327
328 if (compile(shaderString))
329 {
330 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
331 }
332 }
333
334 // The invariant qualifer has to be before the storage qualifiers.
TEST_F(QualificationOrderVertexShaderTest,WrongOrderInvariantNotFirst)335 TEST_F(QualificationOrderVertexShaderTest, WrongOrderInvariantNotFirst)
336 {
337 const std::string &shaderString =
338 "#version 300 es\n"
339 "precision mediump float;\n"
340 "in vec4 positionIN;\n"
341 "centroid out invariant vec4 dataOUT;\n"
342 "void main() {\n"
343 "gl_Position = positionIN;\n"
344 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
345 "}\n";
346
347 if (compile(shaderString))
348 {
349 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
350 }
351 }
352
353 // The precision qualifier is after the storage qualifiers.
TEST_F(QualificationOrderVertexShaderTest,WrongOrderPrecision)354 TEST_F(QualificationOrderVertexShaderTest, WrongOrderPrecision)
355 {
356 const std::string &shaderString =
357 "#version 300 es\n"
358 "precision mediump float;\n"
359 "in vec4 positionIN;\n"
360 "highp centroid out vec4 dataOUT;\n"
361 "void main() {\n"
362 "gl_Position = positionIN;\n"
363 "dataOUT = 0.5 * dataOUT + vec4(0.5);\n"
364 "}\n";
365
366 if (compile(shaderString))
367 {
368 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
369 }
370 }
371
372 // A variable cannot have multiple declarations of the 'in' storage qualifier.
TEST_F(QualificationOrderVertexShaderTest,RepeatingInQualifier)373 TEST_F(QualificationOrderVertexShaderTest, RepeatingInQualifier)
374 {
375 const std::string &shaderString =
376 "#version 300 es\n"
377 "precision mediump float;\n"
378 "in in vec4 positionIN;\n"
379 "void main() {\n"
380 "gl_Position = positionIN;\n"
381 "}\n";
382
383 if (compile(shaderString))
384 {
385 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
386 }
387 }
388
389 // A variable cannot have multiple declarations of the 'attribute' storage qualifier.
TEST_F(QualificationOrderVertexShaderTest,RepeatingAttributeQualifier)390 TEST_F(QualificationOrderVertexShaderTest, RepeatingAttributeQualifier)
391 {
392 const std::string &shaderString =
393 "precision mediump float;\n"
394 "attribute attribute vec4 positionIN;\n"
395 "void main() {\n"
396 "gl_Position = positionIN;\n"
397 "}\n";
398
399 if (compile(shaderString))
400 {
401 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
402 }
403 }
404
405 // Vertex input cannot be qualified with invariant.
TEST_F(QualificationOrderVertexShaderTest,InvariantVertexInput)406 TEST_F(QualificationOrderVertexShaderTest, InvariantVertexInput)
407 {
408 const std::string &shaderString =
409 "precision mediump float;\n"
410 "invariant attribute vec4 positionIN;\n"
411 "void main() {\n"
412 "gl_Position = positionIN;\n"
413 "}\n";
414
415 if (compile(shaderString))
416 {
417 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
418 }
419 }
420
421 // Cannot have a function parameter with the invariant qualifier.
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersInvariant)422 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersInvariant)
423 {
424 const std::string &shaderString =
425 "precision lowp float;\n"
426 "varying float value;\n"
427 "float foo0 (invariant in float x) {\n"
428 " return 2.0*x;\n"
429 "}\n"
430 "void main()\n"
431 "{\n"
432 " gl_FragColor = vec4(foo0(value));\n"
433 "}\n";
434
435 if (compile(shaderString))
436 {
437 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
438 }
439 }
440
441 // Cannot have a function parameter with the attribute qualifier.
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersAttribute)442 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersAttribute)
443 {
444 const std::string &shaderString =
445 "precision lowp float;\n"
446 "varying float value;\n"
447 "float foo0 (attribute float x) {\n"
448 " return 2.0*x;\n"
449 "}\n"
450 "void main()\n"
451 "{\n"
452 " gl_FragColor = vec4(foo0(value));\n"
453 "}\n";
454
455 if (compile(shaderString))
456 {
457 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
458 }
459 }
460
461 // Cannot have a function parameter with the varying qualifier.
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersVarying)462 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersVarying)
463 {
464 const std::string &shaderString =
465 "precision lowp float;\n"
466 "varying float value;\n"
467 "float foo0 (varying float x) {\n"
468 " return 2.0*x;\n"
469 "}\n"
470 "void main()\n"
471 "{\n"
472 " gl_FragColor = vec4(foo0(value));\n"
473 "}\n";
474
475 if (compile(shaderString))
476 {
477 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
478 }
479 }
480
481 // Cannot have a function parameter with the layout qualifier
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersLayout)482 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersLayout)
483 {
484 const std::string &shaderString =
485 "#version 300 es\n"
486 "precision lowp float;\n"
487 "in float value;\n"
488 "float foo0 (layout(location = 3) in float x) {\n"
489 " return 2.0*x;\n"
490 "}\n"
491 "out vec4 colorOUT;\n"
492 "void main()\n"
493 "{\n"
494 " colorOUT = vec4(foo0(value));\n"
495 "}\n";
496
497 if (compile(shaderString))
498 {
499 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
500 }
501 }
502
503 // Cannot have a function parameter with the centroid qualifier
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersCentroidIn)504 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersCentroidIn)
505 {
506 const std::string &shaderString =
507 "#version 300 es\n"
508 "precision lowp float;\n"
509 "in float value;\n"
510 "float foo0 (centroid in float x) {\n"
511 " return 2.0*x;\n"
512 "}\n"
513 "out vec4 colorOUT;\n"
514 "void main()\n"
515 "{\n"
516 " colorOUT = vec4(foo0(value));\n"
517 "}\n";
518
519 if (compile(shaderString))
520 {
521 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
522 }
523 }
524
525 // Cannot have a function parameter with the flat qualifier
TEST_F(QualificationOrderFragmentShaderTest,InvalidFunctionParametersFlatIn)526 TEST_F(QualificationOrderFragmentShaderTest, InvalidFunctionParametersFlatIn)
527 {
528 const std::string &shaderString =
529 "#version 300 es\n"
530 "precision lowp float;\n"
531 "in float value;\n"
532 "float foo0 (flat in float x) {\n"
533 " return 2.0*x;\n"
534 "}\n"
535 "out vec4 colorOUT;\n"
536 "void main()\n"
537 "{\n"
538 " colorOUT = vec4(foo0(value));\n"
539 "}\n";
540
541 if (compile(shaderString))
542 {
543 FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
544 }
545 }
546
547 // Output layout location qualifier can't appear more than once within a declaration.
548 // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers.
TEST_F(QualificationOrderFragmentShaderTest,TwoOutputLocations)549 TEST_F(QualificationOrderFragmentShaderTest, TwoOutputLocations)
550 {
551 const std::string &shaderString =
552 "#version 300 es\n"
553 "precision mediump float;\n"
554 "layout(location=1, location=2) out vec4 myColor;\n"
555 "void main() {\n"
556 "}\n";
557
558 if (compile(shaderString))
559 {
560 FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
561 }
562 }
563