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