• 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 // DebugShaderPrecision_test.cpp:
7 //   Tests for writing the code for shader precision emulation.
8 //
9 
10 #include "GLSLANG/ShaderLang.h"
11 #include "angle_gl.h"
12 #include "gtest/gtest.h"
13 #include "tests/test_utils/compiler_test.h"
14 
15 using namespace sh;
16 
17 class DebugShaderPrecisionTest : public MatchOutputCodeTest
18 {
19   public:
DebugShaderPrecisionTest()20     DebugShaderPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
21     {
22         addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
23 #if defined(ANGLE_ENABLE_HLSL)
24         addOutputType(SH_HLSL_4_1_OUTPUT);
25 #endif
26         getResources()->WEBGL_debug_shader_precision = 1;
27     }
28 
29   protected:
foundInAllGLSLCode(const char * str)30     bool foundInAllGLSLCode(const char *str)
31     {
32         return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, str) && foundInCode(SH_ESSL_OUTPUT, str);
33     }
34 
foundInHLSLCode(const char * stringToFind) const35     bool foundInHLSLCode(const char *stringToFind) const
36     {
37 #if defined(ANGLE_ENABLE_HLSL)
38         return foundInCode(SH_HLSL_4_1_OUTPUT, stringToFind);
39 #else
40         return true;
41 #endif
42     }
43 
foundInHLSLCodeRegex(const char * regexToFind) const44     bool foundInHLSLCodeRegex(const char *regexToFind) const
45     {
46 #if defined(ANGLE_ENABLE_HLSL)
47         return foundInCodeRegex(SH_HLSL_4_1_OUTPUT, std::regex(regexToFind));
48 #else
49         return true;
50 #endif
51     }
52 };
53 
54 class NoDebugShaderPrecisionTest : public MatchOutputCodeTest
55 {
56   public:
NoDebugShaderPrecisionTest()57     NoDebugShaderPrecisionTest()
58         : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_GLSL_COMPATIBILITY_OUTPUT)
59     {}
60 };
61 
TEST_F(DebugShaderPrecisionTest,RoundingFunctionsDefined)62 TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
63 {
64     const std::string &shaderString =
65         "precision mediump float;\n"
66         "uniform float u;\n"
67         "void main() {\n"
68         "   gl_FragColor = vec4(u);\n"
69         "}\n";
70     compile(shaderString);
71     ASSERT_TRUE(foundInESSLCode("highp float angle_frm(in highp float"));
72     ASSERT_TRUE(foundInESSLCode("highp vec2 angle_frm(in highp vec2"));
73     ASSERT_TRUE(foundInESSLCode("highp vec3 angle_frm(in highp vec3"));
74     ASSERT_TRUE(foundInESSLCode("highp vec4 angle_frm(in highp vec4"));
75     ASSERT_TRUE(foundInESSLCode("highp mat2 angle_frm(in highp mat2"));
76     ASSERT_TRUE(foundInESSLCode("highp mat3 angle_frm(in highp mat3"));
77     ASSERT_TRUE(foundInESSLCode("highp mat4 angle_frm(in highp mat4"));
78 
79     ASSERT_TRUE(foundInESSLCode("highp float angle_frl(in highp float"));
80     ASSERT_TRUE(foundInESSLCode("highp vec2 angle_frl(in highp vec2"));
81     ASSERT_TRUE(foundInESSLCode("highp vec3 angle_frl(in highp vec3"));
82     ASSERT_TRUE(foundInESSLCode("highp vec4 angle_frl(in highp vec4"));
83     ASSERT_TRUE(foundInESSLCode("highp mat2 angle_frl(in highp mat2"));
84     ASSERT_TRUE(foundInESSLCode("highp mat3 angle_frl(in highp mat3"));
85     ASSERT_TRUE(foundInESSLCode("highp mat4 angle_frl(in highp mat4"));
86 
87     ASSERT_TRUE(foundInGLSLCode("float angle_frm(in float"));
88     ASSERT_TRUE(foundInGLSLCode("vec2 angle_frm(in vec2"));
89     ASSERT_TRUE(foundInGLSLCode("vec3 angle_frm(in vec3"));
90     ASSERT_TRUE(foundInGLSLCode("vec4 angle_frm(in vec4"));
91     ASSERT_TRUE(foundInGLSLCode("mat2 angle_frm(in mat2"));
92     ASSERT_TRUE(foundInGLSLCode("mat3 angle_frm(in mat3"));
93     ASSERT_TRUE(foundInGLSLCode("mat4 angle_frm(in mat4"));
94 
95     ASSERT_TRUE(foundInGLSLCode("float angle_frl(in float"));
96     ASSERT_TRUE(foundInGLSLCode("vec2 angle_frl(in vec2"));
97     ASSERT_TRUE(foundInGLSLCode("vec3 angle_frl(in vec3"));
98     ASSERT_TRUE(foundInGLSLCode("vec4 angle_frl(in vec4"));
99     ASSERT_TRUE(foundInGLSLCode("mat2 angle_frl(in mat2"));
100     ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3"));
101     ASSERT_TRUE(foundInGLSLCode("mat4 angle_frl(in mat4"));
102 
103     ASSERT_TRUE(foundInHLSLCode("float1 angle_frm(float1"));
104     ASSERT_TRUE(foundInHLSLCode("float2 angle_frm(float2"));
105     ASSERT_TRUE(foundInHLSLCode("float3 angle_frm(float3"));
106     ASSERT_TRUE(foundInHLSLCode("float4 angle_frm(float4"));
107     ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frm(float2x2"));
108     ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frm(float3x3"));
109     ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frm(float4x4"));
110 
111     ASSERT_TRUE(foundInHLSLCode("float1 angle_frl(float1"));
112     ASSERT_TRUE(foundInHLSLCode("float2 angle_frl(float2"));
113     ASSERT_TRUE(foundInHLSLCode("float3 angle_frl(float3"));
114     ASSERT_TRUE(foundInHLSLCode("float4 angle_frl(float4"));
115     ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frl(float2x2"));
116     ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frl(float3x3"));
117     ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frl(float4x4"));
118 
119     // Check that ESSL 3.00 rounding functions for non-square matrices are not defined.
120     ASSERT_TRUE(notFoundInCode("mat2x"));
121     ASSERT_TRUE(notFoundInCode("mat3x"));
122     ASSERT_TRUE(notFoundInCode("mat4x"));
123 }
124 
125 // Test that all ESSL 3.00 shaders get rounding function definitions for non-square matrices.
TEST_F(DebugShaderPrecisionTest,NonSquareMatrixRoundingFunctionsDefinedES3)126 TEST_F(DebugShaderPrecisionTest, NonSquareMatrixRoundingFunctionsDefinedES3)
127 {
128     const std::string &shaderString =
129         "#version 300 es\n"
130         "precision mediump float;\n"
131         "uniform float u;\n"
132         "out vec4 my_FragColor;\n"
133         "void main() {\n"
134         "   my_FragColor = vec4(u);\n"
135         "}\n";
136     compile(shaderString);
137     ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frm(in highp mat2x3"));
138     ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frm(in highp mat2x4"));
139     ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frm(in highp mat3x2"));
140     ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frm(in highp mat3x4"));
141     ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frm(in highp mat4x2"));
142     ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frm(in highp mat4x3"));
143 
144     ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frl(in highp mat2x3"));
145     ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frl(in highp mat2x4"));
146     ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frl(in highp mat3x2"));
147     ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frl(in highp mat3x4"));
148     ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frl(in highp mat4x2"));
149     ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frl(in highp mat4x3"));
150 
151     ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frm(in mat2x3"));
152     ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frm(in mat2x4"));
153     ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frm(in mat3x2"));
154     ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frm(in mat3x4"));
155     ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frm(in mat4x2"));
156     ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frm(in mat4x3"));
157 
158     ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frl(in mat2x3"));
159     ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frl(in mat2x4"));
160     ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frl(in mat3x2"));
161     ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frl(in mat3x4"));
162     ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frl(in mat4x2"));
163     ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frl(in mat4x3"));
164 
165     ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frm(float2x3"));
166     ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frm(float2x4"));
167     ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frm(float3x2"));
168     ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frm(float3x4"));
169     ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frm(float4x2"));
170     ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frm(float4x3"));
171 
172     ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frl(float2x3"));
173     ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frl(float2x4"));
174     ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frl(float3x2"));
175     ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frl(float3x4"));
176     ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frl(float4x2"));
177     ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frl(float4x3"));
178 }
179 
TEST_F(DebugShaderPrecisionTest,PragmaDisablesEmulation)180 TEST_F(DebugShaderPrecisionTest, PragmaDisablesEmulation)
181 {
182     const std::string &shaderString =
183         "#pragma webgl_debug_shader_precision(off)\n"
184         "precision mediump float;\n"
185         "uniform float u;\n"
186         "void main() {\n"
187         "   gl_FragColor = vec4(u);\n"
188         "}\n";
189     compile(shaderString);
190     ASSERT_TRUE(notFoundInCode("angle_frm"));
191     const std::string &shaderStringPragmaOn =
192         "#pragma webgl_debug_shader_precision(on)\n"
193         "precision mediump float;\n"
194         "uniform float u;\n"
195         "void main() {\n"
196         "   gl_FragColor = vec4(u);\n"
197         "}\n";
198     compile(shaderStringPragmaOn);
199     ASSERT_TRUE(foundInCode("angle_frm"));
200 }
201 
202 // Emulation can't be toggled on for only a part of a shader.
203 // Only the last pragma in the shader has an effect.
TEST_F(DebugShaderPrecisionTest,MultiplePragmas)204 TEST_F(DebugShaderPrecisionTest, MultiplePragmas)
205 {
206     const std::string &shaderString =
207         "#pragma webgl_debug_shader_precision(off)\n"
208         "precision mediump float;\n"
209         "uniform float u;\n"
210         "void main() {\n"
211         "   gl_FragColor = vec4(u);\n"
212         "}\n"
213         "#pragma webgl_debug_shader_precision(on)\n";
214     compile(shaderString);
215     ASSERT_TRUE(foundInCode("angle_frm"));
216 }
217 
TEST_F(NoDebugShaderPrecisionTest,HelpersWrittenOnlyWithExtension)218 TEST_F(NoDebugShaderPrecisionTest, HelpersWrittenOnlyWithExtension)
219 {
220     const std::string &shaderString =
221         "precision mediump float;\n"
222         "uniform float u;\n"
223         "void main() {\n"
224         "   gl_FragColor = vec4(u);\n"
225         "}\n";
226     compile(shaderString);
227     ASSERT_FALSE(foundInCode("angle_frm"));
228 }
229 
TEST_F(NoDebugShaderPrecisionTest,PragmaHasEffectsOnlyWithExtension)230 TEST_F(NoDebugShaderPrecisionTest, PragmaHasEffectsOnlyWithExtension)
231 {
232     const std::string &shaderString =
233         "#pragma webgl_debug_shader_precision(on)\n"
234         "precision mediump float;\n"
235         "uniform float u;\n"
236         "void main() {\n"
237         "   gl_FragColor = vec4(u);\n"
238         "}\n";
239     compile(shaderString);
240     ASSERT_FALSE(foundInCode("angle_frm"));
241 }
242 
TEST_F(DebugShaderPrecisionTest,DeclarationsAndConstants)243 TEST_F(DebugShaderPrecisionTest, DeclarationsAndConstants)
244 {
245     const std::string &shaderString =
246         "precision mediump float;\n"
247         "uniform vec4 f;\n"
248         "uniform float uu, uu2;\n"
249         "varying float vv, vv2;\n"
250         "float gg = 0.0, gg2;\n"
251         "void main() {\n"
252         "   float aa = 0.0, aa2;\n"
253         "   gl_FragColor = f;\n"
254         "}\n";
255     compile(shaderString);
256     // Declarations or constants should not have rounding inserted around them
257     ASSERT_TRUE(notFoundInCode("angle_frm(0"));
258     // GLSL output
259     ASSERT_TRUE(notFoundInCode("angle_frm(_uuu"));
260     ASSERT_TRUE(notFoundInCode("angle_frm(_uvv"));
261     ASSERT_TRUE(notFoundInCode("angle_frm(_ugg"));
262     ASSERT_TRUE(notFoundInCode("angle_frm(_uaa"));
263     // HLSL output
264     ASSERT_TRUE(notFoundInCode("angle_frm(_uu"));
265     ASSERT_TRUE(notFoundInCode("angle_frm(_vv"));
266     ASSERT_TRUE(notFoundInCode("angle_frm(_gg"));
267     ASSERT_TRUE(notFoundInCode("angle_frm(_aa"));
268 }
269 
270 // Test that expressions that are part of initialization have rounding.
TEST_F(DebugShaderPrecisionTest,InitializerRounding)271 TEST_F(DebugShaderPrecisionTest, InitializerRounding)
272 {
273     const std::string &shaderString =
274         "precision mediump float;\n"
275         "uniform float u;\n"
276         "void main() {\n"
277         "   float a = u;\n"
278         "   gl_FragColor = vec4(a);\n"
279         "}\n";
280     compile(shaderString);
281     // An expression that's part of initialization should have rounding
282     ASSERT_TRUE(foundInAllGLSLCode("angle_frm(_uu)"));
283     ASSERT_TRUE(foundInHLSLCode("angle_frm(_u)"));
284 }
285 
286 // Test that compound additions have rounding in the GLSL translations.
TEST_F(DebugShaderPrecisionTest,CompoundAddFunction)287 TEST_F(DebugShaderPrecisionTest, CompoundAddFunction)
288 {
289     const std::string &shaderString =
290         "precision mediump float;\n"
291         "uniform vec4 u;\n"
292         "uniform vec4 u2;\n"
293         "void main() {\n"
294         "   vec4 v = u;\n"
295         "   v += u2;\n"
296         "   gl_FragColor = v;\n"
297         "}\n";
298     compile(shaderString);
299     ASSERT_TRUE(
300         foundInESSLCode("highp vec4 angle_compound_add_frm(inout highp vec4 x, in highp vec4 y) {\n"
301                         "    x = angle_frm(angle_frm(x) + y);"));
302     ASSERT_TRUE(
303         foundInGLSLCode("vec4 angle_compound_add_frm(inout vec4 x, in vec4 y) {\n"
304                         "    x = angle_frm(angle_frm(x) + y);"));
305     ASSERT_TRUE(
306         foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float4 y) {\n"
307                         "    x = angle_frm(angle_frm(x) + y);"));
308     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(_uv, angle_frm(_uu2));"));
309     ASSERT_TRUE(foundInHLSLCodeRegex(R"(angle_compound_add_frm\(_v(\d)*, angle_frm\(_u2\)\);)"));
310     ASSERT_TRUE(notFoundInCode("+="));
311 }
312 
TEST_F(DebugShaderPrecisionTest,CompoundSubFunction)313 TEST_F(DebugShaderPrecisionTest, CompoundSubFunction)
314 {
315     const std::string &shaderString =
316         "precision mediump float;\n"
317         "uniform vec4 u;\n"
318         "uniform vec4 u2;\n"
319         "void main() {\n"
320         "   vec4 v = u;\n"
321         "   v -= u2;\n"
322         "   gl_FragColor = v;\n"
323         "}\n";
324     compile(shaderString);
325     ASSERT_TRUE(
326         foundInESSLCode("highp vec4 angle_compound_sub_frm(inout highp vec4 x, in highp vec4 y) {\n"
327                         "    x = angle_frm(angle_frm(x) - y);"));
328     ASSERT_TRUE(
329         foundInGLSLCode("vec4 angle_compound_sub_frm(inout vec4 x, in vec4 y) {\n"
330                         "    x = angle_frm(angle_frm(x) - y);"));
331     ASSERT_TRUE(
332         foundInHLSLCode("float4 angle_compound_sub_frm(inout float4 x, in float4 y) {\n"
333                         "    x = angle_frm(angle_frm(x) - y);"));
334     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_sub_frm(_uv, angle_frm(_uu2));"));
335     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_sub_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
336     ASSERT_TRUE(notFoundInCode("-="));
337 }
338 
TEST_F(DebugShaderPrecisionTest,CompoundDivFunction)339 TEST_F(DebugShaderPrecisionTest, CompoundDivFunction)
340 {
341     const std::string &shaderString =
342         "precision mediump float;\n"
343         "uniform vec4 u;\n"
344         "uniform vec4 u2;\n"
345         "void main() {\n"
346         "   vec4 v = u;\n"
347         "   v /= u2;\n"
348         "   gl_FragColor = v;\n"
349         "}\n";
350     compile(shaderString);
351     ASSERT_TRUE(
352         foundInESSLCode("highp vec4 angle_compound_div_frm(inout highp vec4 x, in highp vec4 y) {\n"
353                         "    x = angle_frm(angle_frm(x) / y);"));
354     ASSERT_TRUE(
355         foundInGLSLCode("vec4 angle_compound_div_frm(inout vec4 x, in vec4 y) {\n"
356                         "    x = angle_frm(angle_frm(x) / y);"));
357     ASSERT_TRUE(
358         foundInHLSLCode("float4 angle_compound_div_frm(inout float4 x, in float4 y) {\n"
359                         "    x = angle_frm(angle_frm(x) / y);"));
360     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_div_frm(_uv, angle_frm(_uu2));"));
361     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_div_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
362     ASSERT_TRUE(notFoundInCode("/="));
363 }
364 
TEST_F(DebugShaderPrecisionTest,CompoundMulFunction)365 TEST_F(DebugShaderPrecisionTest, CompoundMulFunction)
366 {
367     const std::string &shaderString =
368         "precision mediump float;\n"
369         "uniform vec4 u;\n"
370         "uniform vec4 u2;\n"
371         "void main() {\n"
372         "   vec4 v = u;\n"
373         "   v *= u2;\n"
374         "   gl_FragColor = v;\n"
375         "}\n";
376     compile(shaderString);
377     ASSERT_TRUE(
378         foundInESSLCode("highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp vec4 y) {\n"
379                         "    x = angle_frm(angle_frm(x) * y);"));
380     ASSERT_TRUE(
381         foundInGLSLCode("vec4 angle_compound_mul_frm(inout vec4 x, in vec4 y) {\n"
382                         "    x = angle_frm(angle_frm(x) * y);"));
383     ASSERT_TRUE(
384         foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4 y) {\n"
385                         "    x = angle_frm(angle_frm(x) * y);"));
386     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_uv, angle_frm(_uu2));"));
387     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
388     ASSERT_TRUE(notFoundInCode("*="));
389 }
390 
TEST_F(DebugShaderPrecisionTest,CompoundAddVectorPlusScalarFunction)391 TEST_F(DebugShaderPrecisionTest, CompoundAddVectorPlusScalarFunction)
392 {
393     const std::string &shaderString =
394         "precision mediump float;\n"
395         "uniform vec4 u;\n"
396         "uniform float u2;\n"
397         "void main() {\n"
398         "   vec4 v = u;\n"
399         "   v += u2;\n"
400         "   gl_FragColor = v;\n"
401         "}\n";
402     compile(shaderString);
403     ASSERT_TRUE(foundInESSLCode(
404         "highp vec4 angle_compound_add_frm(inout highp vec4 x, in highp float y) {\n"
405         "    x = angle_frm(angle_frm(x) + y);"));
406     ASSERT_TRUE(
407         foundInGLSLCode("vec4 angle_compound_add_frm(inout vec4 x, in float y) {\n"
408                         "    x = angle_frm(angle_frm(x) + y);"));
409     ASSERT_TRUE(
410         foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float y) {\n"
411                         "    x = angle_frm(angle_frm(x) + y);"));
412     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(_uv, angle_frm(_uu2));"));
413     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_add_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
414     ASSERT_TRUE(notFoundInCode("+="));
415 }
416 
TEST_F(DebugShaderPrecisionTest,CompoundMatrixTimesMatrixFunction)417 TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction)
418 {
419     const std::string &shaderString =
420         "precision mediump float;\n"
421         "uniform mat4 u;\n"
422         "uniform mat4 u2;\n"
423         "void main() {\n"
424         "   mat4 m = u;\n"
425         "   m *= u2;\n"
426         "   gl_FragColor = m[0];\n"
427         "}\n";
428     compile(shaderString);
429     ASSERT_TRUE(
430         foundInESSLCode("highp mat4 angle_compound_mul_frm(inout highp mat4 x, in highp mat4 y) {\n"
431                         "    x = angle_frm(angle_frm(x) * y);"));
432     ASSERT_TRUE(
433         foundInGLSLCode("mat4 angle_compound_mul_frm(inout mat4 x, in mat4 y) {\n"
434                         "    x = angle_frm(angle_frm(x) * y);"));
435     ASSERT_TRUE(
436         foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float4x4 y) {\n"
437                         "    x = angle_frm(angle_frm(x) * y);"));
438     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_um, angle_frm(_uu2));"));
439     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_m(\\d)*, angle_frm\\(_u2\\)\\);"));
440     ASSERT_TRUE(notFoundInCode("*="));
441 }
442 
443 // Test that compound multiplying a non-square matrix with another matrix gets translated into an
444 // angle_compound_mul function call.
TEST_F(DebugShaderPrecisionTest,CompoundNonSquareMatrixTimesMatrixFunction)445 TEST_F(DebugShaderPrecisionTest, CompoundNonSquareMatrixTimesMatrixFunction)
446 {
447     const std::string &shaderString =
448         "#version 300 es\n"
449         "precision mediump float;\n"
450         "uniform mat2x4 u;\n"
451         "uniform mat2 u2;\n"
452         "out vec4 my_FragColor;\n"
453         "void main() {\n"
454         "   mat2x4 m = u;\n"
455         "   m *= u2;\n"
456         "   my_FragColor = m[0];\n"
457         "}\n";
458     compile(shaderString);
459     ASSERT_TRUE(foundInESSLCode(
460         "highp mat2x4 angle_compound_mul_frm(inout highp mat2x4 x, in highp mat2 y) {\n"
461         "    x = angle_frm(angle_frm(x) * y);"));
462     ASSERT_TRUE(
463         foundInGLSLCode("mat2x4 angle_compound_mul_frm(inout mat2x4 x, in mat2 y) {\n"
464                         "    x = angle_frm(angle_frm(x) * y);"));
465     ASSERT_TRUE(
466         foundInHLSLCode("float2x4 angle_compound_mul_frm(inout float2x4 x, in float2x2 y) {\n"
467                         "    x = angle_frm(angle_frm(x) * y);"));
468     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_um, angle_frm(_uu2));"));
469     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_m(\\d)*, angle_frm\\(_u2\\)\\);"));
470     ASSERT_TRUE(notFoundInCode("*="));
471 }
472 
TEST_F(DebugShaderPrecisionTest,CompoundMatrixTimesScalarFunction)473 TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesScalarFunction)
474 {
475     const std::string &shaderString =
476         "precision mediump float;\n"
477         "uniform mat4 u;\n"
478         "uniform float u2;\n"
479         "void main() {\n"
480         "   mat4 m = u;\n"
481         "   m *= u2;\n"
482         "   gl_FragColor = m[0];\n"
483         "}\n";
484     compile(shaderString);
485     ASSERT_TRUE(foundInESSLCode(
486         "highp mat4 angle_compound_mul_frm(inout highp mat4 x, in highp float y) {\n"
487         "    x = angle_frm(angle_frm(x) * y);"));
488     ASSERT_TRUE(
489         foundInGLSLCode("mat4 angle_compound_mul_frm(inout mat4 x, in float y) {\n"
490                         "    x = angle_frm(angle_frm(x) * y);"));
491     ASSERT_TRUE(
492         foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float y) {\n"
493                         "    x = angle_frm(angle_frm(x) * y);"));
494     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_um, angle_frm(_uu2));"));
495     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_m(\\d)*, angle_frm\\(_u2\\)\\);"));
496     ASSERT_TRUE(notFoundInCode("*="));
497 }
498 
TEST_F(DebugShaderPrecisionTest,CompoundVectorTimesMatrixFunction)499 TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesMatrixFunction)
500 {
501     const std::string &shaderString =
502         "precision mediump float;\n"
503         "uniform vec4 u;\n"
504         "uniform mat4 u2;\n"
505         "void main() {\n"
506         "   vec4 v = u;\n"
507         "   v *= u2;\n"
508         "   gl_FragColor = v;\n"
509         "}\n";
510     compile(shaderString);
511     ASSERT_TRUE(
512         foundInESSLCode("highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp mat4 y) {\n"
513                         "    x = angle_frm(angle_frm(x) * y);"));
514     ASSERT_TRUE(
515         foundInGLSLCode("vec4 angle_compound_mul_frm(inout vec4 x, in mat4 y) {\n"
516                         "    x = angle_frm(angle_frm(x) * y);"));
517     ASSERT_TRUE(
518         foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4x4 y) {\n"
519                         "    x = angle_frm(angle_frm(x) * y);"));
520     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_uv, angle_frm(_uu2));"));
521     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
522     ASSERT_TRUE(notFoundInCode("*="));
523 }
524 
TEST_F(DebugShaderPrecisionTest,CompoundVectorTimesScalarFunction)525 TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesScalarFunction)
526 {
527     const std::string &shaderString =
528         "precision mediump float;\n"
529         "uniform vec4 u;\n"
530         "uniform float u2;\n"
531         "void main() {\n"
532         "   vec4 v = u;\n"
533         "   v *= u2;\n"
534         "   gl_FragColor = v;\n"
535         "}\n";
536     compile(shaderString);
537     ASSERT_TRUE(foundInESSLCode(
538         "highp vec4 angle_compound_mul_frm(inout highp vec4 x, in highp float y) {\n"
539         "    x = angle_frm(angle_frm(x) * y);"));
540     ASSERT_TRUE(
541         foundInGLSLCode("vec4 angle_compound_mul_frm(inout vec4 x, in float y) {\n"
542                         "    x = angle_frm(angle_frm(x) * y);"));
543     ASSERT_TRUE(
544         foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float y) {\n"
545                         "    x = angle_frm(angle_frm(x) * y);"));
546     ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(_uv, angle_frm(_uu2));"));
547     ASSERT_TRUE(foundInHLSLCodeRegex("angle_compound_mul_frm\\(_v(\\d)*, angle_frm\\(_u2\\)\\);"));
548     ASSERT_TRUE(notFoundInCode("*="));
549 }
550 
TEST_F(DebugShaderPrecisionTest,BinaryMathRounding)551 TEST_F(DebugShaderPrecisionTest, BinaryMathRounding)
552 {
553     const std::string &shaderString =
554         "precision mediump float;\n"
555         "uniform vec4 u1;\n"
556         "uniform vec4 u2;\n"
557         "uniform vec4 u3;\n"
558         "uniform vec4 u4;\n"
559         "uniform vec4 u5;\n"
560         "void main() {\n"
561         "   vec4 v1 = u1 + u2;\n"
562         "   vec4 v2 = u2 - u3;\n"
563         "   vec4 v3 = u3 * u4;\n"
564         "   vec4 v4 = u4 / u5;\n"
565         "   vec4 v5;\n"
566         "   vec4 v6 = (v5 = u5);\n"
567         "   gl_FragColor = v1 + v2 + v3 + v4;\n"
568         "}\n";
569     compile(shaderString);
570     ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm((angle_frm(_uu1) + angle_frm(_uu2)))"));
571     ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm((angle_frm(_uu2) - angle_frm(_uu3)))"));
572     ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm((angle_frm(_uu3) * angle_frm(_uu4)))"));
573     ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm((angle_frm(_uu4) / angle_frm(_uu5)))"));
574     ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm((_uv5 = angle_frm(_uu5)))"));
575 
576     ASSERT_TRUE(foundInHLSLCodeRegex(
577         "v1(\\d)* = angle_frm\\(\\(angle_frm\\(_u1\\) \\+ angle_frm\\(_u2\\)\\)\\)"));
578     ASSERT_TRUE(foundInHLSLCodeRegex(
579         "v2(\\d)* = angle_frm\\(\\(angle_frm\\(_u2\\) - angle_frm\\(_u3\\)\\)\\)"));
580     ASSERT_TRUE(foundInHLSLCodeRegex(
581         "v3(\\d)* = angle_frm\\(\\(angle_frm\\(_u3\\) \\* angle_frm\\(_u4\\)\\)\\)"));
582     ASSERT_TRUE(foundInHLSLCodeRegex(
583         "v4(\\d)* = angle_frm\\(\\(angle_frm\\(_u4\\) / angle_frm\\(_u5\\)\\)\\)"));
584     ASSERT_TRUE(
585         foundInHLSLCodeRegex("v6(\\d)* = angle_frm\\(\\(_v5(\\d)* = angle_frm\\(_u5\\)\\)\\)"));
586 }
587 
TEST_F(DebugShaderPrecisionTest,BuiltInMathFunctionRounding)588 TEST_F(DebugShaderPrecisionTest, BuiltInMathFunctionRounding)
589 {
590     const std::string &shaderString =
591         "precision mediump float;\n"
592         "uniform vec4 u1;\n"
593         "uniform vec4 u2;\n"
594         "uniform vec4 u3;\n"
595         "uniform float uf;\n"
596         "uniform float uf2;\n"
597         "uniform vec3 uf31;\n"
598         "uniform vec3 uf32;\n"
599         "uniform mat4 um1;\n"
600         "uniform mat4 um2;\n"
601         "void main() {\n"
602         "   vec4 v1 = radians(u1);\n"
603         "   vec4 v2 = degrees(u1);\n"
604         "   vec4 v3 = sin(u1);\n"
605         "   vec4 v4 = cos(u1);\n"
606         "   vec4 v5 = tan(u1);\n"
607         "   vec4 v6 = asin(u1);\n"
608         "   vec4 v7 = acos(u1);\n"
609         "   vec4 v8 = atan(u1);\n"
610         "   vec4 v9 = atan(u1, u2);\n"
611         "   vec4 v10 = pow(u1, u2);\n"
612         "   vec4 v11 = exp(u1);\n"
613         "   vec4 v12 = log(u1);\n"
614         "   vec4 v13 = exp2(u1);\n"
615         "   vec4 v14 = log2(u1);\n"
616         "   vec4 v15 = sqrt(u1);\n"
617         "   vec4 v16 = inversesqrt(u1);\n"
618         "   vec4 v17 = abs(u1);\n"
619         "   vec4 v18 = sign(u1);\n"
620         "   vec4 v19 = floor(u1);\n"
621         "   vec4 v20 = ceil(u1);\n"
622         "   vec4 v21 = fract(u1);\n"
623         "   vec4 v22 = mod(u1, uf);\n"
624         "   vec4 v23 = mod(u1, u2);\n"
625         "   vec4 v24 = min(u1, uf);\n"
626         "   vec4 v25 = min(u1, u2);\n"
627         "   vec4 v26 = max(u1, uf);\n"
628         "   vec4 v27 = max(u1, u2);\n"
629         "   vec4 v28 = clamp(u1, u2, u3);\n"
630         "   vec4 v29 = clamp(u1, uf, uf2);\n"
631         "   vec4 v30 = mix(u1, u2, u3);\n"
632         "   vec4 v31 = mix(u1, u2, uf);\n"
633         "   vec4 v32 = step(u1, u2);\n"
634         "   vec4 v33 = step(uf, u1);\n"
635         "   vec4 v34 = smoothstep(u1, u2, u3);\n"
636         "   vec4 v35 = smoothstep(uf, uf2, u1);\n"
637         "   vec4 v36 = normalize(u1);\n"
638         "   vec4 v37 = faceforward(u1, u2, u3);\n"
639         "   vec4 v38 = reflect(u1, u2);\n"
640         "   vec4 v39 = refract(u1, u2, uf);\n"
641 
642         "   float f1 = length(u1);\n"
643         "   float f2 = distance(u1, u2);\n"
644         "   float f3 = dot(u1, u2);\n"
645         "   vec3 vf31 = cross(uf31, uf32);\n"
646         "   mat4 m1 = matrixCompMult(um1, um2);\n"
647 
648         "   gl_FragColor = v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 +"
649         "v11 + v12 + v13 + v14 + v15 + v16 + v17 + v18 + v19 + v20 +"
650         "v21 + v22 + v23 + v24 + v25 + v26 + v27 + v28 + v29 + v30 +"
651         "v31 + v32 + v33 + v34 + v35 + v36 + v37 + v38 + v39 +"
652         "vec4(f1, f2, f3, 0.0) + vec4(vf31, 0.0) + m1[0];\n"
653         "}\n";
654     compile(shaderString);
655     ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(radians(angle_frm(_uu1)))"));
656     ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(degrees(angle_frm(_uu1)))"));
657     ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm(sin(angle_frm(_uu1)))"));
658     ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm(cos(angle_frm(_uu1)))"));
659     ASSERT_TRUE(foundInAllGLSLCode("v5 = angle_frm(tan(angle_frm(_uu1)))"));
660     ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm(asin(angle_frm(_uu1)))"));
661     ASSERT_TRUE(foundInAllGLSLCode("v7 = angle_frm(acos(angle_frm(_uu1)))"));
662     ASSERT_TRUE(foundInAllGLSLCode("v8 = angle_frm(atan(angle_frm(_uu1)))"));
663     ASSERT_TRUE(foundInAllGLSLCode("v9 = angle_frm(atan(angle_frm(_uu1), angle_frm(_uu2)))"));
664     ASSERT_TRUE(foundInAllGLSLCode("v10 = angle_frm(pow(angle_frm(_uu1), angle_frm(_uu2)))"));
665     ASSERT_TRUE(foundInAllGLSLCode("v11 = angle_frm(exp(angle_frm(_uu1)))"));
666     ASSERT_TRUE(foundInAllGLSLCode("v12 = angle_frm(log(angle_frm(_uu1)))"));
667     ASSERT_TRUE(foundInAllGLSLCode("v13 = angle_frm(exp2(angle_frm(_uu1)))"));
668     ASSERT_TRUE(foundInAllGLSLCode("v14 = angle_frm(log2(angle_frm(_uu1)))"));
669     ASSERT_TRUE(foundInAllGLSLCode("v15 = angle_frm(sqrt(angle_frm(_uu1)))"));
670     ASSERT_TRUE(foundInAllGLSLCode("v16 = angle_frm(inversesqrt(angle_frm(_uu1)))"));
671     ASSERT_TRUE(foundInAllGLSLCode("v17 = angle_frm(abs(angle_frm(_uu1)))"));
672     ASSERT_TRUE(foundInAllGLSLCode("v18 = angle_frm(sign(angle_frm(_uu1)))"));
673     ASSERT_TRUE(foundInAllGLSLCode("v19 = angle_frm(floor(angle_frm(_uu1)))"));
674     ASSERT_TRUE(foundInAllGLSLCode("v20 = angle_frm(ceil(angle_frm(_uu1)))"));
675     ASSERT_TRUE(foundInAllGLSLCode("v21 = angle_frm(fract(angle_frm(_uu1)))"));
676     ASSERT_TRUE(foundInAllGLSLCode("v22 = angle_frm(mod(angle_frm(_uu1), angle_frm(_uuf)))"));
677     ASSERT_TRUE(foundInAllGLSLCode("v23 = angle_frm(mod(angle_frm(_uu1), angle_frm(_uu2)))"));
678     ASSERT_TRUE(foundInAllGLSLCode("v24 = angle_frm(min(angle_frm(_uu1), angle_frm(_uuf)))"));
679     ASSERT_TRUE(foundInAllGLSLCode("v25 = angle_frm(min(angle_frm(_uu1), angle_frm(_uu2)))"));
680     ASSERT_TRUE(foundInAllGLSLCode("v26 = angle_frm(max(angle_frm(_uu1), angle_frm(_uuf)))"));
681     ASSERT_TRUE(foundInAllGLSLCode("v27 = angle_frm(max(angle_frm(_uu1), angle_frm(_uu2)))"));
682     ASSERT_TRUE(foundInAllGLSLCode(
683         "v28 = angle_frm(clamp(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uu3)))"));
684     ASSERT_TRUE(foundInAllGLSLCode(
685         "v29 = angle_frm(clamp(angle_frm(_uu1), angle_frm(_uuf), angle_frm(_uuf2)))"));
686     ASSERT_TRUE(foundInAllGLSLCode(
687         "v30 = angle_frm(mix(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uu3)))"));
688     ASSERT_TRUE(foundInAllGLSLCode(
689         "v31 = angle_frm(mix(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uuf)))"));
690     ASSERT_TRUE(foundInAllGLSLCode("v32 = angle_frm(step(angle_frm(_uu1), angle_frm(_uu2)))"));
691     ASSERT_TRUE(foundInAllGLSLCode("v33 = angle_frm(step(angle_frm(_uuf), angle_frm(_uu1)))"));
692     ASSERT_TRUE(foundInAllGLSLCode(
693         "v34 = angle_frm(smoothstep(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uu3)))"));
694     ASSERT_TRUE(foundInAllGLSLCode(
695         "v35 = angle_frm(smoothstep(angle_frm(_uuf), angle_frm(_uuf2), angle_frm(_uu1)))"));
696     ASSERT_TRUE(foundInAllGLSLCode("v36 = angle_frm(normalize(angle_frm(_uu1)))"));
697     ASSERT_TRUE(foundInAllGLSLCode(
698         "v37 = angle_frm(faceforward(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uu3)))"));
699     ASSERT_TRUE(foundInAllGLSLCode("v38 = angle_frm(reflect(angle_frm(_uu1), angle_frm(_uu2)))"));
700     ASSERT_TRUE(foundInAllGLSLCode(
701         "v39 = angle_frm(refract(angle_frm(_uu1), angle_frm(_uu2), angle_frm(_uuf)))"));
702 
703     ASSERT_TRUE(foundInAllGLSLCode("f1 = angle_frm(length(angle_frm(_uu1)))"));
704     ASSERT_TRUE(foundInAllGLSLCode("f2 = angle_frm(distance(angle_frm(_uu1), angle_frm(_uu2)))"));
705     ASSERT_TRUE(foundInAllGLSLCode("f3 = angle_frm(dot(angle_frm(_uu1), angle_frm(_uu2)))"));
706     ASSERT_TRUE(
707         foundInAllGLSLCode("vf31 = angle_frm(cross(angle_frm(_uuf31), angle_frm(_uuf32)))"));
708     ASSERT_TRUE(
709         foundInAllGLSLCode("m1 = angle_frm(matrixCompMult(angle_frm(_uum1), angle_frm(_uum2)))"));
710 
711     ASSERT_TRUE(foundInHLSLCodeRegex("v1(\\d)* = angle_frm\\(radians\\(angle_frm\\(_u1\\)\\)\\)"));
712     ASSERT_TRUE(foundInHLSLCodeRegex("v2(\\d)* = angle_frm\\(degrees\\(angle_frm\\(_u1\\)\\)\\)"));
713     ASSERT_TRUE(foundInHLSLCodeRegex("v3(\\d)* = angle_frm\\(sin\\(angle_frm\\(_u1\\)\\)\\)"));
714     ASSERT_TRUE(foundInHLSLCodeRegex("v4(\\d)* = angle_frm\\(cos\\(angle_frm\\(_u1\\)\\)\\)"));
715     ASSERT_TRUE(foundInHLSLCodeRegex("v5(\\d)* = angle_frm\\(tan\\(angle_frm\\(_u1\\)\\)\\)"));
716     ASSERT_TRUE(foundInHLSLCodeRegex("v6(\\d)* = angle_frm\\(asin\\(angle_frm\\(_u1\\)\\)\\)"));
717     ASSERT_TRUE(foundInHLSLCodeRegex("v7(\\d)* = angle_frm\\(acos\\(angle_frm\\(_u1\\)\\)\\)"));
718     ASSERT_TRUE(foundInHLSLCodeRegex("v8(\\d)* = angle_frm\\(atan\\(angle_frm\\(_u1\\)\\)\\)"));
719     ASSERT_TRUE(foundInHLSLCodeRegex(
720         "v9(\\d)* = angle_frm\\(atan_emu\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
721     ASSERT_TRUE(foundInHLSLCodeRegex(
722         "v10(\\d)* = angle_frm\\(pow\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
723     ASSERT_TRUE(foundInHLSLCodeRegex("v11(\\d)* = angle_frm\\(exp\\(angle_frm\\(_u1\\)\\)\\)"));
724     ASSERT_TRUE(foundInHLSLCodeRegex("v12(\\d)* = angle_frm\\(log\\(angle_frm\\(_u1\\)\\)\\)"));
725     ASSERT_TRUE(foundInHLSLCodeRegex("v13(\\d)* = angle_frm\\(exp2\\(angle_frm\\(_u1\\)\\)\\)"));
726     ASSERT_TRUE(foundInHLSLCodeRegex("v14(\\d)* = angle_frm\\(log2\\(angle_frm\\(_u1\\)\\)\\)"));
727     ASSERT_TRUE(foundInHLSLCodeRegex("v15(\\d)* = angle_frm\\(sqrt\\(angle_frm\\(_u1\\)\\)\\)"));
728     ASSERT_TRUE(foundInHLSLCodeRegex("v16(\\d)* = angle_frm\\(rsqrt\\(angle_frm\\(_u1\\)\\)\\)"));
729     ASSERT_TRUE(foundInHLSLCodeRegex("v17(\\d)* = angle_frm\\(abs\\(angle_frm\\(_u1\\)\\)\\)"));
730     ASSERT_TRUE(foundInHLSLCodeRegex("v18(\\d)* = angle_frm\\(sign\\(angle_frm\\(_u1\\)\\)\\)"));
731     ASSERT_TRUE(foundInHLSLCodeRegex("v19(\\d)* = angle_frm\\(floor\\(angle_frm\\(_u1\\)\\)\\)"));
732     ASSERT_TRUE(foundInHLSLCodeRegex("v20(\\d)* = angle_frm\\(ceil\\(angle_frm\\(_u1\\)\\)\\)"));
733     ASSERT_TRUE(foundInHLSLCodeRegex("v21(\\d)* = angle_frm\\(frac\\(angle_frm\\(_u1\\)\\)\\)"));
734     ASSERT_TRUE(foundInHLSLCodeRegex(
735         "v22(\\d)* = angle_frm\\(mod_emu\\(angle_frm\\(_u1\\), angle_frm\\(_uf\\)\\)\\)"));
736     ASSERT_TRUE(foundInHLSLCodeRegex(
737         "v23(\\d)* = angle_frm\\(mod_emu\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
738     ASSERT_TRUE(foundInHLSLCodeRegex(
739         "v24(\\d)* = angle_frm\\(min\\(angle_frm\\(_u1\\), angle_frm\\(_uf\\)\\)\\)"));
740     ASSERT_TRUE(foundInHLSLCodeRegex(
741         "v25(\\d)* = angle_frm\\(min\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
742     ASSERT_TRUE(foundInHLSLCodeRegex(
743         "v26(\\d)* = angle_frm\\(max\\(angle_frm\\(_u1\\), angle_frm\\(_uf\\)\\)\\)"));
744     ASSERT_TRUE(foundInHLSLCodeRegex(
745         "v27(\\d)* = angle_frm\\(max\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
746     ASSERT_TRUE(foundInHLSLCodeRegex(
747         "v28(\\d)* = angle_frm\\(clamp\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\), "
748         "angle_frm\\(_u3\\)\\)\\)"));
749     ASSERT_TRUE(foundInHLSLCodeRegex(
750         "v29(\\d)* = angle_frm\\(clamp\\(angle_frm\\(_u1\\), angle_frm\\(_uf\\), "
751         "angle_frm\\(_uf2\\)\\)\\)"));
752     ASSERT_TRUE(foundInHLSLCodeRegex(
753         "v30(\\d)* = angle_frm\\(lerp\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\), "
754         "angle_frm\\(_u3\\)\\)\\)"));
755     ASSERT_TRUE(foundInHLSLCodeRegex(
756         "v31(\\d)* = angle_frm\\(lerp\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\), "
757         "angle_frm\\(_uf\\)\\)\\)"));
758     ASSERT_TRUE(foundInHLSLCodeRegex(
759         "v32(\\d)* = angle_frm\\(step\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
760     ASSERT_TRUE(foundInHLSLCodeRegex(
761         "v33(\\d)* = angle_frm\\(step\\(angle_frm\\(_uf\\), angle_frm\\(_u1\\)\\)\\)"));
762     ASSERT_TRUE(
763         foundInHLSLCodeRegex("v34(\\d)* = angle_frm\\(smoothstep\\(angle_frm\\(_u1\\), "
764                              "angle_frm\\(_u2\\), angle_frm\\(_u3\\)\\)\\)"));
765     ASSERT_TRUE(
766         foundInHLSLCodeRegex("v35(\\d)* = angle_frm\\(smoothstep\\(angle_frm\\(_uf\\), "
767                              "angle_frm\\(_uf2\\), angle_frm\\(_u1\\)\\)\\)"));
768     ASSERT_TRUE(
769         foundInHLSLCodeRegex("v36(\\d)* = angle_frm\\(normalize\\(angle_frm\\(_u1\\)\\)\\)"));
770     ASSERT_TRUE(
771         foundInHLSLCodeRegex("v37(\\d)* = angle_frm\\(faceforward_emu\\(angle_frm\\(_u1\\), "
772                              "angle_frm\\(_u2\\), angle_frm\\(_u3\\)\\)\\)"));
773     ASSERT_TRUE(foundInHLSLCodeRegex(
774         "v38(\\d)* = angle_frm\\(reflect\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
775     ASSERT_TRUE(
776         foundInHLSLCodeRegex("v39(\\d)* = angle_frm\\(refract\\(angle_frm\\(_u1\\), "
777                              "angle_frm\\(_u2\\), angle_frm\\(_uf\\)\\)\\)"));
778 
779     ASSERT_TRUE(foundInHLSLCodeRegex("f1(\\d)* = angle_frm\\(length\\(angle_frm\\(_u1\\)\\)\\)"));
780     ASSERT_TRUE(foundInHLSLCodeRegex(
781         "f2(\\d)* = angle_frm\\(distance\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
782     ASSERT_TRUE(foundInHLSLCodeRegex(
783         "f3(\\d)* = angle_frm\\(dot\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)\\)"));
784     ASSERT_TRUE(foundInHLSLCodeRegex(
785         "vf31(\\d)* = angle_frm\\(cross\\(angle_frm\\(_uf31\\), angle_frm\\(_uf32\\)\\)\\)"));
786     ASSERT_TRUE(foundInHLSLCodeRegex(
787         "m1(\\d)* = angle_frm\\(\\(angle_frm\\(_um1\\) \\* angle_frm\\(_um2\\)\\)\\)"));
788 }
789 
TEST_F(DebugShaderPrecisionTest,BuiltInRelationalFunctionRounding)790 TEST_F(DebugShaderPrecisionTest, BuiltInRelationalFunctionRounding)
791 {
792     const std::string &shaderString =
793         "precision mediump float;\n"
794         "uniform vec4 u1;\n"
795         "uniform vec4 u2;\n"
796         "void main() {\n"
797         "   bvec4 bv1 = lessThan(u1, u2);\n"
798         "   bvec4 bv2 = lessThanEqual(u1, u2);\n"
799         "   bvec4 bv3 = greaterThan(u1, u2);\n"
800         "   bvec4 bv4 = greaterThanEqual(u1, u2);\n"
801         "   bvec4 bv5 = equal(u1, u2);\n"
802         "   bvec4 bv6 = notEqual(u1, u2);\n"
803         "   gl_FragColor = vec4(bv1) + vec4(bv2) + vec4(bv3) + vec4(bv4) + vec4(bv5) + vec4(bv6);\n"
804         "}\n";
805     compile(shaderString);
806     ASSERT_TRUE(foundInAllGLSLCode("bv1 = lessThan(angle_frm(_uu1), angle_frm(_uu2))"));
807     ASSERT_TRUE(foundInAllGLSLCode("bv2 = lessThanEqual(angle_frm(_uu1), angle_frm(_uu2))"));
808     ASSERT_TRUE(foundInAllGLSLCode("bv3 = greaterThan(angle_frm(_uu1), angle_frm(_uu2))"));
809     ASSERT_TRUE(foundInAllGLSLCode("bv4 = greaterThanEqual(angle_frm(_uu1), angle_frm(_uu2))"));
810     ASSERT_TRUE(foundInAllGLSLCode("bv5 = equal(angle_frm(_uu1), angle_frm(_uu2))"));
811     ASSERT_TRUE(foundInAllGLSLCode("bv6 = notEqual(angle_frm(_uu1), angle_frm(_uu2))"));
812 
813     ASSERT_TRUE(foundInHLSLCodeRegex("bv1(\\d)* = \\(angle_frm\\(_u1\\) < angle_frm\\(_u2\\)\\)"));
814     ASSERT_TRUE(foundInHLSLCodeRegex("bv2(\\d)* = \\(angle_frm\\(_u1\\) <= angle_frm\\(_u2\\)\\)"));
815     ASSERT_TRUE(foundInHLSLCodeRegex("bv3(\\d)* = \\(angle_frm\\(_u1\\) > angle_frm\\(_u2\\)\\)"));
816     ASSERT_TRUE(foundInHLSLCodeRegex("bv4(\\d)* = \\(angle_frm\\(_u1\\) >= angle_frm\\(_u2\\)\\)"));
817     ASSERT_TRUE(foundInHLSLCodeRegex("bv5(\\d)* = \\(angle_frm\\(_u1\\) == angle_frm\\(_u2\\)\\)"));
818     ASSERT_TRUE(foundInHLSLCodeRegex("bv6(\\d)* = \\(angle_frm\\(_u1\\) != angle_frm\\(_u2\\)\\)"));
819 }
820 
TEST_F(DebugShaderPrecisionTest,ConstructorRounding)821 TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
822 {
823     const std::string &shaderString =
824         "precision mediump float;\n"
825         "precision mediump int;\n"
826         "uniform float u1;\n"
827         "uniform float u2;\n"
828         "uniform lowp float u3;\n"
829         "uniform float u4;\n"
830         "uniform ivec4 uiv;\n"
831         "void main() {\n"
832         "   vec4 v1 = vec4(u1, u2, u3, u4);\n"
833         "   vec4 v2 = vec4(uiv);\n"
834         "   gl_FragColor = v1 + v2;\n"
835         "}\n";
836     compile(shaderString);
837     ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(vec4(_uu1, _uu2, angle_frl(_uu3), _uu4))"));
838     ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(vec4(_uuiv))"));
839 
840     ASSERT_TRUE(foundInHLSLCodeRegex(
841         "v1(\\d)* = angle_frm\\(vec4_ctor\\(_u1, _u2, angle_frl\\(_u3\\), _u4\\)\\)"));
842     ASSERT_TRUE(foundInHLSLCodeRegex("v2(\\d)* = angle_frm\\(vec4_ctor\\(_uiv\\)\\)"));
843 }
844 
TEST_F(DebugShaderPrecisionTest,StructConstructorNoRounding)845 TEST_F(DebugShaderPrecisionTest, StructConstructorNoRounding)
846 {
847     const std::string &shaderString =
848         "precision mediump float;\n"
849         "struct S { mediump vec4 a; };\n"
850         "uniform vec4 u;\n"
851         "void main() {\n"
852         "   S s = S(u);\n"
853         "   gl_FragColor = s.a;\n"
854         "}\n";
855     compile(shaderString);
856     ASSERT_TRUE(foundInAllGLSLCode("s = _uS(angle_frm(_uu))"));
857     ASSERT_TRUE(foundInHLSLCodeRegex("s(\\d)* = _S_ctor\\(angle_frm\\(_u\\)\\)"));
858     ASSERT_TRUE(notFoundInCode("angle_frm(_uS"));  // GLSL
859     ASSERT_TRUE(notFoundInCode("angle_frm(_S"));   // HLSL
860 }
861 
TEST_F(DebugShaderPrecisionTest,SwizzleRounding)862 TEST_F(DebugShaderPrecisionTest, SwizzleRounding)
863 {
864     const std::string &shaderString =
865         "precision mediump float;\n"
866         "uniform vec4 u;\n"
867         "void main() {\n"
868         "   vec4 v = u.xyxy;"
869         "   gl_FragColor = v;\n"
870         "}\n";
871     compile(shaderString);
872     ASSERT_TRUE(foundInAllGLSLCode("v = angle_frm(_uu).xyxy"));
873     ASSERT_TRUE(foundInHLSLCodeRegex("v(\\d)* = angle_frm\\(_u\\)\\.xyxy"));
874 }
875 
TEST_F(DebugShaderPrecisionTest,BuiltInTexFunctionRounding)876 TEST_F(DebugShaderPrecisionTest, BuiltInTexFunctionRounding)
877 {
878     const std::string &shaderString =
879         "precision mediump float;\n"
880         "precision lowp sampler2D;\n"
881         "uniform vec2 u;\n"
882         "uniform sampler2D s;\n"
883         "void main() {\n"
884         "   lowp vec4 v = texture2D(s, u);\n"
885         "   gl_FragColor = v;\n"
886         "}\n";
887     compile(shaderString);
888     ASSERT_TRUE(foundInAllGLSLCode("v = angle_frl(texture2D(_us, angle_frm(_uu)))"));
889     ASSERT_TRUE(
890         foundInHLSLCodeRegex("v(\\d)* = angle_frl\\(gl_texture2D\\(_s, angle_frm\\(_u\\)\\)\\)"));
891 }
892 
TEST_F(DebugShaderPrecisionTest,FunctionCallParameterQualifiersFromDefinition)893 TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromDefinition)
894 {
895     const std::string &shaderString =
896         "precision mediump float;\n"
897         "uniform vec4 u1;\n"
898         "uniform vec4 u2;\n"
899         "uniform vec4 u3;\n"
900         "uniform vec4 u4;\n"
901         "uniform vec4 u5;\n"
902         "vec4 add(in vec4 x, in vec4 y) {\n"
903         "   return x + y;\n"
904         "}\n"
905         "void compound_add(inout vec4 x, in vec4 y) {\n"
906         "   x = x + y;\n"
907         "}\n"
908         "void add_to_last(in vec4 x, in vec4 y, out vec4 z) {\n"
909         "   z = x + y;\n"
910         "}\n"
911         "void main() {\n"
912         "   vec4 v = add(u1, u2);\n"
913         "   compound_add(v, u3);\n"
914         "   vec4 v2;\n"
915         "   add_to_last(u4, u5, v2);\n"
916         "   gl_FragColor = v + v2;\n"
917         "}\n";
918     compile(shaderString);
919     // Note that this is not optimal code, there are redundant frm calls.
920     // However, getting the implementation working when other operations
921     // are nested within function calls would be tricky if to get right
922     // otherwise.
923     // Test in parameters
924     ASSERT_TRUE(foundInAllGLSLCode("v = _uadd(angle_frm(_uu1), angle_frm(_uu2))"));
925     ASSERT_TRUE(foundInHLSLCodeRegex(
926         "v(\\d)* = f_add_float4_float4\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)"));
927     // Test inout parameter
928     ASSERT_TRUE(foundInAllGLSLCode("_ucompound_add(_uv, angle_frm(_uu3))"));
929     ASSERT_TRUE(
930         foundInHLSLCodeRegex("compound_add_float4_float4\\(_v(\\d)*, angle_frm\\(_u3\\)\\)"));
931     // Test out parameter
932     ASSERT_TRUE(foundInAllGLSLCode("_uadd_to_last(angle_frm(_uu4), angle_frm(_uu5), _uv2)"));
933     ASSERT_TRUE(foundInHLSLCodeRegex(
934         "add_to_last_float4_float4_float4\\(angle_frm\\(_u4\\), angle_frm\\(_u5\\), _v2(\\d)*\\)"));
935 }
936 
TEST_F(DebugShaderPrecisionTest,FunctionCallParameterQualifiersFromPrototype)937 TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromPrototype)
938 {
939     const std::string &shaderString =
940         "precision mediump float;\n"
941         "uniform vec4 u1;\n"
942         "uniform vec4 u2;\n"
943         "uniform vec4 u3;\n"
944         "uniform vec4 u4;\n"
945         "uniform vec4 u5;\n"
946         "vec4 add(in vec4 x, in vec4 y);\n"
947         "void compound_add(inout vec4 x, in vec4 y);\n"
948         "void add_to_last(in vec4 x, in vec4 y, out vec4 z);\n"
949         "void main() {\n"
950         "   vec4 v = add(u1, u2);\n"
951         "   compound_add(v, u3);\n"
952         "   vec4 v2;\n"
953         "   add_to_last(u4, u5, v2);\n"
954         "   gl_FragColor = v + v2;\n"
955         "}\n"
956         "vec4 add(in vec4 x, in vec4 y) {\n"
957         "   return x + y;\n"
958         "}\n"
959         "void compound_add(inout vec4 x, in vec4 y) {\n"
960         "   x = x + y;\n"
961         "}\n"
962         "void add_to_last(in vec4 x, in vec4 y, out vec4 z) {\n"
963         "   z = x + y;\n"
964         "}\n";
965     compile(shaderString);
966     // Test in parameters
967     ASSERT_TRUE(foundInAllGLSLCode("v = _uadd(angle_frm(_uu1), angle_frm(_uu2))"));
968     ASSERT_TRUE(foundInHLSLCodeRegex(
969         "v(\\d)* = f_add_float4_float4\\(angle_frm\\(_u1\\), angle_frm\\(_u2\\)\\)"));
970     // Test inout parameter
971     ASSERT_TRUE(foundInAllGLSLCode("_ucompound_add(_uv, angle_frm(_uu3))"));
972     ASSERT_TRUE(
973         foundInHLSLCodeRegex("compound_add_float4_float4\\(_v(\\d)*, angle_frm\\(_u3\\)\\)"));
974     // Test out parameter
975     ASSERT_TRUE(foundInAllGLSLCode("add_to_last(angle_frm(_uu4), angle_frm(_uu5), _uv2)"));
976     ASSERT_TRUE(foundInHLSLCodeRegex(
977         "add_to_last_float4_float4_float4\\(angle_frm\\(_u4\\), angle_frm\\(_u5\\), _v2(\\d)*\\)"));
978 }
979 
TEST_F(DebugShaderPrecisionTest,NestedFunctionCalls)980 TEST_F(DebugShaderPrecisionTest, NestedFunctionCalls)
981 {
982     const std::string &shaderString =
983         "precision mediump float;\n"
984         "uniform vec4 u1;\n"
985         "uniform vec4 u2;\n"
986         "uniform vec4 u3;\n"
987         "vec4 add(in vec4 x, in vec4 y) {\n"
988         "   return x + y;\n"
989         "}\n"
990         "vec4 compound_add(inout vec4 x, in vec4 y) {\n"
991         "   x = x + y;\n"
992         "   return x;\n"
993         "}\n"
994         "void main() {\n"
995         "   vec4 v = u1;\n"
996         "   vec4 v2 = add(compound_add(v, u2), fract(u3));\n"
997         "   gl_FragColor = v + v2;\n"
998         "}\n";
999     compile(shaderString);
1000     // Test nested calls
1001     ASSERT_TRUE(foundInAllGLSLCode(
1002         "v2 = _uadd(_ucompound_add(_uv, angle_frm(_uu2)), angle_frm(fract(angle_frm(_uu3))))"));
1003     ASSERT_TRUE(foundInHLSLCodeRegex(
1004         "v2(\\d)* = f_add_float4_float4\\(f_compound_add_float4_float4\\(_v(\\d)*, "
1005         "angle_frm\\(_u2\\)\\), "
1006         "angle_frm\\(frac\\(angle_frm\\(_u3\\)\\)\\)\\)"));
1007 }
1008 
1009 // Test that code inside an index of a function out parameter gets processed.
TEST_F(DebugShaderPrecisionTest,OpInIndexOfFunctionOutParameter)1010 TEST_F(DebugShaderPrecisionTest, OpInIndexOfFunctionOutParameter)
1011 {
1012     const std::string &shaderString =
1013         "precision mediump float;\n"
1014         "void foo(out vec4 f) { f.x = 0.0; }\n"
1015         "uniform float u2;\n"
1016         "void main() {\n"
1017         "   vec4 v[2];\n"
1018         "   foo(v[int(exp2(u2))]);\n"
1019         "   gl_FragColor = v[0];\n"
1020         "}\n";
1021     compile(shaderString);
1022     ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(_uu2)))"));
1023     ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
1024 }
1025 
1026 // Test that code inside an index of an l-value gets processed.
TEST_F(DebugShaderPrecisionTest,OpInIndexOfLValue)1027 TEST_F(DebugShaderPrecisionTest, OpInIndexOfLValue)
1028 {
1029     const std::string &shaderString =
1030         "precision mediump float;\n"
1031         "uniform vec4 u1;\n"
1032         "uniform float u2;\n"
1033         "void main() {\n"
1034         "   vec4 v[2];\n"
1035         "   v[int(exp2(u2))] = u1;\n"
1036         "   gl_FragColor = v[0];\n"
1037         "}\n";
1038     compile(shaderString);
1039     ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(_uu2)))"));
1040     ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
1041 }
1042 
1043 // Test that the out parameter of modf doesn't get rounded
TEST_F(DebugShaderPrecisionTest,ModfOutParameter)1044 TEST_F(DebugShaderPrecisionTest, ModfOutParameter)
1045 {
1046     const std::string &shaderString =
1047         "#version 300 es\n"
1048         "precision mediump float;\n"
1049         "uniform float u;\n"
1050         "out vec4 my_FragColor;\n"
1051         "void main() {\n"
1052         "   float o;\n"
1053         "   float f = modf(u, o);\n"
1054         "   my_FragColor = vec4(f, o, 0, 1);\n"
1055         "}\n";
1056     compile(shaderString);
1057     ASSERT_TRUE(foundInAllGLSLCode("modf(angle_frm(_uu), _uo)"));
1058     ASSERT_TRUE(foundInHLSLCodeRegex(R"(modf\(angle_frm\(_u\), _o(\d)*)"));
1059 }
1060 
1061 #if defined(ANGLE_ENABLE_HLSL)
1062 // Tests precision emulation with HLSL 3.0 output -- should error gracefully.
TEST(DebugShaderPrecisionNegativeTest,HLSL3Unsupported)1063 TEST(DebugShaderPrecisionNegativeTest, HLSL3Unsupported)
1064 {
1065     const std::string &shaderString =
1066         "precision mediump float;\n"
1067         "uniform float u;\n"
1068         "void main() {\n"
1069         "   gl_FragColor = vec4(u);\n"
1070         "}\n";
1071     std::string infoLog;
1072     std::string translatedCode;
1073     ShBuiltInResources resources;
1074     sh::InitBuiltInResources(&resources);
1075     resources.WEBGL_debug_shader_precision = 1;
1076     ASSERT_FALSE(compileTestShader(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, SH_HLSL_3_0_OUTPUT,
1077                                    shaderString, &resources, 0, &translatedCode, &infoLog));
1078 }
1079 #endif  // defined(ANGLE_ENABLE_HLSL)
1080 
1081 // Test that compound assignment inside an expression compiles correctly. This is a test for a bug
1082 // where incorrect type information on the compound assignment call node caused an assert to trigger
1083 // in the debug build.
TEST_F(DebugShaderPrecisionTest,CompoundAssignmentInsideExpression)1084 TEST_F(DebugShaderPrecisionTest, CompoundAssignmentInsideExpression)
1085 {
1086     const std::string &shaderString =
1087         "#version 300 es\n"
1088         "precision mediump float;\n"
1089         "out vec4 my_FragColor;\n"
1090         "void main() {\n"
1091         "   float f = 0.0;\n"
1092         "   my_FragColor = vec4(abs(f += 1.0), 0, 0, 1);\n"
1093         "}\n";
1094     compile(shaderString);
1095     ASSERT_TRUE(foundInAllGLSLCode("abs(angle_compound_add_frm(_uf, 1.0))"));
1096 }
1097 
1098 // Test that having rounded values inside the right hand side of logical or doesn't trigger asserts
1099 // in HLSL output.
TEST_F(DebugShaderPrecisionTest,RoundedValueOnRightSideOfLogicalOr)1100 TEST_F(DebugShaderPrecisionTest, RoundedValueOnRightSideOfLogicalOr)
1101 {
1102     const std::string &shaderString =
1103         "#version 300 es\n"
1104         "precision mediump float;\n"
1105         "out vec4 my_FragColor;\n"
1106         "uniform float u1, u2;\n"
1107         "void main() {\n"
1108         "   my_FragColor = vec4(u1 == 0.0 || u2 == 0.0);\n"
1109         "}\n";
1110     compile(shaderString);
1111     ASSERT_TRUE(foundInHLSLCode("angle_frm(_u2) == 0.0"));
1112 }
1113