1 //
2 // Copyright 2017 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 // GeometryShader_test.cpp:
7 // tests for compiling a Geometry Shader
8 //
9
10 #include "GLSLANG/ShaderLang.h"
11 #include "angle_gl.h"
12 #include "compiler/translator/BaseTypes.h"
13 #include "gtest/gtest.h"
14 #include "tests/test_utils/ShaderCompileTreeTest.h"
15 #include "tests/test_utils/compiler_test.h"
16
17 using namespace sh;
18
19 class GeometryShaderTest : public ShaderCompileTreeTest
20 {
21 public:
GeometryShaderTest()22 GeometryShaderTest() {}
23
24 protected:
initResources(ShBuiltInResources * resources)25 void initResources(ShBuiltInResources *resources) override
26 {
27 resources->EXT_geometry_shader = 1;
28 }
29
getShaderType() const30 ::GLenum getShaderType() const override { return GL_GEOMETRY_SHADER_EXT; }
31
getShaderSpec() const32 ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
33
compileGeometryShader(const std::string & statement1,const std::string & statement2)34 bool compileGeometryShader(const std::string &statement1, const std::string &statement2)
35 {
36 std::ostringstream sstream;
37 sstream << kHeader << statement1 << statement2 << kEmptyBody;
38 return compile(sstream.str());
39 }
40
compileGeometryShader(const std::string & statement1,const std::string & statement2,const std::string & statement3,const std::string & statement4)41 bool compileGeometryShader(const std::string &statement1,
42 const std::string &statement2,
43 const std::string &statement3,
44 const std::string &statement4)
45 {
46 std::ostringstream sstream;
47 sstream << kHeader << statement1 << statement2 << statement3 << statement4 << kEmptyBody;
48 return compile(sstream.str());
49 }
50
GetGeometryShaderLayout(const std::string & layoutType,const std::string & primitive,int invocations,int maxVertices)51 static std::string GetGeometryShaderLayout(const std::string &layoutType,
52 const std::string &primitive,
53 int invocations,
54 int maxVertices)
55 {
56 std::ostringstream sstream;
57
58 sstream << "layout (";
59 if (!primitive.empty())
60 {
61 sstream << primitive;
62 }
63 if (invocations > 0)
64 {
65 sstream << ", invocations = " << invocations;
66 }
67 if (maxVertices >= 0)
68 {
69 sstream << ", max_vertices = " << maxVertices;
70 }
71 sstream << ") " << layoutType << ";" << std::endl;
72
73 return sstream.str();
74 }
75
GetInputDeclaration(const std::string & var,int size)76 static std::string GetInputDeclaration(const std::string &var, int size)
77 {
78 std::ostringstream sstream;
79
80 sstream << "in ";
81 if (size < 0)
82 {
83 sstream << var << "[];\n";
84 }
85 else
86 {
87 sstream << var << "[" << size << "];\n";
88 }
89
90 return sstream.str();
91 }
92
93 const std::string kVersion = "#version 310 es\n";
94 const std::string kHeader =
95 "#version 310 es\n"
96 "#extension GL_EXT_geometry_shader : require\n";
97 const std::string kInputLayout = "layout (points) in;\n";
98 const std::string kOutputLayout = "layout (points, max_vertices = 1) out;\n";
99
100 const std::array<std::string, 4> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};
101 const std::map<std::string, int> kInputPrimitivesAndInputArraySizeMap = {
102 {"points", 1},
103 {"lines", 2},
104 {"lines_adjacency", 4},
105 {"triangles", 3},
106 {"triangles_adjacency", 6}};
107
108 const std::string kEmptyBody =
109 "void main()\n"
110 "{\n"
111 "}\n";
112 };
113
114 class GeometryShaderOutputCodeTest : public MatchOutputCodeTest
115 {
116 public:
GeometryShaderOutputCodeTest()117 GeometryShaderOutputCodeTest() : MatchOutputCodeTest(GL_GEOMETRY_SHADER_EXT, SH_ESSL_OUTPUT)
118 {
119 ShCompileOptions defaultCompileOptions = {};
120 defaultCompileOptions.objectCode = true;
121 setDefaultCompileOptions(defaultCompileOptions);
122
123 getResources()->EXT_geometry_shader = 1;
124 }
125 };
126
127 // Geometry Shaders are not supported in GLSL ES shaders version lower than 310.
TEST_F(GeometryShaderTest,Version300)128 TEST_F(GeometryShaderTest, Version300)
129 {
130 const std::string &shaderString =
131 R"(#version 300 es
132 void main()
133 {
134 })";
135
136 if (compile(shaderString))
137 {
138 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
139 }
140 }
141
142 // Geometry Shaders are not supported in GLSL ES shaders version 310 without extension
143 // EXT_geometry_shader enabled.
TEST_F(GeometryShaderTest,Version310WithoutExtension)144 TEST_F(GeometryShaderTest, Version310WithoutExtension)
145 {
146 const std::string &shaderString =
147 R"(#version 310 es
148 void main()
149 {
150 })";
151
152 if (compile(shaderString))
153 {
154 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
155 }
156 }
157
158 // Geometry Shaders are not supported in GLSL ES shaders version 310 with extension
159 // EXT_geometry_shader disabled.
TEST_F(GeometryShaderTest,Version310ExtensionDisabled)160 TEST_F(GeometryShaderTest, Version310ExtensionDisabled)
161 {
162 const std::string &shaderString =
163 R"(#version 310 es
164 #extension GL_EXT_geometry_shader : disable
165 void main()
166 {
167 })";
168
169 if (compile(shaderString))
170 {
171 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
172 }
173 }
174
175 // Geometry Shaders are supported in GLSL ES shaders version 310 with EXT_geometry_shader enabled.
TEST_F(GeometryShaderTest,Version310WithEXTExtension)176 TEST_F(GeometryShaderTest, Version310WithEXTExtension)
177 {
178 const std::string &shaderString =
179 R"(#version 310 es
180 #extension GL_EXT_geometry_shader : require
181 layout(points) in;
182 layout(points, max_vertices = 1) out;
183 void main()
184 {
185 })";
186
187 if (!compile(shaderString))
188 {
189 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
190 }
191 }
192
193 // Missing the declaration of input primitive in a geometry shader should be a link error instead of
194 // a compile error.
TEST_F(GeometryShaderTest,NoInputPrimitives)195 TEST_F(GeometryShaderTest, NoInputPrimitives)
196 {
197 const std::string &shaderString =
198 R"(#version 310 es
199 #extension GL_EXT_geometry_shader : require
200 layout(points, max_vertices = 1) out;
201 void main()
202 {
203 })";
204
205 if (!compile(shaderString))
206 {
207 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
208 }
209 }
210
211 // Geometry Shaders can only support 5 kinds of input primitives, which cannot be used as output
212 // primitives except 'points'.
213 // Skip testing "points" as it can be used as both input and output primitives.
TEST_F(GeometryShaderTest,ValidInputPrimitives)214 TEST_F(GeometryShaderTest, ValidInputPrimitives)
215 {
216 const std::array<std::string, 4> kInputPrimitives = {
217 {"lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
218
219 for (const std::string &inputPrimitive : kInputPrimitives)
220 {
221 if (!compileGeometryShader(GetGeometryShaderLayout("in", inputPrimitive, -1, -1),
222 kOutputLayout))
223 {
224 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
225 }
226 if (compileGeometryShader(kInputLayout,
227 GetGeometryShaderLayout("out", inputPrimitive, -1, 6)))
228 {
229 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
230 }
231 }
232 }
233
234 // Geometry Shaders allow duplicated declaration of input primitive, but all of them must be same.
TEST_F(GeometryShaderTest,RedeclareInputPrimitives)235 TEST_F(GeometryShaderTest, RedeclareInputPrimitives)
236 {
237 const std::array<std::string, 5> kInputPrimitives = {
238 {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
239
240 for (GLuint i = 0; i < kInputPrimitives.size(); ++i)
241 {
242 const std::string &inputLayoutStr1 =
243 GetGeometryShaderLayout("in", kInputPrimitives[i], -1, -1);
244 if (!compileGeometryShader(inputLayoutStr1, inputLayoutStr1, kOutputLayout, ""))
245 {
246 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
247 }
248
249 for (GLuint j = i + 1; j < kInputPrimitives.size(); ++j)
250 {
251 const std::string &inputLayoutStr2 =
252 GetGeometryShaderLayout("in", kInputPrimitives[j], -1, -1);
253 if (compileGeometryShader(inputLayoutStr1, inputLayoutStr2, kOutputLayout, ""))
254 {
255 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
256 }
257 }
258 }
259 }
260
261 // Geometry Shaders don't allow declaring different input primitives in one layout.
TEST_F(GeometryShaderTest,DeclareDifferentInputPrimitivesInOneLayout)262 TEST_F(GeometryShaderTest, DeclareDifferentInputPrimitivesInOneLayout)
263 {
264 const std::string &shaderString =
265 R"(#version 310 es
266 #extension GL_EXT_geometry_shader : require
267 layout (points, triangles) in;
268 layout (points, max_vertices = 1) out;
269 void main()
270 {
271 })";
272
273 if (compile(shaderString))
274 {
275 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
276 }
277 }
278
279 // Geometry Shaders don't allow 'invocations' < 1.
TEST_F(GeometryShaderTest,InvocationsLessThanOne)280 TEST_F(GeometryShaderTest, InvocationsLessThanOne)
281 {
282 const std::string &shaderString =
283 R"(#version 310 es
284 #extension GL_EXT_geometry_shader : require
285 layout (points, invocations = 0) in;
286 layout (points, max_vertices = 1) out;
287 void main()
288 {
289 })";
290
291 if (compile(shaderString))
292 {
293 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
294 }
295 }
296
297 // Geometry Shaders allow declaring 'invocations' == 1 together with input primitive declaration in
298 // one layout.
TEST_F(GeometryShaderTest,InvocationsEqualsOne)299 TEST_F(GeometryShaderTest, InvocationsEqualsOne)
300 {
301 const std::string &shaderString =
302 R"(#version 310 es
303 #extension GL_EXT_geometry_shader : require
304 layout (points, invocations = 1) in;
305 layout (points, max_vertices = 1) out;
306 void main()
307 {
308 })";
309
310 if (!compile(shaderString))
311 {
312 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
313 }
314 }
315
316 // Geometry Shaders allow declaring 'invocations' == 1 in an individual layout.
TEST_F(GeometryShaderTest,InvocationsEqualsOneInSeparatedLayout)317 TEST_F(GeometryShaderTest, InvocationsEqualsOneInSeparatedLayout)
318 {
319 const std::string &shaderString =
320 R"(#version 310 es
321 #extension GL_EXT_geometry_shader : require
322 layout (points) in;
323 layout (invocations = 1) in;
324 layout (points, max_vertices = 1) out;
325 void main()
326 {
327 })";
328
329 if (!compile(shaderString))
330 {
331 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
332 }
333 }
334
335 // Geometry Shaders don't allow 'invocations' larger than the implementation-dependent maximum value
336 // (32 in this test).
TEST_F(GeometryShaderTest,TooLargeInvocations)337 TEST_F(GeometryShaderTest, TooLargeInvocations)
338 {
339 const std::string &shaderString =
340 R"(#version 310 es
341 #extension GL_EXT_geometry_shader : require
342 layout (points, invocations = 9989899) in;
343 layout (points, max_vertices = 1) out;
344 void main()
345 {
346 })";
347
348 if (compile(shaderString))
349 {
350 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
351 }
352 }
353
354 // Geometry Shaders allow 'invocations' declared together with input primitives in one layout.
TEST_F(GeometryShaderTest,InvocationsDeclaredWithInputPrimitives)355 TEST_F(GeometryShaderTest, InvocationsDeclaredWithInputPrimitives)
356 {
357 const std::string &shaderString =
358 R"(#version 310 es
359 #extension GL_EXT_geometry_shader : require
360 layout (points, invocations = 3) in;
361 layout (points, max_vertices = 1) out;
362 void main()
363 {
364 })";
365
366 if (!compile(shaderString))
367 {
368 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
369 }
370 }
371
372 // Geometry Shaders allow 'invocations' declared before input primitives in one input layout.
TEST_F(GeometryShaderTest,InvocationsBeforeInputPrimitives)373 TEST_F(GeometryShaderTest, InvocationsBeforeInputPrimitives)
374 {
375 const std::string &shaderString =
376 R"(#version 310 es
377 #extension GL_EXT_geometry_shader : require
378 layout (invocations = 3, points) in;
379 layout (points, max_vertices = 1) out;
380 void main()
381 {
382 })";
383
384 if (!compile(shaderString))
385 {
386 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
387 }
388 }
389
390 // Geometry Shaders allow 'invocations' declared in an individual input layout.
TEST_F(GeometryShaderTest,InvocationsInIndividualLayout)391 TEST_F(GeometryShaderTest, InvocationsInIndividualLayout)
392 {
393 const std::string &shaderString =
394 R"(#version 310 es
395 #extension GL_EXT_geometry_shader : require
396 layout (points) in;
397 layout (invocations = 3) in;
398 layout (points, max_vertices = 1) out;
399 void main()
400 {
401 })";
402
403 if (!compile(shaderString))
404 {
405 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
406 }
407 }
408
409 // Geometry Shaders allow duplicated 'invocations' declarations.
TEST_F(GeometryShaderTest,DuplicatedInvocations)410 TEST_F(GeometryShaderTest, DuplicatedInvocations)
411 {
412 const std::string &shaderString =
413 R"(#version 310 es
414 #extension GL_EXT_geometry_shader : require
415 layout (points, invocations = 3) in;
416 layout (invocations = 3) in;
417 layout (points, max_vertices = 1) out;
418 void main()
419 {
420 })";
421
422 if (!compile(shaderString))
423 {
424 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
425 }
426 }
427
428 // Geometry Shaders don't allow multiple different 'invocations' declarations in different
429 // layouts.
TEST_F(GeometryShaderTest,RedeclareDifferentInvocations)430 TEST_F(GeometryShaderTest, RedeclareDifferentInvocations)
431 {
432 const std::string &shaderString =
433 R"(#version 310 es
434 #extension GL_EXT_geometry_shader : require
435 layout (points, invocations = 3) in;
436 layout (invocations = 5) in;
437 layout (points, max_vertices = 1) out;
438 void main()
439 {
440 })";
441
442 if (compile(shaderString))
443 {
444 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
445 }
446 }
447
448 // Geometry Shaders don't allow multiple different 'invocations' declarations in different
449 // layouts.
TEST_F(GeometryShaderTest,RedeclareDifferentInvocationsAfterInvocationEqualsOne)450 TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsAfterInvocationEqualsOne)
451 {
452 const std::string &shaderString =
453 R"(#version 310 es
454 #extension GL_EXT_geometry_shader : require
455 layout (points, invocations = 1) in;
456 layout (invocations = 5) in;
457 layout (points, max_vertices = 1) out;
458 void main()
459 {
460 })";
461
462 if (compile(shaderString))
463 {
464 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
465 }
466 }
467
468 // Geometry Shaders don't allow multiple different 'invocations' declarations in one layout.
TEST_F(GeometryShaderTest,RedeclareDifferentInvocationsInOneLayout)469 TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsInOneLayout)
470 {
471 const std::string &shaderString =
472 R"(#version 310 es
473 #extension GL_EXT_geometry_shader : require
474 layout (points, invocations = 3, invocations = 5) in;
475 layout (points, max_vertices = 1) out;
476 void main()
477 {
478 })";
479
480 if (compile(shaderString))
481 {
482 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
483 }
484 }
485
486 // Geometry Shaders don't allow 'invocations' in out layouts.
TEST_F(GeometryShaderTest,DeclareInvocationsInOutLayout)487 TEST_F(GeometryShaderTest, DeclareInvocationsInOutLayout)
488 {
489 const std::string &shaderString =
490 R"(#version 310 es
491 #extension GL_EXT_geometry_shader : require
492 layout (points) in;
493 layout (points, invocations = 3, max_vertices = 1) out;
494 void main()
495 {
496 })";
497
498 if (compile(shaderString))
499 {
500 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
501 }
502 }
503
504 // Geometry Shaders don't allow 'invocations' in layouts without 'in' qualifier.
TEST_F(GeometryShaderTest,DeclareInvocationsInLayoutNoQualifier)505 TEST_F(GeometryShaderTest, DeclareInvocationsInLayoutNoQualifier)
506 {
507 const std::string &shaderString =
508 R"(#version 310 es
509 #extension GL_EXT_geometry_shader : require
510 layout (points) in;
511 layout (invocations = 3);
512 layout (points, max_vertices = 1) out;
513 void main()
514 {
515 })";
516
517 if (compile(shaderString))
518 {
519 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
520 }
521 }
522
523 // Geometry Shaders allow declaring output primitive before input primitive declaration.
TEST_F(GeometryShaderTest,DeclareOutputPrimitiveBeforeInputPrimitiveDeclare)524 TEST_F(GeometryShaderTest, DeclareOutputPrimitiveBeforeInputPrimitiveDeclare)
525 {
526 const std::string &shaderString =
527 R"(#version 310 es
528 #extension GL_EXT_geometry_shader : require
529 layout (points, max_vertices = 1) out;
530 layout (points) in;
531 void main()
532 {
533 })";
534
535 if (!compile(shaderString))
536 {
537 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
538 }
539 }
540
541 // Geometry Shaders allow declaring 'max_vertices' before output primitive in one output layout.
TEST_F(GeometryShaderTest,DeclareMaxVerticesBeforeOutputPrimitive)542 TEST_F(GeometryShaderTest, DeclareMaxVerticesBeforeOutputPrimitive)
543 {
544 const std::string &shaderString =
545 R"(#version 310 es
546 #extension GL_EXT_geometry_shader : require
547 layout (points) in;
548 layout (max_vertices = 1, points) out;
549 void main()
550 {
551 })";
552
553 if (!compile(shaderString))
554 {
555 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
556 }
557 }
558
559 // Missing the declaration of output primitive should be a link error instead of a compile error in
560 // a geometry shader.
TEST_F(GeometryShaderTest,NoOutputPrimitives)561 TEST_F(GeometryShaderTest, NoOutputPrimitives)
562 {
563 const std::string &shaderString =
564 R"(#version 310 es
565 #extension GL_EXT_geometry_shader : require
566 layout (points) in;
567 layout (max_vertices = 1) out;
568 void main()
569 {
570 })";
571
572 if (!compile(shaderString))
573 {
574 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
575 }
576 }
577
578 // Geometry Shaders can only support 3 kinds of output primitives, which cannot be used as input
579 // primitives except 'points'.
580 // Skip testing "points" as it can be used as both input and output primitives.
TEST_F(GeometryShaderTest,ValidateOutputPrimitives)581 TEST_F(GeometryShaderTest, ValidateOutputPrimitives)
582 {
583 const std::string outputPrimitives[] = {"line_strip", "triangle_strip"};
584
585 for (const std::string &outPrimitive : outputPrimitives)
586 {
587 if (!compileGeometryShader(kInputLayout,
588 GetGeometryShaderLayout("out", outPrimitive, -1, 6)))
589 {
590 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
591 }
592
593 if (compileGeometryShader(GetGeometryShaderLayout("in", outPrimitive, -1, -1),
594 kOutputLayout))
595 {
596 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
597 }
598 }
599 }
600
601 // Geometry Shaders allow duplicated output primitive declarations, but all of them must be same.
TEST_F(GeometryShaderTest,RedeclareOutputPrimitives)602 TEST_F(GeometryShaderTest, RedeclareOutputPrimitives)
603 {
604 const std::array<std::string, 3> outPrimitives = {{"points", "line_strip", "triangle_strip"}};
605
606 for (GLuint i = 0; i < outPrimitives.size(); i++)
607 {
608 constexpr int maxVertices = 1;
609 const std::string &outputLayoutStr1 =
610 GetGeometryShaderLayout("out", outPrimitives[i], -1, maxVertices);
611 const std::string &outputLayoutStr2 =
612 GetGeometryShaderLayout("out", outPrimitives[i], -1, -1);
613 if (!compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr2, ""))
614 {
615 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
616 }
617 for (GLuint j = i + 1; j < outPrimitives.size(); j++)
618 {
619 const std::string &outputLayoutStr3 =
620 GetGeometryShaderLayout("out", outPrimitives[j], -1, -1);
621 if (compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr3, ""))
622 {
623 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
624 }
625 }
626 }
627 }
628
629 // Geometry Shaders don't allow declaring different output primitives in one layout.
TEST_F(GeometryShaderTest,RedeclareDifferentOutputPrimitivesInOneLayout)630 TEST_F(GeometryShaderTest, RedeclareDifferentOutputPrimitivesInOneLayout)
631 {
632 const std::string &shaderString =
633 R"(#version 310 es
634 #extension GL_EXT_geometry_shader : require
635 layout (points) in;
636 layout (points, max_vertices = 3, line_strip) out;
637 void main()
638 {
639 })";
640
641 if (compile(shaderString))
642 {
643 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
644 }
645 }
646
647 // Missing the declarations of output primitives and 'max_vertices' in a geometry shader should
648 // be a link error instead of a compile error.
TEST_F(GeometryShaderTest,NoOutLayouts)649 TEST_F(GeometryShaderTest, NoOutLayouts)
650 {
651 const std::string &shaderString =
652 R"(#version 310 es
653 #extension GL_EXT_geometry_shader : require
654 layout (points) in;
655 void main()
656 {
657 })";
658
659 if (!compile(shaderString))
660 {
661 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
662 }
663 }
664
665 // Missing the declarations of 'max_vertices' in a geometry shader should be a link error
666 // instead of a compile error.
TEST_F(GeometryShaderTest,NoMaxVertices)667 TEST_F(GeometryShaderTest, NoMaxVertices)
668 {
669 const std::string &shaderString =
670 R"(#version 310 es
671 #extension GL_EXT_geometry_shader : require
672 layout (points) in;
673 layout (points) out;
674 void main()
675 {
676 })";
677
678 if (!compile(shaderString))
679 {
680 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
681 }
682 }
683
684 // Geometry Shaders cannot declare a negative 'max_vertices'.
TEST_F(GeometryShaderTest,NegativeMaxVertices)685 TEST_F(GeometryShaderTest, NegativeMaxVertices)
686 {
687 const std::string &shaderString =
688 R"(#version 310 es
689 #extension GL_EXT_geometry_shader : require
690 layout (points) in;
691 layout (points, max_vertices = -1) out;
692 void main()
693 {
694 })";
695
696 if (compile(shaderString))
697 {
698 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
699 }
700 }
701
702 // Geometry Shaders allow max_vertices == 0.
TEST_F(GeometryShaderTest,ZeroMaxVertices)703 TEST_F(GeometryShaderTest, ZeroMaxVertices)
704 {
705 const std::string &shaderString =
706 R"(#version 310 es
707 #extension GL_EXT_geometry_shader : require
708 layout (points) in;
709 layout (points, max_vertices = 0) out;
710 void main()
711 {
712 })";
713
714 if (!compile(shaderString))
715 {
716 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
717 }
718 }
719
720 // Geometry Shaders cannot declare a 'max_vertices' that is greater than
721 // MAX_GEOMETRY_OUTPUT_VERTICES_EXT (256 in this test).
TEST_F(GeometryShaderTest,TooLargeMaxVertices)722 TEST_F(GeometryShaderTest, TooLargeMaxVertices)
723 {
724 const std::string &shaderString =
725 R"(#version 310 es
726 #extension GL_EXT_geometry_shader : require
727 layout (points) in;
728 layout (points, max_vertices = 257) out;
729 void main()
730 {
731 })";
732
733 if (compile(shaderString))
734 {
735 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
736 }
737 }
738
739 // Geometry Shaders can declare 'max_vertices' in an individual out layout.
TEST_F(GeometryShaderTest,MaxVerticesInIndividualLayout)740 TEST_F(GeometryShaderTest, MaxVerticesInIndividualLayout)
741 {
742 const std::string &shaderString =
743 R"(#version 310 es
744 #extension GL_EXT_geometry_shader : require
745 layout (points) in;
746 layout (points) out;
747 layout (max_vertices = 1) out;
748 void main()
749 {
750 })";
751
752 if (!compile(shaderString))
753 {
754 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
755 }
756 }
757
758 // Geometry Shaders allow duplicated 'max_vertices' declarations.
TEST_F(GeometryShaderTest,DuplicatedMaxVertices)759 TEST_F(GeometryShaderTest, DuplicatedMaxVertices)
760 {
761 const std::string &shaderString =
762 R"(#version 310 es
763 #extension GL_EXT_geometry_shader : require
764 layout (points) in;
765 layout (points, max_vertices = 1) out;
766 layout (max_vertices = 1) out;
767 void main()
768 {
769 })";
770
771 if (!compile(shaderString))
772 {
773 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
774 }
775 }
776
777 // Geometry Shaders don't allow declaring different 'max_vertices'.
TEST_F(GeometryShaderTest,RedeclareDifferentMaxVertices)778 TEST_F(GeometryShaderTest, RedeclareDifferentMaxVertices)
779 {
780 const std::string &shaderString =
781 R"(#version 310 es
782 #extension GL_EXT_geometry_shader : require
783 layout (points) in;
784 layout (points, max_vertices = 1) out;
785 layout (max_vertices = 2) out;
786 void main()
787 {
788 })";
789
790 if (compile(shaderString))
791 {
792 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
793 }
794 }
795
796 // Geometry Shaders don't allow declaring different 'max_vertices'.
TEST_F(GeometryShaderTest,RedeclareDifferentMaxVerticesInOneLayout)797 TEST_F(GeometryShaderTest, RedeclareDifferentMaxVerticesInOneLayout)
798 {
799 const std::string &shaderString =
800 R"(#version 310 es
801 #extension GL_EXT_geometry_shader : require
802 layout (points) in;
803 layout (points, max_vertices = 2, max_vertices = 1) out;
804 void main()
805 {
806 })";
807
808 if (compile(shaderString))
809 {
810 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
811 }
812 }
813
814 // Geometry Shaders don't allow 'location' declared with input/output primitives in one layout.
TEST_F(GeometryShaderTest,InvalidLocation)815 TEST_F(GeometryShaderTest, InvalidLocation)
816 {
817 const std::string &shaderString1 =
818 R"(#version 310 es
819 #extension GL_EXT_geometry_shader : require
820 layout (points, location = 1) in;
821 layout (points, max_vertices = 2) out;
822 void main()
823 {
824 })";
825
826 const std::string &shaderString2 =
827 R"(#version 310 es
828 #extension GL_EXT_geometry_shader : require
829 layout (points) in;
830 layout (invocations = 2, location = 1) in;
831 layout (points, max_vertices = 2) out;
832 void main()
833 {
834 })";
835
836 const std::string &shaderString3 =
837 R"(#version 310 es
838 #extension GL_EXT_geometry_shader : require
839 layout (points) in;
840 layout (points, location = 3, max_vertices = 2) out;
841 void main()
842 {
843 })";
844
845 const std::string &shaderString4 =
846 R"(#version 310 es
847 #extension GL_EXT_geometry_shader : require
848 layout (points) in;
849 layout (points) out;
850 layout (max_vertices = 2, location = 3) out;
851 void main()
852 {
853 })";
854
855 if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||
856 compile(shaderString4))
857 {
858 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
859 }
860 }
861
862 // Geometry Shaders don't allow invalid layout qualifier declarations.
TEST_F(GeometryShaderTest,InvalidLayoutQualifiers)863 TEST_F(GeometryShaderTest, InvalidLayoutQualifiers)
864 {
865 const std::string &shaderString1 =
866 R"(#version 310 es
867 #extension GL_EXT_geometry_shader : require
868 layout (points, abc) in;
869 layout (points, max_vertices = 2) out;
870 void main()
871 {
872 })";
873
874 const std::string &shaderString2 =
875 R"(#version 310 es
876 #extension GL_EXT_geometry_shader : require
877 layout (points) in;
878 layout (points, abc, max_vertices = 2) out;
879 void main()
880 {
881 })";
882
883 const std::string &shaderString3 =
884 R"(#version 310 es
885 #extension GL_EXT_geometry_shader : require
886 layout (points, xyz = 2) in;
887 layout (points, max_vertices = 2) out;
888 void main()
889 {
890 })";
891
892 const std::string &shaderString4 =
893 R"(#version 310 es
894 #extension GL_EXT_geometry_shader : require
895 layout (points) in;
896 layout (points) out;
897 layout (max_vertices = 2, xyz = 3) out;
898 void main()
899 {
900 })";
901
902 if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||
903 compile(shaderString4))
904 {
905 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
906 }
907 }
908
909 // Verify that indexing an array with a constant integer on gl_in is legal.
TEST_F(GeometryShaderTest,IndexGLInByConstantInteger)910 TEST_F(GeometryShaderTest, IndexGLInByConstantInteger)
911 {
912 const std::string &shaderString =
913 R"(#version 310 es
914 #extension GL_EXT_geometry_shader : require
915 layout (points) in;
916 layout (points, max_vertices = 2) out;
917 void main()
918 {
919 vec4 position;
920 position = gl_in[0].gl_Position;
921 })";
922
923 if (!compile(shaderString))
924 {
925 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
926 }
927 }
928
929 // Verify that indexing an array with an integer variable on gl_in is legal.
TEST_F(GeometryShaderTest,IndexGLInByVariable)930 TEST_F(GeometryShaderTest, IndexGLInByVariable)
931 {
932 const std::string &shaderString =
933 R"(#version 310 es
934 #extension GL_EXT_geometry_shader : require
935 layout (lines) in;
936 layout (points, max_vertices = 2) out;
937 void main()
938 {
939 vec4 position;
940 for (int i = 0; i < 2; i++)
941 {
942 position = gl_in[i].gl_Position;
943 }
944 })";
945
946 if (!compile(shaderString))
947 {
948 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
949 }
950 }
951
952 // Verify that indexing an array on gl_in without input primitive declaration causes a compile
953 // error.
TEST_F(GeometryShaderTest,IndexGLInWithoutInputPrimitive)954 TEST_F(GeometryShaderTest, IndexGLInWithoutInputPrimitive)
955 {
956 const std::string &shaderString =
957 R"(#version 310 es
958 #extension GL_EXT_geometry_shader : require
959 layout (points, max_vertices = 2) out;
960 void main()
961 {
962 vec4 position = gl_in[0].gl_Position;
963 })";
964
965 if (compile(shaderString))
966 {
967 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
968 }
969 }
970
971 // Verify that using gl_in.length() without input primitive declaration causes a compile error.
TEST_F(GeometryShaderTest,UseGLInLengthWithoutInputPrimitive)972 TEST_F(GeometryShaderTest, UseGLInLengthWithoutInputPrimitive)
973 {
974 const std::string &shaderString =
975 R"(#version 310 es
976 #extension GL_EXT_geometry_shader : require
977 layout (points, max_vertices = 2) out;
978 void main()
979 {
980 int length = gl_in.length();
981 })";
982
983 if (compile(shaderString))
984 {
985 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
986 }
987 }
988
989 // Verify that using gl_in.length() with input primitive declaration can compile.
TEST_F(GeometryShaderTest,UseGLInLengthWithInputPrimitive)990 TEST_F(GeometryShaderTest, UseGLInLengthWithInputPrimitive)
991 {
992 const std::string &shaderString =
993 R"(#version 310 es
994 #extension GL_EXT_geometry_shader : require
995 layout (points) in;
996 layout (points, max_vertices = 2) out;
997 void main()
998 {
999 gl_Position = vec4(gl_in.length());
1000 EmitVertex();
1001 })";
1002
1003 if (!compile(shaderString))
1004 {
1005 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1006 }
1007 }
1008
1009 // Verify that gl_in[].gl_Position cannot be l-value.
TEST_F(GeometryShaderTest,AssignValueToGLIn)1010 TEST_F(GeometryShaderTest, AssignValueToGLIn)
1011 {
1012 const std::string &shaderString =
1013 R"(#version 310 es
1014 #extension GL_EXT_geometry_shader : require
1015 layout (points) in;
1016 layout (points, max_vertices = 2) out;
1017 void main()
1018 {
1019 gl_in[0].gl_Position = vec4(0, 0, 0, 1);
1020 })";
1021 if (compile(shaderString))
1022 {
1023 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1024 }
1025 }
1026
1027 // Verify Geometry Shader supports all required built-in variables.
TEST_F(GeometryShaderTest,BuiltInVariables)1028 TEST_F(GeometryShaderTest, BuiltInVariables)
1029 {
1030 const std::string &shaderString =
1031 R"(#version 310 es
1032 #extension GL_EXT_geometry_shader : require
1033 layout (points, invocations = 2) in;
1034 layout (points, max_vertices = 2) out;
1035 void main()
1036 {
1037 gl_Position = gl_in[gl_InvocationID].gl_Position;
1038 int invocation = gl_InvocationID;
1039 gl_Layer = invocation;
1040 int primitiveIn = gl_PrimitiveIDIn;
1041 gl_PrimitiveID = primitiveIn;
1042 })";
1043 if (!compile(shaderString))
1044 {
1045 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1046 }
1047 }
1048
1049 // Verify that gl_PrimitiveIDIn cannot be l-value.
TEST_F(GeometryShaderTest,AssignValueToGLPrimitiveIn)1050 TEST_F(GeometryShaderTest, AssignValueToGLPrimitiveIn)
1051 {
1052 const std::string &shaderString =
1053 R"(#version 310 es
1054 #extension GL_EXT_geometry_shader : require
1055 layout (points, invocations = 2) in;
1056 layout (points, max_vertices = 2) out;
1057 void main()
1058 {
1059 gl_PrimitiveIDIn = 1;
1060 })";
1061 if (compile(shaderString))
1062 {
1063 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1064 }
1065 }
1066
1067 // Verify that gl_InvocationID cannot be l-value.
TEST_F(GeometryShaderTest,AssignValueToGLInvocations)1068 TEST_F(GeometryShaderTest, AssignValueToGLInvocations)
1069 {
1070 const std::string &shaderString =
1071 R"(#version 310 es
1072 #extension GL_EXT_geometry_shader : require
1073 layout (points, invocations = 2) in;
1074 layout (points, max_vertices = 2) out;
1075 void main()
1076 {
1077 gl_InvocationID = 1;
1078 })";
1079 if (compile(shaderString))
1080 {
1081 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1082 }
1083 }
1084
1085 // Verify that both EmitVertex() and EndPrimitive() are supported in Geometry Shader.
TEST_F(GeometryShaderTest,GeometryShaderBuiltInFunctions)1086 TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctions)
1087 {
1088 const std::string &shaderString =
1089 R"(#version 310 es
1090 #extension GL_EXT_geometry_shader : require
1091 layout (points) in;
1092 layout (points, max_vertices = 2) out;
1093 void main()
1094 {
1095 gl_Position = gl_in[0].gl_Position;
1096 EmitVertex();
1097 EndPrimitive();
1098 })";
1099
1100 if (!compile(shaderString))
1101 {
1102 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1103 }
1104 }
1105
1106 // Verify that using EmitVertex() or EndPrimitive() without GL_EXT_geometry_shader declared causes a
1107 // compile error.
TEST_F(GeometryShaderTest,GeometryShaderBuiltInFunctionsWithoutExtension)1108 TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctionsWithoutExtension)
1109 {
1110 const std::string &shaderString1 =
1111 R"(#version 310 es
1112 void main()
1113 {
1114 EmitVertex();
1115 })";
1116
1117 const std::string &shaderString2 =
1118 R"(#version 310 es
1119 void main()
1120 {
1121 EndPrimitive();
1122 })";
1123
1124 if (compile(shaderString1) || compile(shaderString2))
1125 {
1126 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1127 }
1128 }
1129
1130 // Verify that all required built-in constant values are supported in Geometry Shaders
TEST_F(GeometryShaderTest,GeometryShaderBuiltInConstants)1131 TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstants)
1132 {
1133 const std::string &kShaderHeader =
1134 R"(#version 310 es
1135 #extension GL_EXT_geometry_shader : require
1136 layout (points) in;
1137 layout (points, max_vertices = 2) out;
1138 void main()
1139 {
1140 gl_Position.x = float()";
1141
1142 const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
1143 "gl_MaxGeometryInputComponents",
1144 "gl_MaxGeometryOutputComponents",
1145 "gl_MaxGeometryImageUniforms",
1146 "gl_MaxGeometryTextureImageUnits",
1147 "gl_MaxGeometryOutputVertices",
1148 "gl_MaxGeometryTotalOutputComponents",
1149 "gl_MaxGeometryUniformComponents",
1150 "gl_MaxGeometryAtomicCounters",
1151 "gl_MaxGeometryAtomicCounterBuffers",
1152 }};
1153
1154 const std::string &kShaderTail =
1155 R"();
1156 EmitVertex();
1157 })";
1158
1159 for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
1160 {
1161 std::ostringstream ostream;
1162 ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
1163 if (!compile(ostream.str()))
1164 {
1165 FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;
1166 }
1167 }
1168 }
1169
1170 // Verify that using any Geometry Shader built-in constant values without GL_EXT_geometry_shader
1171 // declared causes a compile error.
TEST_F(GeometryShaderTest,GeometryShaderBuiltInConstantsWithoutExtension)1172 TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstantsWithoutExtension)
1173 {
1174 const std::string &kShaderHeader =
1175 "#version 310 es\n"
1176 "void main()\n"
1177 "{\n"
1178 " int val = ";
1179
1180 const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
1181 "gl_MaxGeometryInputComponents",
1182 "gl_MaxGeometryOutputComponents",
1183 "gl_MaxGeometryImageUniforms",
1184 "gl_MaxGeometryTextureImageUnits",
1185 "gl_MaxGeometryOutputVertices",
1186 "gl_MaxGeometryTotalOutputComponents",
1187 "gl_MaxGeometryUniformComponents",
1188 "gl_MaxGeometryAtomicCounters",
1189 "gl_MaxGeometryAtomicCounterBuffers",
1190 }};
1191
1192 const std::string &kShaderTail =
1193 ";\n"
1194 "}\n";
1195
1196 for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
1197 {
1198 std::ostringstream ostream;
1199 ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
1200 if (compile(ostream.str()))
1201 {
1202 FAIL() << "Shader compilation succeeded, expecting failure: \n" << mInfoLog;
1203 }
1204 }
1205 }
1206
1207 // Verify that Geometry Shaders cannot accept non-array inputs.
TEST_F(GeometryShaderTest,NonArrayInput)1208 TEST_F(GeometryShaderTest, NonArrayInput)
1209 {
1210 const std::string &shaderString =
1211 R"(#version 310 es
1212 #extension GL_EXT_geometry_shader : require
1213 layout (points) in;
1214 layout (points, max_vertices = 1) out;
1215 in vec4 texcoord;
1216 void main()
1217 {
1218 })";
1219
1220 if (compile(shaderString))
1221 {
1222 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1223 }
1224 }
1225
1226 // Verify that compilation errors do not occur even if declaring an unsized Geometry Shader input
1227 // before a valid input primitive declaration.
TEST_F(GeometryShaderTest,DeclareUnsizedInputBeforeInputPrimitive)1228 TEST_F(GeometryShaderTest, DeclareUnsizedInputBeforeInputPrimitive)
1229 {
1230 const std::string &shaderString1 =
1231 R"(#version 310 es
1232 #extension GL_EXT_geometry_shader : require
1233 in vec4 texcoord[];
1234 layout (points) in;
1235 layout (points, max_vertices = 1) out;
1236 void main()
1237 {
1238 vec4 coord = texcoord[0];
1239 int length = texcoord.length();
1240 })";
1241
1242 const std::string &shaderString2 =
1243 R"(#version 310 es
1244 #extension GL_EXT_geometry_shader : require
1245 in vec4 texcoord1[1];
1246 in vec4 texcoord2[];
1247 layout (points) in;
1248 layout (points, max_vertices = 1) out;
1249 void main()
1250 {
1251 vec4 coord = texcoord2[0];
1252 int length = texcoord2.length();
1253 })";
1254
1255 if (!compile(shaderString1) || !compile(shaderString2))
1256 {
1257 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1258 }
1259 }
1260
1261 // Verify that it is a compile error to declare an unsized Geometry Shader input without a valid
1262 // input primitive declaration.
TEST_F(GeometryShaderTest,DeclareUnsizedInputWithoutInputPrimitive)1263 TEST_F(GeometryShaderTest, DeclareUnsizedInputWithoutInputPrimitive)
1264 {
1265 const std::string &shaderString1 =
1266 R"(#version 310 es
1267 #extension GL_EXT_geometry_shader : require
1268 layout (points, max_vertices = 1) out;
1269 in vec4 texcoord[];
1270 void main()
1271 {
1272 })";
1273
1274 const std::string &shaderString2 =
1275 R"(#version 310 es
1276 #extension GL_EXT_geometry_shader : require
1277 layout (points, max_vertices = 1) out;
1278 in vec4 texcoord1[1];
1279 in vec4 texcoord2[];
1280 void main()
1281 {
1282 })";
1283
1284 if (compile(shaderString1) || compile(shaderString2))
1285 {
1286 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1287 }
1288 }
1289
1290 // Verify that indexing an unsized Geometry Shader input which is declared after a
1291 // valid input primitive declaration can compile.
TEST_F(GeometryShaderTest,IndexingUnsizedInputDeclaredAfterInputPrimitive)1292 TEST_F(GeometryShaderTest, IndexingUnsizedInputDeclaredAfterInputPrimitive)
1293 {
1294 const std::string &shaderString =
1295 R"(#version 310 es
1296 #extension GL_EXT_geometry_shader : require
1297 layout (points) in;
1298 layout (points, max_vertices = 1) out;
1299 in vec4 texcoord[], texcoord2[];
1300 in vec4[] texcoord3, texcoord4;
1301 void main()
1302 {
1303 gl_Position = texcoord[0] + texcoord2[0] + texcoord3[0] + texcoord4[0];
1304 EmitVertex();
1305 })";
1306
1307 if (!compile(shaderString))
1308 {
1309 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1310 }
1311 }
1312
1313 // Verify that calling length() function on an unsized Geometry Shader input which
1314 // is declared before a valid input primitive declaration can compile.
TEST_F(GeometryShaderTest,CallingLengthOnUnsizedInputDeclaredAfterInputPrimitive)1315 TEST_F(GeometryShaderTest, CallingLengthOnUnsizedInputDeclaredAfterInputPrimitive)
1316 {
1317 const std::string &shaderString =
1318 R"(#version 310 es
1319 #extension GL_EXT_geometry_shader : require
1320 layout (points) in;
1321 layout (points, max_vertices = 1) out;
1322 in vec4 texcoord[];
1323 void main()
1324 {
1325 gl_Position = vec4(texcoord.length());
1326 EmitVertex();
1327 })";
1328
1329 if (!compile(shaderString))
1330 {
1331 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1332 }
1333 }
1334
1335 // Verify that assigning a value to the input of a geometry shader causes a compile error.
TEST_F(GeometryShaderTest,AssignValueToInput)1336 TEST_F(GeometryShaderTest, AssignValueToInput)
1337 {
1338 const std::string &shaderString =
1339 R"(#version 310 es
1340 #extension GL_EXT_geometry_shader : require
1341 layout (points) in;
1342 layout (points, max_vertices = 1) out;
1343 in vec4 texcoord[];
1344 void main()
1345 {
1346 texcoord[0] = vec4(1.0, 0.0, 0.0, 1.0);
1347 })";
1348
1349 if (compile(shaderString))
1350 {
1351 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1352 }
1353 }
1354
1355 // Geometry Shaders allow inputs with location qualifier.
TEST_F(GeometryShaderTest,InputWithLocations)1356 TEST_F(GeometryShaderTest, InputWithLocations)
1357 {
1358 const std::string &shaderString =
1359 R"(#version 310 es
1360 #extension GL_EXT_geometry_shader : require
1361 layout (triangles) in;
1362 layout (points, max_vertices = 1) out;
1363 layout (location = 0) in vec4 texcoord1[];
1364 layout (location = 1) in vec4 texcoord2[];
1365 void main()
1366 {
1367 int index = 0;
1368 vec4 coord1 = texcoord1[0];
1369 vec4 coord2 = texcoord2[index];
1370 gl_Position = coord1 + coord2;
1371 })";
1372
1373 if (!compile(shaderString))
1374 {
1375 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1376 }
1377 }
1378
1379 // Geometry Shaders allow inputs with explicit size declared before the declaration of the
1380 // input primitive, but they should have same size and match the declaration of the
1381 // following input primitive declarations.
TEST_F(GeometryShaderTest,InputWithSizeBeforeInputPrimitive)1382 TEST_F(GeometryShaderTest, InputWithSizeBeforeInputPrimitive)
1383 {
1384 for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)
1385 {
1386 const std::string &inputLayoutStr =
1387 GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);
1388 const int inputSize = primitiveAndArraySize.second;
1389
1390 const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);
1391 if (!compileGeometryShader(inputDeclaration1, "", inputLayoutStr, kOutputLayout))
1392 {
1393 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1394 }
1395
1396 const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);
1397 if (compileGeometryShader(inputDeclaration2, "", inputLayoutStr, kOutputLayout) ||
1398 compileGeometryShader(inputDeclaration1, inputDeclaration2, inputLayoutStr,
1399 kOutputLayout))
1400 {
1401 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1402 }
1403 }
1404 }
1405
1406 // Geometry shaders allow inputs with explicit size declared after the declaration of the
1407 // input primitive, but their sizes should match the previous input primitive declaration.
TEST_F(GeometryShaderTest,InputWithSizeAfterInputPrimitive)1408 TEST_F(GeometryShaderTest, InputWithSizeAfterInputPrimitive)
1409 {
1410 for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)
1411 {
1412 const std::string &inputLayoutStr =
1413 GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);
1414 const int inputSize = primitiveAndArraySize.second;
1415
1416 const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);
1417 if (!compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration1, ""))
1418 {
1419 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1420 }
1421
1422 const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);
1423 if (compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration2, ""))
1424 {
1425 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1426 }
1427 }
1428 }
1429
1430 // Verify that Geometry Shaders accept non-array outputs.
TEST_F(GeometryShaderTest,NonArrayOutputs)1431 TEST_F(GeometryShaderTest, NonArrayOutputs)
1432 {
1433 const std::string &shaderString =
1434 R"(#version 310 es
1435 #extension GL_EXT_geometry_shader : require
1436 layout (points) in;
1437 layout (points, max_vertices = 1) out;
1438 out vec4 color;
1439 void main()
1440 {
1441 })";
1442
1443 if (!compile(shaderString))
1444 {
1445 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1446 }
1447 }
1448
1449 // Verify that Geometry Shaders allow declaring outputs with 'location' layout qualifier.
TEST_F(GeometryShaderTest,OutputsWithLocation)1450 TEST_F(GeometryShaderTest, OutputsWithLocation)
1451 {
1452 const std::string &shaderString =
1453 R"(#version 310 es
1454 #extension GL_EXT_geometry_shader : require
1455 layout (triangles) in;
1456 layout (points, max_vertices = 1) out;
1457 layout (location = 0) out vec4 color1;
1458 layout (location = 1) out vec4 color2;
1459 void main()
1460 {
1461 color1 = vec4(0.0, 1.0, 0.0, 1.0);
1462 color2 = vec4(1.0, 0.0, 0.0, 1.0);
1463 })";
1464
1465 if (!compile(shaderString))
1466 {
1467 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1468 }
1469 }
1470
1471 // Geometry Shaders allow declaring sized array outputs.
TEST_F(GeometryShaderTest,SizedArrayOutputs)1472 TEST_F(GeometryShaderTest, SizedArrayOutputs)
1473 {
1474 const std::string &shaderString =
1475 R"(#version 310 es
1476 #extension GL_EXT_geometry_shader : require
1477 layout (triangles) in;
1478 layout (points, max_vertices = 1) out;
1479 out vec4 color[2];
1480 void main()
1481 {
1482 color[0] = vec4(0.0, 1.0, 0.0, 1.0);
1483 color[1] = vec4(1.0, 0.0, 0.0, 1.0);
1484 })";
1485
1486 if (!compile(shaderString))
1487 {
1488 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1489 }
1490 }
1491
1492 // Verify that Geometry Shader outputs cannot be declared as an unsized array.
TEST_F(GeometryShaderTest,UnsizedArrayOutputs)1493 TEST_F(GeometryShaderTest, UnsizedArrayOutputs)
1494 {
1495 const std::string &shaderString =
1496 R"(#version 310 es
1497 #extension GL_EXT_geometry_shader : require
1498 layout (triangles) in;
1499 layout (points, max_vertices = 1) out;
1500 out vec4 color[];
1501 void main()
1502 {
1503 })";
1504
1505 if (compile(shaderString))
1506 {
1507 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1508 }
1509 }
1510
1511 // Verify that Geometry Shader inputs can use interpolation qualifiers.
TEST_F(GeometryShaderTest,InputWithInterpolationQualifiers)1512 TEST_F(GeometryShaderTest, InputWithInterpolationQualifiers)
1513 {
1514 for (const std::string &qualifier : kInterpolationQualifiers)
1515 {
1516 std::ostringstream stream;
1517 stream << kHeader << kInputLayout << kOutputLayout << qualifier << " in vec4 texcoord[];\n"
1518 << kEmptyBody;
1519
1520 if (!compile(stream.str()))
1521 {
1522 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1523 }
1524 }
1525 }
1526
1527 // Verify that Geometry Shader outputs can use interpolation qualifiers.
TEST_F(GeometryShaderTest,OutputWithInterpolationQualifiers)1528 TEST_F(GeometryShaderTest, OutputWithInterpolationQualifiers)
1529 {
1530 for (const std::string &qualifier : kInterpolationQualifiers)
1531 {
1532 std::ostringstream stream;
1533 stream << kHeader << kInputLayout << kOutputLayout << qualifier << " out vec4 color;\n"
1534 << kEmptyBody;
1535
1536 if (!compile(stream.str()))
1537 {
1538 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1539 }
1540 }
1541 }
1542
1543 // Verify that Geometry Shader outputs can use 'invariant' qualifier.
TEST_F(GeometryShaderTest,InvariantOutput)1544 TEST_F(GeometryShaderTest, InvariantOutput)
1545 {
1546 const std::string &shaderString =
1547 R"(#version 310 es
1548 #extension GL_EXT_geometry_shader : require
1549 layout (points) in;
1550 layout (points, max_vertices = 2) out;
1551 invariant out vec4 gs_output;
1552 void main()
1553 {
1554 gl_Position = gl_in[0].gl_Position;
1555 })";
1556
1557 if (!compile(shaderString))
1558 {
1559 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1560 }
1561 }
1562
1563 // Verify that the member of gl_in won't be incorrectly changed in the output shader string.
TEST_F(GeometryShaderOutputCodeTest,ValidateGLInMembersInOutputShaderString)1564 TEST_F(GeometryShaderOutputCodeTest, ValidateGLInMembersInOutputShaderString)
1565 {
1566 const std::string &shaderString1 =
1567 R"(#version 310 es
1568 #extension GL_EXT_geometry_shader : require
1569 layout (lines) in;
1570 layout (points, max_vertices = 2) out;
1571 void main()
1572 {
1573 vec4 position;
1574 for (int i = 0; i < 2; i++)
1575 {
1576 position = gl_in[i].gl_Position;
1577 }
1578 })";
1579
1580 compile(shaderString1);
1581 EXPECT_TRUE(foundInESSLCode("].gl_Position"));
1582
1583 const std::string &shaderString2 =
1584 R"(#version 310 es
1585 #extension GL_EXT_geometry_shader : require
1586 layout (points) in;
1587 layout (points, max_vertices = 2) out;
1588 void main()
1589 {
1590 vec4 position;
1591 position = gl_in[0].gl_Position;
1592 })";
1593
1594 compile(shaderString2);
1595 EXPECT_TRUE(foundInESSLCode("].gl_Position"));
1596 }
1597
1598 // Verify that geometry shader inputs can be declared as struct arrays.
TEST_F(GeometryShaderTest,StructArrayInput)1599 TEST_F(GeometryShaderTest, StructArrayInput)
1600 {
1601 const std::string &shaderString =
1602 R"(#version 310 es
1603 #extension GL_EXT_geometry_shader : require
1604 layout (points) in;
1605 layout (points, max_vertices = 2) out;
1606 struct S
1607 {
1608 float value1;
1609 vec4 value2;
1610 };
1611 in S gs_input[];
1612 out S gs_output;
1613 void main()
1614 {
1615 gs_output = gs_input[0];
1616 })";
1617
1618 if (!compile(shaderString))
1619 {
1620 FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
1621 }
1622 }
1623
1624 // Verify that geometry shader outputs cannot be declared as struct arrays.
TEST_F(GeometryShaderTest,StructArrayOutput)1625 TEST_F(GeometryShaderTest, StructArrayOutput)
1626 {
1627 const std::string &shaderString =
1628 R"(#version 310 es
1629 #extension GL_EXT_geometry_shader : require
1630 layout (points) in;
1631 layout (points, max_vertices = 2) out;
1632 struct S
1633 {
1634 float value1;
1635 vec4 value2;
1636 };
1637 out S gs_output[1];
1638 void main()
1639 {
1640 gs_output[0].value1 = 1.0;
1641 gs_output[0].value2 = vec4(1.0, 0.0, 0.0, 1.0);
1642 })";
1643
1644 if (compile(shaderString))
1645 {
1646 FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
1647 }
1648 }
1649