• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/resolver/resolver.h"
16 
17 #include "gmock/gmock.h"
18 #include "src/ast/struct_block_decoration.h"
19 #include "src/resolver/resolver_test_helper.h"
20 #include "src/sem/struct.h"
21 
22 namespace tint {
23 namespace resolver {
24 namespace {
25 
26 using ResolverStructLayoutTest = ResolverTest;
27 
TEST_F(ResolverStructLayoutTest,Scalars)28 TEST_F(ResolverStructLayoutTest, Scalars) {
29   auto* s = Structure("S", {
30                                Member("a", ty.f32()),
31                                Member("b", ty.u32()),
32                                Member("c", ty.i32()),
33                            });
34 
35   ASSERT_TRUE(r()->Resolve()) << r()->error();
36 
37   auto* sem = TypeOf(s)->As<sem::Struct>();
38   ASSERT_NE(sem, nullptr);
39   EXPECT_EQ(sem->Size(), 12u);
40   EXPECT_EQ(sem->SizeNoPadding(), 12u);
41   EXPECT_EQ(sem->Align(), 4u);
42   ASSERT_EQ(sem->Members().size(), 3u);
43   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
44   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
45   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
46   EXPECT_EQ(sem->Members()[1]->Offset(), 4u);
47   EXPECT_EQ(sem->Members()[1]->Align(), 4u);
48   EXPECT_EQ(sem->Members()[1]->Size(), 4u);
49   EXPECT_EQ(sem->Members()[2]->Offset(), 8u);
50   EXPECT_EQ(sem->Members()[2]->Align(), 4u);
51   EXPECT_EQ(sem->Members()[2]->Size(), 4u);
52 }
53 
TEST_F(ResolverStructLayoutTest,Alias)54 TEST_F(ResolverStructLayoutTest, Alias) {
55   auto* alias_a = Alias("a", ty.f32());
56   auto* alias_b = Alias("b", ty.f32());
57 
58   auto* s = Structure("S", {
59                                Member("a", ty.Of(alias_a)),
60                                Member("b", ty.Of(alias_b)),
61                            });
62 
63   ASSERT_TRUE(r()->Resolve()) << r()->error();
64 
65   auto* sem = TypeOf(s)->As<sem::Struct>();
66   ASSERT_NE(sem, nullptr);
67   EXPECT_EQ(sem->Size(), 8u);
68   EXPECT_EQ(sem->SizeNoPadding(), 8u);
69   EXPECT_EQ(sem->Align(), 4u);
70   ASSERT_EQ(sem->Members().size(), 2u);
71   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
72   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
73   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
74   EXPECT_EQ(sem->Members()[1]->Offset(), 4u);
75   EXPECT_EQ(sem->Members()[1]->Align(), 4u);
76   EXPECT_EQ(sem->Members()[1]->Size(), 4u);
77 }
78 
TEST_F(ResolverStructLayoutTest,ImplicitStrideArrayStaticSize)79 TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayStaticSize) {
80   auto* s = Structure("S", {
81                                Member("a", ty.array<i32, 3>()),
82                                Member("b", ty.array<f32, 5>()),
83                                Member("c", ty.array<f32, 1>()),
84                            });
85 
86   ASSERT_TRUE(r()->Resolve()) << r()->error();
87 
88   auto* sem = TypeOf(s)->As<sem::Struct>();
89   ASSERT_NE(sem, nullptr);
90   EXPECT_EQ(sem->Size(), 36u);
91   EXPECT_EQ(sem->SizeNoPadding(), 36u);
92   EXPECT_EQ(sem->Align(), 4u);
93   ASSERT_EQ(sem->Members().size(), 3u);
94   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
95   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
96   EXPECT_EQ(sem->Members()[0]->Size(), 12u);
97   EXPECT_EQ(sem->Members()[1]->Offset(), 12u);
98   EXPECT_EQ(sem->Members()[1]->Align(), 4u);
99   EXPECT_EQ(sem->Members()[1]->Size(), 20u);
100   EXPECT_EQ(sem->Members()[2]->Offset(), 32u);
101   EXPECT_EQ(sem->Members()[2]->Align(), 4u);
102   EXPECT_EQ(sem->Members()[2]->Size(), 4u);
103 }
104 
TEST_F(ResolverStructLayoutTest,ExplicitStrideArrayStaticSize)105 TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayStaticSize) {
106   auto* s = Structure("S", {
107                                Member("a", ty.array<i32, 3>(/*stride*/ 8)),
108                                Member("b", ty.array<f32, 5>(/*stride*/ 16)),
109                                Member("c", ty.array<f32, 1>(/*stride*/ 32)),
110                            });
111 
112   ASSERT_TRUE(r()->Resolve()) << r()->error();
113 
114   auto* sem = TypeOf(s)->As<sem::Struct>();
115   ASSERT_NE(sem, nullptr);
116   EXPECT_EQ(sem->Size(), 136u);
117   EXPECT_EQ(sem->SizeNoPadding(), 136u);
118   EXPECT_EQ(sem->Align(), 4u);
119   ASSERT_EQ(sem->Members().size(), 3u);
120   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
121   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
122   EXPECT_EQ(sem->Members()[0]->Size(), 24u);
123   EXPECT_EQ(sem->Members()[1]->Offset(), 24u);
124   EXPECT_EQ(sem->Members()[1]->Align(), 4u);
125   EXPECT_EQ(sem->Members()[1]->Size(), 80u);
126   EXPECT_EQ(sem->Members()[2]->Offset(), 104u);
127   EXPECT_EQ(sem->Members()[2]->Align(), 4u);
128   EXPECT_EQ(sem->Members()[2]->Size(), 32u);
129 }
130 
TEST_F(ResolverStructLayoutTest,ImplicitStrideArrayRuntimeSized)131 TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayRuntimeSized) {
132   auto* s =
133       Structure("S",
134                 {
135                     Member("c", ty.array<f32>()),
136                 },
137                 ast::DecorationList{create<ast::StructBlockDecoration>()});
138 
139   ASSERT_TRUE(r()->Resolve()) << r()->error();
140 
141   auto* sem = TypeOf(s)->As<sem::Struct>();
142   ASSERT_NE(sem, nullptr);
143   EXPECT_EQ(sem->Size(), 4u);
144   EXPECT_EQ(sem->SizeNoPadding(), 4u);
145   EXPECT_EQ(sem->Align(), 4u);
146   ASSERT_EQ(sem->Members().size(), 1u);
147   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
148   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
149   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
150 }
151 
TEST_F(ResolverStructLayoutTest,ExplicitStrideArrayRuntimeSized)152 TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayRuntimeSized) {
153   auto* s =
154       Structure("S",
155                 {
156                     Member("c", ty.array<f32>(/*stride*/ 32)),
157                 },
158                 ast::DecorationList{create<ast::StructBlockDecoration>()});
159 
160   ASSERT_TRUE(r()->Resolve()) << r()->error();
161 
162   auto* sem = TypeOf(s)->As<sem::Struct>();
163   ASSERT_NE(sem, nullptr);
164   EXPECT_EQ(sem->Size(), 32u);
165   EXPECT_EQ(sem->SizeNoPadding(), 32u);
166   EXPECT_EQ(sem->Align(), 4u);
167   ASSERT_EQ(sem->Members().size(), 1u);
168   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
169   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
170   EXPECT_EQ(sem->Members()[0]->Size(), 32u);
171 }
172 
TEST_F(ResolverStructLayoutTest,ImplicitStrideArrayOfExplicitStrideArray)173 TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayOfExplicitStrideArray) {
174   auto* inner = ty.array<i32, 2>(/*stride*/ 16);  // size: 32
175   auto* outer = ty.array(inner, 12);              // size: 12 * 32
176   auto* s = Structure("S", {
177                                Member("c", outer),
178                            });
179 
180   ASSERT_TRUE(r()->Resolve()) << r()->error();
181 
182   auto* sem = TypeOf(s)->As<sem::Struct>();
183   ASSERT_NE(sem, nullptr);
184   EXPECT_EQ(sem->Size(), 384u);
185   EXPECT_EQ(sem->SizeNoPadding(), 384u);
186   EXPECT_EQ(sem->Align(), 4u);
187   ASSERT_EQ(sem->Members().size(), 1u);
188   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
189   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
190   EXPECT_EQ(sem->Members()[0]->Size(), 384u);
191 }
192 
TEST_F(ResolverStructLayoutTest,ImplicitStrideArrayOfStructure)193 TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayOfStructure) {
194   auto* inner = Structure("Inner", {
195                                        Member("a", ty.vec2<i32>()),
196                                        Member("b", ty.vec3<i32>()),
197                                        Member("c", ty.vec4<i32>()),
198                                    });       // size: 48
199   auto* outer = ty.array(ty.Of(inner), 12);  // size: 12 * 48
200   auto* s = Structure("S", {
201                                Member("c", outer),
202                            });
203 
204   ASSERT_TRUE(r()->Resolve()) << r()->error();
205 
206   auto* sem = TypeOf(s)->As<sem::Struct>();
207   ASSERT_NE(sem, nullptr);
208   EXPECT_EQ(sem->Size(), 576u);
209   EXPECT_EQ(sem->SizeNoPadding(), 576u);
210   EXPECT_EQ(sem->Align(), 16u);
211   ASSERT_EQ(sem->Members().size(), 1u);
212   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
213   EXPECT_EQ(sem->Members()[0]->Align(), 16u);
214   EXPECT_EQ(sem->Members()[0]->Size(), 576u);
215 }
216 
TEST_F(ResolverStructLayoutTest,Vector)217 TEST_F(ResolverStructLayoutTest, Vector) {
218   auto* s = Structure("S", {
219                                Member("a", ty.vec2<i32>()),
220                                Member("b", ty.vec3<i32>()),
221                                Member("c", ty.vec4<i32>()),
222                            });
223 
224   ASSERT_TRUE(r()->Resolve()) << r()->error();
225 
226   auto* sem = TypeOf(s)->As<sem::Struct>();
227   ASSERT_NE(sem, nullptr);
228   EXPECT_EQ(sem->Size(), 48u);
229   EXPECT_EQ(sem->SizeNoPadding(), 48u);
230   EXPECT_EQ(sem->Align(), 16u);
231   ASSERT_EQ(sem->Members().size(), 3u);
232   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);  // vec2
233   EXPECT_EQ(sem->Members()[0]->Align(), 8u);
234   EXPECT_EQ(sem->Members()[0]->Size(), 8u);
235   EXPECT_EQ(sem->Members()[1]->Offset(), 16u);  // vec3
236   EXPECT_EQ(sem->Members()[1]->Align(), 16u);
237   EXPECT_EQ(sem->Members()[1]->Size(), 12u);
238   EXPECT_EQ(sem->Members()[2]->Offset(), 32u);  // vec4
239   EXPECT_EQ(sem->Members()[2]->Align(), 16u);
240   EXPECT_EQ(sem->Members()[2]->Size(), 16u);
241 }
242 
TEST_F(ResolverStructLayoutTest,Matrix)243 TEST_F(ResolverStructLayoutTest, Matrix) {
244   auto* s = Structure("S", {
245                                Member("a", ty.mat2x2<f32>()),
246                                Member("b", ty.mat2x3<f32>()),
247                                Member("c", ty.mat2x4<f32>()),
248                                Member("d", ty.mat3x2<f32>()),
249                                Member("e", ty.mat3x3<f32>()),
250                                Member("f", ty.mat3x4<f32>()),
251                                Member("g", ty.mat4x2<f32>()),
252                                Member("h", ty.mat4x3<f32>()),
253                                Member("i", ty.mat4x4<f32>()),
254                            });
255 
256   ASSERT_TRUE(r()->Resolve()) << r()->error();
257 
258   auto* sem = TypeOf(s)->As<sem::Struct>();
259   ASSERT_NE(sem, nullptr);
260   EXPECT_EQ(sem->Size(), 368u);
261   EXPECT_EQ(sem->SizeNoPadding(), 368u);
262   EXPECT_EQ(sem->Align(), 16u);
263   ASSERT_EQ(sem->Members().size(), 9u);
264   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);  // mat2x2
265   EXPECT_EQ(sem->Members()[0]->Align(), 8u);
266   EXPECT_EQ(sem->Members()[0]->Size(), 16u);
267   EXPECT_EQ(sem->Members()[1]->Offset(), 16u);  // mat2x3
268   EXPECT_EQ(sem->Members()[1]->Align(), 16u);
269   EXPECT_EQ(sem->Members()[1]->Size(), 32u);
270   EXPECT_EQ(sem->Members()[2]->Offset(), 48u);  // mat2x4
271   EXPECT_EQ(sem->Members()[2]->Align(), 16u);
272   EXPECT_EQ(sem->Members()[2]->Size(), 32u);
273   EXPECT_EQ(sem->Members()[3]->Offset(), 80u);  // mat3x2
274   EXPECT_EQ(sem->Members()[3]->Align(), 8u);
275   EXPECT_EQ(sem->Members()[3]->Size(), 24u);
276   EXPECT_EQ(sem->Members()[4]->Offset(), 112u);  // mat3x3
277   EXPECT_EQ(sem->Members()[4]->Align(), 16u);
278   EXPECT_EQ(sem->Members()[4]->Size(), 48u);
279   EXPECT_EQ(sem->Members()[5]->Offset(), 160u);  // mat3x4
280   EXPECT_EQ(sem->Members()[5]->Align(), 16u);
281   EXPECT_EQ(sem->Members()[5]->Size(), 48u);
282   EXPECT_EQ(sem->Members()[6]->Offset(), 208u);  // mat4x2
283   EXPECT_EQ(sem->Members()[6]->Align(), 8u);
284   EXPECT_EQ(sem->Members()[6]->Size(), 32u);
285   EXPECT_EQ(sem->Members()[7]->Offset(), 240u);  // mat4x3
286   EXPECT_EQ(sem->Members()[7]->Align(), 16u);
287   EXPECT_EQ(sem->Members()[7]->Size(), 64u);
288   EXPECT_EQ(sem->Members()[8]->Offset(), 304u);  // mat4x4
289   EXPECT_EQ(sem->Members()[8]->Align(), 16u);
290   EXPECT_EQ(sem->Members()[8]->Size(), 64u);
291 }
292 
TEST_F(ResolverStructLayoutTest,NestedStruct)293 TEST_F(ResolverStructLayoutTest, NestedStruct) {
294   auto* inner = Structure("Inner", {
295                                        Member("a", ty.mat3x3<f32>()),
296                                    });
297   auto* s = Structure("S", {
298                                Member("a", ty.i32()),
299                                Member("b", ty.Of(inner)),
300                                Member("c", ty.i32()),
301                            });
302 
303   ASSERT_TRUE(r()->Resolve()) << r()->error();
304 
305   auto* sem = TypeOf(s)->As<sem::Struct>();
306   ASSERT_NE(sem, nullptr);
307   EXPECT_EQ(sem->Size(), 80u);
308   EXPECT_EQ(sem->SizeNoPadding(), 68u);
309   EXPECT_EQ(sem->Align(), 16u);
310   ASSERT_EQ(sem->Members().size(), 3u);
311   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
312   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
313   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
314   EXPECT_EQ(sem->Members()[1]->Offset(), 16u);
315   EXPECT_EQ(sem->Members()[1]->Align(), 16u);
316   EXPECT_EQ(sem->Members()[1]->Size(), 48u);
317   EXPECT_EQ(sem->Members()[2]->Offset(), 64u);
318   EXPECT_EQ(sem->Members()[2]->Align(), 4u);
319   EXPECT_EQ(sem->Members()[2]->Size(), 4u);
320 }
321 
TEST_F(ResolverStructLayoutTest,SizeDecorations)322 TEST_F(ResolverStructLayoutTest, SizeDecorations) {
323   auto* inner = Structure("Inner", {
324                                        Member("a", ty.f32(), {MemberSize(8)}),
325                                        Member("b", ty.f32(), {MemberSize(16)}),
326                                        Member("c", ty.f32(), {MemberSize(8)}),
327                                    });
328   auto* s = Structure("S", {
329                                Member("a", ty.f32(), {MemberSize(4)}),
330                                Member("b", ty.u32(), {MemberSize(8)}),
331                                Member("c", ty.Of(inner)),
332                                Member("d", ty.i32(), {MemberSize(32)}),
333                            });
334 
335   ASSERT_TRUE(r()->Resolve()) << r()->error();
336 
337   auto* sem = TypeOf(s)->As<sem::Struct>();
338   ASSERT_NE(sem, nullptr);
339   EXPECT_EQ(sem->Size(), 76u);
340   EXPECT_EQ(sem->SizeNoPadding(), 76u);
341   EXPECT_EQ(sem->Align(), 4u);
342   ASSERT_EQ(sem->Members().size(), 4u);
343   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
344   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
345   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
346   EXPECT_EQ(sem->Members()[1]->Offset(), 4u);
347   EXPECT_EQ(sem->Members()[1]->Align(), 4u);
348   EXPECT_EQ(sem->Members()[1]->Size(), 8u);
349   EXPECT_EQ(sem->Members()[2]->Offset(), 12u);
350   EXPECT_EQ(sem->Members()[2]->Align(), 4u);
351   EXPECT_EQ(sem->Members()[2]->Size(), 32u);
352   EXPECT_EQ(sem->Members()[3]->Offset(), 44u);
353   EXPECT_EQ(sem->Members()[3]->Align(), 4u);
354   EXPECT_EQ(sem->Members()[3]->Size(), 32u);
355 }
356 
TEST_F(ResolverStructLayoutTest,AlignDecorations)357 TEST_F(ResolverStructLayoutTest, AlignDecorations) {
358   auto* inner = Structure("Inner", {
359                                        Member("a", ty.f32(), {MemberAlign(8)}),
360                                        Member("b", ty.f32(), {MemberAlign(16)}),
361                                        Member("c", ty.f32(), {MemberAlign(4)}),
362                                    });
363   auto* s = Structure("S", {
364                                Member("a", ty.f32(), {MemberAlign(4)}),
365                                Member("b", ty.u32(), {MemberAlign(8)}),
366                                Member("c", ty.Of(inner)),
367                                Member("d", ty.i32(), {MemberAlign(32)}),
368                            });
369 
370   ASSERT_TRUE(r()->Resolve()) << r()->error();
371 
372   auto* sem = TypeOf(s)->As<sem::Struct>();
373   ASSERT_NE(sem, nullptr);
374   EXPECT_EQ(sem->Size(), 96u);
375   EXPECT_EQ(sem->SizeNoPadding(), 68u);
376   EXPECT_EQ(sem->Align(), 32u);
377   ASSERT_EQ(sem->Members().size(), 4u);
378   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
379   EXPECT_EQ(sem->Members()[0]->Align(), 4u);
380   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
381   EXPECT_EQ(sem->Members()[1]->Offset(), 8u);
382   EXPECT_EQ(sem->Members()[1]->Align(), 8u);
383   EXPECT_EQ(sem->Members()[1]->Size(), 4u);
384   EXPECT_EQ(sem->Members()[2]->Offset(), 16u);
385   EXPECT_EQ(sem->Members()[2]->Align(), 16u);
386   EXPECT_EQ(sem->Members()[2]->Size(), 32u);
387   EXPECT_EQ(sem->Members()[3]->Offset(), 64u);
388   EXPECT_EQ(sem->Members()[3]->Align(), 32u);
389   EXPECT_EQ(sem->Members()[3]->Size(), 4u);
390 }
391 
TEST_F(ResolverStructLayoutTest,StructWithLotsOfPadding)392 TEST_F(ResolverStructLayoutTest, StructWithLotsOfPadding) {
393   auto* s = Structure("S", {
394                                Member("a", ty.i32(), {MemberAlign(1024)}),
395                            });
396 
397   ASSERT_TRUE(r()->Resolve()) << r()->error();
398 
399   auto* sem = TypeOf(s)->As<sem::Struct>();
400   ASSERT_NE(sem, nullptr);
401   EXPECT_EQ(sem->Size(), 1024u);
402   EXPECT_EQ(sem->SizeNoPadding(), 4u);
403   EXPECT_EQ(sem->Align(), 1024u);
404   ASSERT_EQ(sem->Members().size(), 1u);
405   EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
406   EXPECT_EQ(sem->Members()[0]->Align(), 1024u);
407   EXPECT_EQ(sem->Members()[0]->Size(), 4u);
408 }
409 
410 }  // namespace
411 }  // namespace resolver
412 }  // namespace tint
413