Skip to content

Commit 268bec2

Browse files
committed
[test] Add additional matrix struct_layout tests
Extend existing tests to use dynamic indexing of matrices' columns as well static indexing. Add new tests for arrays of matrices.
1 parent aee8cd1 commit 268bec2

File tree

1 file changed

+261
-15
lines changed

1 file changed

+261
-15
lines changed

tests/tests/wgpu-gpu/shader/struct_layout.rs

Lines changed: 261 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,35 +126,68 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
126126
// - Do `input.member[0].x` (direct)
127127
// - Store `input.member[0]` in a variable; do `var.x` (vector_loaded)
128128
// - 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();
134152
}
135153

136154
let mut output_values = Vec::new();
137155

138156
let mut current_output_idx = 0;
139157
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) {
141159
let component_accessors = ["x", "y", "z", "w"].into_iter().take(rows);
142160
for component in component_accessors {
143161
writeln!(
144-
direct,
162+
direct_static,
145163
"output[{current_output_idx}] = bitcast<u32>(input.member[{column}].{component});"
146164
)
147165
.unwrap();
148166
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,
150178
"output[{current_output_idx}] = bitcast<u32>(vec_{column}.{component});"
151179
)
152180
.unwrap();
153181
writeln!(
154-
fully_loaded,
182+
fully_loaded_static,
155183
"output[{current_output_idx}] = bitcast<u32>(loaded[{column}].{component});"
156184
)
157185
.unwrap();
186+
writeln!(
187+
fully_loaded_dynamic,
188+
"output[{current_output_idx}] = bitcast<u32>(loaded[{column_str}].{component});"
189+
)
190+
.unwrap();
158191

159192
output_values.push(current_input_idx);
160193
current_input_idx += 1;
@@ -175,9 +208,202 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
175208

176209
tests.push(
177210
ShaderTest::new(
178-
format!("{ty} - direct"),
211+
format!("{ty} - direct, static index"),
179212
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,
181407
&input_values,
182408
&output_values,
183409
)
@@ -186,9 +412,19 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
186412

187413
tests.push(
188414
ShaderTest::new(
189-
format!("{ty} - vector loaded"),
415+
format!("{ty} - vector loaded, static index"),
190416
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,
192428
&input_values,
193429
&output_values,
194430
)
@@ -197,9 +433,19 @@ fn create_struct_layout_tests(storage_type: InputStorageType) -> Vec<ShaderTest>
197433

198434
tests.push(
199435
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"),
201447
input_members.clone(),
202-
fully_loaded,
448+
matrix_loaded_dynamic,
203449
&input_values,
204450
&output_values,
205451
)

0 commit comments

Comments
 (0)