xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/RecordConstantPrecision_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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 // RecordConstantPrecision_test.cpp:
7 //   Test for recording constant variable precision when it affects consuming expression.
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 RecordConstantPrecisionTest : public MatchOutputCodeTest
18 {
19   public:
RecordConstantPrecisionTest()20     RecordConstantPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT) {}
21 };
22 
23 // The constant's precision must be specified if its precision is higher than the other operands,
24 // since it increases the precision of the consuming expression.
TEST_F(RecordConstantPrecisionTest,HigherPrecisionConstantAsParameter)25 TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter)
26 {
27     const std::string &shaderString = R"(
28 uniform mediump float u;
29 void main()
30 {
31     const highp float a = 4096.5;
32     mediump float b = fract(a + u);
33     gl_FragColor = vec4(b);
34 })";
35     compile(shaderString);
36     ASSERT_TRUE(foundInCode("const highp float s"));
37     ASSERT_FALSE(foundInCode("fract(4096.5"));
38     ASSERT_FALSE(foundInCode("fract((4096.5"));
39 }
40 
41 // The constant's precision does not need to be specified if its precision is equal to the other
42 // operands, as it does not increase the precision of the consuming expression.  For simplicity
43 // however, the constant's precision is specified anyway.
TEST_F(RecordConstantPrecisionTest,EqualPrecisionConstantAsParameter)44 TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter)
45 {
46     const std::string &shaderString = R"(
47 uniform mediump float u;
48 void main()
49 {
50     const mediump float a = 4096.5;
51     mediump float b = fract(a + u);
52     gl_FragColor = vec4(b);
53 })";
54     compile(shaderString);
55     ASSERT_TRUE(foundInCode("const mediump float s"));
56     ASSERT_FALSE(foundInCode("fract((4096.5"));
57 }
58 
59 // The constant's precision must be specified if its precision is higher than the other operands,
60 // since it increases the precision of the consuming expression.  This applies also when the
61 // constant is part of a constant expression that can be folded.
TEST_F(RecordConstantPrecisionTest,FoldedBinaryConstantPrecisionIsHigher)62 TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher)
63 {
64     const std::string &shaderString = R"(
65 uniform mediump float u;
66 void main()
67 {
68     const highp float a = 4095.5;
69     mediump float b = fract((a + 1.0) + u);
70     gl_FragColor = vec4(b);
71 })";
72     compile(shaderString);
73     ASSERT_TRUE(foundInCode("const highp float s"));
74     ASSERT_FALSE(foundInCode("fract(4096.5"));
75     ASSERT_FALSE(foundInCode("fract((4096.5"));
76 }
77 
78 // The constant's precision must be specified if its precision is higher than the other operands,
79 // since it increases the precision of the consuming expression.  This applies also when the
80 // constant is part of a constant expression that can be folded.
TEST_F(RecordConstantPrecisionTest,FoldedUnaryConstantPrecisionIsHigher)81 TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher)
82 {
83     const std::string &shaderString = R"(
84 uniform mediump float u;
85 void main()
86 {
87     const highp float a = 0.5;
88     mediump float b = sin(fract(a) + u);
89     gl_FragColor = vec4(b);
90 })";
91     compile(shaderString);
92     ASSERT_TRUE(foundInCode("const highp float s"));
93     ASSERT_FALSE(foundInCode("sin(0.5"));
94     ASSERT_FALSE(foundInCode("sin((0.5"));
95 }
96 
97 // The constant's precision must be specified if its precision is higher than the other operands,
98 // since it increases the precision of the consuming expression.  This applies also when the
99 // constant is part of a constructor expression.  Note that lowp constants never need their
100 // precision specified.
TEST_F(RecordConstantPrecisionTest,HigherPrecisionConstantInConstructor)101 TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInConstructor)
102 {
103     const std::string &shaderString = R"(
104 uniform mediump float u;
105 void main()
106 {
107     const highp float a = 4096.5;
108     const lowp float b = 1.0;
109     lowp vec4 result = vec4(b, a, b, u);
110     gl_FragColor = result;
111 })";
112     compile(shaderString);
113     ASSERT_TRUE(foundInCode("const highp float s"));
114     ASSERT_FALSE(foundInCode("const lowp float s"));
115     ASSERT_TRUE(foundInCode("vec4(1.0, s"));
116 }
117 
118 // The constant's precision does not need to be specified if its used to initialize a variable.
TEST_F(RecordConstantPrecisionTest,HigherPrecisionConstantInAssignment)119 TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInAssignment)
120 {
121     const std::string &shaderString = R"(
122 uniform mediump float u;
123 void main()
124 {
125     const highp float a = 4096.5;
126     mediump float b = a;
127     mediump float c;
128     c = a;
129     gl_FragColor = vec4(b, b, c, c);
130 })";
131     compile(shaderString);
132     ASSERT_FALSE(foundInCode("const highp float s"));
133     ASSERT_TRUE(foundInCode("b = 4096.5"));
134     ASSERT_TRUE(foundInCode("c = 4096.5"));
135 }
136 
137 // The constant's precision does not need to be specified if its used as an index.
TEST_F(RecordConstantPrecisionTest,HigherPrecisionConstantInIndex)138 TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInIndex)
139 {
140     const std::string &shaderString = R"(
141 uniform mediump float u;
142 void main()
143 {
144     const highp int a = 330;
145     mediump float b[340];
146     gl_FragColor = vec4(b[a]);
147 })";
148     compile(shaderString);
149     ASSERT_FALSE(foundInCode("const highp int s"));
150     ASSERT_TRUE(foundInCode("b[330]"));
151 }
152