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