xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/SeparateDeclarations_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 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 // SeparateDeclarations.cpp:
7 //   Tests that compound declarations are rewritten to type declarations and variable declarations.
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 namespace
18 {
19 
20 class SeparateDeclarations : public MatchOutputCodeTest
21 {
22   public:
SeparateDeclarations()23     SeparateDeclarations() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT)
24     {
25         ShCompileOptions defaultCompileOptions = {};
26         defaultCompileOptions.validateAST      = true;
27         setDefaultCompileOptions(defaultCompileOptions);
28     }
29 };
30 
31 class SeparateCompoundStructDeclarations : public MatchOutputCodeTest
32 {
33   public:
SeparateCompoundStructDeclarations()34     SeparateCompoundStructDeclarations() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT)
35     {
36         ShCompileOptions defaultCompileOptions                   = {};
37         defaultCompileOptions.validateAST                        = true;
38         defaultCompileOptions.separateCompoundStructDeclarations = true;
39         setDefaultCompileOptions(defaultCompileOptions);
40     }
41 };
42 
43 class SeparateStructFunctionDeclarations : public MatchOutputCodeTest
44 {
45   public:
SeparateStructFunctionDeclarations()46     SeparateStructFunctionDeclarations() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT)
47     {
48         ShCompileOptions defaultCompileOptions = {};
49         defaultCompileOptions.validateAST      = true;
50         setDefaultCompileOptions(defaultCompileOptions);
51     }
52 };
53 
TEST_F(SeparateDeclarations,Arrays)54 TEST_F(SeparateDeclarations, Arrays)
55 {
56     const char kShader[]   = R"(#version 300 es
57 precision highp float;
58 int a[1] = int[1](1), b[1] = int[1](2);
59 out vec4 o;
60 void main() {
61     if (a[0] == b[0])
62         o = vec4(1);
63 })";
64     const char kExpected[] = R"(#version 300 es
65 const mediump int sbbd = 1;
66 mediump int _ua[1] = int[1](sbbd);
67 const mediump int sbbe = 2;
68 mediump int _ub[1] = int[1](sbbe);
69 out highp vec4 _uo;
70 void main(){
71   if ((_ua[0] == _ub[0]))
72   {
73     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
74   }
75 }
76 )";
77     compile(kShader);
78     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
79 }
80 
TEST_F(SeparateDeclarations,StructNoChange)81 TEST_F(SeparateDeclarations, StructNoChange)
82 {
83     const char kShader[]   = R"(#version 300 es
84 precision highp float;
85 struct S { vec3 d; } a;
86 out vec4 o;
87 void main() {
88     if (a.d == vec3(2))
89         o = vec4(1);
90 })";
91     const char kExpected[] = R"(#version 300 es
92 struct _uS {
93   highp vec3 _ud;
94 } _ua;
95 out highp vec4 _uo;
96 void main(){
97   if ((_ua._ud == vec3(2.0, 2.0, 2.0)))
98   {
99     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
100   }
101 }
102 )";
103     compile(kShader);
104     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
105 }
106 
TEST_F(SeparateDeclarations,Structs)107 TEST_F(SeparateDeclarations, Structs)
108 {
109     const char kShader[]   = R"(#version 300 es
110 precision highp float;
111 struct S { vec3 d; } a, b;
112 out vec4 o;
113 void main() {
114     if (a.d == b.d)
115         o = vec4(1);
116 })";
117     const char kExpected[] = R"(#version 300 es
118 struct _uS {
119   highp vec3 _ud;
120 } _ua;
121 _uS _ub;
122 out highp vec4 _uo;
123 void main(){
124   if ((_ua._ud == _ub._ud))
125   {
126     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
127   }
128 }
129 )";
130     compile(kShader);
131     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
132 }
133 
TEST_F(SeparateDeclarations,AnonymousStructNoChange)134 TEST_F(SeparateDeclarations, AnonymousStructNoChange)
135 {
136     const char kShader[]   = R"(#version 300 es
137 precision highp float;
138 struct { vec3 d; } a;
139 out vec4 o;
140 void main() {
141     if (any(lessThan(a.d, vec3(2))))
142         o = vec4(1);
143 })";
144     const char kExpected[] = R"(#version 300 es
145 struct {
146   highp vec3 _ud;
147 } _ua;
148 out highp vec4 _uo;
149 void main(){
150   if (any(lessThan(_ua._ud, vec3(2.0, 2.0, 2.0))))
151   {
152     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
153   }
154 }
155 )";
156     compile(kShader);
157     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
158 }
159 
TEST_F(SeparateDeclarations,AnonymousStructs)160 TEST_F(SeparateDeclarations, AnonymousStructs)
161 {
162     const char kShader[]   = R"(#version 300 es
163 precision highp float;
164 struct { vec3 d; } a, b;
165 out vec4 o;
166 void main() {
167     if (any(lessThan(a.d, b.d)))
168         o = vec4(1);
169 })";
170     const char kExpected[] = R"(#version 300 es
171 struct sbbe {
172   highp vec3 _ud;
173 } _ua;
174 sbbe _ub;
175 out highp vec4 _uo;
176 void main(){
177   if (any(lessThan(_ua._ud, _ub._ud)))
178   {
179     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
180   }
181 }
182 )";
183     compile(kShader);
184     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
185 }
186 
TEST_F(SeparateCompoundStructDeclarations,AnonymousStruct)187 TEST_F(SeparateCompoundStructDeclarations, AnonymousStruct)
188 {
189     const char kShader[]   = R"(#version 300 es
190 precision highp float;
191 struct { vec3 d; } a;
192 out vec4 o;
193 void main() {
194     if (any(lessThan(a.d, vec3(2))))
195         o = vec4(1);
196 })";
197     const char kExpected[] = R"(#version 300 es
198 struct sbbd {
199   highp vec3 _ud;
200 };
201 sbbd _ua;
202 out highp vec4 _uo;
203 void main(){
204   if (any(lessThan(_ua._ud, vec3(2.0, 2.0, 2.0))))
205   {
206     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
207   }
208 }
209 )";
210     compile(kShader);
211     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
212 }
213 
TEST_F(SeparateCompoundStructDeclarations,AnonymousStructs)214 TEST_F(SeparateCompoundStructDeclarations, AnonymousStructs)
215 {
216     const char kShader[]   = R"(#version 300 es
217 precision highp float;
218 struct { vec3 d; } a, b;
219 out vec4 o;
220 void main() {
221     if (any(lessThan(a.d, b.d)))
222         o = vec4(1);
223 })";
224     const char kExpected[] = R"(#version 300 es
225 struct sbbe {
226   highp vec3 _ud;
227 };
228 sbbe _ua;
229 sbbe _ub;
230 out highp vec4 _uo;
231 void main(){
232   if (any(lessThan(_ua._ud, _ub._ud)))
233   {
234     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
235   }
236 }
237 )";
238     compile(kShader);
239     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
240 }
241 
TEST_F(SeparateCompoundStructDeclarations,Struct)242 TEST_F(SeparateCompoundStructDeclarations, Struct)
243 {
244     const char kShader[]   = R"(#version 300 es
245 precision highp float;
246 struct S { vec3 d; } a, b;
247 out vec4 o;
248 void main() {
249     if (a.d == b.d)
250         o = vec4(1);
251 })";
252     const char kExpected[] = R"(#version 300 es
253 struct _uS {
254   highp vec3 _ud;
255 };
256 _uS _ua;
257 _uS _ub;
258 out highp vec4 _uo;
259 void main(){
260   if ((_ua._ud == _ub._ud))
261   {
262     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
263   }
264 }
265 )";
266     compile(kShader);
267     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
268 }
269 
TEST_F(SeparateCompoundStructDeclarations,ConstStruct)270 TEST_F(SeparateCompoundStructDeclarations, ConstStruct)
271 {
272     const char kShader[]   = R"(#version 300 es
273 precision highp float;
274 out vec4 o;
275 void main()
276 {
277   const struct s2 {
278     int i;
279   } s22 = s2(8);
280   const struct s1 {
281     s2 ss;
282     mat4 m;
283   } s11 = s1(s22, mat4(5));
284   if (s11.ss.i > int(o.x))
285     o = vec4(1);
286 })";
287     const char kExpected[] = R"(#version 300 es
288 out highp vec4 _uo;
289 void main(){
290   const mediump int sbc3 = 8;
291   if ((sbc3 > int(_uo.x)))
292   {
293     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
294   }
295 }
296 )";
297     compile(kShader);
298     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
299 }
300 
301 // Example of what the const struct does before evaluating constants.
TEST_F(SeparateCompoundStructDeclarations,ConstStructsCrossRef)302 TEST_F(SeparateCompoundStructDeclarations, ConstStructsCrossRef)
303 {
304     const char kShader[]   = R"(#version 300 es
305 precision highp float;
306 out vec4 o;
307 void main()
308 {
309   struct s2 {
310     int i;
311   } s22 = s2(8);
312   struct s1 {
313     s2 ss;
314     mat4 m;
315   } s11 = s1(s22, mat4(5));
316   if (s11.ss.i > int(o.x))
317     o = vec4(1);
318 })";
319     const char kExpected[] = R"(#version 300 es
320 out highp vec4 _uo;
321 void main(){
322   struct _us2 {
323     mediump int _ui;
324   };
325   _us2 _us22 = _us2(8);
326   struct _us1 {
327     _us2 _uss;
328     highp mat4 _um;
329   };
330   _us1 _us11 = _us1(_us22, mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0));
331   if ((_us11._uss._ui > int(_uo.x)))
332   {
333     (_uo = vec4(1.0, 1.0, 1.0, 1.0));
334   }
335 }
336 )";
337     compile(kShader);
338     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
339 }
340 
341 // Test that struct name validation takes into account that intenal symbol namespace
342 // is different to user namespace. The test should be kept in sync so that struct sbbf is the same
343 // textual symbol as what the anonymous struct gets.
TEST_F(SeparateCompoundStructDeclarations,InternalSymbolNoCrash)344 TEST_F(SeparateCompoundStructDeclarations, InternalSymbolNoCrash)
345 {
346     const char kShader[] = R"(
347 precision highp float;
348 struct { vec4 e; } g;
349 struct sbbf { vec4 f; };
350 void main(){
351   sbbf s;
352   gl_FragColor = g.e + s.f;
353 })";
354     compile(kShader);
355     const char kExpected[] = R"(struct sbbf {
356   highp vec4 _ue;
357 };
358 sbbf _ug;
359 struct _usbbf {
360   highp vec4 _uf;
361 };
362 void main(){
363   _usbbf _us;
364   (gl_FragColor = (_ug._ue + _us._uf));
365 }
366 )";
367     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
368 }
369 
TEST_F(SeparateStructFunctionDeclarations,StructInStruct)370 TEST_F(SeparateStructFunctionDeclarations, StructInStruct)
371 {
372     const char kShader[]   = R"(#version 300 es
373 struct S {
374   int f;
375 };
376 struct S2 { S h; } o()
377 {
378   return S2(S(1));
379 }
380 void main() {
381   S2 s2 = o();
382 })";
383     const char kExpected[] = R"(#version 300 es
384 struct _uS {
385   mediump int _uf;
386 };
387 struct _uS2 {
388   _uS _uh;
389 };
390 _uS2 _uo(){
391   return _uS2(_uS(1));
392 }
393 void main(){
394   _uS2 _us2 = _uo();
395 }
396 )";
397     compile(kShader);
398     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
399 }
400 
TEST_F(SeparateStructFunctionDeclarations,StructInAnonymousStruct)401 TEST_F(SeparateStructFunctionDeclarations, StructInAnonymousStruct)
402 {
403     const char kShader[]   = R"(#version 300 es
404 struct S {
405   int f;
406 };
407 struct { S h; } o();
408 void main() {
409 })";
410     const char kExpected[] = R"(#version 300 es
411 void main(){
412 }
413 )";
414     compile(kShader);
415     EXPECT_EQ(kExpected, outputCode(SH_ESSL_OUTPUT));
416 }
417 
418 }  // namespace
419