Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/compiler_tests/CollectVariables_test.cpp
1693 views
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
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:
35
CollectVariablesTest(::GLenum shaderType) : mShaderType(shaderType) {}
36
37
protected:
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
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.
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.
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
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
129
void compile(const std::string &shaderString) { compile(shaderString, 0u); }
130
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:
149
CollectVertexVariablesTest() : CollectVariablesTest(GL_VERTEX_SHADER) {}
150
};
151
152
class CollectFragmentVariablesTest : public CollectVariablesTest
153
{
154
public:
155
CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {}
156
};
157
158
class CollectVariablesTestES31 : public CollectVariablesTest
159
{
160
public:
161
CollectVariablesTestES31(sh::GLenum shaderType) : CollectVariablesTest(shaderType) {}
162
163
protected:
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:
175
CollectVariablesEXTGeometryShaderTest(sh::GLenum shaderType)
176
: CollectVariablesTestES31(shaderType)
177
{}
178
179
protected:
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:
193
CollectGeometryVariablesTest() : CollectVariablesEXTGeometryShaderTest(GL_GEOMETRY_SHADER_EXT)
194
{}
195
196
protected:
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:
215
CollectFragmentVariablesEXTGeometryShaderTest()
216
: CollectVariablesEXTGeometryShaderTest(GL_FRAGMENT_SHADER)
217
{}
218
219
protected:
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:
231
CollectVertexVariablesES31Test() : CollectVariablesTestES31(GL_VERTEX_SHADER) {}
232
};
233
234
class CollectFragmentVariablesES31Test : public CollectVariablesTestES31
235
{
236
public:
237
CollectFragmentVariablesES31Test() : CollectVariablesTestES31(GL_FRAGMENT_SHADER) {}
238
};
239
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
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
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
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
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
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
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
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
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)
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)
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.
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.
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.
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.
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.
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.
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.
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
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:
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
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.
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.structOrBlockName);
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.
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.structOrBlockName);
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.
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.
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.
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.
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
1042
const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1043
ASSERT_EQ(1u, inVaryings.size());
1044
1045
const ShaderVariable &glIn = inVaryings[0];
1046
EXPECT_EQ("gl_in", glIn.name);
1047
EXPECT_EQ("gl_PerVertex", glIn.structOrBlockName);
1048
EXPECT_TRUE(glIn.staticUse);
1049
EXPECT_TRUE(glIn.active);
1050
EXPECT_TRUE(glIn.isBuiltIn());
1051
1052
ASSERT_EQ(1u, glIn.fields.size());
1053
1054
const ShaderVariable &glPositionField = glIn.fields[0];
1055
EXPECT_EQ("gl_Position", glPositionField.name);
1056
EXPECT_FALSE(glPositionField.isArray());
1057
EXPECT_FALSE(glPositionField.isStruct());
1058
EXPECT_TRUE(glPositionField.staticUse);
1059
// Tracking for "active" not set up currently.
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.
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 std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1085
ASSERT_EQ(1u, inVaryings.size());
1086
1087
const ShaderVariable &glIn = inVaryings[0];
1088
ASSERT_EQ("gl_in", glIn.name);
1089
EXPECT_EQ(kArraySizeForInputPrimitives[i], glIn.arraySizes[0]);
1090
}
1091
}
1092
1093
// Test collecting gl_PrimitiveIDIn in a geometry shader.
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
1111
const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1112
ASSERT_EQ(1u, inputVaryings.size());
1113
1114
const ShaderVariable &varying = inputVaryings[0];
1115
EXPECT_EQ("gl_PrimitiveIDIn", varying.name);
1116
EXPECT_FALSE(varying.isArray());
1117
EXPECT_FALSE(varying.isStruct());
1118
EXPECT_TRUE(varying.staticUse);
1119
EXPECT_TRUE(varying.active);
1120
EXPECT_TRUE(varying.isBuiltIn());
1121
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1122
EXPECT_GLENUM_EQ(GL_INT, varying.type);
1123
}
1124
1125
// Test collecting gl_InvocationID in a geometry shader.
1126
TEST_F(CollectGeometryVariablesTest, CollectInvocationID)
1127
{
1128
const std::string &shaderString =
1129
R"(#version 310 es
1130
#extension GL_EXT_geometry_shader : require
1131
layout (points, invocations = 2) in;
1132
layout (points, max_vertices = 2) out;
1133
void main()
1134
{
1135
gl_Position = vec4(gl_InvocationID);
1136
EmitVertex();
1137
})";
1138
1139
compile(shaderString);
1140
1141
EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1142
1143
const std::vector<ShaderVariable> &inputVaryings = mTranslator->getInputVaryings();
1144
ASSERT_EQ(1u, inputVaryings.size());
1145
1146
const ShaderVariable &varying = inputVaryings[0];
1147
EXPECT_EQ("gl_InvocationID", varying.name);
1148
EXPECT_FALSE(varying.isArray());
1149
EXPECT_FALSE(varying.isStruct());
1150
EXPECT_TRUE(varying.staticUse);
1151
EXPECT_TRUE(varying.active);
1152
EXPECT_TRUE(varying.isBuiltIn());
1153
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1154
EXPECT_GLENUM_EQ(GL_INT, varying.type);
1155
}
1156
1157
// Test collecting gl_in in a geometry shader when gl_in is indexed by an expression.
1158
TEST_F(CollectGeometryVariablesTest, CollectGLInIndexedByExpression)
1159
{
1160
const std::string &shaderString =
1161
R"(#version 310 es
1162
#extension GL_EXT_geometry_shader : require
1163
layout (triangles, invocations = 2) in;
1164
layout (points, max_vertices = 2) out;
1165
void main()
1166
{
1167
gl_Position = gl_in[gl_InvocationID + 1].gl_Position;
1168
EmitVertex();
1169
})";
1170
1171
compile(shaderString);
1172
1173
EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1174
1175
const std::vector<ShaderVariable> &inVaryings = mTranslator->getInputVaryings();
1176
ASSERT_EQ(2u, inVaryings.size());
1177
1178
bool foundGLIn = false;
1179
bool foundInvocationID = false;
1180
1181
for (const ShaderVariable &varying : inVaryings)
1182
{
1183
if (varying.name == "gl_in")
1184
{
1185
foundGLIn = true;
1186
EXPECT_TRUE(varying.isShaderIOBlock);
1187
EXPECT_EQ("gl_PerVertex", varying.structOrBlockName);
1188
}
1189
else if (varying.name == "gl_InvocationID")
1190
{
1191
foundInvocationID = true;
1192
}
1193
}
1194
1195
EXPECT_TRUE(foundGLIn);
1196
EXPECT_TRUE(foundInvocationID);
1197
}
1198
1199
// Test collecting gl_Position in a geometry shader.
1200
TEST_F(CollectGeometryVariablesTest, CollectPosition)
1201
{
1202
const std::string &shaderString =
1203
R"(#version 310 es
1204
#extension GL_EXT_geometry_shader : require
1205
layout (points) in;
1206
layout (points, max_vertices = 2) out;
1207
void main()
1208
{
1209
gl_Position = vec4(0.1, 0.2, 0.3, 1);
1210
})";
1211
1212
compile(shaderString);
1213
1214
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1215
1216
const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1217
ASSERT_EQ(1u, outputVaryings.size());
1218
1219
const ShaderVariable &varying = outputVaryings[0];
1220
EXPECT_EQ("gl_Position", varying.name);
1221
EXPECT_FALSE(varying.isArray());
1222
EXPECT_FALSE(varying.isStruct());
1223
EXPECT_TRUE(varying.staticUse);
1224
EXPECT_TRUE(varying.active);
1225
EXPECT_TRUE(varying.isBuiltIn());
1226
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1227
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1228
}
1229
1230
// Test collecting gl_PrimitiveID in a geometry shader.
1231
TEST_F(CollectGeometryVariablesTest, CollectPrimitiveID)
1232
{
1233
const std::string &shaderString =
1234
R"(#version 310 es
1235
#extension GL_EXT_geometry_shader : require
1236
layout (points) in;
1237
layout (points, max_vertices = 2) out;
1238
void main()
1239
{
1240
gl_PrimitiveID = 100;
1241
})";
1242
1243
compile(shaderString);
1244
1245
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1246
1247
const std::vector<ShaderVariable> &outputVaryings = mTranslator->getOutputVaryings();
1248
ASSERT_EQ(1u, outputVaryings.size());
1249
1250
const ShaderVariable &varying = outputVaryings[0];
1251
EXPECT_EQ("gl_PrimitiveID", varying.name);
1252
EXPECT_FALSE(varying.isArray());
1253
EXPECT_FALSE(varying.isStruct());
1254
EXPECT_TRUE(varying.staticUse);
1255
EXPECT_TRUE(varying.active);
1256
EXPECT_TRUE(varying.isBuiltIn());
1257
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1258
EXPECT_GLENUM_EQ(GL_INT, varying.type);
1259
}
1260
1261
// Test collecting gl_Layer in a geometry shader.
1262
TEST_F(CollectGeometryVariablesTest, CollectLayer)
1263
{
1264
const std::string &shaderString =
1265
R"(#version 310 es
1266
#extension GL_EXT_geometry_shader : require
1267
layout (points) in;
1268
layout (points, max_vertices = 2) out;
1269
void main()
1270
{
1271
gl_Layer = 2;
1272
})";
1273
1274
compile(shaderString);
1275
1276
ASSERT_TRUE(mTranslator->getInputVaryings().empty());
1277
1278
const auto &outputVaryings = mTranslator->getOutputVaryings();
1279
ASSERT_EQ(1u, outputVaryings.size());
1280
1281
const ShaderVariable &varying = outputVaryings[0];
1282
EXPECT_EQ("gl_Layer", varying.name);
1283
EXPECT_FALSE(varying.isArray());
1284
EXPECT_FALSE(varying.isStruct());
1285
EXPECT_TRUE(varying.staticUse);
1286
EXPECT_TRUE(varying.active);
1287
EXPECT_TRUE(varying.isBuiltIn());
1288
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying.precision);
1289
EXPECT_GLENUM_EQ(GL_INT, varying.type);
1290
}
1291
1292
// Test collecting gl_PrimitiveID in a fragment shader.
1293
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectPrimitiveID)
1294
{
1295
const std::string &shaderString =
1296
R"(#version 310 es
1297
#extension GL_EXT_geometry_shader : require
1298
1299
out int my_out;
1300
1301
void main()
1302
{
1303
my_out = gl_PrimitiveID;
1304
})";
1305
1306
compile(shaderString);
1307
1308
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1309
1310
const auto &inputVaryings = mTranslator->getInputVaryings();
1311
ASSERT_EQ(1u, inputVaryings.size());
1312
1313
const ShaderVariable *varying = &inputVaryings[0];
1314
EXPECT_EQ("gl_PrimitiveID", varying->name);
1315
EXPECT_FALSE(varying->isArray());
1316
EXPECT_FALSE(varying->isStruct());
1317
EXPECT_TRUE(varying->staticUse);
1318
EXPECT_TRUE(varying->active);
1319
EXPECT_TRUE(varying->isBuiltIn());
1320
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1321
EXPECT_GLENUM_EQ(GL_INT, varying->type);
1322
}
1323
1324
// Test collecting gl_Layer in a fragment shader.
1325
TEST_F(CollectFragmentVariablesEXTGeometryShaderTest, CollectLayer)
1326
{
1327
const std::string &shaderString =
1328
R"(#version 310 es
1329
#extension GL_EXT_geometry_shader : require
1330
1331
out int my_out;
1332
1333
void main()
1334
{
1335
my_out = gl_Layer;
1336
})";
1337
1338
compile(shaderString);
1339
1340
ASSERT_TRUE(mTranslator->getOutputVaryings().empty());
1341
1342
const auto &inputVaryings = mTranslator->getInputVaryings();
1343
ASSERT_EQ(1u, inputVaryings.size());
1344
1345
const ShaderVariable *varying = &inputVaryings[0];
1346
EXPECT_EQ("gl_Layer", varying->name);
1347
EXPECT_FALSE(varying->isArray());
1348
EXPECT_FALSE(varying->isStruct());
1349
EXPECT_TRUE(varying->staticUse);
1350
EXPECT_TRUE(varying->active);
1351
EXPECT_TRUE(varying->isBuiltIn());
1352
EXPECT_GLENUM_EQ(GL_HIGH_INT, varying->precision);
1353
EXPECT_GLENUM_EQ(GL_INT, varying->type);
1354
}
1355
1356
// Test collecting the location of vertex shader outputs.
1357
TEST_F(CollectVertexVariablesES31Test, CollectOutputWithLocation)
1358
{
1359
const std::string &shaderString =
1360
R"(#version 310 es
1361
out vec4 v_output1;
1362
layout (location = 1) out vec4 v_output2;
1363
void main()
1364
{
1365
})";
1366
1367
compile(shaderString);
1368
1369
const auto &outputVaryings = mTranslator->getOutputVaryings();
1370
ASSERT_EQ(2u, outputVaryings.size());
1371
1372
const ShaderVariable *varying1 = &outputVaryings[0];
1373
EXPECT_EQ("v_output1", varying1->name);
1374
EXPECT_EQ(-1, varying1->location);
1375
1376
const ShaderVariable *varying2 = &outputVaryings[1];
1377
EXPECT_EQ("v_output2", varying2->name);
1378
EXPECT_EQ(1, varying2->location);
1379
}
1380
1381
// Test collecting the location of fragment shader inputs.
1382
TEST_F(CollectFragmentVariablesES31Test, CollectInputWithLocation)
1383
{
1384
const std::string &shaderString =
1385
R"(#version 310 es
1386
precision mediump float;
1387
in vec4 f_input1;
1388
layout (location = 1) in vec4 f_input2;
1389
layout (location = 0) out vec4 o_color;
1390
void main()
1391
{
1392
o_color = f_input2;
1393
})";
1394
1395
compile(shaderString);
1396
1397
const auto &inputVaryings = mTranslator->getInputVaryings();
1398
ASSERT_EQ(2u, inputVaryings.size());
1399
1400
const ShaderVariable *varying1 = &inputVaryings[0];
1401
EXPECT_EQ("f_input1", varying1->name);
1402
EXPECT_EQ(-1, varying1->location);
1403
1404
const ShaderVariable *varying2 = &inputVaryings[1];
1405
EXPECT_EQ("f_input2", varying2->name);
1406
EXPECT_EQ(1, varying2->location);
1407
}
1408
1409
// Test collecting the inputs of a geometry shader.
1410
TEST_F(CollectGeometryVariablesTest, CollectInputs)
1411
{
1412
const std::string &shaderString =
1413
R"(#version 310 es
1414
#extension GL_EXT_geometry_shader : require
1415
layout (points) in;
1416
layout (points, max_vertices = 2) out;
1417
in vec4 texcoord1[];
1418
in vec4 texcoord2[1];
1419
void main()
1420
{
1421
gl_Position = texcoord1[0];
1422
gl_Position += texcoord2[0];
1423
EmitVertex();
1424
})";
1425
1426
compile(shaderString);
1427
1428
EXPECT_EQ(1u, mTranslator->getOutputVaryings().size());
1429
1430
const auto &inputVaryings = mTranslator->getInputVaryings();
1431
ASSERT_EQ(2u, inputVaryings.size());
1432
1433
const std::string kVaryingName[] = {"texcoord1", "texcoord2"};
1434
1435
for (size_t i = 0; i < inputVaryings.size(); ++i)
1436
{
1437
const ShaderVariable &varying = inputVaryings[i];
1438
1439
EXPECT_EQ(kVaryingName[i], varying.name);
1440
EXPECT_TRUE(varying.isArray());
1441
EXPECT_FALSE(varying.isStruct());
1442
EXPECT_TRUE(varying.staticUse);
1443
EXPECT_TRUE(varying.active);
1444
EXPECT_FALSE(varying.isBuiltIn());
1445
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
1446
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
1447
EXPECT_FALSE(varying.isInvariant);
1448
ASSERT_EQ(1u, varying.arraySizes.size());
1449
EXPECT_EQ(1u, varying.arraySizes.back());
1450
}
1451
}
1452
1453
// Test that the unsized input of a geometry shader can be correctly collected.
1454
TEST_F(CollectGeometryVariablesTest, CollectInputArraySizeForUnsizedInput)
1455
{
1456
const std::array<std::string, 5> kInputPrimitives = {
1457
{"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
1458
1459
const GLuint kArraySizeForInputPrimitives[] = {1u, 2u, 4u, 3u, 6u};
1460
1461
const std::string &kVariableDeclaration = "in vec4 texcoord[];\n";
1462
const std::string &kFunctionBody =
1463
R"(void main()
1464
{
1465
gl_Position = texcoord[0];
1466
})";
1467
1468
for (size_t i = 0; i < kInputPrimitives.size(); ++i)
1469
{
1470
compileGeometryShaderWithInputPrimitive(kInputPrimitives[i], kVariableDeclaration,
1471
kFunctionBody);
1472
1473
const auto &inputVaryings = mTranslator->getInputVaryings();
1474
ASSERT_EQ(1u, inputVaryings.size());
1475
1476
const ShaderVariable *varying = &inputVaryings[0];
1477
EXPECT_EQ("texcoord", varying->name);
1478
ASSERT_EQ(1u, varying->arraySizes.size());
1479
EXPECT_EQ(kArraySizeForInputPrimitives[i], varying->arraySizes.back());
1480
}
1481
}
1482
1483
// Test collecting inputs using interpolation qualifiers in a geometry shader.
1484
TEST_F(CollectGeometryVariablesTest, CollectInputsWithInterpolationQualifiers)
1485
{
1486
const std::string &kHeader =
1487
"#version 310 es\n"
1488
"#extension GL_EXT_geometry_shader : require\n";
1489
const std::string &kLayout =
1490
"layout (points) in;\n"
1491
"layout (points, max_vertices = 2) out;\n";
1492
1493
const std::array<std::string, 3> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};
1494
1495
const std::array<InterpolationType, 3> kInterpolationType = {
1496
{INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1497
1498
const std::string &kFunctionBody =
1499
R"(void main()
1500
{
1501
gl_Position = texcoord[0];
1502
EmitVertex();
1503
})";
1504
1505
for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1506
{
1507
const std::string &qualifier = kInterpolationQualifiers[i];
1508
1509
std::ostringstream stream1;
1510
stream1 << kHeader << kLayout << qualifier << " in vec4 texcoord[];\n" << kFunctionBody;
1511
compile(stream1.str());
1512
1513
const auto &inputVaryings = mTranslator->getInputVaryings();
1514
ASSERT_EQ(1u, inputVaryings.size());
1515
const ShaderVariable *varying = &inputVaryings[0];
1516
EXPECT_EQ("texcoord", varying->name);
1517
EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1518
}
1519
}
1520
1521
// Test collecting outputs using interpolation qualifiers in a geometry shader.
1522
TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInterpolationQualifiers)
1523
{
1524
const std::string &kHeader =
1525
"#version 310 es\n"
1526
"#extension GL_EXT_geometry_shader : require\n"
1527
"layout (points) in;\n"
1528
"layout (points, max_vertices = 2) out;\n";
1529
1530
const std::array<std::string, 4> kInterpolationQualifiers = {
1531
{"", "flat", "smooth", "centroid"}};
1532
1533
const std::array<InterpolationType, 4> kInterpolationType = {
1534
{INTERPOLATION_SMOOTH, INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID}};
1535
1536
const std::string &kFunctionBody =
1537
"void main()\n"
1538
"{\n"
1539
" texcoord = vec4(1.0, 0.0, 0.0, 1.0);\n"
1540
"}\n";
1541
1542
for (size_t i = 0; i < kInterpolationQualifiers.size(); ++i)
1543
{
1544
const std::string &qualifier = kInterpolationQualifiers[i];
1545
std::ostringstream stream;
1546
stream << kHeader << qualifier << " out vec4 texcoord;\n" << kFunctionBody;
1547
1548
compile(stream.str());
1549
const auto &outputVaryings = mTranslator->getOutputVaryings();
1550
ASSERT_EQ(1u, outputVaryings.size());
1551
1552
const ShaderVariable *varying = &outputVaryings[0];
1553
EXPECT_EQ("texcoord", varying->name);
1554
EXPECT_EQ(kInterpolationType[i], varying->interpolation);
1555
EXPECT_FALSE(varying->isInvariant);
1556
}
1557
}
1558
1559
// Test collecting outputs using 'invariant' qualifier in a geometry shader.
1560
TEST_F(CollectGeometryVariablesTest, CollectOutputsWithInvariant)
1561
{
1562
const std::string &shaderString =
1563
R"(#version 310 es
1564
#extension GL_EXT_geometry_shader : require
1565
layout (points) in;
1566
layout (points, max_vertices = 2) out;
1567
invariant out vec4 texcoord;
1568
void main()
1569
{
1570
texcoord = vec4(1.0, 0.0, 0.0, 1.0);
1571
})";
1572
1573
compile(shaderString);
1574
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_TRUE(varying->isInvariant);
1581
}
1582
1583
// Test collecting a varying variable that is used inside a folded ternary operator. The result of
1584
// the folded ternary operator has a different qualifier from the original variable, which makes
1585
// this case tricky.
1586
TEST_F(CollectFragmentVariablesTest, VaryingUsedInsideFoldedTernary)
1587
{
1588
const std::string &shaderString =
1589
R"(#version 300 es
1590
precision highp float;
1591
centroid in float vary;
1592
out vec4 color;
1593
void main() {
1594
color = vec4(0.0, true ? vary : 0.0, 0.0, 1.0);
1595
})";
1596
1597
compile(shaderString);
1598
1599
const std::vector<ShaderVariable> &varyings = mTranslator->getInputVaryings();
1600
ASSERT_EQ(1u, varyings.size());
1601
1602
const ShaderVariable *varying = &varyings[0];
1603
1604
EXPECT_FALSE(varying->isArray());
1605
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying->precision);
1606
EXPECT_TRUE(varying->staticUse);
1607
EXPECT_TRUE(varying->active);
1608
EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
1609
EXPECT_EQ("vary", varying->name);
1610
EXPECT_EQ(DecorateName("vary"), varying->mappedName);
1611
EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
1612
}
1613
1614
// Test a variable that is statically used but not active. The variable is used in a branch of a
1615
// ternary op that is not evaluated.
1616
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveInTernaryOp)
1617
{
1618
const std::string &shaderString =
1619
R"(#version 300 es
1620
precision mediump float;
1621
out vec4 out_fragColor;
1622
uniform float u;
1623
void main()
1624
{
1625
out_fragColor = vec4(true ? 0.0 : u);
1626
})";
1627
1628
compile(shaderString);
1629
checkUniformStaticallyUsedButNotActive("u");
1630
}
1631
1632
// Test a variable that is statically used but not active. The variable is a return value in an
1633
// unused function.
1634
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsReturnValue)
1635
{
1636
const std::string &shaderString =
1637
R"(#version 300 es
1638
precision mediump float;
1639
out vec4 out_fragColor;
1640
uniform float u;
1641
float f() {
1642
return u;
1643
}
1644
void main()
1645
{
1646
out_fragColor = vec4(0.0);
1647
})";
1648
1649
compile(shaderString);
1650
checkUniformStaticallyUsedButNotActive("u");
1651
}
1652
1653
// Test a variable that is statically used but not active. The variable is an if statement condition
1654
// inside a block that is not executed.
1655
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsIfCondition)
1656
{
1657
const std::string &shaderString =
1658
R"(#version 300 es
1659
precision mediump float;
1660
out vec4 out_fragColor;
1661
uniform bool u;
1662
void main()
1663
{
1664
if (false) {
1665
if (u) {
1666
out_fragColor = vec4(1.0);
1667
}
1668
}
1669
out_fragColor = vec4(0.0);
1670
})";
1671
1672
compile(shaderString);
1673
checkUniformStaticallyUsedButNotActive("u");
1674
}
1675
1676
// Test a variable that is statically used but not active. The variable is a constructor argument in
1677
// a block that is not executed.
1678
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsConstructorArgument)
1679
{
1680
const std::string &shaderString =
1681
R"(#version 300 es
1682
precision mediump float;
1683
out vec4 out_fragColor;
1684
uniform float u;
1685
void main()
1686
{
1687
if (false) {
1688
out_fragColor = vec4(u);
1689
}
1690
out_fragColor = vec4(0.0);
1691
})";
1692
1693
compile(shaderString);
1694
checkUniformStaticallyUsedButNotActive("u");
1695
}
1696
1697
// Test a variable that is statically used but not active. The variable is a binary operator operand
1698
// in a block that is not executed.
1699
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsBinaryOpOperand)
1700
{
1701
const std::string &shaderString =
1702
R"(#version 300 es
1703
precision mediump float;
1704
out vec4 out_fragColor;
1705
uniform vec4 u;
1706
void main()
1707
{
1708
if (false) {
1709
out_fragColor = u + 1.0;
1710
}
1711
out_fragColor = vec4(0.0);
1712
})";
1713
1714
compile(shaderString);
1715
checkUniformStaticallyUsedButNotActive("u");
1716
}
1717
1718
// Test a variable that is statically used but not active. The variable is a comparison operator
1719
// operand in a block that is not executed.
1720
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsComparisonOpOperand)
1721
{
1722
const std::string &shaderString =
1723
R"(#version 300 es
1724
precision mediump float;
1725
out vec4 out_fragColor;
1726
uniform vec4 u;
1727
void main()
1728
{
1729
if (false) {
1730
if (u == vec4(1.0))
1731
{
1732
out_fragColor = vec4(1.0);
1733
}
1734
}
1735
out_fragColor = vec4(0.0);
1736
})";
1737
1738
compile(shaderString);
1739
checkUniformStaticallyUsedButNotActive("u");
1740
}
1741
1742
// Test a variable that is statically used but not active. The variable is an unary operator operand
1743
// in a block that is not executed.
1744
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsUnaryOpOperand)
1745
{
1746
const std::string &shaderString =
1747
R"(#version 300 es
1748
precision mediump float;
1749
out vec4 out_fragColor;
1750
uniform vec4 u;
1751
void main()
1752
{
1753
if (false) {
1754
out_fragColor = -u;
1755
}
1756
out_fragColor = vec4(0.0);
1757
})";
1758
1759
compile(shaderString);
1760
checkUniformStaticallyUsedButNotActive("u");
1761
}
1762
1763
// Test a variable that is statically used but not active. The variable is an rvalue in an assigment
1764
// in a block that is not executed.
1765
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsAssignmentRValue)
1766
{
1767
const std::string &shaderString =
1768
R"(#version 300 es
1769
precision mediump float;
1770
out vec4 out_fragColor;
1771
uniform vec4 u;
1772
void main()
1773
{
1774
if (false) {
1775
out_fragColor = u;
1776
}
1777
out_fragColor = vec4(0.0);
1778
})";
1779
1780
compile(shaderString);
1781
checkUniformStaticallyUsedButNotActive("u");
1782
}
1783
1784
// Test a variable that is statically used but not active. The variable is a comma operator operand
1785
// in a block that is not executed.
1786
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsCommaOperand)
1787
{
1788
const std::string &shaderString =
1789
R"(#version 300 es
1790
precision mediump float;
1791
out vec4 out_fragColor;
1792
uniform vec4 u;
1793
void main()
1794
{
1795
if (false) {
1796
out_fragColor = u, vec4(1.0);
1797
}
1798
out_fragColor = vec4(0.0);
1799
})";
1800
1801
compile(shaderString);
1802
checkUniformStaticallyUsedButNotActive("u");
1803
}
1804
1805
// Test a variable that is statically used but not active. The variable is a switch init statement
1806
// in a block that is not executed.
1807
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsSwitchInitStatement)
1808
{
1809
const std::string &shaderString =
1810
R"(#version 300 es
1811
precision mediump float;
1812
out vec4 out_fragColor;
1813
uniform int u;
1814
void main()
1815
{
1816
if (false)
1817
{
1818
switch (u)
1819
{
1820
case 1:
1821
out_fragColor = vec4(2.0);
1822
default:
1823
out_fragColor = vec4(1.0);
1824
}
1825
}
1826
out_fragColor = vec4(0.0);
1827
})";
1828
1829
compile(shaderString);
1830
checkUniformStaticallyUsedButNotActive("u");
1831
}
1832
1833
// Test a variable that is statically used but not active. The variable is a loop condition in a
1834
// block that is not executed.
1835
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopCondition)
1836
{
1837
const std::string &shaderString =
1838
R"(#version 300 es
1839
precision mediump float;
1840
out vec4 out_fragColor;
1841
uniform bool u;
1842
void main()
1843
{
1844
int counter = 0;
1845
if (false)
1846
{
1847
while (u)
1848
{
1849
if (++counter > 2)
1850
{
1851
break;
1852
}
1853
}
1854
}
1855
out_fragColor = vec4(0.0);
1856
})";
1857
1858
compile(shaderString);
1859
checkUniformStaticallyUsedButNotActive("u");
1860
}
1861
1862
// Test a variable that is statically used but not active. The variable is a loop expression in a
1863
// block that is not executed.
1864
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsLoopExpression)
1865
{
1866
const std::string &shaderString =
1867
R"(#version 300 es
1868
precision mediump float;
1869
out vec4 out_fragColor;
1870
uniform bool u;
1871
void main()
1872
{
1873
if (false)
1874
{
1875
for (int i = 0; i < 3; u)
1876
{
1877
++i;
1878
}
1879
}
1880
out_fragColor = vec4(0.0);
1881
})";
1882
1883
compile(shaderString);
1884
checkUniformStaticallyUsedButNotActive("u");
1885
}
1886
1887
// Test a variable that is statically used but not active. The variable is a vector index in a block
1888
// that is not executed.
1889
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveAsVectorIndex)
1890
{
1891
const std::string &shaderString =
1892
R"(#version 300 es
1893
precision mediump float;
1894
out vec4 out_fragColor;
1895
uniform int u;
1896
void main()
1897
{
1898
vec4 color = vec4(0.0);
1899
if (false)
1900
{
1901
color[u] = 1.0;
1902
}
1903
out_fragColor = color;
1904
})";
1905
1906
compile(shaderString);
1907
checkUniformStaticallyUsedButNotActive("u");
1908
}
1909
1910
// Test a variable that is statically used but not active. The variable is referenced in a block
1911
// that's not executed. This is a bit of a corner case with some room for interpretation, but we
1912
// treat the variable as statically used.
1913
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReference)
1914
{
1915
const std::string &shaderString =
1916
R"(#version 300 es
1917
precision mediump float;
1918
out vec4 out_fragColor;
1919
uniform int u;
1920
void main()
1921
{
1922
vec4 color = vec4(0.0);
1923
if (false)
1924
{
1925
u;
1926
}
1927
out_fragColor = color;
1928
})";
1929
1930
compile(shaderString);
1931
checkUniformStaticallyUsedButNotActive("u");
1932
}
1933
1934
// Test a variable that is statically used but not active. The variable is referenced in a block
1935
// without braces that's not executed. This is a bit of a corner case with some room for
1936
// interpretation, but we treat the variable as statically used.
1937
TEST_F(CollectFragmentVariablesTest, StaticallyUsedButNotActiveJustAReferenceNoBracesIf)
1938
{
1939
const std::string &shaderString =
1940
R"(#version 300 es
1941
precision mediump float;
1942
out vec4 out_fragColor;
1943
uniform int u;
1944
void main()
1945
{
1946
vec4 color = vec4(0.0);
1947
if (false)
1948
u;
1949
out_fragColor = color;
1950
})";
1951
1952
compile(shaderString);
1953
checkUniformStaticallyUsedButNotActive("u");
1954
}
1955
1956
// Test a variable that is referenced in a loop body without braces.
1957
TEST_F(CollectFragmentVariablesTest, JustAVariableReferenceInNoBracesLoop)
1958
{
1959
const std::string &shaderString =
1960
R"(#version 300 es
1961
precision mediump float;
1962
out vec4 out_fragColor;
1963
uniform int u;
1964
void main()
1965
{
1966
vec4 color = vec4(0.0);
1967
while (false)
1968
u;
1969
out_fragColor = color;
1970
})";
1971
1972
compile(shaderString);
1973
1974
const auto &uniforms = mTranslator->getUniforms();
1975
ASSERT_EQ(1u, uniforms.size());
1976
1977
const ShaderVariable &uniform = uniforms[0];
1978
EXPECT_EQ("u", uniform.name);
1979
EXPECT_TRUE(uniform.staticUse);
1980
// Note that we don't check the active flag here - the usage of the uniform is not currently
1981
// being optimized away.
1982
}
1983
1984
// Test an interface block member variable that is statically used but not active.
1985
TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveSimpleInterfaceBlock)
1986
{
1987
const std::string &shaderString =
1988
R"(#version 300 es
1989
uniform b
1990
{
1991
float f;
1992
};
1993
void main() {
1994
gl_Position = vec4(true ? 0.0 : f);
1995
})";
1996
1997
compile(shaderString);
1998
1999
const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2000
ASSERT_EQ(1u, interfaceBlocks.size());
2001
const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2002
2003
EXPECT_EQ("b", interfaceBlock.name);
2004
EXPECT_TRUE(interfaceBlock.staticUse);
2005
EXPECT_FALSE(interfaceBlock.active);
2006
2007
ASSERT_EQ(1u, interfaceBlock.fields.size());
2008
const ShaderVariable &field = interfaceBlock.fields[0];
2009
2010
EXPECT_EQ("f", field.name);
2011
EXPECT_TRUE(field.staticUse);
2012
EXPECT_FALSE(field.active);
2013
}
2014
2015
// Test an interface block instance variable that is statically used but not active.
2016
TEST_F(CollectVertexVariablesTest, StaticallyUsedButNotActiveInstancedInterfaceBlock)
2017
{
2018
const std::string &shaderString =
2019
R"(#version 300 es
2020
uniform b
2021
{
2022
float f;
2023
} blockInstance;
2024
void main() {
2025
gl_Position = vec4(true ? 0.0 : blockInstance.f);
2026
})";
2027
2028
compile(shaderString);
2029
2030
const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2031
ASSERT_EQ(1u, interfaceBlocks.size());
2032
const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2033
2034
EXPECT_EQ("b", interfaceBlock.name);
2035
EXPECT_TRUE(interfaceBlock.staticUse);
2036
EXPECT_FALSE(interfaceBlock.active);
2037
2038
ASSERT_EQ(1u, interfaceBlock.fields.size());
2039
const ShaderVariable &field = interfaceBlock.fields[0];
2040
2041
EXPECT_EQ("f", field.name);
2042
// See TODO in CollectVariables.cpp about tracking instanced interface block field static use.
2043
// EXPECT_TRUE(field.staticUse);
2044
EXPECT_FALSE(field.active);
2045
}
2046
2047
// Test an interface block member variable that is statically used. The variable is used to call
2048
// array length method.
2049
TEST_F(CollectVertexVariablesTest, StaticallyUsedInArrayLengthOp)
2050
{
2051
const std::string &shaderString =
2052
R"(#version 300 es
2053
uniform b
2054
{
2055
float f[3];
2056
};
2057
void main() {
2058
if (f.length() > 1)
2059
{
2060
gl_Position = vec4(1.0);
2061
}
2062
else
2063
{
2064
gl_Position = vec4(0.0);
2065
}
2066
})";
2067
2068
compile(shaderString);
2069
2070
const std::vector<InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks();
2071
ASSERT_EQ(1u, interfaceBlocks.size());
2072
const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
2073
2074
EXPECT_EQ("b", interfaceBlock.name);
2075
EXPECT_TRUE(interfaceBlock.staticUse);
2076
}
2077
2078
// Test a varying that is declared invariant but not otherwise used.
2079
TEST_F(CollectVertexVariablesTest, VaryingOnlyDeclaredInvariant)
2080
{
2081
const std::string &shaderString =
2082
R"(precision mediump float;
2083
varying float vf;
2084
invariant vf;
2085
void main()
2086
{
2087
})";
2088
2089
compile(shaderString);
2090
2091
const auto &varyings = mTranslator->getOutputVaryings();
2092
ASSERT_EQ(1u, varyings.size());
2093
2094
const ShaderVariable &varying = varyings[0];
2095
EXPECT_EQ("vf", varying.name);
2096
EXPECT_FALSE(varying.staticUse);
2097
EXPECT_FALSE(varying.active);
2098
}
2099
2100
// Test an output variable that is declared with the index layout qualifier from
2101
// EXT_blend_func_extended.
2102
TEST_F(CollectFragmentVariablesTest, OutputVarESSL3EXTBlendFuncExtendedIndex)
2103
{
2104
const std::string &shaderString =
2105
R"(#version 300 es
2106
#extension GL_EXT_blend_func_extended : require
2107
precision mediump float;
2108
layout(location = 0, index = 1) out float outVar;
2109
void main()
2110
{
2111
outVar = 0.0;
2112
})";
2113
2114
compile(shaderString);
2115
2116
const auto &outputs = mTranslator->getOutputVariables();
2117
ASSERT_EQ(1u, outputs.size());
2118
2119
const ShaderVariable &output = outputs[0];
2120
EXPECT_EQ("outVar", output.name);
2121
EXPECT_TRUE(output.staticUse);
2122
EXPECT_TRUE(output.active);
2123
EXPECT_EQ(1, output.index);
2124
}
2125
2126