Skip to content

Commit 249807a

Browse files
authored
Add validation tests for statement behavior analysis (#3506)
1 parent 10e77ea commit 249807a

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/webgpu/listing_meta.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,6 +2119,10 @@
21192119
"webgpu:shader,validation,parse,source:empty:*": { "subcaseMS": 1.101 },
21202120
"webgpu:shader,validation,parse,source:invalid_source:*": { "subcaseMS": 1.100 },
21212121
"webgpu:shader,validation,parse,source:valid_source:*": { "subcaseMS": 1.101 },
2122+
"webgpu:shader,validation,parse,statement_behavior:invalid_functions:*": { "subcaseMS": 1.107 },
2123+
"webgpu:shader,validation,parse,statement_behavior:invalid_statements:*": { "subcaseMS": 80.699 },
2124+
"webgpu:shader,validation,parse,statement_behavior:valid_functions:*": { "subcaseMS": 0.978 },
2125+
"webgpu:shader,validation,parse,statement_behavior:valid_statements:*": { "subcaseMS": 15.781 },
21222126
"webgpu:shader,validation,parse,unary_ops:all:*": { "subcaseMS": 1.000 },
21232127
"webgpu:shader,validation,parse,var_and_let:initializer_type:*": { "subcaseMS": 0.900 },
21242128
"webgpu:shader,validation,parse,var_and_let:var_access_mode_bad_other_template_contents:*": { "subcaseMS": 4.071 },
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
export const description = `
2+
Test statement behavior analysis.
3+
4+
Functions must have a behavior of {Return}, {Next}, or {Return, Next}.
5+
Functions with a return type must have a behavior of {Return}.
6+
7+
Each statement in the function must be valid according to the table.
8+
`;
9+
10+
import { makeTestGroup } from '../../../../common/framework/test_group.js';
11+
import { keysOf } from '../../../../common/util/data_tables.js';
12+
import { ShaderValidationTest } from '../shader_validation_test.js';
13+
14+
export const g = makeTestGroup(ShaderValidationTest);
15+
16+
const kInvalidStatements = {
17+
break: `break`,
18+
break_if: `break if true`,
19+
continue: `continue`,
20+
loop1: `loop { }`,
21+
loop2: `loop { continuing { } }`,
22+
loop3: `loop { continue; continuing { } }`,
23+
loop4: `loop { continuing { break; } }`,
24+
loop5: `loop { continuing { continue; } }`,
25+
loop6: `loop { continuing { return; } }`,
26+
loop7: `loop { continue; break; }`,
27+
loop8: `loop { continuing { break if true; return; } }`,
28+
for1: `for (;;) { }`,
29+
for2: `for (var i = 0; ; i++) { }`,
30+
for3: `for (;; break) { }`,
31+
for4: `for (;; continue ) { }`,
32+
for5: `for (;; return ) { }`,
33+
for6: `for (;;) { continue; break; }`,
34+
// while loops always have break in their behaviors.
35+
switch1: `switch (1) { case 1 { } }`,
36+
sequence1: `return; loop { }`,
37+
compound1: `{ loop { } }`,
38+
};
39+
40+
g.test('invalid_statements')
41+
.desc('Test statements with invalid behaviors')
42+
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules')
43+
.params(u => u.combine('body', keysOf(kInvalidStatements)))
44+
.fn(t => {
45+
const body = kInvalidStatements[t.params.body];
46+
const code = `fn foo() {
47+
${body};
48+
}`;
49+
t.expectCompileResult(false, code);
50+
});
51+
52+
const kValidStatements = {
53+
empty: ``,
54+
const_assert: `const_assert true`,
55+
let: `let x = 1`,
56+
var1: `var x = 1`,
57+
var2: `var x : i32`,
58+
assign: `v = 1`,
59+
phony_assign: `_ = 1`,
60+
compound_assign: `v += 1`,
61+
return: `return`,
62+
discard: `discard`,
63+
function_call1: `bar()`,
64+
function_call2: `workgroupBarrier()`,
65+
66+
if1: `if true { } else { }`,
67+
if2: `if true { }`,
68+
69+
break1: `loop { break; }`,
70+
break2: `loop { if false { break; } }`,
71+
break_if: `loop { continuing { break if false; } }`,
72+
73+
continue1: `loop { continue; continuing { break if true; } }`,
74+
75+
loop1: `loop { break; }`,
76+
loop2: `loop { break; continuing { } }`,
77+
loop3: `loop { continue; continuing { break if true; } }`,
78+
loop4: `loop { break; continue; }`,
79+
80+
for1: `for (; true; ) { }`,
81+
for2: `for (;;) { break; }`,
82+
for3: `for (;true;) { continue; }`,
83+
84+
while1: `while true { }`,
85+
while2: `while true { continue; }`,
86+
while3: `while true { continue; break; }`,
87+
88+
switch1: `switch 1 { default { } }`,
89+
swtich2: `switch 1 { case 1 { } default { } }`,
90+
switch3: `switch 1 { default { break; } }`,
91+
switch4: `switch 1 { default { } case 1 { break; } }`,
92+
93+
sequence1: `return; let x = 1`,
94+
sequence2: `if true { } let x = 1`,
95+
sequence3: `switch 1 { default { break; return; } }`,
96+
97+
compound1: `{ }`,
98+
compound2: `{ loop { break; } if true { return; } }`,
99+
};
100+
101+
g.test('valid_statements')
102+
.desc('Test statements with valid behaviors')
103+
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules')
104+
.params(u => u.combine('body', keysOf(kValidStatements)))
105+
.fn(t => {
106+
const body = kValidStatements[t.params.body];
107+
const code = `
108+
var<private> v : i32;
109+
fn bar() { }
110+
fn foo() {
111+
${body};
112+
}`;
113+
t.expectCompileResult(true, code);
114+
});
115+
116+
const kInvalidFunctions = {
117+
next_for_type: `fn foo() -> bool { }`,
118+
next_return_for_type: `fn foo() -> bool { if true { return true; } }`,
119+
};
120+
121+
g.test('invalid_functions')
122+
.desc('Test functions with invalid behaviors')
123+
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules')
124+
.params(u => u.combine('function', keysOf(kInvalidFunctions)))
125+
.fn(t => {
126+
const func = kInvalidFunctions[t.params.function];
127+
t.expectCompileResult(false, func);
128+
});
129+
130+
const kValidFunctions = {
131+
empty: `fn foo() { }`,
132+
next_return: `fn foo() { if true { return; } }`,
133+
no_final_return: `fn foo() -> bool { if true { return true; } else { return false; } }`,
134+
};
135+
136+
g.test('valid_functions')
137+
.desc('Test functions with valid behaviors')
138+
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules')
139+
.params(u => u.combine('function', keysOf(kValidFunctions)))
140+
.fn(t => {
141+
const func = kValidFunctions[t.params.function];
142+
t.expectCompileResult(true, func);
143+
});

0 commit comments

Comments
 (0)