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