@@ -126,35 +126,68 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
126
126
// - Do `input.member[0].x` (direct)
127
127
// - Store `input.member[0]` in a variable; do `var.x` (vector_loaded)
128
128
// - Store `input.member` in a variable; do `var[0].x` (fully_loaded)
129
- let mut direct = String :: new ( ) ;
130
- let mut vector_loaded = String :: new ( ) ;
131
- let mut fully_loaded = String :: from ( "let loaded = input.member;" ) ;
132
- for column in 0 ..columns {
133
- writeln ! ( vector_loaded, "let vec_{column} = input.member[{column}];" ) . unwrap ( ) ;
129
+ // For each of these, we can either use a static or dynamic index.
130
+ let mut direct_static = String :: new ( ) ;
131
+ let mut direct_dynamic = String :: new ( ) ;
132
+ let mut vector_loaded_static = String :: new ( ) ;
133
+ let mut vector_loaded_dynamic = String :: new ( ) ;
134
+ let mut fully_loaded_static = String :: from ( "let loaded = input.member;" ) ;
135
+ let mut fully_loaded_dynamic = String :: from ( "let loaded = input.member;" ) ;
136
+ let column_index_names = [ "zero" , "one" , "two" , "three" ] ;
137
+ for ( column, column_str) in column_index_names. iter ( ) . enumerate ( ) . take ( columns) {
138
+ writeln ! ( direct_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
139
+ writeln ! ( vector_loaded_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
140
+ writeln ! ( fully_loaded_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
141
+
142
+ writeln ! (
143
+ vector_loaded_static,
144
+ "let vec_{column} = input.member[{column}];"
145
+ )
146
+ . unwrap ( ) ;
147
+ writeln ! (
148
+ vector_loaded_dynamic,
149
+ "let vec_{column} = input.member[{column_str}];" ,
150
+ )
151
+ . unwrap ( ) ;
134
152
}
135
153
136
154
let mut output_values = Vec :: new ( ) ;
137
155
138
156
let mut current_output_idx = 0 ;
139
157
let mut current_input_idx = 0 ;
140
- for column in 0 .. columns {
158
+ for ( column, column_str ) in column_index_names . iter ( ) . enumerate ( ) . take ( columns) {
141
159
let component_accessors = [ "x" , "y" , "z" , "w" ] . into_iter ( ) . take ( rows) ;
142
160
for component in component_accessors {
143
161
writeln ! (
144
- direct ,
162
+ direct_static ,
145
163
"output[{current_output_idx}] = bitcast<u32>(input.member[{column}].{component});"
146
164
)
147
165
. unwrap ( ) ;
148
166
writeln ! (
149
- vector_loaded,
167
+ direct_dynamic,
168
+ "output[{current_output_idx}] = bitcast<u32>(input.member[{column_str}].{component});"
169
+ )
170
+ . unwrap ( ) ;
171
+ writeln ! (
172
+ vector_loaded_static,
173
+ "output[{current_output_idx}] = bitcast<u32>(vec_{column}.{component});"
174
+ )
175
+ . unwrap ( ) ;
176
+ writeln ! (
177
+ vector_loaded_dynamic,
150
178
"output[{current_output_idx}] = bitcast<u32>(vec_{column}.{component});"
151
179
)
152
180
. unwrap ( ) ;
153
181
writeln ! (
154
- fully_loaded ,
182
+ fully_loaded_static ,
155
183
"output[{current_output_idx}] = bitcast<u32>(loaded[{column}].{component});"
156
184
)
157
185
. unwrap ( ) ;
186
+ writeln ! (
187
+ fully_loaded_dynamic,
188
+ "output[{current_output_idx}] = bitcast<u32>(loaded[{column_str}].{component});"
189
+ )
190
+ . unwrap ( ) ;
158
191
159
192
output_values. push ( current_input_idx) ;
160
193
current_input_idx += 1 ;
@@ -175,9 +208,202 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
175
208
176
209
tests. push (
177
210
ShaderTest :: new (
178
- format ! ( "{ty} - direct" ) ,
211
+ format ! ( "{ty} - direct, static index " ) ,
179
212
input_members. clone ( ) ,
180
- direct,
213
+ direct_static,
214
+ & input_values,
215
+ & output_values,
216
+ )
217
+ . failures ( failures) ,
218
+ ) ;
219
+ tests. push (
220
+ ShaderTest :: new (
221
+ format ! ( "{ty} - direct, dynamic index" ) ,
222
+ input_members. clone ( ) ,
223
+ direct_dynamic,
224
+ & input_values,
225
+ & output_values,
226
+ )
227
+ . failures ( failures) ,
228
+ ) ;
229
+
230
+ tests. push (
231
+ ShaderTest :: new (
232
+ format ! ( "{ty} - vector loaded, static index" ) ,
233
+ input_members. clone ( ) ,
234
+ vector_loaded_static,
235
+ & input_values,
236
+ & output_values,
237
+ )
238
+ . failures ( failures) ,
239
+ ) ;
240
+ tests. push (
241
+ ShaderTest :: new (
242
+ format ! ( "{ty} - vector loaded, dynamic index" ) ,
243
+ input_members. clone ( ) ,
244
+ vector_loaded_dynamic,
245
+ & input_values,
246
+ & output_values,
247
+ )
248
+ . failures ( failures) ,
249
+ ) ;
250
+
251
+ tests. push (
252
+ ShaderTest :: new (
253
+ format ! ( "{ty} - fully loaded, static index" ) ,
254
+ input_members. clone ( ) ,
255
+ fully_loaded_static,
256
+ & input_values,
257
+ & output_values,
258
+ )
259
+ . failures ( failures) ,
260
+ ) ;
261
+ tests. push (
262
+ ShaderTest :: new (
263
+ format ! ( "{ty} - fully loaded, dynamic index" ) ,
264
+ input_members. clone ( ) ,
265
+ fully_loaded_dynamic,
266
+ & input_values,
267
+ & output_values,
268
+ )
269
+ . failures ( failures) ,
270
+ ) ;
271
+ }
272
+ }
273
+
274
+ // Array of matrix tests
275
+ for columns in [ 2 , 4 ] {
276
+ for rows in [ 2 , 3 , 4 ] {
277
+ let array_size = 2 ;
278
+ let ty = format ! ( "mat{columns}x{rows}<f32>" ) ;
279
+ let input_members = format ! ( "members: array<{ty}, {array_size}>" ) ;
280
+ // There's 4 possible ways to load a component of a matrix in an array:
281
+ // - Do `input.members[0][0].x` (direct)
282
+ // - Store `input.members[0][0]` in a variable; do `var.x` (vector_loaded)
283
+ // - Store `input.members[0]` in a variable; do `var[0].x` (matrix_loaded)
284
+ // - Store `input.members` in a variable; do `var[0][0].x` (fully_loaded)
285
+ // For each of these, we can either use a static or dynamic index.
286
+ let mut direct_static = String :: new ( ) ;
287
+ let mut direct_dynamic = String :: new ( ) ;
288
+ let mut vector_loaded_static = String :: new ( ) ;
289
+ let mut vector_loaded_dynamic = String :: new ( ) ;
290
+ let mut matrix_loaded_static = String :: new ( ) ;
291
+ let mut matrix_loaded_dynamic = String :: new ( ) ;
292
+ let mut fully_loaded_static = String :: from ( "let loaded = input.members;" ) ;
293
+ let mut fully_loaded_dynamic = String :: from ( "let loaded = input.members;" ) ;
294
+ let column_index_names = [ "zero" , "one" , "two" , "three" ] ;
295
+ for ( column, column_str) in column_index_names. iter ( ) . enumerate ( ) . take ( columns) {
296
+ writeln ! ( direct_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
297
+ writeln ! ( vector_loaded_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
298
+ writeln ! ( matrix_loaded_dynamic, "var {column_str} = {column};" ) . unwrap ( ) ;
299
+ }
300
+ for element in 0 ..array_size {
301
+ writeln ! (
302
+ matrix_loaded_static,
303
+ "let mat_{element} = input.members[{element}];"
304
+ )
305
+ . unwrap ( ) ;
306
+ writeln ! (
307
+ matrix_loaded_dynamic,
308
+ "let mat_{element} = input.members[{element}];"
309
+ )
310
+ . unwrap ( ) ;
311
+ for ( column, column_str) in column_index_names. iter ( ) . enumerate ( ) . take ( columns) {
312
+ writeln ! (
313
+ vector_loaded_static,
314
+ "let mat_{element}_vec_{column} = input.members[{element}][{column}];"
315
+ )
316
+ . unwrap ( ) ;
317
+ writeln ! (
318
+ vector_loaded_dynamic,
319
+ "let mat_{element}_vec_{column} = input.members[{element}][{column_str}];" ,
320
+ )
321
+ . unwrap ( ) ;
322
+ }
323
+ }
324
+
325
+ let mut output_values = Vec :: new ( ) ;
326
+
327
+ let mut current_output_idx = 0 ;
328
+ let mut current_input_idx = 0 ;
329
+ for element in 0 ..array_size {
330
+ for ( column, column_str) in column_index_names. iter ( ) . enumerate ( ) . take ( columns) {
331
+ let component_accessors = [ "x" , "y" , "z" , "w" ] . into_iter ( ) . take ( rows) ;
332
+ for component in component_accessors {
333
+ writeln ! (
334
+ direct_static,
335
+ "output[{current_output_idx}] = bitcast<u32>(input.members[{element}][{column}].{component});"
336
+ )
337
+ . unwrap ( ) ;
338
+ writeln ! (
339
+ direct_dynamic,
340
+ "output[{current_output_idx}] = bitcast<u32>(input.members[{element}][{column_str}].{component});"
341
+ )
342
+ . unwrap ( ) ;
343
+ writeln ! (
344
+ vector_loaded_static,
345
+ "output[{current_output_idx}] = bitcast<u32>(mat_{element}_vec_{column}.{component});"
346
+ )
347
+ . unwrap ( ) ;
348
+ writeln ! (
349
+ vector_loaded_dynamic,
350
+ "output[{current_output_idx}] = bitcast<u32>(mat_{element}_vec_{column}.{component});"
351
+ )
352
+ . unwrap ( ) ;
353
+ writeln ! (
354
+ matrix_loaded_static,
355
+ "output[{current_output_idx}] = bitcast<u32>(mat_{element}[{column}].{component});"
356
+ )
357
+ . unwrap ( ) ;
358
+ writeln ! (
359
+ matrix_loaded_dynamic,
360
+ "output[{current_output_idx}] = bitcast<u32>(mat_{element}[{column_str}].{component});"
361
+ )
362
+ . unwrap ( ) ;
363
+ writeln ! (
364
+ fully_loaded_static,
365
+ "output[{current_output_idx}] = bitcast<u32>(loaded[{column}].{component});"
366
+ )
367
+ . unwrap ( ) ;
368
+ writeln ! (
369
+ fully_loaded_dynamic,
370
+ "output[{current_output_idx}] = bitcast<u32>(loaded[{column_str}].{component});"
371
+ )
372
+ . unwrap ( ) ;
373
+
374
+ output_values. push ( current_input_idx) ;
375
+ current_input_idx += 1 ;
376
+ current_output_idx += 1 ;
377
+ }
378
+ // Round to next vec4 if we're matrices with vec3 columns
379
+ if rows == 3 {
380
+ current_input_idx += 1 ;
381
+ }
382
+ }
383
+ }
384
+
385
+ // https://github.com/gfx-rs/wgpu/issues/4371
386
+ let failures = if storage_type == InputStorageType :: Uniform && rows == 2 {
387
+ Backends :: GL
388
+ } else {
389
+ Backends :: empty ( )
390
+ } ;
391
+
392
+ tests. push (
393
+ ShaderTest :: new (
394
+ format ! ( "{ty} - direct, static index" ) ,
395
+ input_members. clone ( ) ,
396
+ direct_static,
397
+ & input_values,
398
+ & output_values,
399
+ )
400
+ . failures ( failures) ,
401
+ ) ;
402
+ tests. push (
403
+ ShaderTest :: new (
404
+ format ! ( "{ty} - direct, dynamic index" ) ,
405
+ input_members. clone ( ) ,
406
+ direct_dynamic,
181
407
& input_values,
182
408
& output_values,
183
409
)
@@ -186,9 +412,19 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
186
412
187
413
tests. push (
188
414
ShaderTest :: new (
189
- format ! ( "{ty} - vector loaded" ) ,
415
+ format ! ( "{ty} - vector loaded, static index " ) ,
190
416
input_members. clone ( ) ,
191
- vector_loaded,
417
+ vector_loaded_static,
418
+ & input_values,
419
+ & output_values,
420
+ )
421
+ . failures ( failures) ,
422
+ ) ;
423
+ tests. push (
424
+ ShaderTest :: new (
425
+ format ! ( "{ty} - vector loaded, dynamic index" ) ,
426
+ input_members. clone ( ) ,
427
+ vector_loaded_dynamic,
192
428
& input_values,
193
429
& output_values,
194
430
)
@@ -197,9 +433,19 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
197
433
198
434
tests. push (
199
435
ShaderTest :: new (
200
- format ! ( "{ty} - fully loaded" ) ,
436
+ format ! ( "{ty} - matrix loaded, static index" ) ,
437
+ input_members. clone ( ) ,
438
+ matrix_loaded_static,
439
+ & input_values,
440
+ & output_values,
441
+ )
442
+ . failures ( failures) ,
443
+ ) ;
444
+ tests. push (
445
+ ShaderTest :: new (
446
+ format ! ( "{ty} - matrix loaded, dynamic index" ) ,
201
447
input_members. clone ( ) ,
202
- fully_loaded ,
448
+ matrix_loaded_dynamic ,
203
449
& input_values,
204
450
& output_values,
205
451
)
0 commit comments