1 //
2 // Copyright 2014 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 // CollectVariables_test.cpp:
7 // Some tests for shader inspection
8 //
9
10 #include <memory>
11
12 #include "GLSLANG/ShaderLang.h"
13 #include "angle_gl.h"
14 #include "compiler/translator/glsl/TranslatorGLSL.h"
15 #include "gtest/gtest.h"
16
17 using namespace sh;
18
19 #define EXPECT_GLENUM_EQ(expected, actual) \
20 EXPECT_EQ(static_cast<::GLenum>(expected), static_cast<::GLenum>(actual))
21
22 namespace
23 {
24
DecorateName(const char * name)25 std::string DecorateName(const char *name)
26 {
27 return std::string("_u") + name;
28 }
29
30 } // anonymous namespace
31
32 class CollectVariablesTest : public testing::Test
33 {
34 public:
CollectVariablesTest(::GLenum shaderType)35 CollectVariablesTest(::GLenum shaderType) : mShaderType(shaderType) {}
36
37 protected:
SetUp()38 void SetUp() override
39 {
40 ShBuiltInResources resources;
41 InitBuiltInResources(&resources);
42 resources.MaxDrawBuffers = 8;
43 resources.EXT_blend_func_extended = true;
44 resources.MaxDualSourceDrawBuffers = 1;
45
46 initTranslator(resources);
47 }
48
initTranslator(const ShBuiltInResources & resources)49 virtual void initTranslator(const ShBuiltInResources &resources)
50 {
51 mTranslator.reset(
52 new TranslatorGLSL(mShaderType, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
53 ASSERT_TRUE(mTranslator->Init(resources));
54 }
55
56 // For use in the gl_DepthRange tests.
validateDepthRangeShader(const std::string & shaderString)57 void validateDepthRangeShader(const std::string &shaderString)
58 {
59 const char *shaderStrings[] = {shaderString.c_str()};
60 ShCompileOptions compileOptions = {};
61 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, compileOptions));
62
63 const std::vector<ShaderVariable> &uniforms = mTranslator->getUniforms();
64 ASSERT_EQ(1u, uniforms.size());
65
66 const ShaderVariable &uniform = uniforms[0];
67 EXPECT_EQ("gl_DepthRange", uniform.name);
68 ASSERT_TRUE(uniform.isStruct());
69 ASSERT_EQ(3u, uniform.fields.size());
70
71 bool foundNear = false;
72 bool foundFar = false;
73 bool foundDiff = false;
74
75 for (const auto &field : uniform.fields)
76 {
77 if (field.name == "near")
78 {
79 EXPECT_FALSE(foundNear);
80 foundNear = true;
81 }
82 else if (field.name == "far")
83 {
84 EXPECT_FALSE(foundFar);
85 foundFar = true;
86 }
87 else
88 {
89 ASSERT_EQ("diff", field.name);
90 EXPECT_FALSE(foundDiff);
91 foundDiff = true;
92 }
93
94 EXPECT_FALSE(field.isArray());
95 EXPECT_FALSE(field.isStruct());
96 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
97 EXPECT_TRUE(field.staticUse);
98 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
99 }
100
101 EXPECT_TRUE(foundNear && foundFar && foundDiff);
102 }
103
104 // For use in tests for output varibles.
validateOutputVariableForShader(const std::string & shaderString,unsigned int varIndex,const char * varName,const ShaderVariable ** outResult)105 void validateOutputVariableForShader(const std::string &shaderString,
106 unsigned int varIndex,
107 const char *varName,
108 const ShaderVariable **outResult)
109 {
110 const char *shaderStrings[] = {shaderString.c_str()};
111 ShCompileOptions compileOptions = {};
112 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, compileOptions))
113 << mTranslator->getInfoSink().info.str();
114
115 const auto &outputVariables = mTranslator->getOutputVariables();
116 ASSERT_LT(varIndex, outputVariables.size());
117 const ShaderVariable &outputVariable = outputVariables[varIndex];
118 EXPECT_EQ(-1, outputVariable.location);
119 EXPECT_TRUE(outputVariable.staticUse);
120 EXPECT_TRUE(outputVariable.active);
121 EXPECT_EQ(varName, outputVariable.name);
122 *outResult = &outputVariable;
123 }
124
compile(const std::string & shaderString,ShCompileOptions * compileOptions)125 void compile(const std::string &shaderString, ShCompileOptions *compileOptions)
126 {
127 const char *shaderStrings[] = {shaderString.c_str()};
128 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, *compileOptions));
129 }
130
compile(const std::string & shaderString)131 void compile(const std::string &shaderString)
132 {
133 ShCompileOptions options = {};
134 compile(shaderString, &options);
135 }
136
checkUniformStaticallyUsedButNotActive(const char * name)137 void checkUniformStaticallyUsedButNotActive(const char *name)
138 {
139 const auto &uniforms = mTranslator->getUniforms();
140 ASSERT_EQ(1u, uniforms.size());
141
142 const ShaderVariable &uniform = uniforms[0];
143 EXPECT_EQ(name, uniform.name);
144 EXPECT_TRUE(uniform.staticUse);
145 EXPECT_FALSE(uniform.active);
146 }
147
148 ::GLenum mShaderType;
149 std::unique_ptr<TranslatorGLSL> mTranslator;
150 };
151
152 class CollectVertexVariablesTest : public CollectVariablesTest
153 {
154 public:
CollectVertexVariablesTest()155 CollectVertexVariablesTest() : CollectVariablesTest(GL_VERTEX_SHADER) {}
156 };
157
158 class CollectFragmentVariablesTest : public CollectVariablesTest
159 {
160 public:
CollectFragmentVariablesTest()161 CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {}
162 };
163
164 class CollectVariablesTestES31 : public CollectVariablesTest
165 {
166 public:
CollectVariablesTestES31(sh::GLenum shaderType)167 CollectVariablesTestES31(sh::GLenum shaderType) : CollectVariablesTest(shaderType) {}
168
169 protected:
initTranslator(const ShBuiltInResources & resources)170 void initTranslator(const ShBuiltInResources &resources) override
171 {
172 mTranslator.reset(
173 new TranslatorGLSL(mShaderType, SH_GLES3_1_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
174 ASSERT_TRUE(mTranslator->Init(resources));
175 }
176 };
177
178 class CollectVariablesEXTGeometryShaderTest : public CollectVariablesTestES31
179 {
180 public:
CollectVariablesEXTGeometryShaderTest(sh::GLenum shaderType)181 CollectVariablesEXTGeometryShaderTest(sh::GLenum shaderType)
182 : CollectVariablesTestES31(shaderType)
183 {}
184
185 protected:
SetUp()186 void SetUp() override
187 {
188 ShBuiltInResources resources;
189 InitBuiltInResources(&resources);
190 resources.EXT_geometry_shader = 1;
191
192 initTranslator(resources);
193 }
194 };
195
196 class CollectGeometryVariablesTest : public CollectVariablesEXTGeometryShaderTest
197 {
198 public:
CollectGeometryVariablesTest()199 CollectGeometryVariablesTest() : CollectVariablesEXTGeometryShaderTest(GL_GEOMETRY_SHADER_EXT)
200 {}
201
202 protected:
compileGeometryShaderWithInputPrimitive(const std::string & inputPrimitive,const std::string & inputVarying,const std::string & functionBody)203 void compileGeometryShaderWithInputPrimitive(const std::string &inputPrimitive,
204 const std::string &inputVarying,
205 const std::string &functionBody)
206 {
207 std::ostringstream sstream;
208 sstream << "#version 310 es\n"
209 << "#extension GL_EXT_geometry_shader : require\n"
210 << "layout (" << inputPrimitive << ") in;\n"
211 << "layout (points, max_vertices = 2) out;\n"
212 << inputVarying << functionBody;
213
214 compile(sstream.str());
215 }
216 };
217
218 class CollectFragmentVariablesEXTGeometryShaderTest : public CollectVariablesEXTGeometryShaderTest
219 {
220 public:
CollectFragmentVariablesEXTGeometryShaderTest()221 CollectFragmentVariablesEXTGeometryShaderTest()
222 : CollectVariablesEXTGeometryShaderTest(GL_FRAGMENT_SHADER)
223 {}
224
225 protected:
initTranslator(const ShBuiltInResources & resources)226 void initTranslator(const ShBuiltInResources &resources)
227 {
228 mTranslator.reset(
229 new TranslatorGLSL(mShaderType, SH_GLES3_1_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT));
230 ASSERT_TRUE(mTranslator->Init(resources));
231 }
232 };
233
234 class CollectVertexVariablesES31Test : public CollectVariablesTestES31
235 {
236 public:
CollectVertexVariablesES31Test()237 CollectVertexVariablesES31Test() : CollectVariablesTestES31(GL_VERTEX_SHADER) {}
238 };
239
240 class CollectFragmentVariablesES31Test : public CollectVariablesTestES31
241 {
242 public:
CollectFragmentVariablesES31Test()243 CollectFragmentVariablesES31Test() : CollectVariablesTestES31(GL_FRAGMENT_SHADER) {}
244 };
245
TEST_F(CollectFragmentVariablesTest,SimpleOutputVar)246 TEST_F(CollectFragmentVariablesTest, SimpleOutputVar)
247 {
248 const std::string &shaderString =
249 "#version 300 es\n"
250 "precision mediump float;\n"
251 "out vec4 out_fragColor;\n"
252 "void main() {\n"
253 " out_fragColor = vec4(1.0);\n"
254 "}\n";
255
256 compile(shaderString);
257
258 const auto &outputVariables = mTranslator->getOutputVariables();
259 ASSERT_EQ(1u, outputVariables.size());
260
261 const ShaderVariable &outputVariable = outputVariables[0];
262
263 EXPECT_FALSE(outputVariable.isArray());
264 EXPECT_EQ(-1, outputVariable.location);
265 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
266 EXPECT_TRUE(outputVariable.staticUse);
267 EXPECT_TRUE(outputVariable.active);
268 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
269 EXPECT_EQ("out_fragColor", outputVariable.name);
270 }
271
TEST_F(CollectFragmentVariablesTest,LocationOutputVar)272 TEST_F(CollectFragmentVariablesTest, LocationOutputVar)
273 {
274 const std::string &shaderString =
275 "#version 300 es\n"
276 "precision mediump float;\n"
277 "layout(location=5) out vec4 out_fragColor;\n"
278 "void main() {\n"
279 " out_fragColor = vec4(1.0);\n"
280 "}\n";
281
282 compile(shaderString);
283
284 const auto &outputVariables = mTranslator->getOutputVariables();
285 ASSERT_EQ(1u, outputVariables.size());
286
287 const ShaderVariable &outputVariable = outputVariables[0];
288
289 EXPECT_FALSE(outputVariable.isArray());
290 EXPECT_EQ(5, outputVariable.location);
291 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision);
292 EXPECT_TRUE(outputVariable.staticUse);
293 EXPECT_TRUE(outputVariable.active);
294 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type);
295 EXPECT_EQ("out_fragColor", outputVariable.name);
296 }
297
TEST_F(CollectVertexVariablesTest,LocationAttribute)298 TEST_F(CollectVertexVariablesTest, LocationAttribute)
299 {
300 const std::string &shaderString =
301 "#version 300 es\n"
302 "layout(location=5) in vec4 in_Position;\n"
303 "void main() {\n"
304 " gl_Position = in_Position;\n"
305 "}\n";
306
307 compile(shaderString);
308
309 const std::vector<ShaderVariable> &attributes = mTranslator->getAttributes();
310 ASSERT_EQ(1u, attributes.size());
311
312 const ShaderVariable &attribute = attributes[0];
313
314 EXPECT_FALSE(attribute.isArray());
315 EXPECT_EQ(5, attribute.location);
316 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, attribute.precision);
317 EXPECT_TRUE(attribute.staticUse);
318 EXPECT_TRUE(attribute.active);
319 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, attribute.type);
320 EXPECT_EQ("in_Position", attribute.name);
321 }
322
TEST_F(CollectVertexVariablesTest,SimpleInterfaceBlock)323 TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
324 {
325 const std::string &shaderString =
326 "#version 300 es\n"
327 "uniform b {\n"
328 " float f;\n"
329 "};"
330 "void main() {\n"
331 " gl_Position = vec4(f, 0.0, 0.0, 1.0);\n"
332 "}\n";
333
334 compile(shaderString);
335
336 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
337 ASSERT_EQ(1u, interfaceBlocks.size());
338
339 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
340
341 EXPECT_EQ(0u, interfaceBlock.arraySize);
342 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
343 EXPECT_EQ("b", interfaceBlock.name);
344 EXPECT_TRUE(interfaceBlock.staticUse);
345 EXPECT_TRUE(interfaceBlock.active);
346
347 ASSERT_EQ(1u, interfaceBlock.fields.size());
348
349 const ShaderVariable &field = interfaceBlock.fields[0];
350
351 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
352 EXPECT_TRUE(field.staticUse);
353 EXPECT_TRUE(field.active);
354 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
355 EXPECT_EQ("f", field.name);
356 EXPECT_FALSE(field.isRowMajorLayout);
357 EXPECT_TRUE(field.fields.empty());
358 }
359
TEST_F(CollectVertexVariablesTest,SimpleInstancedInterfaceBlock)360 TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
361 {
362 const std::string &shaderString =
363 "#version 300 es\n"
364 "uniform b {\n"
365 " float f;\n"
366 "} blockInstance;"
367 "void main() {\n"
368 " gl_Position = vec4(blockInstance.f, 0.0, 0.0, 1.0);\n"
369 "}\n";
370
371 compile(shaderString);
372
373 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
374 ASSERT_EQ(1u, interfaceBlocks.size());
375
376 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
377
378 EXPECT_EQ(0u, interfaceBlock.arraySize);
379 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
380 EXPECT_EQ("b", interfaceBlock.name);
381 EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
382 EXPECT_TRUE(interfaceBlock.staticUse);
383 EXPECT_TRUE(interfaceBlock.active);
384
385 ASSERT_EQ(1u, interfaceBlock.fields.size());
386
387 const ShaderVariable &field = interfaceBlock.fields[0];
388
389 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
390 EXPECT_TRUE(field.staticUse);
391 EXPECT_TRUE(field.active);
392 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
393 EXPECT_EQ("f", field.name);
394 EXPECT_FALSE(field.isRowMajorLayout);
395 EXPECT_TRUE(field.fields.empty());
396 }
397
TEST_F(CollectVertexVariablesTest,StructInterfaceBlock)398 TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
399 {
400 const std::string &shaderString =
401 "#version 300 es\n"
402 "struct st { float f; };"
403 "uniform b {\n"
404 " st s;\n"
405 "};"
406 "void main() {\n"
407 " gl_Position = vec4(s.f, 0.0, 0.0, 1.0);\n"
408 "}\n";
409
410 compile(shaderString);
411
412 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
413 ASSERT_EQ(1u, interfaceBlocks.size());
414
415 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
416
417 EXPECT_EQ(0u, interfaceBlock.arraySize);
418 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
419 EXPECT_EQ("b", interfaceBlock.name);
420 EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
421 EXPECT_TRUE(interfaceBlock.staticUse);
422 EXPECT_TRUE(interfaceBlock.active);
423
424 ASSERT_EQ(1u, interfaceBlock.fields.size());
425
426 const ShaderVariable &blockField = interfaceBlock.fields[0];
427
428 EXPECT_TRUE(blockField.isStruct());
429 EXPECT_TRUE(blockField.staticUse);
430 EXPECT_TRUE(blockField.active);
431 EXPECT_EQ("s", blockField.name);
432 EXPECT_EQ(DecorateName("s"), blockField.mappedName);
433 EXPECT_FALSE(blockField.isRowMajorLayout);
434
435 const ShaderVariable &structField = blockField.fields[0];
436
437 // NOTE: we don't track static use or active at individual struct member granularity.
438 EXPECT_FALSE(structField.isStruct());
439 EXPECT_EQ("f", structField.name);
440 EXPECT_EQ(DecorateName("f"), structField.mappedName);
441 EXPECT_GLENUM_EQ(GL_FLOAT, structField.type);
442 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, structField.precision);
443 }
444
TEST_F(CollectVertexVariablesTest,StructInstancedInterfaceBlock)445 TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
446 {
447 const std::string &shaderString =
448 "#version 300 es\n"
449 "struct st { float f; };"
450 "uniform b {\n"
451 " st s;\n"
452 "} instanceName;"
453 "void main() {\n"
454 " gl_Position = vec4(instanceName.s.f, 0.0, 0.0, 1.0);\n"
455 "}\n";
456
457 compile(shaderString);
458
459 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
460 ASSERT_EQ(1u, interfaceBlocks.size());
461
462 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
463
464 EXPECT_EQ(0u, interfaceBlock.arraySize);
465 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
466 EXPECT_EQ("b", interfaceBlock.name);
467 EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
468 EXPECT_EQ("instanceName", interfaceBlock.instanceName);
469 EXPECT_TRUE(interfaceBlock.staticUse);
470 EXPECT_TRUE(interfaceBlock.active);
471
472 ASSERT_EQ(1u, interfaceBlock.fields.size());
473
474 const ShaderVariable &blockField = interfaceBlock.fields[0];
475
476 EXPECT_TRUE(blockField.isStruct());
477 EXPECT_TRUE(blockField.staticUse);
478 EXPECT_TRUE(blockField.active);
479 EXPECT_EQ("s", blockField.name);
480 EXPECT_EQ(DecorateName("s"), blockField.mappedName);
481 EXPECT_FALSE(blockField.isRowMajorLayout);
482
483 const ShaderVariable &structField = blockField.fields[0];
484
485 // NOTE: we don't track static use or active at individual struct member granularity.
486 EXPECT_FALSE(structField.isStruct());
487 EXPECT_EQ("f", structField.name);
488 EXPECT_EQ(DecorateName("f"), structField.mappedName);
489 EXPECT_GLENUM_EQ(GL_FLOAT, structField.type);
490 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, structField.precision);
491 }
492
TEST_F(CollectVertexVariablesTest,NestedStructRowMajorInterfaceBlock)493 TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
494 {
495 const std::string &shaderString =
496 "#version 300 es\n"
497 "struct st { mat2 m; };"
498 "layout(row_major) uniform b {\n"
499 " st s;\n"
500 "};"
501 "void main() {\n"
502 " gl_Position = vec4(s.m);\n"
503 "}\n";
504
505 compile(shaderString);
506
507 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
508 ASSERT_EQ(1u, interfaceBlocks.size());
509
510 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
511
512 EXPECT_EQ(0u, interfaceBlock.arraySize);
513 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
514 EXPECT_EQ("b", interfaceBlock.name);
515 EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
516 EXPECT_TRUE(interfaceBlock.staticUse);
517 EXPECT_TRUE(interfaceBlock.active);
518
519 ASSERT_EQ(1u, interfaceBlock.fields.size());
520
521 const ShaderVariable &blockField = interfaceBlock.fields[0];
522
523 EXPECT_TRUE(blockField.isStruct());
524 EXPECT_TRUE(blockField.staticUse);
525 EXPECT_TRUE(blockField.active);
526 EXPECT_EQ("s", blockField.name);
527 EXPECT_EQ(DecorateName("s"), blockField.mappedName);
528 EXPECT_TRUE(blockField.isRowMajorLayout);
529
530 const ShaderVariable &structField = blockField.fields[0];
531
532 // NOTE: we don't track static use or active at individual struct member granularity.
533 EXPECT_FALSE(structField.isStruct());
534 EXPECT_EQ("m", structField.name);
535 EXPECT_EQ(DecorateName("m"), structField.mappedName);
536 EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, structField.type);
537 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, structField.precision);
538 }
539
TEST_F(CollectVertexVariablesTest,VaryingInterpolation)540 TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
541 {
542 const std::string &shaderString =
543 "#version 300 es\n"
544 "precision mediump float;\n"
545 "centroid out float vary;\n"
546 "void main() {\n"
547 " gl_Position = vec4(1.0);\n"
548 " vary = 1.0;\n"
549 "}\n";
550
551 compile(shaderString);
552
553 const std::vector<ShaderVariable> &varyings = mTranslator->getOutputVaryings();
554 ASSERT_EQ(2u, varyings.size());
555
556 const ShaderVariable *varying = &varyings[0];
557
558 if (varying->name == "gl_Position")
559 {
560 varying = &varyings[1];
561 }
562
563 EXPECT_FALSE(varying->isArray());
564 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, varying->precision);
565 EXPECT_TRUE(varying->staticUse);
566 EXPECT_TRUE(varying->active);
567 EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
568 EXPECT_EQ("vary", varying->name);
569 EXPECT_EQ(DecorateName("vary"), varying->mappedName);
570 EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
571 }
572
573 // Test for builtin uniform "gl_DepthRange" (Vertex shader)
TEST_F(CollectVertexVariablesTest,DepthRange)574 TEST_F(CollectVertexVariablesTest, DepthRange)
575 {
576 const std::string &shaderString =
577 "attribute vec4 position;\n"
578 "void main() {\n"
579 " gl_Position = position + vec4(gl_DepthRange.near, gl_DepthRange.far, "
580 "gl_DepthRange.diff, 1.0);\n"
581 "}\n";
582
583 validateDepthRangeShader(shaderString);
584 }
585
586 // Test for builtin uniform "gl_DepthRange" (Fragment shader)
TEST_F(CollectFragmentVariablesTest,DepthRange)587 TEST_F(CollectFragmentVariablesTest, DepthRange)
588 {
589 const std::string &shaderString =
590 "precision mediump float;\n"
591 "void main() {\n"
592 " gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1.0);\n"
593 "}\n";
594
595 validateDepthRangeShader(shaderString);
596 }
597
598 // Test that gl_FragColor built-in usage in ESSL1 fragment shader is reflected in the output
599 // variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragColor)600 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragColor)
601 {
602 const std::string &fragColorShader =
603 "precision mediump float;\n"
604 "void main() {\n"
605 " gl_FragColor = vec4(1.0);\n"
606 "}\n";
607
608 const ShaderVariable *outputVariable = nullptr;
609 validateOutputVariableForShader(fragColorShader, 0u, "gl_FragColor", &outputVariable);
610 ASSERT_NE(outputVariable, nullptr);
611 EXPECT_FALSE(outputVariable->isArray());
612 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
613 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
614 }
615
616 // Test that gl_FragData built-in usage in ESSL1 fragment shader is reflected in the output
617 // variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragData)618 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData)
619 {
620 const std::string &fragDataShader =
621 "#extension GL_EXT_draw_buffers : require\n"
622 "precision mediump float;\n"
623 "void main() {\n"
624 " gl_FragData[0] = vec4(1.0);\n"
625 " gl_FragData[1] = vec4(0.5);\n"
626 "}\n";
627
628 ShBuiltInResources resources = mTranslator->getResources();
629 resources.EXT_draw_buffers = 1;
630 const unsigned int kMaxDrawBuffers = 3u;
631 resources.MaxDrawBuffers = kMaxDrawBuffers;
632 initTranslator(resources);
633
634 const ShaderVariable *outputVariable = nullptr;
635 validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
636 ASSERT_NE(outputVariable, nullptr);
637 ASSERT_EQ(1u, outputVariable->arraySizes.size());
638 EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
639 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
640 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
641 }
642
643 // Test that gl_FragData built-in usage in ESSL1 fragment shader is reflected in the output
644 // variables list, even if the EXT_draw_buffers extension isn't exposed. This covers the
645 // usage in the dEQP test dEQP-GLES3.functional.shaders.fragdata.draw_buffers.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDataUniform)646 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDataUniform)
647 {
648 const std::string &fragDataShader =
649 "precision mediump float;\n"
650 "uniform int uniIndex;"
651 "void main() {\n"
652 " gl_FragData[uniIndex] = vec4(1.0);\n"
653 "}\n";
654
655 ShBuiltInResources resources = mTranslator->getResources();
656 const unsigned int kMaxDrawBuffers = 3u;
657 resources.MaxDrawBuffers = kMaxDrawBuffers;
658 initTranslator(resources);
659
660 const ShaderVariable *outputVariable = nullptr;
661 validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
662 ASSERT_NE(outputVariable, nullptr);
663 ASSERT_EQ(1u, outputVariable->arraySizes.size());
664 EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
665 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
666 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
667 }
668
669 // Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
670 // variables list. Also test that the precision is mediump.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDepthMediump)671 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthMediump)
672 {
673 const std::string &fragDepthShader =
674 "#extension GL_EXT_frag_depth : require\n"
675 "precision mediump float;\n"
676 "void main() {\n"
677 " gl_FragDepthEXT = 0.7;"
678 "}\n";
679
680 ShBuiltInResources resources = mTranslator->getResources();
681 resources.EXT_frag_depth = 1;
682 initTranslator(resources);
683
684 const ShaderVariable *outputVariable = nullptr;
685 validateOutputVariableForShader(fragDepthShader, 0u, "gl_FragDepthEXT", &outputVariable);
686 ASSERT_NE(outputVariable, nullptr);
687 EXPECT_FALSE(outputVariable->isArray());
688 EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
689 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
690 }
691
692 // Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
693 // variables list. Also test that the precision is highp if user requests it.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDepthHighp)694 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp)
695 {
696 const std::string &fragDepthHighShader =
697 "#extension GL_EXT_frag_depth : require\n"
698 "void main() {\n"
699 " gl_FragDepthEXT = 0.7;"
700 "}\n";
701
702 ShBuiltInResources resources = mTranslator->getResources();
703 resources.EXT_frag_depth = 1;
704 resources.FragmentPrecisionHigh = 1;
705 initTranslator(resources);
706
707 const ShaderVariable *outputVariable = nullptr;
708 validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepthEXT", &outputVariable);
709 ASSERT_NE(outputVariable, nullptr);
710 EXPECT_FALSE(outputVariable->isArray());
711 EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
712 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
713 }
714
715 // Test that gl_FragData built-in usage in ESSL3 fragment shader is reflected in the output
716 // variables list. Also test that the precision is highp.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL3FragDepthHighp)717 TEST_F(CollectFragmentVariablesTest, OutputVarESSL3FragDepthHighp)
718 {
719 const std::string &fragDepthHighShader =
720 "#version 300 es\n"
721 "precision mediump float;\n"
722 "void main() {\n"
723 " gl_FragDepth = 0.7;"
724 "}\n";
725
726 ShBuiltInResources resources = mTranslator->getResources();
727 resources.EXT_frag_depth = 1;
728 initTranslator(resources);
729
730 const ShaderVariable *outputVariable = nullptr;
731 validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepth", &outputVariable);
732 ASSERT_NE(outputVariable, nullptr);
733 EXPECT_FALSE(outputVariable->isArray());
734 EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
735 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
736 }
737
738 // Test that gl_SecondaryFragColorEXT built-in usage in ESSL1 fragment shader is reflected in the
739 // output variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1EXTBlendFuncExtendedSecondaryFragColor)740 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragColor)
741 {
742 const char *secondaryFragColorShader =
743 "#extension GL_EXT_blend_func_extended : require\n"
744 "precision mediump float;\n"
745 "void main() {\n"
746 " gl_FragColor = vec4(1.0);\n"
747 " gl_SecondaryFragColorEXT = vec4(1.0);\n"
748 "}\n";
749
750 const unsigned int kMaxDrawBuffers = 3u;
751 ShBuiltInResources resources = mTranslator->getResources();
752 resources.EXT_blend_func_extended = 1;
753 resources.EXT_draw_buffers = 1;
754 resources.MaxDrawBuffers = kMaxDrawBuffers;
755 resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
756 initTranslator(resources);
757
758 const ShaderVariable *outputVariable = nullptr;
759 validateOutputVariableForShader(secondaryFragColorShader, 0u, "gl_FragColor", &outputVariable);
760 ASSERT_NE(outputVariable, nullptr);
761 EXPECT_FALSE(outputVariable->isArray());
762 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
763 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
764
765 outputVariable = nullptr;
766 validateOutputVariableForShader(secondaryFragColorShader, 1u, "gl_SecondaryFragColorEXT",
767 &outputVariable);
768 ASSERT_NE(outputVariable, nullptr);
769 EXPECT_FALSE(outputVariable->isArray());
770 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
771 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
772 }
773
774 // Test that gl_SecondaryFragDataEXT built-in usage in ESSL1 fragment shader is reflected in the
775 // output variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1EXTBlendFuncExtendedSecondaryFragData)776 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragData)
777 {
778 const char *secondaryFragDataShader =
779 "#extension GL_EXT_blend_func_extended : require\n"
780 "#extension GL_EXT_draw_buffers : require\n"
781 "precision mediump float;\n"
782 "void main() {\n"
783 " gl_FragData[0] = vec4(1.0);\n"
784 " gl_FragData[1] = vec4(0.5);\n"
785 " gl_SecondaryFragDataEXT[0] = vec4(1.0);\n"
786 " gl_SecondaryFragDataEXT[1] = vec4(0.8);\n"
787 "}\n";
788 const unsigned int kMaxDrawBuffers = 3u;
789 ShBuiltInResources resources = mTranslator->getResources();
790 resources.EXT_blend_func_extended = 1;
791 resources.EXT_draw_buffers = 1;
792 resources.MaxDrawBuffers = kMaxDrawBuffers;
793 resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
794 initTranslator(resources);
795
796 const ShaderVariable *outputVariable = nullptr;
797 validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
798 ASSERT_NE(outputVariable, nullptr);
799 ASSERT_EQ(1u, outputVariable->arraySizes.size());
800 EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
801 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
802 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
803
804 outputVariable = nullptr;
805 validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT",
806 &outputVariable);
807 ASSERT_NE(outputVariable, nullptr);
808 ASSERT_EQ(1u, outputVariable->arraySizes.size());
809 EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
810 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
811 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
812 }
813
SimpleTestHash(const char * str,size_t len)814 static khronos_uint64_t SimpleTestHash(const char *str, size_t len)
815 {
816 return static_cast<uint64_t>(len);
817 }
818
819 class CollectHashedVertexVariablesTest : public CollectVertexVariablesTest
820 {
821 protected:
SetUp()822 void SetUp() override
823 {
824 // Initialize the translate with a hash function
825 ShBuiltInResources resources;
826 sh::InitBuiltInResources(&resources);
827 resources.HashFunction = SimpleTestHash;
828 initTranslator(resources);
829 }
830 };
831
TEST_F(CollectHashedVertexVariablesTest,InstancedInterfaceBlock)832 TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
833 {
834 const std::string &shaderString =
835 "#version 300 es\n"
836 "uniform blockName {\n"
837 " float field;\n"
838 "} blockInstance;"
839 "void main() {\n"
840 " gl_Position = vec4(blockInstance.field, 0.0, 0.0, 1.0);\n"
841 "}\n";
842
843 compile(shaderString);
844
845 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
846 ASSERT_EQ(1u, interfaceBlocks.size());
847
848 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
849
850 EXPECT_EQ(0u, interfaceBlock.arraySize);
851 EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
852 EXPECT_EQ("blockName", interfaceBlock.name);
853 EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
854 EXPECT_EQ("webgl_9", interfaceBlock.mappedName);
855 EXPECT_TRUE(interfaceBlock.staticUse);
856 EXPECT_TRUE(interfaceBlock.active);
857
858 ASSERT_EQ(1u, interfaceBlock.fields.size());
859
860 const ShaderVariable &field = interfaceBlock.fields[0];
861
862 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
863 EXPECT_TRUE(field.staticUse);
864 EXPECT_TRUE(field.active);
865 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
866 EXPECT_EQ("field", field.name);
867 EXPECT_EQ("webgl_5", field.mappedName);
868 EXPECT_FALSE(field.isRowMajorLayout);
869 EXPECT_TRUE(field.fields.empty());
870 }
871
872 // Test a struct uniform where the struct does have a name.
TEST_F(CollectHashedVertexVariablesTest,StructUniform)873 TEST_F(CollectHashedVertexVariablesTest, StructUniform)
874 {
875 const std::string &shaderString =
876 R"(#version 300 es
877 struct sType
878 {
879 float field;
880 };
881 uniform sType u;
882
883 void main()
884 {
885 gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
886 })";
887
888 compile(shaderString);
889
890 const auto &uniforms = mTranslator->getUniforms();
891 ASSERT_EQ(1u, uniforms.size());
892
893 const ShaderVariable &uniform = uniforms[0];
894
895 EXPECT_FALSE(uniform.isArray());
896 EXPECT_EQ("u", uniform.name);
897 EXPECT_EQ("webgl_1", uniform.mappedName);
898 EXPECT_EQ("sType", uniform.structOrBlockName);
899 EXPECT_TRUE(uniform.staticUse);
900 EXPECT_TRUE(uniform.active);
901
902 ASSERT_EQ(1u, uniform.fields.size());
903
904 const ShaderVariable &field = uniform.fields[0];
905
906 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
907 // We don't yet support tracking static use per field, but fields are marked statically used in
908 // case the struct is.
909 EXPECT_TRUE(field.staticUse);
910 EXPECT_TRUE(field.active);
911 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
912 EXPECT_EQ("field", field.name);
913 EXPECT_EQ("webgl_5", field.mappedName);
914 EXPECT_TRUE(field.fields.empty());
915 }
916
917 // Test a struct uniform where the struct doesn't have a name.
TEST_F(CollectHashedVertexVariablesTest,NamelessStructUniform)918 TEST_F(CollectHashedVertexVariablesTest, NamelessStructUniform)
919 {
920 const std::string &shaderString =
921 R"(#version 300 es
922 uniform struct
923 {
924 float field;
925 } u;
926
927 void main()
928 {
929 gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
930 })";
931
932 compile(shaderString);
933
934 const auto &uniforms = mTranslator->getUniforms();
935 ASSERT_EQ(1u, uniforms.size());
936
937 const ShaderVariable &uniform = uniforms[0];
938
939 EXPECT_FALSE(uniform.isArray());
940 EXPECT_EQ("u", uniform.name);
941 EXPECT_EQ("webgl_1", uniform.mappedName);
942 EXPECT_EQ("", uniform.structOrBlockName);
943 EXPECT_TRUE(uniform.staticUse);
944 EXPECT_TRUE(uniform.active);
945
946 ASSERT_EQ(1u, uniform.fields.size());
947
948 const ShaderVariable &field = uniform.fields[0];
949
950 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
951 // We don't yet support tracking static use per field, but fields are marked statically used in
952 // case the struct is.
953 EXPECT_TRUE(field.staticUse);
954 EXPECT_TRUE(field.active);
955 EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
956 EXPECT_EQ("field", field.name);
957 EXPECT_EQ("webgl_5", field.mappedName);
958 EXPECT_TRUE(field.fields.empty());
959 }
960
961 // Test a uniform declaration with multiple declarators.
TEST_F(CollectFragmentVariablesTest,MultiDeclaration)962 TEST_F(CollectFragmentVariablesTest, MultiDeclaration)
963 {
964 const std::string &shaderString =
965 "#version 300 es\n"
966 "precision mediump float;\n"
967 "out vec4 out_fragColor;\n"
968 "uniform float uA, uB;\n"
969 "void main()\n"
970 "{\n"
971 " vec4 color = vec4(uA, uA, uA, uB);\n"
972 " out_fragColor = color;\n"
973 "}\n";
974
975 compile(shaderString);
976
977 const auto &uniforms = mTranslator->getUniforms();
978 ASSERT_EQ(2u, uniforms.size());
979
980 const ShaderVariable &uniform = uniforms[0];
981 EXPECT_FALSE(uniform.isArray());
982 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniform.precision);
983 EXPECT_TRUE(uniform.staticUse);
984 EXPECT_TRUE(uniform.active);
985 EXPECT_GLENUM_EQ(GL_FLOAT, uniform.type);
986 EXPECT_EQ("uA", uniform.name);
987
988 const ShaderVariable &uniformB = uniforms[1];
989 EXPECT_FALSE(uniformB.isArray());
990 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
991 EXPECT_TRUE(uniformB.staticUse);
992 EXPECT_TRUE(uniformB.active);
993 EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
994 EXPECT_EQ("uB", uniformB.name);
995 }
996
997 // Test a uniform declaration starting with an empty declarator.
TEST_F(CollectFragmentVariablesTest,EmptyDeclarator)998 TEST_F(CollectFragmentVariablesTest, EmptyDeclarator)
999 {
1000 const std::string &shaderString =
1001 "#version 300 es\n"
1002 "precision mediump float;\n"
1003 "out vec4 out_fragColor;\n"
1004 "uniform float /* empty declarator */, uB;\n"
1005 "void main()\n"
1006 "{\n"
1007 " out_fragColor = vec4(uB, uB, uB, uB);\n"
1008 "}\n";
1009
1010 compile(shaderString);
1011
1012 const auto &uniforms = mTranslator->getUniforms();
1013 ASSERT_EQ(1u, uniforms.size());
1014
1015 const ShaderVariable &uniformB = uniforms[0];
1016 EXPECT_FALSE(uniformB.isArray());
1017 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
1018 EXPECT_TRUE(uniformB.staticUse);
1019 EXPECT_TRUE(uniformB.active);
1020 EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
1021 EXPECT_EQ("uB", uniformB.name);
1022 }
1023
1024 // Test collecting variables from an instanced multiview shader that has an internal ViewID_OVR
1025 // varying.
TEST_F(CollectVertexVariablesTest,ViewIdOVR)1026 TEST_F(CollectVertexVariablesTest, ViewIdOVR)
1027 {
1028 const std::string &shaderString =
1029 "#version 300 es\n"
1030 "#extension GL_OVR_multiview2 : require\n"
1031 "precision mediump float;\n"
1032 "void main()\n"
1033 "{\n"
1034 " gl_Position = vec4(0.0);\n"
1035 "}\n";
1036
1037 ShBuiltInResources resources = mTranslator->getResources();
1038 resources.OVR_multiview2 = 1;
1039 resources.MaxViewsOVR = 4;
1040 initTranslator(resources);
1041
1042 ShCompileOptions compileOptions = {};
1043 compileOptions.initializeBuiltinsForInstancedMultiview = true;
1044 compileOptions.selectViewInNvGLSLVertexShader = true;
1045 compile(shaderString, &compileOptions);
1046
1047 // The internal ViewID_OVR varying is not exposed through the ShaderVars interface.
1048 const auto &varyings = mTranslator->getOutputVaryings();
1049 ASSERT_EQ(1u, varyings.size());
1050 const ShaderVariable *varying = &varyings[0];
1051 EXPECT_EQ("gl_Position", varying->name);
1052 }
1053
1054 // Test all the fields of gl_in can be collected correctly in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectGLInFields)1055 TEST_F(CollectGeometryVariablesTest, CollectGLInFields)
1056 {
1057 const std::string &shaderString =
1058 R"(#version 310 es
1059 #extension GL_EXT_geometry_shader : require
1060
1061 layout (points) in;
1062 layout (points, max_vertices = 2) out;
1063
1064 void main()
1065 {
1066 vec4 value = gl_in[0].gl_Position;
1067 vec4 value2 = gl_in[0].gl_Position;
1068 gl_Position = value + value2;
1069 EmitVertex();
1070 })";
1071
1072 compile(shaderString);
1073
1074 EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1075
1076 const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1077 ASSERT_EQ(1u, inVaryings.size());
1078
1079 const ShaderVariable &glIn = inVaryings[0];
1080 EXPECT_EQ("gl_in", glIn.name);
1081 EXPECT_EQ("gl_PerVertex", glIn.structOrBlockName);
1082 EXPECT_TRUE(glIn.staticUse);
1083 EXPECT_TRUE(glIn.active);
1084 EXPECT_TRUE(glIn.isBuiltIn());
1085
1086 ASSERT_EQ(1u, glIn.fields.size());
1087
1088 const ShaderVariable &glPositionField = glIn.fields[0];
1089 EXPECT_EQ("gl_Position", glPositionField.name);
1090 EXPECT_FALSE(glPositionField.isArray());
1091 EXPECT_FALSE(glPositionField.isStruct());
1092 EXPECT_TRUE(glPositionField.staticUse);
1093 // Tracking for "active" not set up currently.
1094 // EXPECT_TRUE(glPositionField.active);
1095 EXPECT_TRUE(glPositionField.isBuiltIn());
1096 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, glPositionField.precision);
1097 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, glPositionField.type);
1098 }
1099
1100 // Test the collected array size of gl_in matches the input primitive declaration.
TEST_F(CollectGeometryVariablesTest,GLInArraySize)1101 TEST_F(CollectGeometryVariablesTest, GLInArraySize)
1102 {
1103 const std::array<std::string, 5> kInputPrimitives = {
1104 {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
1105
1106 const GLuint kArraySizeForInputPrimitives[] = {1u, 2u, 4u, 3u, 6u};
1107
1108 const std::string &functionBody =
1109 R"(void main()
1110 {
1111 gl_Position = gl_in[0].gl_Position;
1112 })";
1113
1114 for (size_t i = 0; i < kInputPrimitives.size(); ++i)
1115 {
1116 compileGeometryShaderWithInputPrimitive(kInputPrimitives[i], "", functionBody);
1117
1118 const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1119 ASSERT_EQ(1u, inVaryings.size());
1120
1121 const ShaderVariable &glIn = inVaryings[0];
1122 ASSERT_EQ("gl_in", glIn.name);
1123 EXPECT_EQ(kArraySizeForInputPrimitives[i], glIn.arraySizes[0]);
1124 }
1125 }
1126
1127 // Test collecting gl_PrimitiveIDIn in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPrimitiveIDIn)1128 TEST_F(CollectGeometryVariablesTest, CollectPrimitiveIDIn)
1129 {
1130 const std::string &shaderString =
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 = vec4(gl_PrimitiveIDIn);
1138 EmitVertex();
1139 })";
1140
1141 compile(shaderString);
1142
1143 EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1144
1145 const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1146 ASSERT_EQ(1u, inputVaryings.size());
1147
1148 const ShaderVariable &varying = inputVaryings[0];
1149 EXPECT_EQ("gl_PrimitiveIDIn", varying.name);
1150 EXPECT_FALSE(varying.isArray());
1151 EXPECT_FALSE(varying.isStruct());
1152 EXPECT_TRUE(varying.staticUse);
1153 EXPECT_TRUE(varying.active);
1154 EXPECT_TRUE(varying.isBuiltIn());
1155 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1156 EXPECT_GLENUM_EQ(GL_INT, varying.type);
1157 }
1158
1159 // Test collecting gl_InvocationID in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInvocationID)1160 TEST_F(CollectGeometryVariablesTest, CollectInvocationID)
1161 {
1162 const std::string &shaderString =
1163 R"(#version 310 es
1164 #extension GL_EXT_geometry_shader : require
1165 layout (points, invocations = 2) in;
1166 layout (points, max_vertices = 2) out;
1167 void main()
1168 {
1169 gl_Position = vec4(gl_InvocationID);
1170 EmitVertex();
1171 })";
1172
1173 compile(shaderString);
1174
1175 EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1176
1177 const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1178 ASSERT_EQ(1u, inputVaryings.size());
1179
1180 const ShaderVariable &varying = inputVaryings[0];
1181 EXPECT_EQ("gl_InvocationID", varying.name);
1182 EXPECT_FALSE(varying.isArray());
1183 EXPECT_FALSE(varying.isStruct());
1184 EXPECT_TRUE(varying.staticUse);
1185 EXPECT_TRUE(varying.active);
1186 EXPECT_TRUE(varying.isBuiltIn());
1187 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1188 EXPECT_GLENUM_EQ(GL_INT, varying.type);
1189 }
1190
1191 // Test collecting gl_in in a geometry shader when gl_in is indexed by an expression.
TEST_F(CollectGeometryVariablesTest,CollectGLInIndexedByExpression)1192 TEST_F(CollectGeometryVariablesTest, CollectGLInIndexedByExpression)
1193 {
1194 const std::string &shaderString =
1195 R"(#version 310 es
1196 #extension GL_EXT_geometry_shader : require
1197 layout (triangles, invocations = 2) in;
1198 layout (points, max_vertices = 2) out;
1199 void main()
1200 {
1201 gl_Position = gl_in[gl_InvocationID + 1].gl_Position;
1202 EmitVertex();
1203 })";
1204
1205 compile(shaderString);
1206
1207 EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1208
1209 const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1210 ASSERT_EQ(2u, inVaryings.size());
1211
1212 bool foundGLIn = false;
1213 bool foundInvocationID = false;
1214
1215 for (const ShaderVariable &varying : inVaryings)
1216 {
1217 if (varying.name == "gl_in")
1218 {
1219 foundGLIn = true;
1220 EXPECT_TRUE(varying.isShaderIOBlock);
1221 EXPECT_EQ("gl_PerVertex", varying.structOrBlockName);
1222 }
1223 else if (varying.name == "gl_InvocationID")
1224 {
1225 foundInvocationID = true;
1226 }
1227 }
1228
1229 EXPECT_TRUE(foundGLIn);
1230 EXPECT_TRUE(foundInvocationID);
1231 }
1232
1233 // Test collecting gl_Position in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPosition)1234 TEST_F(CollectGeometryVariablesTest, CollectPosition)
1235 {
1236 const std::string &shaderString =
1237 R"(#version 310 es
1238 #extension GL_EXT_geometry_shader : require
1239 layout (points) in;
1240 layout (points, max_vertices = 2) out;
1241 void main()
1242 {
1243 gl_Position = vec4(0.1, 0.2, 0.3, 1);
1244 })";
1245
1246 compile(shaderString);
1247
1248 ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1249
1250 const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1251 ASSERT_EQ(1u, outputVaryings.size());
1252
1253 const ShaderVariable &varying = outputVaryings[0];
1254 EXPECT_EQ("gl_Position", varying.name);
1255 EXPECT_FALSE(varying.isArray());
1256 EXPECT_FALSE(varying.isStruct());
1257 EXPECT_TRUE(varying.staticUse);
1258 EXPECT_TRUE(varying.active);
1259 EXPECT_TRUE(varying.isBuiltIn());
1260 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1261 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1262 }
1263
1264 // Test collecting gl_PrimitiveID in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPrimitiveID)1265 TEST_F(CollectGeometryVariablesTest, CollectPrimitiveID)
1266 {
1267 const std::string &shaderString =
1268 R"(#version 310 es
1269 #extension GL_EXT_geometry_shader : require
1270 layout (points) in;
1271 layout (points, max_vertices = 2) out;
1272 void main()
1273 {
1274 gl_PrimitiveID = 100;
1275 })";
1276
1277 compile(shaderString);
1278
1279 ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1280
1281 const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1282 ASSERT_EQ(1u, outputVaryings.size());
1283
1284 const ShaderVariable &varying = outputVaryings[0];
1285 EXPECT_EQ("gl_PrimitiveID", varying.name);
1286 EXPECT_FALSE(varying.isArray());
1287 EXPECT_FALSE(varying.isStruct());
1288 EXPECT_TRUE(varying.staticUse);
1289 EXPECT_TRUE(varying.active);
1290 EXPECT_TRUE(varying.isBuiltIn());
1291 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1292 EXPECT_GLENUM_EQ(GL_INT, varying.type);
1293 }
1294
1295 // Test collecting gl_Layer in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectLayer)1296 TEST_F(CollectGeometryVariablesTest, CollectLayer)
1297 {
1298 const std::string &shaderString =
1299 R"(#version 310 es
1300 #extension GL_EXT_geometry_shader : require
1301 layout (points) in;
1302 layout (points, max_vertices = 2) out;
1303 void main()
1304 {
1305 gl_Layer = 2;
1306 })";
1307
1308 compile(shaderString);
1309
1310 ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1311
1312 const auto &outputVaryings = mTranslator->getOutputVaryings();
1313 ASSERT_EQ(1u, outputVaryings.size());
1314
1315 const ShaderVariable &varying = outputVaryings[0];
1316 EXPECT_EQ("gl_Layer", varying.name);
1317 EXPECT_FALSE(varying.isArray());
1318 EXPECT_FALSE(varying.isStruct());
1319 EXPECT_TRUE(varying.staticUse);
1320 EXPECT_TRUE(varying.active);
1321 EXPECT_TRUE(varying.isBuiltIn());
1322 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1323 EXPECT_GLENUM_EQ(GL_INT, varying.type);
1324 }
1325
1326 // Test collecting gl_PrimitiveID in a fragment shader.
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest,CollectPrimitiveID)1327 TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectPrimitiveID)
1328 {
1329 const std::string &shaderString =
1330 R"(#version 310 es
1331 #extension GL_EXT_geometry_shader : require
1332
1333 out int my_out;
1334
1335 void main()
1336 {
1337 my_out = gl_PrimitiveID;
1338 })";
1339
1340 compile(shaderString);
1341
1342 ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1343
1344 const auto &inputVaryings = mTranslator->getInputVaryings();
1345 ASSERT_EQ(1u, inputVaryings.size());
1346
1347 const ShaderVariable *varying = &inputVaryings[0];
1348 EXPECT_EQ("gl_PrimitiveID", varying->name);
1349 EXPECT_FALSE(varying->isArray());
1350 EXPECT_FALSE(varying->isStruct());
1351 EXPECT_TRUE(varying->staticUse);
1352 EXPECT_TRUE(varying->active);
1353 EXPECT_TRUE(varying->isBuiltIn());
1354 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1355 EXPECT_GLENUM_EQ(GL_INT, varying->type);
1356 }
1357
1358 // Test collecting gl_Layer in a fragment shader.
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest,CollectLayer)1359 TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectLayer)
1360 {
1361 const std::string &shaderString =
1362 R"(#version 310 es
1363 #extension GL_EXT_geometry_shader : require
1364
1365 out int my_out;
1366
1367 void main()
1368 {
1369 my_out = gl_Layer;
1370 })";
1371
1372 compile(shaderString);
1373
1374 ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1375
1376 const auto &inputVaryings = mTranslator->getInputVaryings();
1377 ASSERT_EQ(1u, inputVaryings.size());
1378
1379 const ShaderVariable *varying = &inputVaryings[0];
1380 EXPECT_EQ("gl_Layer", varying->name);
1381 EXPECT_FALSE(varying->isArray());
1382 EXPECT_FALSE(varying->isStruct());
1383 EXPECT_TRUE(varying->staticUse);
1384 EXPECT_TRUE(varying->active);
1385 EXPECT_TRUE(varying->isBuiltIn());
1386 EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1387 EXPECT_GLENUM_EQ(GL_INT, varying->type);
1388 }
1389
1390 // Test collecting the location of vertex shader outputs.
TEST_F(CollectVertexVariablesES31Test,CollectOutputWithLocation)1391 TEST_F(CollectVertexVariablesES31Test, CollectOutputWithLocation)
1392 {
1393 const std::string &shaderString =
1394 R"(#version 310 es
1395 out vec4 v_output1;
1396 layout (location = 1) out vec4 v_output2;
1397 void main()
1398 {
1399 })";
1400
1401 compile(shaderString);
1402
1403 const auto &outputVaryings = mTranslator->getOutputVaryings();
1404 ASSERT_EQ(2u, outputVaryings.size());
1405
1406 const ShaderVariable *varying1 = &outputVaryings[0];
1407 EXPECT_EQ("v_output1", varying1->name);
1408 EXPECT_EQ(-1, varying1->location);
1409
1410 const ShaderVariable *varying2 = &outputVaryings[1];
1411 EXPECT_EQ("v_output2", varying2->name);
1412 EXPECT_EQ(1, varying2->location);
1413 }
1414
1415 // Test collecting the location of fragment shader inputs.
TEST_F(CollectFragmentVariablesES31Test,CollectInputWithLocation)1416 TEST_F(CollectFragmentVariablesES31Test, CollectInputWithLocation)
1417 {
1418 const std::string &shaderString =
1419 R"(#version 310 es
1420 precision mediump float;
1421 in vec4 f_input1;
1422 layout (location = 1) in vec4 f_input2;
1423 layout (location = 0) out vec4 o_color;
1424 void main()
1425 {
1426 o_color = f_input2;
1427 })";
1428
1429 compile(shaderString);
1430
1431 const auto &inputVaryings = mTranslator->getInputVaryings();
1432 ASSERT_EQ(2u, inputVaryings.size());
1433
1434 const ShaderVariable *varying1 = &inputVaryings[0];
1435 EXPECT_EQ("f_input1", varying1->name);
1436 EXPECT_EQ(-1, varying1->location);
1437
1438 const ShaderVariable *varying2 = &inputVaryings[1];
1439 EXPECT_EQ("f_input2", varying2->name);
1440 EXPECT_EQ(1, varying2->location);
1441 }
1442
1443 // Test collecting the inputs of a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInputs)1444 TEST_F(CollectGeometryVariablesTest, CollectInputs)
1445 {
1446 const std::string &shaderString =
1447 R"(#version 310 es
1448 #extension GL_EXT_geometry_shader : require
1449 layout (points) in;
1450 layout (points, max_vertices = 2) out;
1451 in vec4 texcoord1[];
1452 in vec4 texcoord2[1];
1453 void main()
1454 {
1455 gl_Position = texcoord1[0];
1456 gl_Position += texcoord2[0];
1457 EmitVertex();
1458 })";
1459
1460 compile(shaderString);
1461
1462 EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1463
1464 const auto &inputVaryings = mTranslator->getInputVaryings();
1465 ASSERT_EQ(2u, inputVaryings.size());
1466
1467 const std::string kVaryingName[] = {"texcoord1", "texcoord2"};
1468
1469 for (size_t i = 0; i < inputVaryings.size(); ++i)
1470 {
1471 const ShaderVariable &varying = inputVaryings[i];
1472
1473 EXPECT_EQ(kVaryingName[i], varying.name);
1474 EXPECT_TRUE(varying.isArray());
1475 EXPECT_FALSE(varying.isStruct());
1476 EXPECT_TRUE(varying.staticUse);
1477 EXPECT_TRUE(varying.active);
1478 EXPECT_FALSE(varying.isBuiltIn());
1479 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1480 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1481 EXPECT_FALSE(varying.isInvariant);
1482 ASSERT_EQ(1u, varying.arraySizes.size());
1483 EXPECT_EQ(1u, varying.arraySizes.back());
1484 }
1485 }
1486
1487 // Test that the unsized input of a geometry shader can be correctly collected.
TEST_F(CollectGeometryVariablesTest,CollectInputArraySizeForUnsizedInput)1488 TEST_F(CollectGeometryVariablesTest, CollectInputArraySizeForUnsizedInput)
1489 {
1490 const std::array<std::string, 5> kInputPrimitives = {
1491 {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
1492
1493 const GLuint kArraySizeForInputPrimitives[] = {1u, 2u, 4u, 3u, 6u};
1494
1495 const std::string &kVariableDeclaration = "in vec4 texcoord[];\n";
1496 const std::string &kFunctionBody =
1497 R"(void main()
1498 {
1499 gl_Position = texcoord[0];
1500 })";
1501
1502 for (size_t i = 0; i < kInputPrimitives.size(); ++i)
1503 {
1504 compileGeometryShaderWithInputPrimitive(kInputPrimitives[i], kVariableDeclaration,
1505 kFunctionBody);
1506
1507 const auto &inputVaryings = mTranslator->getInputVaryings();
1508 ASSERT_EQ(1u, inputVaryings.size());
1509
1510 const ShaderVariable *varying = &inputVaryings[0];
1511 EXPECT_EQ("texcoord", varying->name);
1512 ASSERT_EQ(1u, varying->arraySizes.size());
1513 EXPECT_EQ(kArraySizeForInputPrimitives[i], varying->arraySizes.back());
1514 }
1515 }
1516
1517 // Test collecting inputs using interpolation qualifiers in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInputsWithInterpolationQualifiers)1518 TEST_F(CollectGeometryVariablesTest, CollectInputsWithInterpolationQualifiers)
1519 {
1520 const std::string &kHeader =
1521 "#version 310 es\n"
1522 "#extension GL_EXT_geometry_shader : require\n";
1523 const std::string &kLayout =
1524 "layout (points) in;\n"
1525 "layout (points, max_vertices = 2) out;\n";
1526
1527 const std::array<std::string, 3> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};
1528
1529 const std::array<InterpolationType, 3> kInterpolationType = {
1530 {INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1531
1532 const std::string &kFunctionBody =
1533 R"(void main()
1534 {
1535 gl_Position = texcoord[0];
1536 EmitVertex();
1537 })";
1538
1539 for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1540 {
1541 const std::string &qualifier = kInterpolationQualifiers[i];
1542
1543 std::ostringstream stream1;
1544 stream1 << kHeader << kLayout << qualifier << " in vec4 texcoord[];\n" << kFunctionBody;
1545 compile(stream1.str());
1546
1547 const auto &inputVaryings = mTranslator->getInputVaryings();
1548 ASSERT_EQ(1u, inputVaryings.size());
1549 const ShaderVariable *varying = &inputVaryings[0];
1550 EXPECT_EQ("texcoord", varying->name);
1551 EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1552 }
1553 }
1554
1555 // Test collecting outputs using interpolation qualifiers in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectOutputsWithInterpolationQualifiers)1556 TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInterpolationQualifiers)
1557 {
1558 const std::string &kHeader =
1559 "#version 310 es\n"
1560 "#extension GL_EXT_geometry_shader : require\n"
1561 "layout (points) in;\n"
1562 "layout (points, max_vertices = 2) out;\n";
1563
1564 const std::array<std::string, 4> kInterpolationQualifiers = {
1565 {"", "flat", "smooth", "centroid"}};
1566
1567 const std::array<InterpolationType, 4> kInterpolationType = {
1568 {INTERPOLATION_SMOOTH, INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1569
1570 const std::string &kFunctionBody =
1571 "void main()\n"
1572 "{\n"
1573 " texcoord = vec4(1.0, 0.0, 0.0, 1.0);\n"
1574 "}\n";
1575
1576 for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1577 {
1578 const std::string &qualifier = kInterpolationQualifiers[i];
1579 std::ostringstream stream;
1580 stream << kHeader << qualifier << " out vec4 texcoord;\n" << kFunctionBody;
1581
1582 compile(stream.str());
1583 const auto &outputVaryings = mTranslator->getOutputVaryings();
1584 ASSERT_EQ(1u, outputVaryings.size());
1585
1586 const ShaderVariable *varying = &outputVaryings[0];
1587 EXPECT_EQ("texcoord", varying->name);
1588 EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1589 EXPECT_FALSE(varying->isInvariant);
1590 }
1591 }
1592
1593 // Test collecting outputs using 'invariant' qualifier in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectOutputsWithInvariant)1594 TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInvariant)
1595 {
1596 const std::string &shaderString =
1597 R"(#version 310 es
1598 #extension GL_EXT_geometry_shader : require
1599 layout (points) in;
1600 layout (points, max_vertices = 2) out;
1601 invariant out vec4 texcoord;
1602 void main()
1603 {
1604 texcoord = vec4(1.0, 0.0, 0.0, 1.0);
1605 })";
1606
1607 compile(shaderString);
1608
1609 const auto &outputVaryings = mTranslator->getOutputVaryings();
1610 ASSERT_EQ(1u, outputVaryings.size());
1611
1612 const ShaderVariable *varying = &outputVaryings[0];
1613 EXPECT_EQ("texcoord", varying->name);
1614 EXPECT_TRUE(varying->isInvariant);
1615 }
1616
1617 // Test collecting a varying variable that is used inside a folded ternary operator. The result of
1618 // the folded ternary operator has a different qualifier from the original variable, which makes
1619 // this case tricky.
TEST_F(CollectFragmentVariablesTest,VaryingUsedInsideFoldedTernary)1620 TEST_F(CollectFragmentVariablesTest, VaryingUsedInsideFoldedTernary)
1621 {
1622 const std::string &shaderString =
1623 R"(#version 300 es
1624 precision highp float;
1625 centroid in float vary;
1626 out vec4 color;
1627 void main() {
1628 color = vec4(0.0, true ? vary : 0.0, 0.0, 1.0);
1629 })";
1630
1631 compile(shaderString);
1632
1633 const std::vector<ShaderVariable> &varyings = mTranslator->getInputVaryings();
1634 ASSERT_EQ(1u, varyings.size());
1635
1636 const ShaderVariable *varying = &varyings[0];
1637
1638 EXPECT_FALSE(varying->isArray());
1639 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying->precision);
1640 EXPECT_TRUE(varying->staticUse);
1641 EXPECT_TRUE(varying->active);
1642 EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
1643 EXPECT_EQ("vary", varying->name);
1644 EXPECT_EQ(DecorateName("vary"), varying->mappedName);
1645 EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
1646 }
1647
1648 // Test a variable that is statically used but not active. The variable is used in a branch of a
1649 // ternary op that is not evaluated.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveInTernaryOp)1650 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveInTernaryOp)
1651 {
1652 const std::string &shaderString =
1653 R"(#version 300 es
1654 precision mediump float;
1655 out vec4 out_fragColor;
1656 uniform float u;
1657 void main()
1658 {
1659 out_fragColor = vec4(true ? 0.0 : u);
1660 })";
1661
1662 compile(shaderString);
1663 checkUniformStaticallyUsedButNotActive("u");
1664 }
1665
1666 // Test a variable that is statically used but not active. The variable is a return value in an
1667 // unused function.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsReturnValue)1668 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsReturnValue)
1669 {
1670 const std::string &shaderString =
1671 R"(#version 300 es
1672 precision mediump float;
1673 out vec4 out_fragColor;
1674 uniform float u;
1675 float f() {
1676 return u;
1677 }
1678 void main()
1679 {
1680 out_fragColor = vec4(0.0);
1681 })";
1682
1683 compile(shaderString);
1684 checkUniformStaticallyUsedButNotActive("u");
1685 }
1686
1687 // Test a variable that is statically used but not active. The variable is an if statement condition
1688 // inside a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsIfCondition)1689 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsIfCondition)
1690 {
1691 const std::string &shaderString =
1692 R"(#version 300 es
1693 precision mediump float;
1694 out vec4 out_fragColor;
1695 uniform bool u;
1696 void main()
1697 {
1698 if (false) {
1699 if (u) {
1700 out_fragColor = vec4(1.0);
1701 }
1702 }
1703 out_fragColor = vec4(0.0);
1704 })";
1705
1706 compile(shaderString);
1707 checkUniformStaticallyUsedButNotActive("u");
1708 }
1709
1710 // Test a variable that is statically used but not active. The variable is a constructor argument in
1711 // a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsConstructorArgument)1712 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsConstructorArgument)
1713 {
1714 const std::string &shaderString =
1715 R"(#version 300 es
1716 precision mediump float;
1717 out vec4 out_fragColor;
1718 uniform float u;
1719 void main()
1720 {
1721 if (false) {
1722 out_fragColor = vec4(u);
1723 }
1724 out_fragColor = vec4(0.0);
1725 })";
1726
1727 compile(shaderString);
1728 checkUniformStaticallyUsedButNotActive("u");
1729 }
1730
1731 // Test a variable that is statically used but not active. The variable is a binary operator operand
1732 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsBinaryOpOperand)1733 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsBinaryOpOperand)
1734 {
1735 const std::string &shaderString =
1736 R"(#version 300 es
1737 precision mediump float;
1738 out vec4 out_fragColor;
1739 uniform vec4 u;
1740 void main()
1741 {
1742 if (false) {
1743 out_fragColor = u + 1.0;
1744 }
1745 out_fragColor = vec4(0.0);
1746 })";
1747
1748 compile(shaderString);
1749 checkUniformStaticallyUsedButNotActive("u");
1750 }
1751
1752 // Test a variable that is statically used but not active. The variable is a comparison operator
1753 // operand in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsComparisonOpOperand)1754 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsComparisonOpOperand)
1755 {
1756 const std::string &shaderString =
1757 R"(#version 300 es
1758 precision mediump float;
1759 out vec4 out_fragColor;
1760 uniform vec4 u;
1761 void main()
1762 {
1763 if (false) {
1764 if (u == vec4(1.0))
1765 {
1766 out_fragColor = vec4(1.0);
1767 }
1768 }
1769 out_fragColor = vec4(0.0);
1770 })";
1771
1772 compile(shaderString);
1773 checkUniformStaticallyUsedButNotActive("u");
1774 }
1775
1776 // Test a variable that is statically used but not active. The variable is an unary operator operand
1777 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsUnaryOpOperand)1778 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsUnaryOpOperand)
1779 {
1780 const std::string &shaderString =
1781 R"(#version 300 es
1782 precision mediump float;
1783 out vec4 out_fragColor;
1784 uniform vec4 u;
1785 void main()
1786 {
1787 if (false) {
1788 out_fragColor = -u;
1789 }
1790 out_fragColor = vec4(0.0);
1791 })";
1792
1793 compile(shaderString);
1794 checkUniformStaticallyUsedButNotActive("u");
1795 }
1796
1797 // Test a variable that is statically used but not active. The variable is an rvalue in an assigment
1798 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsAssignmentRValue)1799 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsAssignmentRValue)
1800 {
1801 const std::string &shaderString =
1802 R"(#version 300 es
1803 precision mediump float;
1804 out vec4 out_fragColor;
1805 uniform vec4 u;
1806 void main()
1807 {
1808 if (false) {
1809 out_fragColor = u;
1810 }
1811 out_fragColor = vec4(0.0);
1812 })";
1813
1814 compile(shaderString);
1815 checkUniformStaticallyUsedButNotActive("u");
1816 }
1817
1818 // Test a variable that is statically used but not active. The variable is a comma operator operand
1819 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsCommaOperand)1820 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsCommaOperand)
1821 {
1822 const std::string &shaderString =
1823 R"(#version 300 es
1824 precision mediump float;
1825 out vec4 out_fragColor;
1826 uniform vec4 u;
1827 void main()
1828 {
1829 if (false) {
1830 out_fragColor = u, vec4(1.0);
1831 }
1832 out_fragColor = vec4(0.0);
1833 })";
1834
1835 compile(shaderString);
1836 checkUniformStaticallyUsedButNotActive("u");
1837 }
1838
1839 // Test a variable that is statically used but not active. The variable is a switch init statement
1840 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsSwitchInitStatement)1841 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsSwitchInitStatement)
1842 {
1843 const std::string &shaderString =
1844 R"(#version 300 es
1845 precision mediump float;
1846 out vec4 out_fragColor;
1847 uniform int u;
1848 void main()
1849 {
1850 if (false)
1851 {
1852 switch (u)
1853 {
1854 case 1:
1855 out_fragColor = vec4(2.0);
1856 default:
1857 out_fragColor = vec4(1.0);
1858 }
1859 }
1860 out_fragColor = vec4(0.0);
1861 })";
1862
1863 compile(shaderString);
1864 checkUniformStaticallyUsedButNotActive("u");
1865 }
1866
1867 // Test a variable that is statically used but not active. The variable is a loop condition in a
1868 // block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsLoopCondition)1869 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopCondition)
1870 {
1871 const std::string &shaderString =
1872 R"(#version 300 es
1873 precision mediump float;
1874 out vec4 out_fragColor;
1875 uniform bool u;
1876 void main()
1877 {
1878 int counter = 0;
1879 if (false)
1880 {
1881 while (u)
1882 {
1883 if (++counter > 2)
1884 {
1885 break;
1886 }
1887 }
1888 }
1889 out_fragColor = vec4(0.0);
1890 })";
1891
1892 compile(shaderString);
1893 checkUniformStaticallyUsedButNotActive("u");
1894 }
1895
1896 // Test a variable that is statically used but not active. The variable is a loop expression in a
1897 // block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsLoopExpression)1898 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopExpression)
1899 {
1900 const std::string &shaderString =
1901 R"(#version 300 es
1902 precision mediump float;
1903 out vec4 out_fragColor;
1904 uniform bool u;
1905 void main()
1906 {
1907 if (false)
1908 {
1909 for (int i = 0; i < 3; u)
1910 {
1911 ++i;
1912 }
1913 }
1914 out_fragColor = vec4(0.0);
1915 })";
1916
1917 compile(shaderString);
1918 checkUniformStaticallyUsedButNotActive("u");
1919 }
1920
1921 // Test a variable that is statically used but not active. The variable is a vector index in a block
1922 // that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsVectorIndex)1923 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsVectorIndex)
1924 {
1925 const std::string &shaderString =
1926 R"(#version 300 es
1927 precision mediump float;
1928 out vec4 out_fragColor;
1929 uniform int u;
1930 void main()
1931 {
1932 vec4 color = vec4(0.0);
1933 if (false)
1934 {
1935 color[u] = 1.0;
1936 }
1937 out_fragColor = color;
1938 })";
1939
1940 compile(shaderString);
1941 checkUniformStaticallyUsedButNotActive("u");
1942 }
1943
1944 // Test a variable that is statically used but not active. The variable is referenced in a block
1945 // that's not executed. This is a bit of a corner case with some room for interpretation, but we
1946 // treat the variable as statically used.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveJustAReference)1947 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReference)
1948 {
1949 const std::string &shaderString =
1950 R"(#version 300 es
1951 precision mediump float;
1952 out vec4 out_fragColor;
1953 uniform int u;
1954 void main()
1955 {
1956 vec4 color = vec4(0.0);
1957 if (false)
1958 {
1959 u;
1960 }
1961 out_fragColor = color;
1962 })";
1963
1964 compile(shaderString);
1965 checkUniformStaticallyUsedButNotActive("u");
1966 }
1967
1968 // Test a variable that is statically used but not active. The variable is referenced in a block
1969 // without braces that's not executed. This is a bit of a corner case with some room for
1970 // interpretation, but we treat the variable as statically used.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveJustAReferenceNoBracesIf)1971 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReferenceNoBracesIf)
1972 {
1973 const std::string &shaderString =
1974 R"(#version 300 es
1975 precision mediump float;
1976 out vec4 out_fragColor;
1977 uniform int u;
1978 void main()
1979 {
1980 vec4 color = vec4(0.0);
1981 if (false)
1982 u;
1983 out_fragColor = color;
1984 })";
1985
1986 compile(shaderString);
1987 checkUniformStaticallyUsedButNotActive("u");
1988 }
1989
1990 // Test a variable that is referenced in a loop body without braces.
TEST_F(CollectFragmentVariablesTest,JustAVariableReferenceInNoBracesLoop)1991 TEST_F(CollectFragmentVariablesTest, JustAVariableReferenceInNoBracesLoop)
1992 {
1993 const std::string &shaderString =
1994 R"(#version 300 es
1995 precision mediump float;
1996 out vec4 out_fragColor;
1997 uniform int u;
1998 void main()
1999 {
2000 vec4 color = vec4(0.0);
2001 while (false)
2002 u;
2003 out_fragColor = color;
2004 })";
2005
2006 compile(shaderString);
2007
2008 const auto &uniforms = mTranslator->getUniforms();
2009 ASSERT_EQ(1u, uniforms.size());
2010
2011 const ShaderVariable &uniform = uniforms[0];
2012 EXPECT_EQ("u", uniform.name);
2013 EXPECT_TRUE(uniform.staticUse);
2014 // Note that we don't check the active flag here - the usage of the uniform is not currently
2015 // being optimized away.
2016 }
2017
2018 // Test an interface block member variable that is statically used but not active.
TEST_F(CollectVertexVariablesTest,StaticallyUsedButNotActiveSimpleInterfaceBlock)2019 TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveSimpleInterfaceBlock)
2020 {
2021 const std::string &shaderString =
2022 R"(#version 300 es
2023 uniform b
2024 {
2025 float f;
2026 };
2027 void main() {
2028 gl_Position = vec4(true ? 0.0 : f);
2029 })";
2030
2031 compile(shaderString);
2032
2033 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2034 ASSERT_EQ(1u, interfaceBlocks.size());
2035 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2036
2037 EXPECT_EQ("b", interfaceBlock.name);
2038 EXPECT_TRUE(interfaceBlock.staticUse);
2039 EXPECT_FALSE(interfaceBlock.active);
2040
2041 ASSERT_EQ(1u, interfaceBlock.fields.size());
2042 const ShaderVariable &field = interfaceBlock.fields[0];
2043
2044 EXPECT_EQ("f", field.name);
2045 EXPECT_TRUE(field.staticUse);
2046 EXPECT_FALSE(field.active);
2047 }
2048
2049 // Test an interface block instance variable that is statically used but not active.
TEST_F(CollectVertexVariablesTest,StaticallyUsedButNotActiveInstancedInterfaceBlock)2050 TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveInstancedInterfaceBlock)
2051 {
2052 const std::string &shaderString =
2053 R"(#version 300 es
2054 uniform b
2055 {
2056 float f;
2057 } blockInstance;
2058 void main() {
2059 gl_Position = vec4(true ? 0.0 : blockInstance.f);
2060 })";
2061
2062 compile(shaderString);
2063
2064 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2065 ASSERT_EQ(1u, interfaceBlocks.size());
2066 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2067
2068 EXPECT_EQ("b", interfaceBlock.name);
2069 EXPECT_TRUE(interfaceBlock.staticUse);
2070 EXPECT_FALSE(interfaceBlock.active);
2071
2072 ASSERT_EQ(1u, interfaceBlock.fields.size());
2073 const ShaderVariable &field = interfaceBlock.fields[0];
2074
2075 EXPECT_EQ("f", field.name);
2076 // See TODO in CollectVariables.cpp about tracking instanced interface block field static use.
2077 // EXPECT_TRUE(field.staticUse);
2078 EXPECT_FALSE(field.active);
2079 }
2080
2081 // Test an interface block member variable that is statically used. The variable is used to call
2082 // array length method.
TEST_F(CollectVertexVariablesTest,StaticallyUsedInArrayLengthOp)2083 TEST_F(CollectVertexVariablesTest, StaticallyUsedInArrayLengthOp)
2084 {
2085 const std::string &shaderString =
2086 R"(#version 300 es
2087 uniform b
2088 {
2089 float f[3];
2090 };
2091 void main() {
2092 if (f.length() > 1)
2093 {
2094 gl_Position = vec4(1.0);
2095 }
2096 else
2097 {
2098 gl_Position = vec4(0.0);
2099 }
2100 })";
2101
2102 compile(shaderString);
2103
2104 const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2105 ASSERT_EQ(1u, interfaceBlocks.size());
2106 const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2107
2108 EXPECT_EQ("b", interfaceBlock.name);
2109 EXPECT_TRUE(interfaceBlock.staticUse);
2110 }
2111
2112 // Test a varying that is declared invariant but not otherwise used.
TEST_F(CollectVertexVariablesTest,VaryingOnlyDeclaredInvariant)2113 TEST_F(CollectVertexVariablesTest, VaryingOnlyDeclaredInvariant)
2114 {
2115 const std::string &shaderString =
2116 R"(precision mediump float;
2117 varying float vf;
2118 invariant vf;
2119 void main()
2120 {
2121 })";
2122
2123 compile(shaderString);
2124
2125 const auto &varyings = mTranslator->getOutputVaryings();
2126 ASSERT_EQ(1u, varyings.size());
2127
2128 const ShaderVariable &varying = varyings[0];
2129 EXPECT_EQ("vf", varying.name);
2130 EXPECT_FALSE(varying.staticUse);
2131 EXPECT_FALSE(varying.active);
2132 }
2133
2134 // Test an output variable that is declared with the index layout qualifier from
2135 // EXT_blend_func_extended.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL3EXTBlendFuncExtendedIndex)2136 TEST_F(CollectFragmentVariablesTest, OutputVarESSL3EXTBlendFuncExtendedIndex)
2137 {
2138 const std::string &shaderString =
2139 R"(#version 300 es
2140 #extension GL_EXT_blend_func_extended : require
2141 precision mediump float;
2142 layout(location = 0, index = 1) out float outVar;
2143 void main()
2144 {
2145 outVar = 0.0;
2146 })";
2147
2148 compile(shaderString);
2149
2150 const auto &outputs = mTranslator->getOutputVariables();
2151 ASSERT_EQ(1u, outputs.size());
2152
2153 const ShaderVariable &output = outputs[0];
2154 EXPECT_EQ("outVar", output.name);
2155 EXPECT_TRUE(output.staticUse);
2156 EXPECT_TRUE(output.active);
2157 EXPECT_EQ(1, output.index);
2158 }
2159