• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 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 // HLSLOutput_test.cpp:
7 //   Tests for HLSL output.
8 //
9 
10 #include <regex>
11 #include "GLSLANG/ShaderLang.h"
12 #include "angle_gl.h"
13 #include "gtest/gtest.h"
14 #include "tests/test_utils/compiler_test.h"
15 
16 using namespace sh;
17 
18 class HLSLOutputTest : public MatchOutputCodeTest
19 {
20   public:
HLSLOutputTest()21     HLSLOutputTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_HLSL_4_1_OUTPUT) {}
22 };
23 
24 class HLSL30VertexOutputTest : public MatchOutputCodeTest
25 {
26   public:
HLSL30VertexOutputTest()27     HLSL30VertexOutputTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, 0, SH_HLSL_3_0_OUTPUT) {}
28 };
29 
30 // Test that having dynamic indexing of a vector inside the right hand side of logical or doesn't
31 // trigger asserts in HLSL output.
TEST_F(HLSLOutputTest,DynamicIndexingOfVectorOnRightSideOfLogicalOr)32 TEST_F(HLSLOutputTest, DynamicIndexingOfVectorOnRightSideOfLogicalOr)
33 {
34     const std::string &shaderString =
35         "#version 300 es\n"
36         "precision highp float;\n"
37         "out vec4 my_FragColor;\n"
38         "uniform int u1;\n"
39         "void main() {\n"
40         "   bvec4 v = bvec4(true, true, true, false);\n"
41         "   my_FragColor = vec4(v[u1 + 1] || v[u1]);\n"
42         "}\n";
43     compile(shaderString);
44 }
45 
46 // Test that rewriting else blocks in a function that returns a struct doesn't use the struct name
47 // without a prefix.
TEST_F(HLSL30VertexOutputTest,RewriteElseBlockReturningStruct)48 TEST_F(HLSL30VertexOutputTest, RewriteElseBlockReturningStruct)
49 {
50     const std::string &shaderString =
51         "struct foo\n"
52         "{\n"
53         "    float member;\n"
54         "};\n"
55         "uniform bool b;\n"
56         "foo getFoo()\n"
57         "{\n"
58         "    if (b)\n"
59         "    {\n"
60         "        return foo(0.0);\n"
61         "    }\n"
62         "    else\n"
63         "    {\n"
64         "        return foo(1.0);\n"
65         "    }\n"
66         "}\n"
67         "void main()\n"
68         "{\n"
69         "   gl_Position = vec4(getFoo().member);\n"
70         "}\n";
71     compile(shaderString);
72     EXPECT_TRUE(foundInCode("_foo"));
73     EXPECT_FALSE(foundInCode("(foo)"));
74     EXPECT_FALSE(foundInCode(" foo"));
75 }
76 
77 // Test that having an array constructor as a statement doesn't trigger an assert in HLSL output.
78 // This test has a constant array constructor statement.
TEST_F(HLSLOutputTest,ConstArrayConstructorStatement)79 TEST_F(HLSLOutputTest, ConstArrayConstructorStatement)
80 {
81     const std::string &shaderString =
82         R"(#version 300 es
83         void main()
84         {
85             int[1](0);
86         })";
87     compile(shaderString);
88 }
89 
90 // Test that having an array constructor as a statement doesn't trigger an assert in HLSL output.
TEST_F(HLSLOutputTest,ArrayConstructorStatement)91 TEST_F(HLSLOutputTest, ArrayConstructorStatement)
92 {
93     const std::string &shaderString =
94         R"(#version 300 es
95         precision mediump float;
96         out vec4 outColor;
97         void main()
98         {
99             outColor = vec4(0.0, 0.0, 0.0, 1.0);
100             float[1](outColor[1]++);
101         })";
102     compile(shaderString);
103 }
104 
105 // Test an array of arrays constructor as a statement.
TEST_F(HLSLOutputTest,ArrayOfArraysStatement)106 TEST_F(HLSLOutputTest, ArrayOfArraysStatement)
107 {
108     const std::string &shaderString =
109         R"(#version 310 es
110         precision mediump float;
111         out vec4 outColor;
112         void main()
113         {
114             outColor = vec4(0.0, 0.0, 0.0, 1.0);
115             float[2][2](float[2](outColor[1]++, 0.0), float[2](1.0, 2.0));
116         })";
117     compile(shaderString);
118 }
119 
120 // Test dynamic indexing of a vector. This makes sure that helper functions added for dynamic
121 // indexing have correct data that subsequent traversal steps rely on.
TEST_F(HLSLOutputTest,VectorDynamicIndexing)122 TEST_F(HLSLOutputTest, VectorDynamicIndexing)
123 {
124     const std::string &shaderString =
125         R"(#version 300 es
126         precision mediump float;
127         out vec4 outColor;
128         uniform int i;
129         void main()
130         {
131             vec4 foo = vec4(0.0, 0.0, 0.0, 1.0);
132             foo[i] = foo[i + 1];
133             outColor = foo;
134         })";
135     compile(shaderString);
136 }
137 
138 // Test returning an array from a user-defined function. This makes sure that function symbols are
139 // changed consistently when the user-defined function is changed to have an array out parameter.
TEST_F(HLSLOutputTest,ArrayReturnValue)140 TEST_F(HLSLOutputTest, ArrayReturnValue)
141 {
142     const std::string &shaderString =
143         R"(#version 300 es
144         precision mediump float;
145         uniform float u;
146         out vec4 outColor;
147 
148         float[2] getArray(float f)
149         {
150             return float[2](f, f + 1.0);
151         }
152 
153         void main()
154         {
155             float[2] arr = getArray(u);
156             outColor = vec4(arr[0], arr[1], 0.0, 1.0);
157         })";
158     compile(shaderString);
159 }
160 
161 // Test that writing parameters without a name doesn't assert.
TEST_F(HLSLOutputTest,ParameterWithNoName)162 TEST_F(HLSLOutputTest, ParameterWithNoName)
163 {
164     const std::string &shaderString =
165         R"(precision mediump float;
166 
167         uniform vec4 v;
168 
169         vec4 s(vec4)
170         {
171             return v;
172         }
173         void main()
174         {
175             gl_FragColor = s(v);
176         })";
177     compile(shaderString);
178 }
179 
180 // Test that array dimensions are written out correctly.
TEST_F(HLSLOutputTest,Array)181 TEST_F(HLSLOutputTest, Array)
182 {
183     const std::string &shaderString =
184         R"(#version 300 es
185         precision mediump float;
186 
187         uniform float uf;
188 
189         out vec4 my_FragColor;
190 
191         void main()
192         {
193             my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
194             float arr[2];
195             for (int i = 0; i < 2; ++i) {
196                 arr[i] = uf * 2.0;
197                 my_FragColor.x += arr[i];
198             }
199         })";
200     compile(shaderString);
201     EXPECT_TRUE(foundInCodeRegex(std::regex("_arr(\\d)*\\[2\\]")));
202 }
203 
204 // Test that initializing array with previously declared array will not be overwritten
TEST_F(HLSLOutputTest,SameNameArray)205 TEST_F(HLSLOutputTest, SameNameArray)
206 {
207     const std::string &shaderString =
208         R"(#version 300 es
209         precision highp float;
210         out vec4 my_FragColor;
211 
212         void main()
213         {
214           float arr[2] = float[2](1.0, 1.0);
215           {
216             float arr[2] = arr;
217             my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
218           }
219         })";
220     compile(shaderString);
221     // There should be two different arr defined, e.g. _arr1000 and _arr1001
222     // Use Workaround for now.
223     // Once the build team fixes libc++ we could use the following one line solution instead.
224     // EXPECT_TRUE(foundInCodeRegex(std::regex("_arr(\\d*)\\[2\\](.|\\r|\\n)*_arr(?!\\1)\\d*\\[2\\]")));
225     std::smatch m;
226     EXPECT_TRUE(foundInCodeRegex(std::regex("_arr(\\d)*\\[2\\]"), &m));
227     EXPECT_TRUE(m.size() == 2);
228     EXPECT_TRUE(m[0].str() != m[1].str());
229 }
230 
231 // Test that passing a non-struct member of a std140 structure to a function won't trigger the
232 // struct mapping.
TEST_F(HLSLOutputTest,NonStructMemberAsFunctionArgument)233 TEST_F(HLSLOutputTest, NonStructMemberAsFunctionArgument)
234 {
235     constexpr char shaderString[] = R"(#version 300 es
236 precision highp float;
237 out vec4 my_FragColor;
238 
239 struct InstancingData
240 {
241     vec4 data;
242 };
243 
244 layout(std140) uniform InstanceBlock
245 {
246     InstancingData instances[8];
247 };
248 
249 void main()
250 {
251     int index = int(gl_FragCoord.x);
252     float result = dot(instances[index].data, vec4(1.0, 1.0, 1.0, 1.0));
253     my_FragColor = vec4(result, 0.0, 0.0, 1.0);
254 })";
255 
256     compile(shaderString);
257     EXPECT_FALSE(foundInCode("map_instances"));
258 }
259