• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // TypeTracking_test.cpp:
7 //   Test for tracking types resulting from math operations, including their
8 //   precision.
9 //
10 
11 #include "GLSLANG/ShaderLang.h"
12 #include "angle_gl.h"
13 #include "compiler/translator/TranslatorESSL.h"
14 #include "gtest/gtest.h"
15 
16 using namespace sh;
17 
18 class TypeTrackingTest : public testing::Test
19 {
20   public:
TypeTrackingTest()21     TypeTrackingTest() {}
22 
23   protected:
SetUp()24     void SetUp() override
25     {
26         ShBuiltInResources resources;
27         InitBuiltInResources(&resources);
28         resources.FragmentPrecisionHigh = 1;
29 
30         mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC);
31         ASSERT_TRUE(mTranslator->Init(resources));
32     }
33 
TearDown()34     void TearDown() override { delete mTranslator; }
35 
compile(const std::string & shaderString)36     void compile(const std::string &shaderString)
37     {
38         const char *shaderStrings[] = {shaderString.c_str()};
39         bool compilationSuccess     = mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE);
40         TInfoSink &infoSink         = mTranslator->getInfoSink();
41         mInfoLog                    = RemoveSymbolIdsFromInfoLog(infoSink.info.c_str());
42         if (!compilationSuccess)
43             FAIL() << "Shader compilation failed " << mInfoLog;
44     }
45 
foundErrorInIntermediateTree() const46     bool foundErrorInIntermediateTree() const { return foundInIntermediateTree("ERROR:"); }
47 
foundInIntermediateTree(const char * stringToFind) const48     bool foundInIntermediateTree(const char *stringToFind) const
49     {
50         return mInfoLog.find(stringToFind) != std::string::npos;
51     }
52 
53   private:
54     // Remove symbol ids from info log - the tests don't care about them.
RemoveSymbolIdsFromInfoLog(const char * infoLog)55     static std::string RemoveSymbolIdsFromInfoLog(const char *infoLog)
56     {
57         std::string filteredLog(infoLog);
58         size_t idPrefixPos = 0u;
59         do
60         {
61             idPrefixPos = filteredLog.find(" (symbol id");
62             if (idPrefixPos != std::string::npos)
63             {
64                 size_t idSuffixPos = filteredLog.find(")", idPrefixPos);
65                 filteredLog.erase(idPrefixPos, idSuffixPos - idPrefixPos + 1u);
66             }
67         } while (idPrefixPos != std::string::npos);
68         return filteredLog;
69     }
70 
71     TranslatorESSL *mTranslator;
72     std::string mInfoLog;
73 };
74 
TEST_F(TypeTrackingTest,FunctionPrototype)75 TEST_F(TypeTrackingTest, FunctionPrototype)
76 {
77     const std::string &shaderString =
78         "precision mediump float;\n"
79         "float fun(float a);\n"
80         "uniform float f;\n"
81         "void main() {\n"
82         "   float ff = fun(f);\n"
83         "   gl_FragColor = vec4(ff);\n"
84         "}\n"
85         "float fun(float a) {\n"
86         "   return a * 2.0;\n"
87         "}\n";
88     compile(shaderString);
89     ASSERT_FALSE(foundErrorInIntermediateTree());
90     ASSERT_TRUE(foundInIntermediateTree("Function Prototype: fun"));
91 }
92 
TEST_F(TypeTrackingTest,BuiltInFunctionResultPrecision)93 TEST_F(TypeTrackingTest, BuiltInFunctionResultPrecision)
94 {
95     const std::string &shaderString =
96         "precision mediump float;\n"
97         "uniform float f;\n"
98         "void main() {\n"
99         "   float ff = sin(f);\n"
100         "   gl_FragColor = vec4(ff);\n"
101         "}\n";
102     compile(shaderString);
103     ASSERT_FALSE(foundErrorInIntermediateTree());
104     ASSERT_TRUE(foundInIntermediateTree("sin (mediump float)"));
105 }
106 
TEST_F(TypeTrackingTest,BinaryMathResultPrecision)107 TEST_F(TypeTrackingTest, BinaryMathResultPrecision)
108 {
109     const std::string &shaderString =
110         "precision mediump float;\n"
111         "uniform float f;\n"
112         "void main() {\n"
113         "   float ff = f * 0.5;\n"
114         "   gl_FragColor = vec4(ff);\n"
115         "}\n";
116     compile(shaderString);
117     ASSERT_FALSE(foundErrorInIntermediateTree());
118     ASSERT_TRUE(foundInIntermediateTree("multiply (mediump float)"));
119 }
120 
TEST_F(TypeTrackingTest,BuiltInVecFunctionResultTypeAndPrecision)121 TEST_F(TypeTrackingTest, BuiltInVecFunctionResultTypeAndPrecision)
122 {
123     const std::string &shaderString =
124         "precision mediump float;\n"
125         "uniform vec2 a;\n"
126         "void main() {\n"
127         "   float b = length(a);\n"
128         "   float c = dot(a, vec2(0.5));\n"
129         "   float d = distance(vec2(0.5), a);\n"
130         "   gl_FragColor = vec4(b, c, d, 1.0);\n"
131         "}\n";
132     compile(shaderString);
133     ASSERT_FALSE(foundErrorInIntermediateTree());
134     ASSERT_TRUE(foundInIntermediateTree("length (mediump float)"));
135     ASSERT_TRUE(foundInIntermediateTree("dot product (mediump float)"));
136     ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
137 }
138 
TEST_F(TypeTrackingTest,BuiltInMatFunctionResultTypeAndPrecision)139 TEST_F(TypeTrackingTest, BuiltInMatFunctionResultTypeAndPrecision)
140 {
141     const std::string &shaderString =
142         "#version 300 es\n"
143         "precision mediump float;\n"
144         "out vec4 my_FragColor;\n"
145         "uniform mat4 m;\n"
146         "void main() {\n"
147         "   mat3x2 tmp32 = mat3x2(m);\n"
148         "   mat2x3 tmp23 = mat2x3(m);\n"
149         "   mat4x2 tmp42 = mat4x2(m);\n"
150         "   mat2x4 tmp24 = mat2x4(m);\n"
151         "   mat4x3 tmp43 = mat4x3(m);\n"
152         "   mat3x4 tmp34 = mat3x4(m);\n"
153         "   my_FragColor = vec4(tmp32[2][1] * tmp23[1][2], tmp42[3][1] * tmp24[1][3], tmp43[3][2] "
154         "* tmp34[2][3], 1.0);\n"
155         "}\n";
156     compile(shaderString);
157     ASSERT_FALSE(foundErrorInIntermediateTree());
158     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 2X3 matrix of float)"));
159     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 3X2 matrix of float)"));
160     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 2X4 matrix of float)"));
161     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4X2 matrix of float)"));
162     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 3X4 matrix of float)"));
163     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4X3 matrix of float)"));
164 }
165 
TEST_F(TypeTrackingTest,BuiltInFunctionChoosesHigherPrecision)166 TEST_F(TypeTrackingTest, BuiltInFunctionChoosesHigherPrecision)
167 {
168     const std::string &shaderString =
169         "precision lowp float;\n"
170         "uniform mediump vec2 a;\n"
171         "uniform lowp vec2 b;\n"
172         "void main() {\n"
173         "   float c = dot(a, b);\n"
174         "   float d = distance(b, a);\n"
175         "   gl_FragColor = vec4(c, d, 0.0, 1.0);\n"
176         "}\n";
177     compile(shaderString);
178     ASSERT_FALSE(foundErrorInIntermediateTree());
179     ASSERT_TRUE(foundInIntermediateTree("dot product (mediump float)"));
180     ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
181 }
182 
TEST_F(TypeTrackingTest,BuiltInBoolFunctionResultType)183 TEST_F(TypeTrackingTest, BuiltInBoolFunctionResultType)
184 {
185     const std::string &shaderString =
186         "uniform bvec4 bees;\n"
187         "void main() {\n"
188         "   bool b = any(bees);\n"
189         "   bool c = all(bees);\n"
190         "   bvec4 d = not(bees);\n"
191         "   gl_FragColor = vec4(b ? 1.0 : 0.0, c ? 1.0 : 0.0, d.x ? 1.0 : 0.0, 1.0);\n"
192         "}\n";
193     compile(shaderString);
194     ASSERT_FALSE(foundErrorInIntermediateTree());
195     ASSERT_TRUE(foundInIntermediateTree("any (bool)"));
196     ASSERT_TRUE(foundInIntermediateTree("all (bool)"));
197     ASSERT_TRUE(foundInIntermediateTree("component-wise not (4-component vector of bool)"));
198 }
199 
TEST_F(TypeTrackingTest,BuiltInVecToBoolFunctionResultType)200 TEST_F(TypeTrackingTest, BuiltInVecToBoolFunctionResultType)
201 {
202     const std::string &shaderString =
203         "precision mediump float;\n"
204         "uniform vec2 apples;\n"
205         "uniform vec2 oranges;\n"
206         "uniform ivec2 foo;\n"
207         "uniform ivec2 bar;\n"
208         "void main() {\n"
209         "   bvec2 a = lessThan(apples, oranges);\n"
210         "   bvec2 b = greaterThan(foo, bar);\n"
211         "   gl_FragColor = vec4(any(a) ? 1.0 : 0.0, any(b) ? 1.0 : 0.0, 0.0, 1.0);\n"
212         "}\n";
213     compile(shaderString);
214     ASSERT_FALSE(foundErrorInIntermediateTree());
215     ASSERT_TRUE(foundInIntermediateTree("component-wise less than (2-component vector of bool)"));
216     ASSERT_TRUE(
217         foundInIntermediateTree("component-wise greater than (2-component vector of bool)"));
218 }
219 
TEST_F(TypeTrackingTest,Texture2DResultTypeAndPrecision)220 TEST_F(TypeTrackingTest, Texture2DResultTypeAndPrecision)
221 {
222     // ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
223     // ESSL spec section 8: For the texture functions, the precision of the return type matches the
224     // precision of the sampler type.
225     const std::string &shaderString =
226         "precision mediump float;\n"
227         "uniform sampler2D s;\n"
228         "uniform vec2 a;\n"
229         "void main() {\n"
230         "   vec4 c = texture2D(s, a);\n"
231         "   gl_FragColor = c;\n"
232         "}\n";
233     compile(shaderString);
234     ASSERT_FALSE(foundErrorInIntermediateTree());
235     ASSERT_TRUE(foundInIntermediateTree("texture2D (lowp 4-component vector of float)"));
236 }
237 
TEST_F(TypeTrackingTest,TextureCubeResultTypeAndPrecision)238 TEST_F(TypeTrackingTest, TextureCubeResultTypeAndPrecision)
239 {
240     // ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
241     // ESSL spec section 8: For the texture functions, the precision of the return type matches the
242     // precision of the sampler type.
243     const std::string &shaderString =
244         "precision mediump float;\n"
245         "uniform samplerCube sc;\n"
246         "uniform vec3 a;\n"
247         "void main() {\n"
248         "   vec4 c = textureCube(sc, a);\n"
249         "   gl_FragColor = c;\n"
250         "}\n";
251     compile(shaderString);
252     ASSERT_FALSE(foundErrorInIntermediateTree());
253     ASSERT_TRUE(foundInIntermediateTree("textureCube (lowp 4-component vector of float)"));
254 }
255 
TEST_F(TypeTrackingTest,TextureSizeResultTypeAndPrecision)256 TEST_F(TypeTrackingTest, TextureSizeResultTypeAndPrecision)
257 {
258     // ESSL 3.0 spec section 8: textureSize has predefined precision highp
259     const std::string &shaderString =
260         "#version 300 es\n"
261         "precision mediump float;\n"
262         "out vec4 my_FragColor;\n"
263         "uniform sampler2D s;\n"
264         "void main() {\n"
265         "   ivec2 size = textureSize(s, 0);\n"
266         "   if (size.x > 100) {\n"
267         "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
268         "   } else {\n"
269         "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
270         "   }\n"
271         "}\n";
272     compile(shaderString);
273     ASSERT_FALSE(foundErrorInIntermediateTree());
274     ASSERT_TRUE(foundInIntermediateTree("textureSize (highp 2-component vector of int)"));
275 }
276 
TEST_F(TypeTrackingTest,BuiltInConstructorResultTypeAndPrecision)277 TEST_F(TypeTrackingTest, BuiltInConstructorResultTypeAndPrecision)
278 {
279     const std::string &shaderString =
280         "precision mediump float;\n"
281         "uniform float u1;\n"
282         "uniform float u2;\n"
283         "uniform float u3;\n"
284         "uniform float u4;\n"
285         "void main() {\n"
286         "   vec4 a = vec4(u1, u2, u3, u4);\n"
287         "   gl_FragColor = a;\n"
288         "}\n";
289     compile(shaderString);
290     ASSERT_FALSE(foundErrorInIntermediateTree());
291     ASSERT_TRUE(foundInIntermediateTree("Construct (mediump 4-component vector of float)"));
292 }
293 
TEST_F(TypeTrackingTest,StructConstructorResultNoPrecision)294 TEST_F(TypeTrackingTest, StructConstructorResultNoPrecision)
295 {
296     const std::string &shaderString =
297         "precision mediump float;\n"
298         "uniform vec4 u1;\n"
299         "uniform vec4 u2;\n"
300         "struct S { highp vec4 a; highp vec4 b; };\n"
301         "void main() {\n"
302         "   S s = S(u1, u2);\n"
303         "   gl_FragColor = s.a;\n"
304         "}\n";
305     compile(shaderString);
306     ASSERT_FALSE(foundErrorInIntermediateTree());
307     ASSERT_TRUE(foundInIntermediateTree("Construct (structure)"));
308 }
309 
TEST_F(TypeTrackingTest,PackResultTypeAndPrecision)310 TEST_F(TypeTrackingTest, PackResultTypeAndPrecision)
311 {
312     // ESSL 3.0 spec section 8.4: pack functions have predefined precision highp
313     const std::string &shaderString =
314         "#version 300 es\n"
315         "precision mediump float;\n"
316         "precision mediump int;\n"
317         "uniform vec2 uv;\n"
318         "out vec4 my_FragColor;\n"
319         "void main() {\n"
320         "   uint u0 = packSnorm2x16(uv);\n"
321         "   uint u1 = packUnorm2x16(uv);\n"
322         "   uint u2 = packHalf2x16(uv);\n"
323         "   if (u0 + u1 + u2 > 100u) {\n"
324         "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
325         "   } else {\n"
326         "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
327         "   }\n"
328         "}\n";
329     compile(shaderString);
330     ASSERT_FALSE(foundErrorInIntermediateTree());
331     ASSERT_TRUE(foundInIntermediateTree("packSnorm2x16 (highp uint)"));
332     ASSERT_TRUE(foundInIntermediateTree("packUnorm2x16 (highp uint)"));
333     ASSERT_TRUE(foundInIntermediateTree("packHalf2x16 (highp uint)"));
334 }
335 
TEST_F(TypeTrackingTest,UnpackNormResultTypeAndPrecision)336 TEST_F(TypeTrackingTest, UnpackNormResultTypeAndPrecision)
337 {
338     // ESSL 3.0 spec section 8.4: unpack(S/U)norm2x16 has predefined precision highp
339     const std::string &shaderString =
340         "#version 300 es\n"
341         "precision mediump float;\n"
342         "precision mediump int;\n"
343         "uniform uint uu;\n"
344         "out vec4 my_FragColor;\n"
345         "void main() {\n"
346         "   vec2 v0 = unpackSnorm2x16(uu);\n"
347         "   vec2 v1 = unpackUnorm2x16(uu);\n"
348         "   if (v0.x * v1.x > 1.0) {\n"
349         "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
350         "   } else {\n"
351         "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
352         "   }\n"
353         "}\n";
354     compile(shaderString);
355     ASSERT_FALSE(foundErrorInIntermediateTree());
356     ASSERT_TRUE(foundInIntermediateTree("unpackSnorm2x16 (highp 2-component vector of float)"));
357     ASSERT_TRUE(foundInIntermediateTree("unpackUnorm2x16 (highp 2-component vector of float)"));
358 }
359 
TEST_F(TypeTrackingTest,UnpackHalfResultTypeAndPrecision)360 TEST_F(TypeTrackingTest, UnpackHalfResultTypeAndPrecision)
361 {
362     // ESSL 3.0 spec section 8.4: unpackHalf2x16 has predefined precision mediump
363     const std::string &shaderString =
364         "#version 300 es\n"
365         "precision highp float;\n"
366         "precision highp int;\n"
367         "uniform uint uu;\n"
368         "out vec4 my_FragColor;\n"
369         "void main() {\n"
370         "   vec2 v = unpackHalf2x16(uu);\n"
371         "   if (v.x > 1.0) {\n"
372         "       my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
373         "   } else {\n"
374         "       my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
375         "   }\n"
376         "}\n";
377     compile(shaderString);
378     ASSERT_FALSE(foundErrorInIntermediateTree());
379     ASSERT_TRUE(foundInIntermediateTree("unpackHalf2x16 (mediump 2-component vector of float)"));
380 }
381 
TEST_F(TypeTrackingTest,BuiltInAbsSignFunctionFloatResultTypeAndPrecision)382 TEST_F(TypeTrackingTest, BuiltInAbsSignFunctionFloatResultTypeAndPrecision)
383 {
384     const std::string &shaderString =
385         "precision mediump float;\n"
386         "uniform float fval1;\n"
387         "void main() {\n"
388         "   float fval2 = abs(fval1);\n"
389         "   float fval3 = sign(fval1);\n"
390         "   gl_FragColor = vec4(fval1, fval2, fval3, 1.0); \n"
391         "}\n";
392     compile(shaderString);
393     ASSERT_FALSE(foundErrorInIntermediateTree());
394     ASSERT_TRUE(foundInIntermediateTree("abs (mediump float)"));
395     ASSERT_TRUE(foundInIntermediateTree("sign (mediump float)"));
396 }
397 
TEST_F(TypeTrackingTest,BuiltInAbsSignFunctionIntResultTypeAndPrecision)398 TEST_F(TypeTrackingTest, BuiltInAbsSignFunctionIntResultTypeAndPrecision)
399 {
400     const std::string &shaderString =
401         "#version 300 es\n"
402         "precision mediump float;\n"
403         "precision mediump int;\n"
404         "uniform int ival1;\n"
405         "out vec4 my_FragColor;\n"
406         "void main() {\n"
407         "   int ival2 = abs(ival1);\n"
408         "   int ival3 = sign(ival1);\n"
409         "   my_FragColor = vec4(ival2, ival3, 0, 1); \n"
410         "}\n";
411     compile(shaderString);
412     ASSERT_FALSE(foundErrorInIntermediateTree());
413     ASSERT_TRUE(foundInIntermediateTree("abs (mediump int)"));
414     ASSERT_TRUE(foundInIntermediateTree("sign (mediump int)"));
415 }
416 
TEST_F(TypeTrackingTest,BuiltInFloatBitsToIntResultTypeAndPrecision)417 TEST_F(TypeTrackingTest, BuiltInFloatBitsToIntResultTypeAndPrecision)
418 {
419     // ESSL 3.00 section 8.3: floatBitsTo(U)int returns a highp value.
420     const std::string &shaderString =
421         "#version 300 es\n"
422         "precision mediump float;\n"
423         "precision mediump int;\n"
424         "uniform float f;\n"
425         "out vec4 my_FragColor;\n"
426         "void main() {\n"
427         "   int i = floatBitsToInt(f);\n"
428         "   uint u = floatBitsToUint(f);\n"
429         "   my_FragColor = vec4(i, int(u), 0, 1); \n"
430         "}\n";
431     compile(shaderString);
432     ASSERT_FALSE(foundErrorInIntermediateTree());
433     ASSERT_TRUE(foundInIntermediateTree("floatBitsToInt (highp int)"));
434     ASSERT_TRUE(foundInIntermediateTree("floatBitsToUint (highp uint)"));
435 }
436 
TEST_F(TypeTrackingTest,BuiltInIntBitsToFloatResultTypeAndPrecision)437 TEST_F(TypeTrackingTest, BuiltInIntBitsToFloatResultTypeAndPrecision)
438 {
439     // ESSL 3.00 section 8.3: (u)intBitsToFloat returns a highp value.
440     const std::string &shaderString =
441         "#version 300 es\n"
442         "precision mediump float;\n"
443         "precision mediump int;\n"
444         "uniform int i;\n"
445         "uniform uint u;\n"
446         "out vec4 my_FragColor;\n"
447         "void main() {\n"
448         "   float f1 = intBitsToFloat(i);\n"
449         "   float f2 = uintBitsToFloat(u);\n"
450         "   my_FragColor = vec4(f1, f2, 0.0, 1.0); \n"
451         "}\n";
452     compile(shaderString);
453     ASSERT_FALSE(foundErrorInIntermediateTree());
454     ASSERT_TRUE(foundInIntermediateTree("intBitsToFloat (highp float)"));
455     ASSERT_TRUE(foundInIntermediateTree("uintBitsToFloat (highp float)"));
456 }
457 
458 // Test that bitfieldExtract returns a precision consistent with its "value" parameter.
TEST_F(TypeTrackingTest,BuiltInBitfieldExtractResultTypeAndPrecision)459 TEST_F(TypeTrackingTest, BuiltInBitfieldExtractResultTypeAndPrecision)
460 {
461     const std::string &shaderString =
462         "#version 310 es\n"
463         "precision mediump float;\n"
464         "uniform mediump int i;\n"
465         "uniform highp uint u;\n"
466         "uniform lowp int offset;\n"
467         "uniform highp int bits;\n"
468         "out vec4 my_FragColor;\n"
469         "void main() {\n"
470         "   lowp int i2 = bitfieldExtract(i, offset, bits);\n"
471         "   lowp uint u2 = bitfieldExtract(u, offset, bits);\n"
472         "   my_FragColor = vec4(i2, u2, 0.0, 1.0); \n"
473         "}\n";
474     compile(shaderString);
475     ASSERT_FALSE(foundErrorInIntermediateTree());
476     ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (mediump int)"));
477     ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (highp uint)"));
478 }
479 
480 // Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
TEST_F(TypeTrackingTest,BuiltInBitfieldInsertResultTypeAndPrecision)481 TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision)
482 {
483     const std::string &shaderString =
484         "#version 310 es\n"
485         "precision mediump float;\n"
486         "uniform lowp int iBase;\n"
487         "uniform mediump int iInsert;\n"
488         "uniform highp uint uBase;\n"
489         "uniform mediump uint uInsert;\n"
490         "uniform highp int offset;\n"
491         "uniform highp int bits;\n"
492         "out vec4 my_FragColor;\n"
493         "void main() {\n"
494         "   lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
495         "   lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
496         "   my_FragColor = vec4(i, u, 0.0, 1.0); \n"
497         "}\n";
498     compile(shaderString);
499     ASSERT_FALSE(foundErrorInIntermediateTree());
500     ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump int)"));
501     ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp uint)"));
502 }
503 
504 // Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
505 // Another variation on parameter precisions.
TEST_F(TypeTrackingTest,BuiltInBitfieldInsertResultTypeAndPrecision2)506 TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision2)
507 {
508     const std::string &shaderString =
509         "#version 310 es\n"
510         "precision mediump float;\n"
511         "uniform highp int iBase;\n"
512         "uniform mediump int iInsert;\n"
513         "uniform lowp uint uBase;\n"
514         "uniform mediump uint uInsert;\n"
515         "uniform lowp int offset;\n"
516         "uniform lowp int bits;\n"
517         "out vec4 my_FragColor;\n"
518         "void main() {\n"
519         "   lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
520         "   lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
521         "   my_FragColor = vec4(i, u, 0.0, 1.0); \n"
522         "}\n";
523     compile(shaderString);
524     ASSERT_FALSE(foundErrorInIntermediateTree());
525     ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp int)"));
526     ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump uint)"));
527 }
528 
529 // Test that bitfieldReverse always results in highp precision.
TEST_F(TypeTrackingTest,BuiltInBitfieldReversePrecision)530 TEST_F(TypeTrackingTest, BuiltInBitfieldReversePrecision)
531 {
532     const std::string &shaderString =
533         "#version 310 es\n"
534         "precision mediump float;\n"
535         "uniform lowp uint u;\n"
536         "uniform mediump int i;\n"
537         "out vec4 my_FragColor;\n"
538         "void main() {\n"
539         "   lowp uint u2 = bitfieldReverse(u);\n"
540         "   lowp int i2 = bitfieldReverse(i);\n"
541         "   my_FragColor = vec4(u2, i2, 0.0, 1.0); \n"
542         "}\n";
543     compile(shaderString);
544     ASSERT_FALSE(foundErrorInIntermediateTree());
545     ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp uint)"));
546     ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp int)"));
547 }
548 
549 // Test that bitCount always results in lowp precision integer.
TEST_F(TypeTrackingTest,BuiltInBitCountTypeAndPrecision)550 TEST_F(TypeTrackingTest, BuiltInBitCountTypeAndPrecision)
551 {
552     const std::string &shaderString =
553         "#version 310 es\n"
554         "precision mediump float;\n"
555         "uniform highp uint u;\n"
556         "uniform mediump int i;\n"
557         "out vec4 my_FragColor;\n"
558         "void main() {\n"
559         "   highp int count1 = bitCount(u);\n"
560         "   highp int count2 = bitCount(i);\n"
561         "   my_FragColor = vec4(count1, count2, 0.0, 1.0); \n"
562         "}\n";
563     compile(shaderString);
564     ASSERT_FALSE(foundErrorInIntermediateTree());
565     ASSERT_TRUE(foundInIntermediateTree("bitCount (lowp int)"));
566     ASSERT_FALSE(foundInIntermediateTree("bitCount (lowp uint)"));
567 }
568 
569 // Test that findLSB always results in a lowp precision integer.
TEST_F(TypeTrackingTest,BuiltInFindLSBTypeAndPrecision)570 TEST_F(TypeTrackingTest, BuiltInFindLSBTypeAndPrecision)
571 {
572     const std::string &shaderString =
573         "#version 310 es\n"
574         "precision mediump float;\n"
575         "uniform highp uint u;\n"
576         "uniform mediump int i;\n"
577         "out vec4 my_FragColor;\n"
578         "void main() {\n"
579         "   highp int index1 = findLSB(u);\n"
580         "   highp int index2 = findLSB(i);\n"
581         "   my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
582         "}\n";
583     compile(shaderString);
584     ASSERT_FALSE(foundErrorInIntermediateTree());
585     ASSERT_TRUE(foundInIntermediateTree("findLSB (lowp int)"));
586     ASSERT_FALSE(foundInIntermediateTree("findLSB (lowp uint)"));
587 }
588 
589 // Test that findMSB always results in a lowp precision integer.
TEST_F(TypeTrackingTest,BuiltInFindMSBTypeAndPrecision)590 TEST_F(TypeTrackingTest, BuiltInFindMSBTypeAndPrecision)
591 {
592     const std::string &shaderString =
593         "#version 310 es\n"
594         "precision mediump float;\n"
595         "uniform highp uint u;\n"
596         "uniform mediump int i;\n"
597         "out vec4 my_FragColor;\n"
598         "void main() {\n"
599         "   highp int index1 = findMSB(u);\n"
600         "   highp int index2 = findMSB(i);\n"
601         "   my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
602         "}\n";
603     compile(shaderString);
604     ASSERT_FALSE(foundErrorInIntermediateTree());
605     ASSERT_TRUE(foundInIntermediateTree("findMSB (lowp int)"));
606     ASSERT_FALSE(foundInIntermediateTree("findMSB (lowp uint)"));
607 }
608 
609 // Test that uaddCarry always results in highp precision.
TEST_F(TypeTrackingTest,BuiltInUaddCarryPrecision)610 TEST_F(TypeTrackingTest, BuiltInUaddCarryPrecision)
611 {
612     const std::string &shaderString =
613         "#version 310 es\n"
614         "precision mediump float;\n"
615         "uniform mediump uvec2 x;\n"
616         "uniform mediump uvec2 y;\n"
617         "out vec4 my_FragColor;\n"
618         "void main() {\n"
619         "   lowp uvec2 carry;\n"
620         "   mediump uvec2 result = uaddCarry(x, y, carry);\n"
621         "   my_FragColor = vec4(result.x, carry.y, 0.0, 1.0); \n"
622         "}\n";
623     compile(shaderString);
624     ASSERT_FALSE(foundErrorInIntermediateTree());
625     ASSERT_TRUE(foundInIntermediateTree("uaddCarry (highp 2-component vector of uint)"));
626 }
627 
628 // Test that usubBorrow always results in highp precision.
TEST_F(TypeTrackingTest,BuiltInUsubBorrowPrecision)629 TEST_F(TypeTrackingTest, BuiltInUsubBorrowPrecision)
630 {
631     const std::string &shaderString =
632         "#version 310 es\n"
633         "precision mediump float;\n"
634         "uniform mediump uvec2 x;\n"
635         "uniform mediump uvec2 y;\n"
636         "out vec4 my_FragColor;\n"
637         "void main() {\n"
638         "   lowp uvec2 borrow;\n"
639         "   mediump uvec2 result = usubBorrow(x, y, borrow);\n"
640         "   my_FragColor = vec4(result.x, borrow.y, 0.0, 1.0); \n"
641         "}\n";
642     compile(shaderString);
643     ASSERT_FALSE(foundErrorInIntermediateTree());
644     ASSERT_TRUE(foundInIntermediateTree("usubBorrow (highp 2-component vector of uint)"));
645 }
646