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