• 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_FragData built-in usage in ESSL1 fragment shader is reflected in the output
638 // variables list, even if the EXT_draw_buffers extension isn't exposed. This covers the
639 // usage in the dEQP test dEQP-GLES3.functional.shaders.fragdata.draw_buffers.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDataUniform)640 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDataUniform)
641 {
642     const std::string &fragDataShader =
643         "precision mediump float;\n"
644         "uniform int uniIndex;"
645         "void main() {\n"
646         "   gl_FragData[uniIndex] = vec4(1.0);\n"
647         "}\n";
648 
649     ShBuiltInResources resources       = mTranslator->getResources();
650     const unsigned int kMaxDrawBuffers = 3u;
651     resources.MaxDrawBuffers           = kMaxDrawBuffers;
652     initTranslator(resources);
653 
654     const ShaderVariable *outputVariable = nullptr;
655     validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
656     ASSERT_NE(outputVariable, nullptr);
657     ASSERT_EQ(1u, outputVariable->arraySizes.size());
658     EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
659     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
660     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
661 }
662 
663 // Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
664 // variables list. Also test that the precision is mediump.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDepthMediump)665 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthMediump)
666 {
667     const std::string &fragDepthShader =
668         "#extension GL_EXT_frag_depth : require\n"
669         "precision mediump float;\n"
670         "void main() {\n"
671         "   gl_FragDepthEXT = 0.7;"
672         "}\n";
673 
674     ShBuiltInResources resources = mTranslator->getResources();
675     resources.EXT_frag_depth     = 1;
676     initTranslator(resources);
677 
678     const ShaderVariable *outputVariable = nullptr;
679     validateOutputVariableForShader(fragDepthShader, 0u, "gl_FragDepthEXT", &outputVariable);
680     ASSERT_NE(outputVariable, nullptr);
681     EXPECT_FALSE(outputVariable->isArray());
682     EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
683     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
684 }
685 
686 // Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output
687 // variables list. Also test that the precision is highp if user requests it.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1FragDepthHighp)688 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp)
689 {
690     const std::string &fragDepthHighShader =
691         "#extension GL_EXT_frag_depth : require\n"
692         "void main() {\n"
693         "   gl_FragDepthEXT = 0.7;"
694         "}\n";
695 
696     ShBuiltInResources resources    = mTranslator->getResources();
697     resources.EXT_frag_depth        = 1;
698     resources.FragmentPrecisionHigh = 1;
699     initTranslator(resources);
700 
701     const ShaderVariable *outputVariable = nullptr;
702     validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepthEXT", &outputVariable);
703     ASSERT_NE(outputVariable, nullptr);
704     EXPECT_FALSE(outputVariable->isArray());
705     EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
706     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
707 }
708 
709 // Test that gl_FragData built-in usage in ESSL3 fragment shader is reflected in the output
710 // variables list. Also test that the precision is highp.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL3FragDepthHighp)711 TEST_F(CollectFragmentVariablesTest, OutputVarESSL3FragDepthHighp)
712 {
713     const std::string &fragDepthHighShader =
714         "#version 300 es\n"
715         "precision mediump float;\n"
716         "void main() {\n"
717         "   gl_FragDepth = 0.7;"
718         "}\n";
719 
720     ShBuiltInResources resources = mTranslator->getResources();
721     resources.EXT_frag_depth     = 1;
722     initTranslator(resources);
723 
724     const ShaderVariable *outputVariable = nullptr;
725     validateOutputVariableForShader(fragDepthHighShader, 0u, "gl_FragDepth", &outputVariable);
726     ASSERT_NE(outputVariable, nullptr);
727     EXPECT_FALSE(outputVariable->isArray());
728     EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type);
729     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision);
730 }
731 
732 // Test that gl_SecondaryFragColorEXT built-in usage in ESSL1 fragment shader is reflected in the
733 // output variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1EXTBlendFuncExtendedSecondaryFragColor)734 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragColor)
735 {
736     const char *secondaryFragColorShader =
737         "#extension GL_EXT_blend_func_extended : require\n"
738         "precision mediump float;\n"
739         "void main() {\n"
740         "   gl_FragColor = vec4(1.0);\n"
741         "   gl_SecondaryFragColorEXT = vec4(1.0);\n"
742         "}\n";
743 
744     const unsigned int kMaxDrawBuffers = 3u;
745     ShBuiltInResources resources       = mTranslator->getResources();
746     resources.EXT_blend_func_extended  = 1;
747     resources.EXT_draw_buffers         = 1;
748     resources.MaxDrawBuffers           = kMaxDrawBuffers;
749     resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
750     initTranslator(resources);
751 
752     const ShaderVariable *outputVariable = nullptr;
753     validateOutputVariableForShader(secondaryFragColorShader, 0u, "gl_FragColor", &outputVariable);
754     ASSERT_NE(outputVariable, nullptr);
755     EXPECT_FALSE(outputVariable->isArray());
756     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
757     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
758 
759     outputVariable = nullptr;
760     validateOutputVariableForShader(secondaryFragColorShader, 1u, "gl_SecondaryFragColorEXT",
761                                     &outputVariable);
762     ASSERT_NE(outputVariable, nullptr);
763     EXPECT_FALSE(outputVariable->isArray());
764     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
765     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
766 }
767 
768 // Test that gl_SecondaryFragDataEXT built-in usage in ESSL1 fragment shader is reflected in the
769 // output variables list.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL1EXTBlendFuncExtendedSecondaryFragData)770 TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondaryFragData)
771 {
772     const char *secondaryFragDataShader =
773         "#extension GL_EXT_blend_func_extended : require\n"
774         "#extension GL_EXT_draw_buffers : require\n"
775         "precision mediump float;\n"
776         "void main() {\n"
777         "   gl_FragData[0] = vec4(1.0);\n"
778         "   gl_FragData[1] = vec4(0.5);\n"
779         "   gl_SecondaryFragDataEXT[0] = vec4(1.0);\n"
780         "   gl_SecondaryFragDataEXT[1] = vec4(0.8);\n"
781         "}\n";
782     const unsigned int kMaxDrawBuffers = 3u;
783     ShBuiltInResources resources       = mTranslator->getResources();
784     resources.EXT_blend_func_extended  = 1;
785     resources.EXT_draw_buffers         = 1;
786     resources.MaxDrawBuffers           = kMaxDrawBuffers;
787     resources.MaxDualSourceDrawBuffers = resources.MaxDrawBuffers;
788     initTranslator(resources);
789 
790     const ShaderVariable *outputVariable = nullptr;
791     validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
792     ASSERT_NE(outputVariable, nullptr);
793     ASSERT_EQ(1u, outputVariable->arraySizes.size());
794     EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
795     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
796     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
797 
798     outputVariable = nullptr;
799     validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT",
800                                     &outputVariable);
801     ASSERT_NE(outputVariable, nullptr);
802     ASSERT_EQ(1u, outputVariable->arraySizes.size());
803     EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
804     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
805     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
806 }
807 
SimpleTestHash(const char * str,size_t len)808 static khronos_uint64_t SimpleTestHash(const char *str, size_t len)
809 {
810     return static_cast<uint64_t>(len);
811 }
812 
813 class CollectHashedVertexVariablesTest : public CollectVertexVariablesTest
814 {
815   protected:
SetUp()816     void SetUp() override
817     {
818         // Initialize the translate with a hash function
819         ShBuiltInResources resources;
820         sh::InitBuiltInResources(&resources);
821         resources.HashFunction = SimpleTestHash;
822         initTranslator(resources);
823     }
824 };
825 
TEST_F(CollectHashedVertexVariablesTest,InstancedInterfaceBlock)826 TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
827 {
828     const std::string &shaderString =
829         "#version 300 es\n"
830         "uniform blockName {\n"
831         "  float field;\n"
832         "} blockInstance;"
833         "void main() {\n"
834         "   gl_Position = vec4(blockInstance.field, 0.0, 0.0, 1.0);\n"
835         "}\n";
836 
837     compile(shaderString);
838 
839     const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
840     ASSERT_EQ(1u, interfaceBlocks.size());
841 
842     const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
843 
844     EXPECT_EQ(0u, interfaceBlock.arraySize);
845     EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
846     EXPECT_EQ("blockName", interfaceBlock.name);
847     EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
848     EXPECT_EQ("webgl_9", interfaceBlock.mappedName);
849     EXPECT_TRUE(interfaceBlock.staticUse);
850     EXPECT_TRUE(interfaceBlock.active);
851 
852     ASSERT_EQ(1u, interfaceBlock.fields.size());
853 
854     const ShaderVariable &field = interfaceBlock.fields[0];
855 
856     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
857     EXPECT_TRUE(field.staticUse);
858     EXPECT_TRUE(field.active);
859     EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
860     EXPECT_EQ("field", field.name);
861     EXPECT_EQ("webgl_5", field.mappedName);
862     EXPECT_FALSE(field.isRowMajorLayout);
863     EXPECT_TRUE(field.fields.empty());
864 }
865 
866 // Test a struct uniform where the struct does have a name.
TEST_F(CollectHashedVertexVariablesTest,StructUniform)867 TEST_F(CollectHashedVertexVariablesTest, StructUniform)
868 {
869     const std::string &shaderString =
870         R"(#version 300 es
871         struct sType
872         {
873             float field;
874         };
875         uniform sType u;
876 
877         void main()
878         {
879             gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
880         })";
881 
882     compile(shaderString);
883 
884     const auto &uniforms = mTranslator->getUniforms();
885     ASSERT_EQ(1u, uniforms.size());
886 
887     const ShaderVariable &uniform = uniforms[0];
888 
889     EXPECT_FALSE(uniform.isArray());
890     EXPECT_EQ("u", uniform.name);
891     EXPECT_EQ("webgl_1", uniform.mappedName);
892     EXPECT_EQ("sType", uniform.structOrBlockName);
893     EXPECT_TRUE(uniform.staticUse);
894     EXPECT_TRUE(uniform.active);
895 
896     ASSERT_EQ(1u, uniform.fields.size());
897 
898     const ShaderVariable &field = uniform.fields[0];
899 
900     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
901     // We don't yet support tracking static use per field, but fields are marked statically used in
902     // case the struct is.
903     EXPECT_TRUE(field.staticUse);
904     EXPECT_TRUE(field.active);
905     EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
906     EXPECT_EQ("field", field.name);
907     EXPECT_EQ("webgl_5", field.mappedName);
908     EXPECT_TRUE(field.fields.empty());
909 }
910 
911 // Test a struct uniform where the struct doesn't have a name.
TEST_F(CollectHashedVertexVariablesTest,NamelessStructUniform)912 TEST_F(CollectHashedVertexVariablesTest, NamelessStructUniform)
913 {
914     const std::string &shaderString =
915         R"(#version 300 es
916         uniform struct
917         {
918             float field;
919         } u;
920 
921         void main()
922         {
923             gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
924         })";
925 
926     compile(shaderString);
927 
928     const auto &uniforms = mTranslator->getUniforms();
929     ASSERT_EQ(1u, uniforms.size());
930 
931     const ShaderVariable &uniform = uniforms[0];
932 
933     EXPECT_FALSE(uniform.isArray());
934     EXPECT_EQ("u", uniform.name);
935     EXPECT_EQ("webgl_1", uniform.mappedName);
936     EXPECT_EQ("", uniform.structOrBlockName);
937     EXPECT_TRUE(uniform.staticUse);
938     EXPECT_TRUE(uniform.active);
939 
940     ASSERT_EQ(1u, uniform.fields.size());
941 
942     const ShaderVariable &field = uniform.fields[0];
943 
944     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
945     // We don't yet support tracking static use per field, but fields are marked statically used in
946     // case the struct is.
947     EXPECT_TRUE(field.staticUse);
948     EXPECT_TRUE(field.active);
949     EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
950     EXPECT_EQ("field", field.name);
951     EXPECT_EQ("webgl_5", field.mappedName);
952     EXPECT_TRUE(field.fields.empty());
953 }
954 
955 // Test a uniform declaration with multiple declarators.
TEST_F(CollectFragmentVariablesTest,MultiDeclaration)956 TEST_F(CollectFragmentVariablesTest, MultiDeclaration)
957 {
958     const std::string &shaderString =
959         "#version 300 es\n"
960         "precision mediump float;\n"
961         "out vec4 out_fragColor;\n"
962         "uniform float uA, uB;\n"
963         "void main()\n"
964         "{\n"
965         "    vec4 color = vec4(uA, uA, uA, uB);\n"
966         "    out_fragColor = color;\n"
967         "}\n";
968 
969     compile(shaderString);
970 
971     const auto &uniforms = mTranslator->getUniforms();
972     ASSERT_EQ(2u, uniforms.size());
973 
974     const ShaderVariable &uniform = uniforms[0];
975     EXPECT_FALSE(uniform.isArray());
976     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniform.precision);
977     EXPECT_TRUE(uniform.staticUse);
978     EXPECT_TRUE(uniform.active);
979     EXPECT_GLENUM_EQ(GL_FLOAT, uniform.type);
980     EXPECT_EQ("uA", uniform.name);
981 
982     const ShaderVariable &uniformB = uniforms[1];
983     EXPECT_FALSE(uniformB.isArray());
984     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
985     EXPECT_TRUE(uniformB.staticUse);
986     EXPECT_TRUE(uniformB.active);
987     EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
988     EXPECT_EQ("uB", uniformB.name);
989 }
990 
991 // Test a uniform declaration starting with an empty declarator.
TEST_F(CollectFragmentVariablesTest,EmptyDeclarator)992 TEST_F(CollectFragmentVariablesTest, EmptyDeclarator)
993 {
994     const std::string &shaderString =
995         "#version 300 es\n"
996         "precision mediump float;\n"
997         "out vec4 out_fragColor;\n"
998         "uniform float /* empty declarator */, uB;\n"
999         "void main()\n"
1000         "{\n"
1001         "    out_fragColor = vec4(uB, uB, uB, uB);\n"
1002         "}\n";
1003 
1004     compile(shaderString);
1005 
1006     const auto &uniforms = mTranslator->getUniforms();
1007     ASSERT_EQ(1u, uniforms.size());
1008 
1009     const ShaderVariable &uniformB = uniforms[0];
1010     EXPECT_FALSE(uniformB.isArray());
1011     EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, uniformB.precision);
1012     EXPECT_TRUE(uniformB.staticUse);
1013     EXPECT_TRUE(uniformB.active);
1014     EXPECT_GLENUM_EQ(GL_FLOAT, uniformB.type);
1015     EXPECT_EQ("uB", uniformB.name);
1016 }
1017 
1018 // Test collecting variables from an instanced multiview shader that has an internal ViewID_OVR
1019 // varying.
TEST_F(CollectVertexVariablesTest,ViewID_OVR)1020 TEST_F(CollectVertexVariablesTest, ViewID_OVR)
1021 {
1022     const std::string &shaderString =
1023         "#version 300 es\n"
1024         "#extension GL_OVR_multiview2 : require\n"
1025         "precision mediump float;\n"
1026         "void main()\n"
1027         "{\n"
1028         "    gl_Position = vec4(0.0);\n"
1029         "}\n";
1030 
1031     ShBuiltInResources resources = mTranslator->getResources();
1032     resources.OVR_multiview2     = 1;
1033     resources.MaxViewsOVR        = 4;
1034     initTranslator(resources);
1035 
1036     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
1037                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
1038 
1039     // The internal ViewID_OVR varying is not exposed through the ShaderVars interface.
1040     const auto &varyings = mTranslator->getOutputVaryings();
1041     ASSERT_EQ(1u, varyings.size());
1042     const ShaderVariable *varying = &varyings[0];
1043     EXPECT_EQ("gl_Position", varying->name);
1044 }
1045 
1046 // Test all the fields of gl_in can be collected correctly in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectGLInFields)1047 TEST_F(CollectGeometryVariablesTest, CollectGLInFields)
1048 {
1049     const std::string &shaderString =
1050         R"(#version 310 es
1051         #extension GL_EXT_geometry_shader : require
1052 
1053         layout (points) in;
1054         layout (points, max_vertices = 2) out;
1055 
1056         void main()
1057         {
1058             vec4 value = gl_in[0].gl_Position;
1059             vec4 value2 = gl_in[0].gl_Position;
1060             gl_Position = value + value2;
1061             EmitVertex();
1062         })";
1063 
1064     compile(shaderString);
1065 
1066     EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1067 
1068     const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1069     ASSERT_EQ(1u, inVaryings.size());
1070 
1071     const ShaderVariable &glIn = inVaryings[0];
1072     EXPECT_EQ("gl_in", glIn.name);
1073     EXPECT_EQ("gl_PerVertex", glIn.structOrBlockName);
1074     EXPECT_TRUE(glIn.staticUse);
1075     EXPECT_TRUE(glIn.active);
1076     EXPECT_TRUE(glIn.isBuiltIn());
1077 
1078     ASSERT_EQ(1u, glIn.fields.size());
1079 
1080     const ShaderVariable &glPositionField = glIn.fields[0];
1081     EXPECT_EQ("gl_Position", glPositionField.name);
1082     EXPECT_FALSE(glPositionField.isArray());
1083     EXPECT_FALSE(glPositionField.isStruct());
1084     EXPECT_TRUE(glPositionField.staticUse);
1085     // Tracking for "active" not set up currently.
1086     // EXPECT_TRUE(glPositionField.active);
1087     EXPECT_TRUE(glPositionField.isBuiltIn());
1088     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, glPositionField.precision);
1089     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, glPositionField.type);
1090 }
1091 
1092 // Test the collected array size of gl_in matches the input primitive declaration.
TEST_F(CollectGeometryVariablesTest,GLInArraySize)1093 TEST_F(CollectGeometryVariablesTest, GLInArraySize)
1094 {
1095     const std::array<std::string, 5> kInputPrimitives = {
1096         {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
1097 
1098     const GLuint kArraySizeForInputPrimitives[] = {1u, 2u, 4u, 3u, 6u};
1099 
1100     const std::string &functionBody =
1101         R"(void main()
1102         {
1103             gl_Position = gl_in[0].gl_Position;
1104         })";
1105 
1106     for (size_t i = 0; i < kInputPrimitives.size(); ++i)
1107     {
1108         compileGeometryShaderWithInputPrimitive(kInputPrimitives[i], "", functionBody);
1109 
1110         const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1111         ASSERT_EQ(1u, inVaryings.size());
1112 
1113         const ShaderVariable &glIn = inVaryings[0];
1114         ASSERT_EQ("gl_in", glIn.name);
1115         EXPECT_EQ(kArraySizeForInputPrimitives[i], glIn.arraySizes[0]);
1116     }
1117 }
1118 
1119 // Test collecting gl_PrimitiveIDIn in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPrimitiveIDIn)1120 TEST_F(CollectGeometryVariablesTest, CollectPrimitiveIDIn)
1121 {
1122     const std::string &shaderString =
1123         R"(#version 310 es
1124         #extension GL_EXT_geometry_shader : require
1125         layout (points) in;
1126         layout (points, max_vertices = 2) out;
1127         void main()
1128         {
1129             gl_Position = vec4(gl_PrimitiveIDIn);
1130             EmitVertex();
1131         })";
1132 
1133     compile(shaderString);
1134 
1135     EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1136 
1137     const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1138     ASSERT_EQ(1u, inputVaryings.size());
1139 
1140     const ShaderVariable &varying = inputVaryings[0];
1141     EXPECT_EQ("gl_PrimitiveIDIn", varying.name);
1142     EXPECT_FALSE(varying.isArray());
1143     EXPECT_FALSE(varying.isStruct());
1144     EXPECT_TRUE(varying.staticUse);
1145     EXPECT_TRUE(varying.active);
1146     EXPECT_TRUE(varying.isBuiltIn());
1147     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1148     EXPECT_GLENUM_EQ(GL_INT, varying.type);
1149 }
1150 
1151 // Test collecting gl_InvocationID in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInvocationID)1152 TEST_F(CollectGeometryVariablesTest, CollectInvocationID)
1153 {
1154     const std::string &shaderString =
1155         R"(#version 310 es
1156         #extension GL_EXT_geometry_shader : require
1157         layout (points, invocations = 2) in;
1158         layout (points, max_vertices = 2) out;
1159         void main()
1160         {
1161             gl_Position = vec4(gl_InvocationID);
1162             EmitVertex();
1163         })";
1164 
1165     compile(shaderString);
1166 
1167     EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1168 
1169     const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1170     ASSERT_EQ(1u, inputVaryings.size());
1171 
1172     const ShaderVariable &varying = inputVaryings[0];
1173     EXPECT_EQ("gl_InvocationID", varying.name);
1174     EXPECT_FALSE(varying.isArray());
1175     EXPECT_FALSE(varying.isStruct());
1176     EXPECT_TRUE(varying.staticUse);
1177     EXPECT_TRUE(varying.active);
1178     EXPECT_TRUE(varying.isBuiltIn());
1179     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1180     EXPECT_GLENUM_EQ(GL_INT, varying.type);
1181 }
1182 
1183 // Test collecting gl_in in a geometry shader when gl_in is indexed by an expression.
TEST_F(CollectGeometryVariablesTest,CollectGLInIndexedByExpression)1184 TEST_F(CollectGeometryVariablesTest, CollectGLInIndexedByExpression)
1185 {
1186     const std::string &shaderString =
1187         R"(#version 310 es
1188         #extension GL_EXT_geometry_shader : require
1189         layout (triangles, invocations = 2) in;
1190         layout (points, max_vertices = 2) out;
1191         void main()
1192         {
1193             gl_Position = gl_in[gl_InvocationID + 1].gl_Position;
1194             EmitVertex();
1195         })";
1196 
1197     compile(shaderString);
1198 
1199     EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1200 
1201     const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1202     ASSERT_EQ(2u, inVaryings.size());
1203 
1204     bool foundGLIn         = false;
1205     bool foundInvocationID = false;
1206 
1207     for (const ShaderVariable &varying : inVaryings)
1208     {
1209         if (varying.name == "gl_in")
1210         {
1211             foundGLIn = true;
1212             EXPECT_TRUE(varying.isShaderIOBlock);
1213             EXPECT_EQ("gl_PerVertex", varying.structOrBlockName);
1214         }
1215         else if (varying.name == "gl_InvocationID")
1216         {
1217             foundInvocationID = true;
1218         }
1219     }
1220 
1221     EXPECT_TRUE(foundGLIn);
1222     EXPECT_TRUE(foundInvocationID);
1223 }
1224 
1225 // Test collecting gl_Position in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPosition)1226 TEST_F(CollectGeometryVariablesTest, CollectPosition)
1227 {
1228     const std::string &shaderString =
1229         R"(#version 310 es
1230         #extension GL_EXT_geometry_shader : require
1231         layout (points) in;
1232         layout (points, max_vertices = 2) out;
1233         void main()
1234         {
1235             gl_Position = vec4(0.1, 0.2, 0.3, 1);
1236         })";
1237 
1238     compile(shaderString);
1239 
1240     ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1241 
1242     const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1243     ASSERT_EQ(1u, outputVaryings.size());
1244 
1245     const ShaderVariable &varying = outputVaryings[0];
1246     EXPECT_EQ("gl_Position", varying.name);
1247     EXPECT_FALSE(varying.isArray());
1248     EXPECT_FALSE(varying.isStruct());
1249     EXPECT_TRUE(varying.staticUse);
1250     EXPECT_TRUE(varying.active);
1251     EXPECT_TRUE(varying.isBuiltIn());
1252     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1253     EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1254 }
1255 
1256 // Test collecting gl_PrimitiveID in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectPrimitiveID)1257 TEST_F(CollectGeometryVariablesTest, CollectPrimitiveID)
1258 {
1259     const std::string &shaderString =
1260         R"(#version 310 es
1261         #extension GL_EXT_geometry_shader : require
1262         layout (points) in;
1263         layout (points, max_vertices = 2) out;
1264         void main()
1265         {
1266             gl_PrimitiveID = 100;
1267         })";
1268 
1269     compile(shaderString);
1270 
1271     ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1272 
1273     const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1274     ASSERT_EQ(1u, outputVaryings.size());
1275 
1276     const ShaderVariable &varying = outputVaryings[0];
1277     EXPECT_EQ("gl_PrimitiveID", varying.name);
1278     EXPECT_FALSE(varying.isArray());
1279     EXPECT_FALSE(varying.isStruct());
1280     EXPECT_TRUE(varying.staticUse);
1281     EXPECT_TRUE(varying.active);
1282     EXPECT_TRUE(varying.isBuiltIn());
1283     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1284     EXPECT_GLENUM_EQ(GL_INT, varying.type);
1285 }
1286 
1287 // Test collecting gl_Layer in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectLayer)1288 TEST_F(CollectGeometryVariablesTest, CollectLayer)
1289 {
1290     const std::string &shaderString =
1291         R"(#version 310 es
1292         #extension GL_EXT_geometry_shader : require
1293         layout (points) in;
1294         layout (points, max_vertices = 2) out;
1295         void main()
1296         {
1297             gl_Layer = 2;
1298         })";
1299 
1300     compile(shaderString);
1301 
1302     ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1303 
1304     const auto &outputVaryings = mTranslator->getOutputVaryings();
1305     ASSERT_EQ(1u, outputVaryings.size());
1306 
1307     const ShaderVariable &varying = outputVaryings[0];
1308     EXPECT_EQ("gl_Layer", varying.name);
1309     EXPECT_FALSE(varying.isArray());
1310     EXPECT_FALSE(varying.isStruct());
1311     EXPECT_TRUE(varying.staticUse);
1312     EXPECT_TRUE(varying.active);
1313     EXPECT_TRUE(varying.isBuiltIn());
1314     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1315     EXPECT_GLENUM_EQ(GL_INT, varying.type);
1316 }
1317 
1318 // Test collecting gl_PrimitiveID in a fragment shader.
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest,CollectPrimitiveID)1319 TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectPrimitiveID)
1320 {
1321     const std::string &shaderString =
1322         R"(#version 310 es
1323         #extension GL_EXT_geometry_shader : require
1324 
1325         out int my_out;
1326 
1327         void main()
1328         {
1329             my_out = gl_PrimitiveID;
1330         })";
1331 
1332     compile(shaderString);
1333 
1334     ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1335 
1336     const auto &inputVaryings = mTranslator->getInputVaryings();
1337     ASSERT_EQ(1u, inputVaryings.size());
1338 
1339     const ShaderVariable *varying = &inputVaryings[0];
1340     EXPECT_EQ("gl_PrimitiveID", varying->name);
1341     EXPECT_FALSE(varying->isArray());
1342     EXPECT_FALSE(varying->isStruct());
1343     EXPECT_TRUE(varying->staticUse);
1344     EXPECT_TRUE(varying->active);
1345     EXPECT_TRUE(varying->isBuiltIn());
1346     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1347     EXPECT_GLENUM_EQ(GL_INT, varying->type);
1348 }
1349 
1350 // Test collecting gl_Layer in a fragment shader.
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest,CollectLayer)1351 TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectLayer)
1352 {
1353     const std::string &shaderString =
1354         R"(#version 310 es
1355         #extension GL_EXT_geometry_shader : require
1356 
1357         out int my_out;
1358 
1359         void main()
1360         {
1361             my_out = gl_Layer;
1362         })";
1363 
1364     compile(shaderString);
1365 
1366     ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1367 
1368     const auto &inputVaryings = mTranslator->getInputVaryings();
1369     ASSERT_EQ(1u, inputVaryings.size());
1370 
1371     const ShaderVariable *varying = &inputVaryings[0];
1372     EXPECT_EQ("gl_Layer", varying->name);
1373     EXPECT_FALSE(varying->isArray());
1374     EXPECT_FALSE(varying->isStruct());
1375     EXPECT_TRUE(varying->staticUse);
1376     EXPECT_TRUE(varying->active);
1377     EXPECT_TRUE(varying->isBuiltIn());
1378     EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1379     EXPECT_GLENUM_EQ(GL_INT, varying->type);
1380 }
1381 
1382 // Test collecting the location of vertex shader outputs.
TEST_F(CollectVertexVariablesES31Test,CollectOutputWithLocation)1383 TEST_F(CollectVertexVariablesES31Test, CollectOutputWithLocation)
1384 {
1385     const std::string &shaderString =
1386         R"(#version 310 es
1387         out vec4 v_output1;
1388         layout (location = 1) out vec4 v_output2;
1389         void main()
1390         {
1391         })";
1392 
1393     compile(shaderString);
1394 
1395     const auto &outputVaryings = mTranslator->getOutputVaryings();
1396     ASSERT_EQ(2u, outputVaryings.size());
1397 
1398     const ShaderVariable *varying1 = &outputVaryings[0];
1399     EXPECT_EQ("v_output1", varying1->name);
1400     EXPECT_EQ(-1, varying1->location);
1401 
1402     const ShaderVariable *varying2 = &outputVaryings[1];
1403     EXPECT_EQ("v_output2", varying2->name);
1404     EXPECT_EQ(1, varying2->location);
1405 }
1406 
1407 // Test collecting the location of fragment shader inputs.
TEST_F(CollectFragmentVariablesES31Test,CollectInputWithLocation)1408 TEST_F(CollectFragmentVariablesES31Test, CollectInputWithLocation)
1409 {
1410     const std::string &shaderString =
1411         R"(#version 310 es
1412         precision mediump float;
1413         in vec4 f_input1;
1414         layout (location = 1) in vec4 f_input2;
1415         layout (location = 0) out vec4 o_color;
1416         void main()
1417         {
1418             o_color = f_input2;
1419         })";
1420 
1421     compile(shaderString);
1422 
1423     const auto &inputVaryings = mTranslator->getInputVaryings();
1424     ASSERT_EQ(2u, inputVaryings.size());
1425 
1426     const ShaderVariable *varying1 = &inputVaryings[0];
1427     EXPECT_EQ("f_input1", varying1->name);
1428     EXPECT_EQ(-1, varying1->location);
1429 
1430     const ShaderVariable *varying2 = &inputVaryings[1];
1431     EXPECT_EQ("f_input2", varying2->name);
1432     EXPECT_EQ(1, varying2->location);
1433 }
1434 
1435 // Test collecting the inputs of a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInputs)1436 TEST_F(CollectGeometryVariablesTest, CollectInputs)
1437 {
1438     const std::string &shaderString =
1439         R"(#version 310 es
1440         #extension GL_EXT_geometry_shader : require
1441         layout (points) in;
1442         layout (points, max_vertices = 2) out;
1443         in vec4 texcoord1[];
1444         in vec4 texcoord2[1];
1445         void main()
1446         {
1447             gl_Position = texcoord1[0];
1448             gl_Position += texcoord2[0];
1449             EmitVertex();
1450         })";
1451 
1452     compile(shaderString);
1453 
1454     EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1455 
1456     const auto &inputVaryings = mTranslator->getInputVaryings();
1457     ASSERT_EQ(2u, inputVaryings.size());
1458 
1459     const std::string kVaryingName[] = {"texcoord1", "texcoord2"};
1460 
1461     for (size_t i = 0; i < inputVaryings.size(); ++i)
1462     {
1463         const ShaderVariable &varying = inputVaryings[i];
1464 
1465         EXPECT_EQ(kVaryingName[i], varying.name);
1466         EXPECT_TRUE(varying.isArray());
1467         EXPECT_FALSE(varying.isStruct());
1468         EXPECT_TRUE(varying.staticUse);
1469         EXPECT_TRUE(varying.active);
1470         EXPECT_FALSE(varying.isBuiltIn());
1471         EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1472         EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1473         EXPECT_FALSE(varying.isInvariant);
1474         ASSERT_EQ(1u, varying.arraySizes.size());
1475         EXPECT_EQ(1u, varying.arraySizes.back());
1476     }
1477 }
1478 
1479 // Test that the unsized input of a geometry shader can be correctly collected.
TEST_F(CollectGeometryVariablesTest,CollectInputArraySizeForUnsizedInput)1480 TEST_F(CollectGeometryVariablesTest, CollectInputArraySizeForUnsizedInput)
1481 {
1482     const std::array<std::string, 5> kInputPrimitives = {
1483         {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
1484 
1485     const GLuint kArraySizeForInputPrimitives[] = {1u, 2u, 4u, 3u, 6u};
1486 
1487     const std::string &kVariableDeclaration = "in vec4 texcoord[];\n";
1488     const std::string &kFunctionBody =
1489         R"(void main()
1490         {
1491             gl_Position = texcoord[0];
1492         })";
1493 
1494     for (size_t i = 0; i < kInputPrimitives.size(); ++i)
1495     {
1496         compileGeometryShaderWithInputPrimitive(kInputPrimitives[i], kVariableDeclaration,
1497                                                 kFunctionBody);
1498 
1499         const auto &inputVaryings = mTranslator->getInputVaryings();
1500         ASSERT_EQ(1u, inputVaryings.size());
1501 
1502         const ShaderVariable *varying = &inputVaryings[0];
1503         EXPECT_EQ("texcoord", varying->name);
1504         ASSERT_EQ(1u, varying->arraySizes.size());
1505         EXPECT_EQ(kArraySizeForInputPrimitives[i], varying->arraySizes.back());
1506     }
1507 }
1508 
1509 // Test collecting inputs using interpolation qualifiers in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectInputsWithInterpolationQualifiers)1510 TEST_F(CollectGeometryVariablesTest, CollectInputsWithInterpolationQualifiers)
1511 {
1512     const std::string &kHeader =
1513         "#version 310 es\n"
1514         "#extension GL_EXT_geometry_shader : require\n";
1515     const std::string &kLayout =
1516         "layout (points) in;\n"
1517         "layout (points, max_vertices = 2) out;\n";
1518 
1519     const std::array<std::string, 3> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};
1520 
1521     const std::array<InterpolationType, 3> kInterpolationType = {
1522         {INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1523 
1524     const std::string &kFunctionBody =
1525         R"(void main()
1526         {
1527             gl_Position = texcoord[0];
1528             EmitVertex();
1529         })";
1530 
1531     for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1532     {
1533         const std::string &qualifier = kInterpolationQualifiers[i];
1534 
1535         std::ostringstream stream1;
1536         stream1 << kHeader << kLayout << qualifier << " in vec4 texcoord[];\n" << kFunctionBody;
1537         compile(stream1.str());
1538 
1539         const auto &inputVaryings = mTranslator->getInputVaryings();
1540         ASSERT_EQ(1u, inputVaryings.size());
1541         const ShaderVariable *varying = &inputVaryings[0];
1542         EXPECT_EQ("texcoord", varying->name);
1543         EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1544     }
1545 }
1546 
1547 // Test collecting outputs using interpolation qualifiers in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectOutputsWithInterpolationQualifiers)1548 TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInterpolationQualifiers)
1549 {
1550     const std::string &kHeader =
1551         "#version 310 es\n"
1552         "#extension GL_EXT_geometry_shader : require\n"
1553         "layout (points) in;\n"
1554         "layout (points, max_vertices = 2) out;\n";
1555 
1556     const std::array<std::string, 4> kInterpolationQualifiers = {
1557         {"", "flat", "smooth", "centroid"}};
1558 
1559     const std::array<InterpolationType, 4> kInterpolationType = {
1560         {INTERPOLATION_SMOOTH, INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1561 
1562     const std::string &kFunctionBody =
1563         "void main()\n"
1564         "{\n"
1565         "    texcoord = vec4(1.0, 0.0, 0.0, 1.0);\n"
1566         "}\n";
1567 
1568     for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1569     {
1570         const std::string &qualifier = kInterpolationQualifiers[i];
1571         std::ostringstream stream;
1572         stream << kHeader << qualifier << " out vec4 texcoord;\n" << kFunctionBody;
1573 
1574         compile(stream.str());
1575         const auto &outputVaryings = mTranslator->getOutputVaryings();
1576         ASSERT_EQ(1u, outputVaryings.size());
1577 
1578         const ShaderVariable *varying = &outputVaryings[0];
1579         EXPECT_EQ("texcoord", varying->name);
1580         EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1581         EXPECT_FALSE(varying->isInvariant);
1582     }
1583 }
1584 
1585 // Test collecting outputs using 'invariant' qualifier in a geometry shader.
TEST_F(CollectGeometryVariablesTest,CollectOutputsWithInvariant)1586 TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInvariant)
1587 {
1588     const std::string &shaderString =
1589         R"(#version 310 es
1590         #extension GL_EXT_geometry_shader : require
1591         layout (points) in;
1592         layout (points, max_vertices = 2) out;
1593         invariant out vec4 texcoord;
1594         void main()
1595         {
1596             texcoord = vec4(1.0, 0.0, 0.0, 1.0);
1597         })";
1598 
1599     compile(shaderString);
1600 
1601     const auto &outputVaryings = mTranslator->getOutputVaryings();
1602     ASSERT_EQ(1u, outputVaryings.size());
1603 
1604     const ShaderVariable *varying = &outputVaryings[0];
1605     EXPECT_EQ("texcoord", varying->name);
1606     EXPECT_TRUE(varying->isInvariant);
1607 }
1608 
1609 // Test collecting a varying variable that is used inside a folded ternary operator. The result of
1610 // the folded ternary operator has a different qualifier from the original variable, which makes
1611 // this case tricky.
TEST_F(CollectFragmentVariablesTest,VaryingUsedInsideFoldedTernary)1612 TEST_F(CollectFragmentVariablesTest, VaryingUsedInsideFoldedTernary)
1613 {
1614     const std::string &shaderString =
1615         R"(#version 300 es
1616         precision highp float;
1617         centroid in float vary;
1618         out vec4 color;
1619         void main() {
1620            color = vec4(0.0, true ? vary : 0.0, 0.0, 1.0);
1621         })";
1622 
1623     compile(shaderString);
1624 
1625     const std::vector<ShaderVariable> &varyings = mTranslator->getInputVaryings();
1626     ASSERT_EQ(1u, varyings.size());
1627 
1628     const ShaderVariable *varying = &varyings[0];
1629 
1630     EXPECT_FALSE(varying->isArray());
1631     EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying->precision);
1632     EXPECT_TRUE(varying->staticUse);
1633     EXPECT_TRUE(varying->active);
1634     EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
1635     EXPECT_EQ("vary", varying->name);
1636     EXPECT_EQ(DecorateName("vary"), varying->mappedName);
1637     EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
1638 }
1639 
1640 // Test a variable that is statically used but not active. The variable is used in a branch of a
1641 // ternary op that is not evaluated.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveInTernaryOp)1642 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveInTernaryOp)
1643 {
1644     const std::string &shaderString =
1645         R"(#version 300 es
1646         precision mediump float;
1647         out vec4 out_fragColor;
1648         uniform float u;
1649         void main()
1650         {
1651             out_fragColor = vec4(true ? 0.0 : u);
1652         })";
1653 
1654     compile(shaderString);
1655     checkUniformStaticallyUsedButNotActive("u");
1656 }
1657 
1658 // Test a variable that is statically used but not active. The variable is a return value in an
1659 // unused function.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsReturnValue)1660 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsReturnValue)
1661 {
1662     const std::string &shaderString =
1663         R"(#version 300 es
1664         precision mediump float;
1665         out vec4 out_fragColor;
1666         uniform float u;
1667         float f() {
1668             return u;
1669         }
1670         void main()
1671         {
1672             out_fragColor = vec4(0.0);
1673         })";
1674 
1675     compile(shaderString);
1676     checkUniformStaticallyUsedButNotActive("u");
1677 }
1678 
1679 // Test a variable that is statically used but not active. The variable is an if statement condition
1680 // inside a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsIfCondition)1681 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsIfCondition)
1682 {
1683     const std::string &shaderString =
1684         R"(#version 300 es
1685         precision mediump float;
1686         out vec4 out_fragColor;
1687         uniform bool u;
1688         void main()
1689         {
1690             if (false) {
1691                 if (u) {
1692                     out_fragColor = vec4(1.0);
1693                 }
1694             }
1695             out_fragColor = vec4(0.0);
1696         })";
1697 
1698     compile(shaderString);
1699     checkUniformStaticallyUsedButNotActive("u");
1700 }
1701 
1702 // Test a variable that is statically used but not active. The variable is a constructor argument in
1703 // a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsConstructorArgument)1704 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsConstructorArgument)
1705 {
1706     const std::string &shaderString =
1707         R"(#version 300 es
1708         precision mediump float;
1709         out vec4 out_fragColor;
1710         uniform float u;
1711         void main()
1712         {
1713             if (false) {
1714                 out_fragColor = vec4(u);
1715             }
1716             out_fragColor = vec4(0.0);
1717         })";
1718 
1719     compile(shaderString);
1720     checkUniformStaticallyUsedButNotActive("u");
1721 }
1722 
1723 // Test a variable that is statically used but not active. The variable is a binary operator operand
1724 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsBinaryOpOperand)1725 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsBinaryOpOperand)
1726 {
1727     const std::string &shaderString =
1728         R"(#version 300 es
1729         precision mediump float;
1730         out vec4 out_fragColor;
1731         uniform vec4 u;
1732         void main()
1733         {
1734             if (false) {
1735                 out_fragColor = u + 1.0;
1736             }
1737             out_fragColor = vec4(0.0);
1738         })";
1739 
1740     compile(shaderString);
1741     checkUniformStaticallyUsedButNotActive("u");
1742 }
1743 
1744 // Test a variable that is statically used but not active. The variable is a comparison operator
1745 // operand in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsComparisonOpOperand)1746 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsComparisonOpOperand)
1747 {
1748     const std::string &shaderString =
1749         R"(#version 300 es
1750         precision mediump float;
1751         out vec4 out_fragColor;
1752         uniform vec4 u;
1753         void main()
1754         {
1755             if (false) {
1756                 if (u == vec4(1.0))
1757                 {
1758                     out_fragColor = vec4(1.0);
1759                 }
1760             }
1761             out_fragColor = vec4(0.0);
1762         })";
1763 
1764     compile(shaderString);
1765     checkUniformStaticallyUsedButNotActive("u");
1766 }
1767 
1768 // Test a variable that is statically used but not active. The variable is an unary operator operand
1769 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsUnaryOpOperand)1770 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsUnaryOpOperand)
1771 {
1772     const std::string &shaderString =
1773         R"(#version 300 es
1774         precision mediump float;
1775         out vec4 out_fragColor;
1776         uniform vec4 u;
1777         void main()
1778         {
1779             if (false) {
1780                 out_fragColor = -u;
1781             }
1782             out_fragColor = vec4(0.0);
1783         })";
1784 
1785     compile(shaderString);
1786     checkUniformStaticallyUsedButNotActive("u");
1787 }
1788 
1789 // Test a variable that is statically used but not active. The variable is an rvalue in an assigment
1790 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsAssignmentRValue)1791 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsAssignmentRValue)
1792 {
1793     const std::string &shaderString =
1794         R"(#version 300 es
1795         precision mediump float;
1796         out vec4 out_fragColor;
1797         uniform vec4 u;
1798         void main()
1799         {
1800             if (false) {
1801                 out_fragColor = u;
1802             }
1803             out_fragColor = vec4(0.0);
1804         })";
1805 
1806     compile(shaderString);
1807     checkUniformStaticallyUsedButNotActive("u");
1808 }
1809 
1810 // Test a variable that is statically used but not active. The variable is a comma operator operand
1811 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsCommaOperand)1812 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsCommaOperand)
1813 {
1814     const std::string &shaderString =
1815         R"(#version 300 es
1816         precision mediump float;
1817         out vec4 out_fragColor;
1818         uniform vec4 u;
1819         void main()
1820         {
1821             if (false) {
1822                 out_fragColor = u, vec4(1.0);
1823             }
1824             out_fragColor = vec4(0.0);
1825         })";
1826 
1827     compile(shaderString);
1828     checkUniformStaticallyUsedButNotActive("u");
1829 }
1830 
1831 // Test a variable that is statically used but not active. The variable is a switch init statement
1832 // in a block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsSwitchInitStatement)1833 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsSwitchInitStatement)
1834 {
1835     const std::string &shaderString =
1836         R"(#version 300 es
1837         precision mediump float;
1838         out vec4 out_fragColor;
1839         uniform int u;
1840         void main()
1841         {
1842             if (false)
1843             {
1844                 switch (u)
1845                 {
1846                     case 1:
1847                         out_fragColor = vec4(2.0);
1848                     default:
1849                         out_fragColor = vec4(1.0);
1850                 }
1851             }
1852             out_fragColor = vec4(0.0);
1853         })";
1854 
1855     compile(shaderString);
1856     checkUniformStaticallyUsedButNotActive("u");
1857 }
1858 
1859 // Test a variable that is statically used but not active. The variable is a loop condition in a
1860 // block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsLoopCondition)1861 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopCondition)
1862 {
1863     const std::string &shaderString =
1864         R"(#version 300 es
1865         precision mediump float;
1866         out vec4 out_fragColor;
1867         uniform bool u;
1868         void main()
1869         {
1870             int counter = 0;
1871             if (false)
1872             {
1873                 while (u)
1874                 {
1875                     if (++counter > 2)
1876                     {
1877                         break;
1878                     }
1879                 }
1880             }
1881             out_fragColor = vec4(0.0);
1882         })";
1883 
1884     compile(shaderString);
1885     checkUniformStaticallyUsedButNotActive("u");
1886 }
1887 
1888 // Test a variable that is statically used but not active. The variable is a loop expression in a
1889 // block that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsLoopExpression)1890 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopExpression)
1891 {
1892     const std::string &shaderString =
1893         R"(#version 300 es
1894         precision mediump float;
1895         out vec4 out_fragColor;
1896         uniform bool u;
1897         void main()
1898         {
1899             if (false)
1900             {
1901                 for (int i = 0; i < 3; u)
1902                 {
1903                     ++i;
1904                 }
1905             }
1906             out_fragColor = vec4(0.0);
1907         })";
1908 
1909     compile(shaderString);
1910     checkUniformStaticallyUsedButNotActive("u");
1911 }
1912 
1913 // Test a variable that is statically used but not active. The variable is a vector index in a block
1914 // that is not executed.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveAsVectorIndex)1915 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsVectorIndex)
1916 {
1917     const std::string &shaderString =
1918         R"(#version 300 es
1919         precision mediump float;
1920         out vec4 out_fragColor;
1921         uniform int u;
1922         void main()
1923         {
1924             vec4 color = vec4(0.0);
1925             if (false)
1926             {
1927                 color[u] = 1.0;
1928             }
1929             out_fragColor = color;
1930         })";
1931 
1932     compile(shaderString);
1933     checkUniformStaticallyUsedButNotActive("u");
1934 }
1935 
1936 // Test a variable that is statically used but not active. The variable is referenced in a block
1937 // that's not executed. This is a bit of a corner case with some room for interpretation, but we
1938 // treat the variable as statically used.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveJustAReference)1939 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReference)
1940 {
1941     const std::string &shaderString =
1942         R"(#version 300 es
1943         precision mediump float;
1944         out vec4 out_fragColor;
1945         uniform int u;
1946         void main()
1947         {
1948             vec4 color = vec4(0.0);
1949             if (false)
1950             {
1951                 u;
1952             }
1953             out_fragColor = color;
1954         })";
1955 
1956     compile(shaderString);
1957     checkUniformStaticallyUsedButNotActive("u");
1958 }
1959 
1960 // Test a variable that is statically used but not active. The variable is referenced in a block
1961 // without braces that's not executed. This is a bit of a corner case with some room for
1962 // interpretation, but we treat the variable as statically used.
TEST_F(CollectFragmentVariablesTest,StaticallyUsedButNotActiveJustAReferenceNoBracesIf)1963 TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReferenceNoBracesIf)
1964 {
1965     const std::string &shaderString =
1966         R"(#version 300 es
1967         precision mediump float;
1968         out vec4 out_fragColor;
1969         uniform int u;
1970         void main()
1971         {
1972             vec4 color = vec4(0.0);
1973             if (false)
1974                 u;
1975             out_fragColor = color;
1976         })";
1977 
1978     compile(shaderString);
1979     checkUniformStaticallyUsedButNotActive("u");
1980 }
1981 
1982 // Test a variable that is referenced in a loop body without braces.
TEST_F(CollectFragmentVariablesTest,JustAVariableReferenceInNoBracesLoop)1983 TEST_F(CollectFragmentVariablesTest, JustAVariableReferenceInNoBracesLoop)
1984 {
1985     const std::string &shaderString =
1986         R"(#version 300 es
1987         precision mediump float;
1988         out vec4 out_fragColor;
1989         uniform int u;
1990         void main()
1991         {
1992             vec4 color = vec4(0.0);
1993             while (false)
1994                 u;
1995             out_fragColor = color;
1996         })";
1997 
1998     compile(shaderString);
1999 
2000     const auto &uniforms = mTranslator->getUniforms();
2001     ASSERT_EQ(1u, uniforms.size());
2002 
2003     const ShaderVariable &uniform = uniforms[0];
2004     EXPECT_EQ("u", uniform.name);
2005     EXPECT_TRUE(uniform.staticUse);
2006     // Note that we don't check the active flag here - the usage of the uniform is not currently
2007     // being optimized away.
2008 }
2009 
2010 // Test an interface block member variable that is statically used but not active.
TEST_F(CollectVertexVariablesTest,StaticallyUsedButNotActiveSimpleInterfaceBlock)2011 TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveSimpleInterfaceBlock)
2012 {
2013     const std::string &shaderString =
2014         R"(#version 300 es
2015         uniform b
2016         {
2017             float f;
2018         };
2019         void main() {
2020             gl_Position = vec4(true ? 0.0 : f);
2021         })";
2022 
2023     compile(shaderString);
2024 
2025     const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2026     ASSERT_EQ(1u, interfaceBlocks.size());
2027     const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2028 
2029     EXPECT_EQ("b", interfaceBlock.name);
2030     EXPECT_TRUE(interfaceBlock.staticUse);
2031     EXPECT_FALSE(interfaceBlock.active);
2032 
2033     ASSERT_EQ(1u, interfaceBlock.fields.size());
2034     const ShaderVariable &field = interfaceBlock.fields[0];
2035 
2036     EXPECT_EQ("f", field.name);
2037     EXPECT_TRUE(field.staticUse);
2038     EXPECT_FALSE(field.active);
2039 }
2040 
2041 // Test an interface block instance variable that is statically used but not active.
TEST_F(CollectVertexVariablesTest,StaticallyUsedButNotActiveInstancedInterfaceBlock)2042 TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveInstancedInterfaceBlock)
2043 {
2044     const std::string &shaderString =
2045         R"(#version 300 es
2046         uniform b
2047         {
2048             float f;
2049         } blockInstance;
2050         void main() {
2051             gl_Position = vec4(true ? 0.0 : blockInstance.f);
2052         })";
2053 
2054     compile(shaderString);
2055 
2056     const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2057     ASSERT_EQ(1u, interfaceBlocks.size());
2058     const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2059 
2060     EXPECT_EQ("b", interfaceBlock.name);
2061     EXPECT_TRUE(interfaceBlock.staticUse);
2062     EXPECT_FALSE(interfaceBlock.active);
2063 
2064     ASSERT_EQ(1u, interfaceBlock.fields.size());
2065     const ShaderVariable &field = interfaceBlock.fields[0];
2066 
2067     EXPECT_EQ("f", field.name);
2068     // See TODO in CollectVariables.cpp about tracking instanced interface block field static use.
2069     // EXPECT_TRUE(field.staticUse);
2070     EXPECT_FALSE(field.active);
2071 }
2072 
2073 // Test an interface block member variable that is statically used. The variable is used to call
2074 // array length method.
TEST_F(CollectVertexVariablesTest,StaticallyUsedInArrayLengthOp)2075 TEST_F(CollectVertexVariablesTest, StaticallyUsedInArrayLengthOp)
2076 {
2077     const std::string &shaderString =
2078         R"(#version 300 es
2079         uniform b
2080         {
2081             float f[3];
2082         };
2083         void main() {
2084             if (f.length() > 1)
2085             {
2086                 gl_Position = vec4(1.0);
2087             }
2088             else
2089             {
2090                 gl_Position = vec4(0.0);
2091             }
2092         })";
2093 
2094     compile(shaderString);
2095 
2096     const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2097     ASSERT_EQ(1u, interfaceBlocks.size());
2098     const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2099 
2100     EXPECT_EQ("b", interfaceBlock.name);
2101     EXPECT_TRUE(interfaceBlock.staticUse);
2102 }
2103 
2104 // Test a varying that is declared invariant but not otherwise used.
TEST_F(CollectVertexVariablesTest,VaryingOnlyDeclaredInvariant)2105 TEST_F(CollectVertexVariablesTest, VaryingOnlyDeclaredInvariant)
2106 {
2107     const std::string &shaderString =
2108         R"(precision mediump float;
2109         varying float vf;
2110         invariant vf;
2111         void main()
2112         {
2113         })";
2114 
2115     compile(shaderString);
2116 
2117     const auto &varyings = mTranslator->getOutputVaryings();
2118     ASSERT_EQ(1u, varyings.size());
2119 
2120     const ShaderVariable &varying = varyings[0];
2121     EXPECT_EQ("vf", varying.name);
2122     EXPECT_FALSE(varying.staticUse);
2123     EXPECT_FALSE(varying.active);
2124 }
2125 
2126 // Test an output variable that is declared with the index layout qualifier from
2127 // EXT_blend_func_extended.
TEST_F(CollectFragmentVariablesTest,OutputVarESSL3EXTBlendFuncExtendedIndex)2128 TEST_F(CollectFragmentVariablesTest, OutputVarESSL3EXTBlendFuncExtendedIndex)
2129 {
2130     const std::string &shaderString =
2131         R"(#version 300 es
2132 #extension GL_EXT_blend_func_extended : require
2133 precision mediump float;
2134 layout(location = 0, index = 1) out float outVar;
2135 void main()
2136 {
2137     outVar = 0.0;
2138 })";
2139 
2140     compile(shaderString);
2141 
2142     const auto &outputs = mTranslator->getOutputVariables();
2143     ASSERT_EQ(1u, outputs.size());
2144 
2145     const ShaderVariable &output = outputs[0];
2146     EXPECT_EQ("outVar", output.name);
2147     EXPECT_TRUE(output.staticUse);
2148     EXPECT_TRUE(output.active);
2149     EXPECT_EQ(1, output.index);
2150 }
2151