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