xref: /aosp_15_r20/external/skia/tests/SkSLMemoryLayoutTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/private/base/SkTArray.h"
9 #include "src/sksl/SkSLBuiltinTypes.h"
10 #include "src/sksl/SkSLContext.h"
11 #include "src/sksl/SkSLErrorReporter.h"
12 #include "src/sksl/SkSLMemoryLayout.h"
13 #include "src/sksl/SkSLPosition.h"
14 #include "src/sksl/SkSLProgramSettings.h"
15 #include "src/sksl/SkSLUtil.h"
16 #include "src/sksl/ir/SkSLLayout.h"
17 #include "src/sksl/ir/SkSLModifierFlags.h"
18 #include "src/sksl/ir/SkSLType.h"
19 #include "tests/Test.h"
20 
21 #include <memory>
22 #include <string>
23 #include <string_view>
24 #include <utility>
25 
26 using namespace skia_private;
27 
DEF_TEST(SkSLMemoryLayoutTest_std140,r)28 DEF_TEST(SkSLMemoryLayoutTest_std140, r) {
29     SkSL::TestingOnly_AbortErrorReporter errors;
30     SkSL::BuiltinTypes types;
31     SkSL::Context context(types, errors);
32     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::k140);
33     SkSL::ProgramConfig config = {};
34     context.fConfig = &config;
35 
36     // basic types
37     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fFloat));
38     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fFloat2));
39     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
40     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
41     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fInt));
42     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fInt2));
43     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
44     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
45     REPORTER_ASSERT(r,  1 == layout.size(*context.fTypes.fBool));
46     REPORTER_ASSERT(r,  2 == layout.size(*context.fTypes.fBool2));
47     REPORTER_ASSERT(r,  3 == layout.size(*context.fTypes.fBool3));
48     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fBool4));
49     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x2));
50     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
51     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
52     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x2));
53     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
54     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fAtomicUInt));
55     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fFloat));
56     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fFloat2));
57     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
58     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
59     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fInt));
60     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fInt2));
61     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
62     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
63     REPORTER_ASSERT(r,  1 == layout.alignment(*context.fTypes.fBool));
64     REPORTER_ASSERT(r,  2 == layout.alignment(*context.fTypes.fBool2));
65     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fBool3));
66     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fBool4));
67     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x2));
68     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
69     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
70     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x2));
71     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
72     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fAtomicUInt));
73 
74     // struct 1
75     TArray<SkSL::Field> fields1;
76     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
77                          std::string_view("a"), context.fTypes.fFloat3.get());
78     std::unique_ptr<SkSL::Type> s1 =
79             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s1"), fields1);
80     REPORTER_ASSERT(r, 16 == layout.size(*s1));
81     REPORTER_ASSERT(r, 16 == layout.alignment(*s1));
82 
83     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
84                          std::string_view("b"), context.fTypes.fFloat.get());
85     std::unique_ptr<SkSL::Type> s2 =
86             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s2"), fields1);
87     REPORTER_ASSERT(r, 16 == layout.size(*s2));
88     REPORTER_ASSERT(r, 16 == layout.alignment(*s2));
89 
90     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
91                          std::string_view("c"), context.fTypes.fBool.get());
92     std::unique_ptr<SkSL::Type> s3 =
93             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s3"), fields1);
94     REPORTER_ASSERT(r, 32 == layout.size(*s3));
95     REPORTER_ASSERT(r, 16 == layout.alignment(*s3));
96 
97     // struct 2
98     TArray<SkSL::Field> fields2;
99     fields2.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
100                          std::string_view("a"), context.fTypes.fInt.get());
101     std::unique_ptr<SkSL::Type> s4 =
102             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s4"), fields2);
103     REPORTER_ASSERT(r, 16 == layout.size(*s4));
104     REPORTER_ASSERT(r, 16 == layout.alignment(*s4));
105 
106     fields2.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
107                          std::string_view("b"), context.fTypes.fFloat3.get());
108     std::unique_ptr<SkSL::Type> s5 =
109             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s5"), fields2);
110     REPORTER_ASSERT(r, 32 == layout.size(*s5));
111     REPORTER_ASSERT(r, 16 == layout.alignment(*s5));
112 
113     // arrays
114     std::unique_ptr<SkSL::Type> array1 =
115             SkSL::Type::MakeArrayType(context, std::string("float[4]"), *context.fTypes.fFloat, 4);
116     REPORTER_ASSERT(r, 64 == layout.size(*array1));
117     REPORTER_ASSERT(r, 16 == layout.alignment(*array1));
118     REPORTER_ASSERT(r, 16 == layout.stride(*array1));
119 
120     std::unique_ptr<SkSL::Type> array2 =
121             SkSL::Type::MakeArrayType(context, std::string("float4[4]"), *context.fTypes.fFloat4, 4);
122     REPORTER_ASSERT(r, 64 == layout.size(*array2));
123     REPORTER_ASSERT(r, 16 == layout.alignment(*array2));
124     REPORTER_ASSERT(r, 16 == layout.stride(*array2));
125 }
126 
DEF_TEST(SkSLMemoryLayoutTest_std430,r)127 DEF_TEST(SkSLMemoryLayoutTest_std430, r) {
128     SkSL::TestingOnly_AbortErrorReporter errors;
129     SkSL::BuiltinTypes types;
130     SkSL::Context context(types, errors);
131     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::k430);
132     SkSL::ProgramConfig config = {};
133     context.fConfig = &config;
134 
135     // basic types
136     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fFloat));
137     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fFloat2));
138     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
139     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
140     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fInt));
141     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fInt2));
142     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
143     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
144     REPORTER_ASSERT(r,  1 == layout.size(*context.fTypes.fBool));
145     REPORTER_ASSERT(r,  2 == layout.size(*context.fTypes.fBool2));
146     REPORTER_ASSERT(r,  3 == layout.size(*context.fTypes.fBool3));
147     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fBool4));
148     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat2x2));
149     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
150     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
151     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat4x2));
152     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
153     REPORTER_ASSERT(r,  4 == layout.size(*context.fTypes.fAtomicUInt));
154     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fFloat));
155     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fFloat2));
156     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
157     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
158     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fInt));
159     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fInt2));
160     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
161     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
162     REPORTER_ASSERT(r,  1 == layout.alignment(*context.fTypes.fBool));
163     REPORTER_ASSERT(r,  2 == layout.alignment(*context.fTypes.fBool2));
164     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fBool3));
165     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fBool4));
166     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fFloat2x2));
167     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
168     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
169     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fFloat4x2));
170     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
171     REPORTER_ASSERT(r,  4 == layout.alignment(*context.fTypes.fAtomicUInt));
172 
173     // struct 1
174     TArray<SkSL::Field> fields1;
175     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
176                          std::string_view("a"), context.fTypes.fFloat3.get());
177     std::unique_ptr<SkSL::Type> s1 =
178             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s1"), fields1);
179     REPORTER_ASSERT(r, 16 == layout.size(*s1));
180     REPORTER_ASSERT(r, 16 == layout.alignment(*s1));
181 
182     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
183                          std::string_view("b"), context.fTypes.fFloat.get());
184     std::unique_ptr<SkSL::Type> s2 =
185             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s2"), fields1);
186     REPORTER_ASSERT(r, 16 == layout.size(*s2));
187     REPORTER_ASSERT(r, 16 == layout.alignment(*s2));
188 
189     fields1.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
190                          std::string_view("c"), context.fTypes.fBool.get());
191     std::unique_ptr<SkSL::Type> s3 =
192             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s3"), fields1);
193     REPORTER_ASSERT(r, 32 == layout.size(*s3));
194     REPORTER_ASSERT(r, 16 == layout.alignment(*s3));
195 
196     // struct 2
197     TArray<SkSL::Field> fields2;
198     fields2.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
199                          std::string_view("a"), context.fTypes.fInt.get());
200     std::unique_ptr<SkSL::Type> s4 =
201             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s4"), fields2);
202     REPORTER_ASSERT(r, 4 == layout.size(*s4));
203     REPORTER_ASSERT(r, 4 == layout.alignment(*s4));
204 
205     fields2.emplace_back(SkSL::Position(), SkSL::Layout(), SkSL::ModifierFlag::kNone,
206                          std::string_view("b"), context.fTypes.fFloat3.get());
207     std::unique_ptr<SkSL::Type> s5 =
208             SkSL::Type::MakeStructType(context, SkSL::Position(), std::string("s5"), fields2);
209     REPORTER_ASSERT(r, 32 == layout.size(*s5));
210     REPORTER_ASSERT(r, 16 == layout.alignment(*s5));
211 
212     // arrays
213     std::unique_ptr<SkSL::Type> array1 =
214             SkSL::Type::MakeArrayType(context, std::string("float[4]"), *context.fTypes.fFloat, 4);
215     REPORTER_ASSERT(r, 16 == layout.size(*array1));
216     REPORTER_ASSERT(r, 4 == layout.alignment(*array1));
217     REPORTER_ASSERT(r, 4 == layout.stride(*array1));
218 
219     std::unique_ptr<SkSL::Type> array2 =
220             SkSL::Type::MakeArrayType(context, std::string("float4[4]"), *context.fTypes.fFloat4, 4);
221     REPORTER_ASSERT(r, 64 == layout.size(*array2));
222     REPORTER_ASSERT(r, 16 == layout.alignment(*array2));
223     REPORTER_ASSERT(r, 16 == layout.stride(*array2));
224 }
225 
DEF_TEST(SkSLMemoryLayoutTest_WGSLUniform_Base,r)226 DEF_TEST(SkSLMemoryLayoutTest_WGSLUniform_Base, r) {
227     SkSL::TestingOnly_AbortErrorReporter errors;
228     SkSL::BuiltinTypes types;
229     SkSL::Context context(types, errors);
230     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLUniform_Base);
231     SkSL::ProgramConfig config = {};
232     context.fConfig = &config;
233 
234     // The values here are taken from https://www.w3.org/TR/WGSL/#alignment-and-size, table titled
235     // "Alignment and size for host-shareable types". WGSL does not have an i16 type, so short and
236     // unsigned-short integer types are treated as full-size integers in WGSL.
237 
238     // scalars (i32, u32, f32, f16)
239     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fInt));
240     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUInt));
241     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fShort));
242     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUShort));
243     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fFloat));
244     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fHalf));
245     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fInt));
246     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUInt));
247     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fShort));
248     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUShort));
249     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fFloat));
250     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf));
251 
252     // vec2<T>, T: i32, u32, f32, f16
253     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fInt2));
254     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUInt2));
255     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fShort2));
256     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUShort2));
257     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fFloat2));
258     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fHalf2));
259     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fInt2));
260     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUInt2));
261     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fShort2));
262     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUShort2));
263     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2));
264     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2));
265 
266     // vec3<T>, T: i32, u32, f32, f16
267     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
268     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUInt3));
269     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fShort3));
270     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUShort3));
271     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
272     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fHalf3));
273     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
274     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt3));
275     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort3));
276     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort3));
277     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
278     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3));
279 
280     // vec4<T>, T: i32, u32, f32, f16
281     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
282     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUInt4));
283     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fShort4));
284     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUShort4));
285     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
286     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf4));
287     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
288     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt4));
289     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort4));
290     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort4));
291     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
292     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4));
293 
294     // mat2x2<f32>, mat2x2<f16>
295     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat2x2));
296     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x2));
297     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2x2));
298     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x2));
299     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat2x2));
300     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x2));
301 
302     // mat3x2<f32>, mat3x2<f16>
303     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fFloat3x2));
304     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x2));
305     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat3x2));
306     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x2));
307     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat3x2));
308     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x2));
309 
310     // mat4x2<f32>, mat4x2<f16>
311     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat4x2));
312     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x2));
313     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat4x2));
314     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x2));
315     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat4x2));
316     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x2));
317 
318     // mat2x3<f32>, mat2x3<f16>
319     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x3));
320     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf2x3));
321     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x3));
322     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf2x3));
323     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x3));
324     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf2x3));
325 
326     // mat3x3<f32>, mat3x3<f16>
327     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
328     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fHalf3x3));
329     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
330     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3x3));
331     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x3));
332     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf3x3));
333 
334     // mat4x3<f32>, mat4x3<f16>
335     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x3));
336     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fHalf4x3));
337     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x3));
338     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4x3));
339     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x3));
340     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf4x3));
341 
342     // mat2x4<f32>, mat2x4<f16>
343     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
344     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf2x4));
345     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
346     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf2x4));
347     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x4));
348     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf2x4));
349 
350     // mat3x4<f32>, mat3x4<f16>
351     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x4));
352     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fHalf3x4));
353     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x4));
354     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3x4));
355     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x4));
356     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf3x4));
357 
358     // mat4x4<f32>, mat4x4<f16>
359     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
360     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fHalf4x4));
361     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
362     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4x4));
363     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x4));
364     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf4x4));
365 
366     // atomic<u32>
367     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fAtomicUInt));
368     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fAtomicUInt));
369 
370     // bool is not a host-shareable type and returns 0 for WGSL.
371     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool));
372     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool2));
373     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool3));
374     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool4));
375 
376     // Arrays
377     // array<f32, 4>
378     {
379         auto array = SkSL::Type::MakeArrayType(context, "float[4]", *context.fTypes.fFloat, 4);
380         REPORTER_ASSERT(r, 64 == layout.size(*array));
381         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
382         REPORTER_ASSERT(r, 16 == layout.stride(*array));
383     }
384     // array<f16, 4>
385     {
386         auto array = SkSL::Type::MakeArrayType(context, "half[4]", *context.fTypes.fHalf, 4);
387         REPORTER_ASSERT(r, 64 == layout.size(*array));
388         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
389         REPORTER_ASSERT(r, 16 == layout.stride(*array));
390     }
391     // array<vec2<f32>, 4>
392     {
393         auto array = SkSL::Type::MakeArrayType(context, "float2[4]", *context.fTypes.fFloat2, 4);
394         REPORTER_ASSERT(r, 64 == layout.size(*array));
395         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
396         REPORTER_ASSERT(r, 16 == layout.stride(*array));
397     }
398     // array<vec3<f32>, 4>
399     {
400         auto array = SkSL::Type::MakeArrayType(context, "float3[4]", *context.fTypes.fFloat3, 4);
401         REPORTER_ASSERT(r, 64 == layout.size(*array));
402         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
403         REPORTER_ASSERT(r, 16 == layout.stride(*array));
404     }
405     // array<vec4<f32>, 4>
406     {
407         auto array = SkSL::Type::MakeArrayType(context, "float4[4]", *context.fTypes.fFloat4, 4);
408         REPORTER_ASSERT(r, 64 == layout.size(*array));
409         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
410         REPORTER_ASSERT(r, 16 == layout.stride(*array));
411     }
412     // array<mat3x3<f32>, 4>
413     {
414         auto array = SkSL::Type::MakeArrayType(context, "mat3[4]", *context.fTypes.fFloat3x3, 4);
415         REPORTER_ASSERT(r, 192 == layout.size(*array));
416         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
417         REPORTER_ASSERT(r, 48 == layout.stride(*array));
418     }
419 
420     // Structs A and B from example in https://www.w3.org/TR/WGSL/#structure-member-layout, with
421     // offsets adjusted for uniform address space constraints.
422     //
423     // struct A {        //            align(roundUp(16, 8))  size(roundUp(16, 24))
424     //     u: f32,       // offset(0)  align(4)               size(4)
425     //     v: f32,       // offset(4)  align(4)               size(4)
426     //     w: vec2<f32>, // offset(8)  align(8)               size(8)
427     //     x: f32        // offset(16) align(4)               size(4)
428     //     // padding    // offset(20)                        size(12)
429     // }
430     TArray<SkSL::Field> fields;
431     fields.emplace_back(SkSL::Position(),
432                         SkSL::Layout(),
433                         SkSL::ModifierFlag::kNone,
434                         std::string_view("u"),
435                         context.fTypes.fFloat.get());
436     fields.emplace_back(SkSL::Position(),
437                         SkSL::Layout(),
438                         SkSL::ModifierFlag::kNone,
439                         std::string_view("v"),
440                         context.fTypes.fFloat.get());
441     fields.emplace_back(SkSL::Position(),
442                         SkSL::Layout(),
443                         SkSL::ModifierFlag::kNone,
444                         std::string_view("w"),
445                         context.fTypes.fFloat2.get());
446     fields.emplace_back(SkSL::Position(),
447                         SkSL::Layout(),
448                         SkSL::ModifierFlag::kNone,
449                         std::string_view("x"),
450                         context.fTypes.fFloat.get());
451     std::unique_ptr<SkSL::Type> structA = SkSL::Type::MakeStructType(
452             context, SkSL::Position(), std::string_view("A"), std::move(fields));
453     REPORTER_ASSERT(r, 32 == layout.size(*structA));
454     REPORTER_ASSERT(r, 16 == layout.alignment(*structA));
455     fields = {};
456 
457     // struct B {          //             align(16) size(208)
458     //     a: vec2<f32>,   // offset(0)   align(8)  size(8)
459     //     // padding      // offset(8)             size(8)
460     //     b: vec3<f32>,   // offset(16)  align(16) size(12)
461     //     c: f32,         // offset(28)  align(4)  size(4)
462     //     d: f32,         // offset(32)  align(4)  size(4)
463     //     // padding      // offset(36)            size(12)
464     //     e: A,           // offset(48)  align(16) size(32)
465     //     f: vec3<f32>,   // offset(80)  align(16) size(12)
466     //     // padding      // offset(92)            size(4)
467     //     g: array<A, 3>, // offset(96)  align(16) size(96)
468     //     h: i32          // offset(192) align(4)  size(4)
469     //     // padding      // offset(196)           size(12)
470     // }
471     fields.emplace_back(SkSL::Position(),
472                         SkSL::Layout(),
473                         SkSL::ModifierFlag::kNone,
474                         std::string_view("a"),
475                         context.fTypes.fFloat2.get());
476     fields.emplace_back(SkSL::Position(),
477                         SkSL::Layout(),
478                         SkSL::ModifierFlag::kNone,
479                         std::string_view("b"),
480                         context.fTypes.fFloat3.get());
481     fields.emplace_back(SkSL::Position(),
482                         SkSL::Layout(),
483                         SkSL::ModifierFlag::kNone,
484                         std::string_view("c"),
485                         context.fTypes.fFloat.get());
486     fields.emplace_back(SkSL::Position(),
487                         SkSL::Layout(),
488                         SkSL::ModifierFlag::kNone,
489                         std::string_view("d"),
490                         context.fTypes.fFloat.get());
491     fields.emplace_back(SkSL::Position(),
492                         SkSL::Layout(),
493                         SkSL::ModifierFlag::kNone,
494                         std::string_view("e"),
495                         structA.get());
496     fields.emplace_back(SkSL::Position(),
497                         SkSL::Layout(),
498                         SkSL::ModifierFlag::kNone,
499                         std::string_view("f"),
500                         context.fTypes.fFloat3.get());
501     auto array = SkSL::Type::MakeArrayType(context, "A[3]", *structA, 3);
502     fields.emplace_back(SkSL::Position(),
503                         SkSL::Layout(),
504                         SkSL::ModifierFlag::kNone,
505                         std::string_view("g"),
506                         array.get());
507     fields.emplace_back(SkSL::Position(),
508                         SkSL::Layout(),
509                         SkSL::ModifierFlag::kNone,
510                         std::string_view("h"),
511                         context.fTypes.fInt.get());
512     std::unique_ptr<SkSL::Type> structB = SkSL::Type::MakeStructType(
513             context, SkSL::Position(), std::string_view("B"), std::move(fields));
514     REPORTER_ASSERT(r, 208 == layout.size(*structB));
515     REPORTER_ASSERT(r, 16 == layout.alignment(*structB));
516 }
517 
DEF_TEST(SkSLMemoryLayoutTest_WGSLUniform_EnableF16,r)518 DEF_TEST(SkSLMemoryLayoutTest_WGSLUniform_EnableF16, r) {
519     SkSL::TestingOnly_AbortErrorReporter errors;
520     SkSL::BuiltinTypes types;
521     SkSL::Context context(types, errors);
522     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLUniform_EnableF16);
523     SkSL::ProgramConfig config = {};
524     context.fConfig = &config;
525 
526     // The values here are taken from https://www.w3.org/TR/WGSL/#alignment-and-size, table titled
527     // "Alignment and size for host-shareable types". WGSL does not have an i16 type, so short and
528     // unsigned-short integer types are treated as full-size integers in WGSL.
529 
530     // scalars (i32, u32, f32, f16)
531     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fInt));
532     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUInt));
533     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fShort));
534     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUShort));
535     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fFloat));
536     REPORTER_ASSERT(r, 2 == layout.size(*context.fTypes.fHalf));
537     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fInt));
538     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUInt));
539     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fShort));
540     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUShort));
541     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fFloat));
542     REPORTER_ASSERT(r, 2 == layout.alignment(*context.fTypes.fHalf));
543 
544     // vec2<T>, T: i32, u32, f32, f16
545     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fInt2));
546     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUInt2));
547     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fShort2));
548     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUShort2));
549     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fFloat2));
550     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fHalf2));
551     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fInt2));
552     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUInt2));
553     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fShort2));
554     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUShort2));
555     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2));
556     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf2));
557 
558     // vec3<T>, T: i32, u32, f32, f16
559     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
560     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUInt3));
561     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fShort3));
562     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUShort3));
563     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
564     REPORTER_ASSERT(r,  6 == layout.size(*context.fTypes.fHalf3));
565     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
566     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt3));
567     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort3));
568     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort3));
569     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
570     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fHalf3));
571 
572     // vec4<T>, T: i32, u32, f32, f16
573     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
574     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUInt4));
575     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fShort4));
576     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUShort4));
577     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
578     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fHalf4));
579     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
580     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt4));
581     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort4));
582     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort4));
583     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
584     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fHalf4));
585 
586     // mat2x2<f32>, mat2x2<f16>
587     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat2x2));
588     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fHalf2x2));
589     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2x2));
590     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf2x2));
591     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat2x2));
592     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf2x2));
593 
594     // mat3x2<f32>, mat3x2<f16>
595     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fFloat3x2));
596     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fHalf3x2));
597     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat3x2));
598     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf3x2));
599     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat3x2));
600     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf3x2));
601 
602     // mat4x2<f32>, mat4x2<f16>
603     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat4x2));
604     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf4x2));
605     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat4x2));
606     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf4x2));
607     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat4x2));
608     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf4x2));
609 
610     // mat2x3<f32>, mat2x3<f16>
611     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x3));
612     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x3));
613     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x3));
614     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x3));
615     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x3));
616     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x3));
617 
618     // mat3x3<f32>, mat3x3<f16>
619     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
620     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x3));
621     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
622     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x3));
623     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x3));
624     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x3));
625 
626     // mat4x3<f32>, mat4x3<f16>
627     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x3));
628     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x3));
629     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x3));
630     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x3));
631     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x3));
632     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x3));
633 
634     // mat2x4<f32>, mat2x4<f16>
635     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
636     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x4));
637     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
638     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x4));
639     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x4));
640     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x4));
641 
642     // mat3x4<f32>, mat3x4<f16>
643     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x4));
644     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x4));
645     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x4));
646     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x4));
647     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x4));
648     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x4));
649 
650     // mat4x4<f32>, mat4x4<f16>
651     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
652     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x4));
653     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
654     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x4));
655     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x4));
656     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x4));
657 
658     // atomic<u32>
659     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fAtomicUInt));
660     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fAtomicUInt));
661 
662     // bool is not a host-shareable type and returns 0 for WGSL.
663     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool));
664     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool2));
665     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool3));
666     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool4));
667 
668     // Arrays
669     // array<f32, 4>
670     {
671         auto array = SkSL::Type::MakeArrayType(context, "float[4]", *context.fTypes.fFloat, 4);
672         REPORTER_ASSERT(r, 64 == layout.size(*array));
673         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
674         REPORTER_ASSERT(r, 16 == layout.stride(*array));
675     }
676     // array<f16, 4>
677     {
678         auto array = SkSL::Type::MakeArrayType(context, "half[4]", *context.fTypes.fHalf, 4);
679         REPORTER_ASSERT(r, 64 == layout.size(*array));
680         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
681         REPORTER_ASSERT(r, 16 == layout.stride(*array));
682     }
683     // array<vec2<f32>, 4>
684     {
685         auto array = SkSL::Type::MakeArrayType(context, "float2[4]", *context.fTypes.fFloat2, 4);
686         REPORTER_ASSERT(r, 64 == layout.size(*array));
687         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
688         REPORTER_ASSERT(r, 16 == layout.stride(*array));
689     }
690     // array<vec3<f32>, 4>
691     {
692         auto array = SkSL::Type::MakeArrayType(context, "float3[4]", *context.fTypes.fFloat3, 4);
693         REPORTER_ASSERT(r, 64 == layout.size(*array));
694         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
695         REPORTER_ASSERT(r, 16 == layout.stride(*array));
696     }
697     // array<vec4<f32>, 4>
698     {
699         auto array = SkSL::Type::MakeArrayType(context, "float4[4]", *context.fTypes.fFloat4, 4);
700         REPORTER_ASSERT(r, 64 == layout.size(*array));
701         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
702         REPORTER_ASSERT(r, 16 == layout.stride(*array));
703     }
704     // array<mat3x3<f32>, 4>
705     {
706         auto array = SkSL::Type::MakeArrayType(context, "mat3[4]", *context.fTypes.fFloat3x3, 4);
707         REPORTER_ASSERT(r, 192 == layout.size(*array));
708         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
709         REPORTER_ASSERT(r, 48 == layout.stride(*array));
710     }
711 
712     // Structs A and B from example in https://www.w3.org/TR/WGSL/#structure-member-layout, with
713     // offsets adjusted for uniform address space constraints.
714     //
715     // struct A {        //            align(roundUp(16, 8))  size(roundUp(16, 24))
716     //     u: f32,       // offset(0)  align(4)               size(4)
717     //     v: f32,       // offset(4)  align(4)               size(4)
718     //     w: vec2<f32>, // offset(8)  align(8)               size(8)
719     //     x: f32        // offset(16) align(4)               size(4)
720     //     // padding    // offset(20)                        size(12)
721     // }
722     TArray<SkSL::Field> fields;
723     fields.emplace_back(SkSL::Position(),
724                         SkSL::Layout(),
725                         SkSL::ModifierFlag::kNone,
726                         std::string_view("u"),
727                         context.fTypes.fFloat.get());
728     fields.emplace_back(SkSL::Position(),
729                         SkSL::Layout(),
730                         SkSL::ModifierFlag::kNone,
731                         std::string_view("v"),
732                         context.fTypes.fFloat.get());
733     fields.emplace_back(SkSL::Position(),
734                         SkSL::Layout(),
735                         SkSL::ModifierFlag::kNone,
736                         std::string_view("w"),
737                         context.fTypes.fFloat2.get());
738     fields.emplace_back(SkSL::Position(),
739                         SkSL::Layout(),
740                         SkSL::ModifierFlag::kNone,
741                         std::string_view("x"),
742                         context.fTypes.fFloat.get());
743     std::unique_ptr<SkSL::Type> structA = SkSL::Type::MakeStructType(
744             context, SkSL::Position(), std::string_view("A"), std::move(fields));
745     REPORTER_ASSERT(r, 32 == layout.size(*structA));
746     REPORTER_ASSERT(r, 16 == layout.alignment(*structA));
747     fields = {};
748 
749     // struct B {          //             align(16) size(208)
750     //     a: vec2<f32>,   // offset(0)   align(8)  size(8)
751     //     // padding      // offset(8)             size(8)
752     //     b: vec3<f32>,   // offset(16)  align(16) size(12)
753     //     c: f32,         // offset(28)  align(4)  size(4)
754     //     d: f32,         // offset(32)  align(4)  size(4)
755     //     // padding      // offset(36)            size(12)
756     //     e: A,           // offset(48)  align(16) size(32)
757     //     f: vec3<f32>,   // offset(80)  align(16) size(12)
758     //     // padding      // offset(92)            size(4)
759     //     g: array<A, 3>, // offset(96)  align(16) size(96)
760     //     h: i32          // offset(192) align(4)  size(4)
761     //     // padding      // offset(196)           size(12)
762     // }
763     fields.emplace_back(SkSL::Position(),
764                         SkSL::Layout(),
765                         SkSL::ModifierFlag::kNone,
766                         std::string_view("a"),
767                         context.fTypes.fFloat2.get());
768     fields.emplace_back(SkSL::Position(),
769                         SkSL::Layout(),
770                         SkSL::ModifierFlag::kNone,
771                         std::string_view("b"),
772                         context.fTypes.fFloat3.get());
773     fields.emplace_back(SkSL::Position(),
774                         SkSL::Layout(),
775                         SkSL::ModifierFlag::kNone,
776                         std::string_view("c"),
777                         context.fTypes.fFloat.get());
778     fields.emplace_back(SkSL::Position(),
779                         SkSL::Layout(),
780                         SkSL::ModifierFlag::kNone,
781                         std::string_view("d"),
782                         context.fTypes.fFloat.get());
783     fields.emplace_back(SkSL::Position(),
784                         SkSL::Layout(),
785                         SkSL::ModifierFlag::kNone,
786                         std::string_view("e"),
787                         structA.get());
788     fields.emplace_back(SkSL::Position(),
789                         SkSL::Layout(),
790                         SkSL::ModifierFlag::kNone,
791                         std::string_view("f"),
792                         context.fTypes.fFloat3.get());
793     auto array = SkSL::Type::MakeArrayType(context, "A[3]", *structA, 3);
794     fields.emplace_back(SkSL::Position(),
795                         SkSL::Layout(),
796                         SkSL::ModifierFlag::kNone,
797                         std::string_view("g"),
798                         array.get());
799     fields.emplace_back(SkSL::Position(),
800                         SkSL::Layout(),
801                         SkSL::ModifierFlag::kNone,
802                         std::string_view("h"),
803                         context.fTypes.fInt.get());
804     std::unique_ptr<SkSL::Type> structB = SkSL::Type::MakeStructType(
805             context, SkSL::Position(), std::string_view("B"), std::move(fields));
806     REPORTER_ASSERT(r, 208 == layout.size(*structB));
807     REPORTER_ASSERT(r, 16 == layout.alignment(*structB));
808 }
809 
DEF_TEST(SkSLMemoryLayoutTest_WGSLStorage_Base,r)810 DEF_TEST(SkSLMemoryLayoutTest_WGSLStorage_Base, r) {
811     SkSL::TestingOnly_AbortErrorReporter errors;
812     SkSL::BuiltinTypes types;
813     SkSL::Context context(types, errors);
814     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLStorage_Base);
815     SkSL::ProgramConfig config = {};
816     context.fConfig = &config;
817 
818     // The values here are taken from https://www.w3.org/TR/WGSL/#alignment-and-size, table titled
819     // "Alignment and size for host-shareable types".
820 
821     // scalars (i32, u32, f32, f16)
822     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fInt));
823     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUInt));
824     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fShort));
825     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUShort));
826     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fFloat));
827     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fHalf));
828     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fInt));
829     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUInt));
830     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fShort));
831     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUShort));
832     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fFloat));
833     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf));
834 
835     // vec2<T>, T: i32, u32, f32, f16
836     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fInt2));
837     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUInt2));
838     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fShort2));
839     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUShort2));
840     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fFloat2));
841     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fHalf2));
842     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fInt2));
843     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUInt2));
844     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fShort2));
845     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUShort2));
846     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2));
847     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2));
848 
849     // vec3<T>, T: i32, u32, f32, f16
850     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
851     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUInt3));
852     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fShort3));
853     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUShort3));
854     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
855     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fHalf3));
856     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
857     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt3));
858     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort3));
859     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort3));
860     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
861     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3));
862 
863     // vec4<T>, T: i32, u32, f32, f16
864     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
865     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUInt4));
866     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fShort4));
867     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUShort4));
868     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
869     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf4));
870     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
871     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt4));
872     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort4));
873     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort4));
874     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
875     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4));
876 
877     // mat2x2<f32>, mat2x2<f16>
878     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat2x2));
879     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x2));
880     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2x2));
881     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x2));
882     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat2x2));
883     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x2));
884 
885     // mat3x2<f32>, mat3x2<f16>
886     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fFloat3x2));
887     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x2));
888     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat3x2));
889     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x2));
890     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat3x2));
891     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x2));
892 
893     // mat4x2<f32>, mat4x2<f16>
894     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat4x2));
895     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x2));
896     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat4x2));
897     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x2));
898     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat4x2));
899     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x2));
900 
901     // mat2x3<f32>, mat2x3<f16>
902     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x3));
903     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf2x3));
904     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x3));
905     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf2x3));
906     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x3));
907     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf2x3));
908 
909     // mat3x3<f32>, mat3x3<f16>
910     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
911     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fHalf3x3));
912     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
913     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3x3));
914     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x3));
915     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf3x3));
916 
917     // mat4x3<f32>, mat4x3<f16>
918     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x3));
919     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fHalf4x3));
920     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x3));
921     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4x3));
922     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x3));
923     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf4x3));
924 
925     // mat2x4<f32>, mat2x4<f16>
926     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
927     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf2x4));
928     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
929     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf2x4));
930     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x4));
931     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf2x4));
932 
933     // mat3x4<f32>, mat3x4<f16>
934     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x4));
935     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fHalf3x4));
936     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x4));
937     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf3x4));
938     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x4));
939     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf3x4));
940 
941     // mat4x4<f32>, mat4x4<f16>
942     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
943     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fHalf4x4));
944     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
945     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fHalf4x4));
946     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x4));
947     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fHalf4x4));
948 
949     // atomic<u32>
950     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fAtomicUInt));
951     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fAtomicUInt));
952 
953     // bool is not a host-shareable type and returns 0 for WGSL.
954     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool));
955     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool2));
956     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool3));
957     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool4));
958 
959     // Arrays
960     // array<f32, 4>
961     {
962         auto array = SkSL::Type::MakeArrayType(context, "float[4]", *context.fTypes.fFloat, 4);
963         REPORTER_ASSERT(r, 16 == layout.size(*array));
964         REPORTER_ASSERT(r, 4 == layout.alignment(*array));
965         REPORTER_ASSERT(r, 4 == layout.stride(*array));
966     }
967     // array<f16, 4>
968     {
969         auto array = SkSL::Type::MakeArrayType(context, "half[4]", *context.fTypes.fHalf, 4);
970         REPORTER_ASSERT(r, 16 == layout.size(*array));
971         REPORTER_ASSERT(r, 4 == layout.alignment(*array));
972         REPORTER_ASSERT(r, 4 == layout.stride(*array));
973     }
974     // array<vec2<f32>, 4>
975     {
976         auto array = SkSL::Type::MakeArrayType(context, "float2[4]", *context.fTypes.fFloat2, 4);
977         REPORTER_ASSERT(r, 32 == layout.size(*array));
978         REPORTER_ASSERT(r, 8 == layout.alignment(*array));
979         REPORTER_ASSERT(r, 8 == layout.stride(*array));
980     }
981     // array<vec3<f32>, 4>
982     {
983         auto array = SkSL::Type::MakeArrayType(context, "float3[4]", *context.fTypes.fFloat3, 4);
984         REPORTER_ASSERT(r, 64 == layout.size(*array));
985         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
986         REPORTER_ASSERT(r, 16 == layout.stride(*array));
987     }
988     // array<vec4<f32>, 4>
989     {
990         auto array = SkSL::Type::MakeArrayType(context, "float4[4]", *context.fTypes.fFloat4, 4);
991         REPORTER_ASSERT(r, 64 == layout.size(*array));
992         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
993         REPORTER_ASSERT(r, 16 == layout.stride(*array));
994     }
995     // array<mat3x3<f32>, 4>
996     {
997         auto array = SkSL::Type::MakeArrayType(context, "mat3[4]", *context.fTypes.fFloat3x3, 4);
998         REPORTER_ASSERT(r, 192 == layout.size(*array));
999         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
1000         REPORTER_ASSERT(r, 48 == layout.stride(*array));
1001     }
1002 
1003     // Structs A and B from example in https://www.w3.org/TR/WGSL/#structure-member-layout
1004     //
1005     // struct A {        //            align(8)               size(24)
1006     //     u: f32,       // offset(0)  align(4)               size(4)
1007     //     v: f32,       // offset(4)  align(4)               size(4)
1008     //     w: vec2<f32>, // offset(8)  align(8)               size(8)
1009     //     x: f32        // offset(16) align(4)               size(4)
1010     //     // padding    // offset(20)                        size(4)
1011     // }
1012     TArray<SkSL::Field> fields;
1013     fields.emplace_back(SkSL::Position(),
1014                         SkSL::Layout(),
1015                         SkSL::ModifierFlag::kNone,
1016                         std::string_view("u"),
1017                         context.fTypes.fFloat.get());
1018     fields.emplace_back(SkSL::Position(),
1019                         SkSL::Layout(),
1020                         SkSL::ModifierFlag::kNone,
1021                         std::string_view("v"),
1022                         context.fTypes.fFloat.get());
1023     fields.emplace_back(SkSL::Position(),
1024                         SkSL::Layout(),
1025                         SkSL::ModifierFlag::kNone,
1026                         std::string_view("w"),
1027                         context.fTypes.fFloat2.get());
1028     fields.emplace_back(SkSL::Position(),
1029                         SkSL::Layout(),
1030                         SkSL::ModifierFlag::kNone,
1031                         std::string_view("x"),
1032                         context.fTypes.fFloat.get());
1033     std::unique_ptr<SkSL::Type> structA = SkSL::Type::MakeStructType(
1034             context, SkSL::Position(), std::string_view("A"), std::move(fields));
1035     REPORTER_ASSERT(r, 24 == layout.size(*structA));
1036     REPORTER_ASSERT(r, 8 == layout.alignment(*structA));
1037     fields = {};
1038 
1039     // struct B {          //             align(16) size(160)
1040     //     a: vec2<f32>,   // offset(0)   align(8)  size(8)
1041     //     // padding      // offset(8)             size(8)
1042     //     b: vec3<f32>,   // offset(16)  align(16) size(12)
1043     //     c: f32,         // offset(28)  align(4)  size(4)
1044     //     d: f32,         // offset(32)  align(4)  size(4)
1045     //     // padding      // offset(36)            size(4)
1046     //     e: A,           // offset(40)  align(8)  size(24)
1047     //     f: vec3<f32>,   // offset(64)  align(16) size(12)
1048     //     // padding      // offset(76)            size(4)
1049     //     g: array<A, 3>, // offset(80)  align(16) size(72)
1050     //     h: i32          // offset(152) align(4)  size(4)
1051     //     // padding      // offset(156)           size(4)
1052     // }
1053     fields.emplace_back(SkSL::Position(),
1054                         SkSL::Layout(),
1055                         SkSL::ModifierFlag::kNone,
1056                         std::string_view("a"),
1057                         context.fTypes.fFloat2.get());
1058     fields.emplace_back(SkSL::Position(),
1059                         SkSL::Layout(),
1060                         SkSL::ModifierFlag::kNone,
1061                         std::string_view("b"),
1062                         context.fTypes.fFloat3.get());
1063     fields.emplace_back(SkSL::Position(),
1064                         SkSL::Layout(),
1065                         SkSL::ModifierFlag::kNone,
1066                         std::string_view("c"),
1067                         context.fTypes.fFloat.get());
1068     fields.emplace_back(SkSL::Position(),
1069                         SkSL::Layout(),
1070                         SkSL::ModifierFlag::kNone,
1071                         std::string_view("d"),
1072                         context.fTypes.fFloat.get());
1073     fields.emplace_back(SkSL::Position(),
1074                         SkSL::Layout(),
1075                         SkSL::ModifierFlag::kNone,
1076                         std::string_view("e"),
1077                         structA.get());
1078     fields.emplace_back(SkSL::Position(),
1079                         SkSL::Layout(),
1080                         SkSL::ModifierFlag::kNone,
1081                         std::string_view("f"),
1082                         context.fTypes.fFloat3.get());
1083     auto array = SkSL::Type::MakeArrayType(context, "A[3]", *structA, 3);
1084     fields.emplace_back(SkSL::Position(),
1085                         SkSL::Layout(),
1086                         SkSL::ModifierFlag::kNone,
1087                         std::string_view("g"),
1088                         array.get());
1089     fields.emplace_back(SkSL::Position(),
1090                         SkSL::Layout(),
1091                         SkSL::ModifierFlag::kNone,
1092                         std::string_view("h"),
1093                         context.fTypes.fInt.get());
1094     std::unique_ptr<SkSL::Type> structB = SkSL::Type::MakeStructType(
1095             context, SkSL::Position(), std::string_view("B"), std::move(fields));
1096     REPORTER_ASSERT(r, 160 == layout.size(*structB));
1097     REPORTER_ASSERT(r, 16 == layout.alignment(*structB));
1098 }
1099 
DEF_TEST(SkSLMemoryLayoutTest_WGSLStorage_EnableF16,r)1100 DEF_TEST(SkSLMemoryLayoutTest_WGSLStorage_EnableF16, r) {
1101     SkSL::TestingOnly_AbortErrorReporter errors;
1102     SkSL::BuiltinTypes types;
1103     SkSL::Context context(types, errors);
1104     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLStorage_EnableF16);
1105     SkSL::ProgramConfig config = {};
1106     context.fConfig = &config;
1107 
1108     // The values here are taken from https://www.w3.org/TR/WGSL/#alignment-and-size, table titled
1109     // "Alignment and size for host-shareable types".
1110 
1111     // scalars (i32, u32, f32, f16)
1112     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fInt));
1113     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUInt));
1114     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fShort));
1115     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fUShort));
1116     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fFloat));
1117     REPORTER_ASSERT(r, 2 == layout.size(*context.fTypes.fHalf));
1118     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fInt));
1119     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUInt));
1120     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fShort));
1121     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fUShort));
1122     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fFloat));
1123     REPORTER_ASSERT(r, 2 == layout.alignment(*context.fTypes.fHalf));
1124 
1125     // vec2<T>, T: i32, u32, f32, f16
1126     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fInt2));
1127     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUInt2));
1128     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fShort2));
1129     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fUShort2));
1130     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fFloat2));
1131     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fHalf2));
1132     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fInt2));
1133     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUInt2));
1134     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fShort2));
1135     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fUShort2));
1136     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2));
1137     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf2));
1138 
1139     // vec3<T>, T: i32, u32, f32, f16
1140     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fInt3));
1141     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUInt3));
1142     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fShort3));
1143     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fUShort3));
1144     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fFloat3));
1145     REPORTER_ASSERT(r,  6 == layout.size(*context.fTypes.fHalf3));
1146     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt3));
1147     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt3));
1148     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort3));
1149     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort3));
1150     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3));
1151     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fHalf3));
1152 
1153     // vec4<T>, T: i32, u32, f32, f16
1154     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fInt4));
1155     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUInt4));
1156     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fShort4));
1157     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fUShort4));
1158     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat4));
1159     REPORTER_ASSERT(r,  8 == layout.size(*context.fTypes.fHalf4));
1160     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fInt4));
1161     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUInt4));
1162     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fShort4));
1163     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fUShort4));
1164     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4));
1165     REPORTER_ASSERT(r,  8 == layout.alignment(*context.fTypes.fHalf4));
1166 
1167     // mat2x2<f32>, mat2x2<f16>
1168     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fFloat2x2));
1169     REPORTER_ASSERT(r, 8 == layout.size(*context.fTypes.fHalf2x2));
1170     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat2x2));
1171     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf2x2));
1172     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat2x2));
1173     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf2x2));
1174 
1175     // mat3x2<f32>, mat3x2<f16>
1176     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fFloat3x2));
1177     REPORTER_ASSERT(r, 12 == layout.size(*context.fTypes.fHalf3x2));
1178     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat3x2));
1179     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf3x2));
1180     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat3x2));
1181     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf3x2));
1182 
1183     // mat4x2<f32>, mat4x2<f16>
1184     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat4x2));
1185     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf4x2));
1186     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fFloat4x2));
1187     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fHalf4x2));
1188     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fFloat4x2));
1189     REPORTER_ASSERT(r, 4 == layout.stride(*context.fTypes.fHalf4x2));
1190 
1191     // mat2x3<f32>, mat2x3<f16>
1192     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x3));
1193     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x3));
1194     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x3));
1195     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x3));
1196     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x3));
1197     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x3));
1198 
1199     // mat3x3<f32>, mat3x3<f16>
1200     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x3));
1201     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x3));
1202     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x3));
1203     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x3));
1204     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x3));
1205     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x3));
1206 
1207     // mat4x3<f32>, mat4x3<f16>
1208     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x3));
1209     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x3));
1210     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x3));
1211     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x3));
1212     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x3));
1213     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x3));
1214 
1215     // mat2x4<f32>, mat2x4<f16>
1216     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fFloat2x4));
1217     REPORTER_ASSERT(r, 16 == layout.size(*context.fTypes.fHalf2x4));
1218     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat2x4));
1219     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf2x4));
1220     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat2x4));
1221     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf2x4));
1222 
1223     // mat3x4<f32>, mat3x4<f16>
1224     REPORTER_ASSERT(r, 48 == layout.size(*context.fTypes.fFloat3x4));
1225     REPORTER_ASSERT(r, 24 == layout.size(*context.fTypes.fHalf3x4));
1226     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat3x4));
1227     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf3x4));
1228     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat3x4));
1229     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf3x4));
1230 
1231     // mat4x4<f32>, mat4x4<f16>
1232     REPORTER_ASSERT(r, 64 == layout.size(*context.fTypes.fFloat4x4));
1233     REPORTER_ASSERT(r, 32 == layout.size(*context.fTypes.fHalf4x4));
1234     REPORTER_ASSERT(r, 16 == layout.alignment(*context.fTypes.fFloat4x4));
1235     REPORTER_ASSERT(r, 8 == layout.alignment(*context.fTypes.fHalf4x4));
1236     REPORTER_ASSERT(r, 16 == layout.stride(*context.fTypes.fFloat4x4));
1237     REPORTER_ASSERT(r, 8 == layout.stride(*context.fTypes.fHalf4x4));
1238 
1239     // atomic<u32>
1240     REPORTER_ASSERT(r, 4 == layout.size(*context.fTypes.fAtomicUInt));
1241     REPORTER_ASSERT(r, 4 == layout.alignment(*context.fTypes.fAtomicUInt));
1242 
1243     // bool is not a host-shareable type and returns 0 for WGSL.
1244     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool));
1245     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool2));
1246     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool3));
1247     REPORTER_ASSERT(r, 0 == layout.size(*context.fTypes.fBool4));
1248 
1249     // Arrays
1250     // array<f32, 4>
1251     {
1252         auto array = SkSL::Type::MakeArrayType(context, "float[4]", *context.fTypes.fFloat, 4);
1253         REPORTER_ASSERT(r, 16 == layout.size(*array));
1254         REPORTER_ASSERT(r, 4 == layout.alignment(*array));
1255         REPORTER_ASSERT(r, 4 == layout.stride(*array));
1256     }
1257     // array<f16, 4>
1258     {
1259         auto array = SkSL::Type::MakeArrayType(context, "half[4]", *context.fTypes.fHalf, 4);
1260         REPORTER_ASSERT(r, 8 == layout.size(*array));
1261         REPORTER_ASSERT(r, 2 == layout.alignment(*array));
1262         REPORTER_ASSERT(r, 2 == layout.stride(*array));
1263     }
1264     // array<vec2<f32>, 4>
1265     {
1266         auto array = SkSL::Type::MakeArrayType(context, "float2[4]", *context.fTypes.fFloat2, 4);
1267         REPORTER_ASSERT(r, 32 == layout.size(*array));
1268         REPORTER_ASSERT(r, 8 == layout.alignment(*array));
1269         REPORTER_ASSERT(r, 8 == layout.stride(*array));
1270     }
1271     // array<vec3<f32>, 4>
1272     {
1273         auto array = SkSL::Type::MakeArrayType(context, "float3[4]", *context.fTypes.fFloat3, 4);
1274         REPORTER_ASSERT(r, 64 == layout.size(*array));
1275         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
1276         REPORTER_ASSERT(r, 16 == layout.stride(*array));
1277     }
1278     // array<vec4<f32>, 4>
1279     {
1280         auto array = SkSL::Type::MakeArrayType(context, "float4[4]", *context.fTypes.fFloat4, 4);
1281         REPORTER_ASSERT(r, 64 == layout.size(*array));
1282         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
1283         REPORTER_ASSERT(r, 16 == layout.stride(*array));
1284     }
1285     // array<mat3x3<f32>, 4>
1286     {
1287         auto array = SkSL::Type::MakeArrayType(context, "mat3[4]", *context.fTypes.fFloat3x3, 4);
1288         REPORTER_ASSERT(r, 192 == layout.size(*array));
1289         REPORTER_ASSERT(r, 16 == layout.alignment(*array));
1290         REPORTER_ASSERT(r, 48 == layout.stride(*array));
1291     }
1292 
1293     // Structs A and B from example in https://www.w3.org/TR/WGSL/#structure-member-layout
1294     //
1295     // struct A {        //            align(8)               size(24)
1296     //     u: f32,       // offset(0)  align(4)               size(4)
1297     //     v: f32,       // offset(4)  align(4)               size(4)
1298     //     w: vec2<f32>, // offset(8)  align(8)               size(8)
1299     //     x: f32        // offset(16) align(4)               size(4)
1300     //     // padding    // offset(20)                        size(4)
1301     // }
1302     TArray<SkSL::Field> fields;
1303     fields.emplace_back(SkSL::Position(),
1304                         SkSL::Layout(),
1305                         SkSL::ModifierFlag::kNone,
1306                         std::string_view("u"),
1307                         context.fTypes.fFloat.get());
1308     fields.emplace_back(SkSL::Position(),
1309                         SkSL::Layout(),
1310                         SkSL::ModifierFlag::kNone,
1311                         std::string_view("v"),
1312                         context.fTypes.fFloat.get());
1313     fields.emplace_back(SkSL::Position(),
1314                         SkSL::Layout(),
1315                         SkSL::ModifierFlag::kNone,
1316                         std::string_view("w"),
1317                         context.fTypes.fFloat2.get());
1318     fields.emplace_back(SkSL::Position(),
1319                         SkSL::Layout(),
1320                         SkSL::ModifierFlag::kNone,
1321                         std::string_view("x"),
1322                         context.fTypes.fFloat.get());
1323     std::unique_ptr<SkSL::Type> structA = SkSL::Type::MakeStructType(
1324             context, SkSL::Position(), std::string_view("A"), std::move(fields));
1325     REPORTER_ASSERT(r, 24 == layout.size(*structA));
1326     REPORTER_ASSERT(r, 8 == layout.alignment(*structA));
1327     fields = {};
1328 
1329     // struct B {          //             align(16) size(160)
1330     //     a: vec2<f32>,   // offset(0)   align(8)  size(8)
1331     //     // padding      // offset(8)             size(8)
1332     //     b: vec3<f32>,   // offset(16)  align(16) size(12)
1333     //     c: f32,         // offset(28)  align(4)  size(4)
1334     //     d: f32,         // offset(32)  align(4)  size(4)
1335     //     // padding      // offset(36)            size(4)
1336     //     e: A,           // offset(40)  align(8)  size(24)
1337     //     f: vec3<f32>,   // offset(64)  align(16) size(12)
1338     //     // padding      // offset(76)            size(4)
1339     //     g: array<A, 3>, // offset(80)  align(16) size(72)
1340     //     h: i32          // offset(152) align(4)  size(4)
1341     //     // padding      // offset(156)           size(4)
1342     // }
1343     fields.emplace_back(SkSL::Position(),
1344                         SkSL::Layout(),
1345                         SkSL::ModifierFlag::kNone,
1346                         std::string_view("a"),
1347                         context.fTypes.fFloat2.get());
1348     fields.emplace_back(SkSL::Position(),
1349                         SkSL::Layout(),
1350                         SkSL::ModifierFlag::kNone,
1351                         std::string_view("b"),
1352                         context.fTypes.fFloat3.get());
1353     fields.emplace_back(SkSL::Position(),
1354                         SkSL::Layout(),
1355                         SkSL::ModifierFlag::kNone,
1356                         std::string_view("c"),
1357                         context.fTypes.fFloat.get());
1358     fields.emplace_back(SkSL::Position(),
1359                         SkSL::Layout(),
1360                         SkSL::ModifierFlag::kNone,
1361                         std::string_view("d"),
1362                         context.fTypes.fFloat.get());
1363     fields.emplace_back(SkSL::Position(),
1364                         SkSL::Layout(),
1365                         SkSL::ModifierFlag::kNone,
1366                         std::string_view("e"),
1367                         structA.get());
1368     fields.emplace_back(SkSL::Position(),
1369                         SkSL::Layout(),
1370                         SkSL::ModifierFlag::kNone,
1371                         std::string_view("f"),
1372                         context.fTypes.fFloat3.get());
1373     auto array = SkSL::Type::MakeArrayType(context, "A[3]", *structA, 3);
1374     fields.emplace_back(SkSL::Position(),
1375                         SkSL::Layout(),
1376                         SkSL::ModifierFlag::kNone,
1377                         std::string_view("g"),
1378                         array.get());
1379     fields.emplace_back(SkSL::Position(),
1380                         SkSL::Layout(),
1381                         SkSL::ModifierFlag::kNone,
1382                         std::string_view("h"),
1383                         context.fTypes.fInt.get());
1384     std::unique_ptr<SkSL::Type> structB = SkSL::Type::MakeStructType(
1385             context, SkSL::Position(), std::string_view("B"), std::move(fields));
1386     REPORTER_ASSERT(r, 160 == layout.size(*structB));
1387     REPORTER_ASSERT(r, 16 == layout.alignment(*structB));
1388 }
1389 
DEF_TEST(SkSLMemoryLayoutTest_WGSLUnsupportedTypes,r)1390 DEF_TEST(SkSLMemoryLayoutTest_WGSLUnsupportedTypes, r) {
1391     SkSL::TestingOnly_AbortErrorReporter errors;
1392     SkSL::BuiltinTypes types;
1393     SkSL::Context context(types, errors);
1394     SkSL::ProgramConfig config = {};
1395     context.fConfig = &config;
1396 
1397     auto testArray = SkSL::Type::MakeArrayType(context, "bool[3]", *context.fTypes.fBool, 3);
1398 
1399     TArray<SkSL::Field> fields;
1400     fields.emplace_back(SkSL::Position(),
1401                         SkSL::Layout(),
1402                         SkSL::ModifierFlag::kNone,
1403                         std::string_view("foo"),
1404                         testArray.get());
1405     auto testStruct = SkSL::Type::MakeStructType(
1406             context, SkSL::Position(), std::string_view("Test"), std::move(fields));
1407 
1408     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLUniform_EnableF16);
1409     REPORTER_ASSERT(r, !layout.isSupported(*context.fTypes.fBool));
1410     REPORTER_ASSERT(r, !layout.isSupported(*context.fTypes.fBool2));
1411     REPORTER_ASSERT(r, !layout.isSupported(*context.fTypes.fBool3));
1412     REPORTER_ASSERT(r, !layout.isSupported(*context.fTypes.fBool4));
1413     REPORTER_ASSERT(r, !layout.isSupported(*testArray));
1414     REPORTER_ASSERT(r, !layout.isSupported(*testStruct));
1415 }
1416 
DEF_TEST(SkSLMemoryLayoutTest_WGSLSupportedTypes,r)1417 DEF_TEST(SkSLMemoryLayoutTest_WGSLSupportedTypes, r) {
1418     SkSL::TestingOnly_AbortErrorReporter errors;
1419     SkSL::BuiltinTypes types;
1420     SkSL::Context context(types, errors);
1421     SkSL::ProgramConfig config = {};
1422     context.fConfig = &config;
1423 
1424     auto testArray = SkSL::Type::MakeArrayType(context, "float[3]", *context.fTypes.fFloat, 3);
1425 
1426     TArray<SkSL::Field> fields;
1427     fields.emplace_back(SkSL::Position(),
1428                         SkSL::Layout(),
1429                         SkSL::ModifierFlag::kNone,
1430                         std::string_view("foo"),
1431                         testArray.get());
1432     auto testStruct = SkSL::Type::MakeStructType(
1433             context, SkSL::Position(), std::string_view("Test"), std::move(fields));
1434 
1435     SkSL::MemoryLayout layout(SkSL::MemoryLayout::Standard::kWGSLUniform_EnableF16);
1436 
1437     // scalars (i32, u32, f32, f16)
1438     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fInt));
1439     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUInt));
1440     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fShort));
1441     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUShort));
1442     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat));
1443     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf));
1444 
1445     // vec2<T>, T: i32, u32, f32, f16
1446     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fInt2));
1447     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUInt2));
1448     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fShort2));
1449     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUShort2));
1450     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat2));
1451     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf2));
1452 
1453     // vec3<T>, T: i32, u32, f32, f16
1454     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fInt3));
1455     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUInt3));
1456     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fShort3));
1457     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUShort3));
1458     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat3));
1459     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf3));
1460 
1461     // vec4<T>, T: i32, u32, f32, f16
1462     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fInt4));
1463     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUInt4));
1464     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat4));
1465     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fShort4));
1466     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fUShort4));
1467     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf4));
1468 
1469     // mat2x2<f32>, mat2x2<f16>
1470     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat2x2));
1471     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf2x2));
1472 
1473     // mat3x2<f32>, mat3x2<f16>
1474     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat3x2));
1475     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf3x2));
1476 
1477     // mat4x2<f32>, mat4x2<f16>
1478     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat4x2));
1479     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf4x2));
1480 
1481     // mat2x3<f32>, mat2x3<f16>
1482     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat2x3));
1483     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf2x3));
1484 
1485     // mat3x3<f32>, mat3x3<f16>
1486     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat3x3));
1487     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf3x3));
1488 
1489     // mat4x3<f32>, mat4x3<f16>
1490     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat4x3));
1491     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf4x3));
1492 
1493     // mat2x4<f32>, mat2x4<f16>
1494     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat2x4));
1495     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf2x4));
1496 
1497     // mat3x4<f32>, mat3x4<f16>
1498     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat3x4));
1499     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf3x4));
1500 
1501     // mat4x4<f32>, mat4x4<f16>
1502     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fFloat4x4));
1503     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fHalf4x4));
1504 
1505     // atomic<u32>
1506     REPORTER_ASSERT(r, layout.isSupported(*context.fTypes.fAtomicUInt));
1507 
1508     // arrays and structs
1509     REPORTER_ASSERT(r, layout.isSupported(*testArray));
1510     REPORTER_ASSERT(r, layout.isSupported(*testStruct));
1511 }
1512