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