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