From 25959c16d150ac89b6bc81bca827e3e043f454f7 Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Wed, 24 Jan 2024 15:52:04 -0500 Subject: [PATCH] Add `continuing` validation tests. (#3314) This CL adds validation tests for the `continuing` block. --- src/webgpu/listing_meta.json | 1 + .../validation/parse/continuing.spec.ts | 185 ++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 src/webgpu/shader/validation/parse/continuing.spec.ts diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index 01aa3713db32..3f6ce7cd6f24 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -2102,6 +2102,7 @@ "webgpu:shader,execution,expression,call,builtin,bitcast:ai_to_f32:*": { "subcaseMS": 0 }, "webgpu:shader,execution,expression,call,builtin,bitcast:ai_to_vec2f16:*": { "subcaseMS": 0 }, "webgpu:shader,execution,expression,call,builtin,bitcast:vec2ai_to_vec4f16:*": { "subcaseMS": 0 }, + "webgpu:shader,validation,parse,continuing:placement:*": { "subcaseMS": 0 }, "webgpu:shader,validation,parse,break_if:placement:*": { "subcaseMS": 0 }, "webgpu:shader,validation,parse,break_if:non_bool_param:*": { "subcaseMS": 0 }, "webgpu:shader,validation,expression,call,builtin,arrayLength:bool_type:*": { "subcaseMS": 0 }, diff --git a/src/webgpu/shader/validation/parse/continuing.spec.ts b/src/webgpu/shader/validation/parse/continuing.spec.ts new file mode 100644 index 000000000000..7b53e4eab81a --- /dev/null +++ b/src/webgpu/shader/validation/parse/continuing.spec.ts @@ -0,0 +1,185 @@ +export const description = `Validation tests for continuing`; + +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { keysOf } from '../../../../common/util/data_tables.js'; +import { ShaderValidationTest } from '../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +const kTests = { + continuing_break_if: { + src: 'loop { continuing { break if true; } }', + pass: true, + }, + continuing_empty: { + src: 'loop { if a == 4 { break; } continuing { } }', + pass: true, + }, + continuing_break_if_parens: { + src: 'loop { continuing { break if (true); } }', + pass: true, + }, + continuing_discard: { + src: 'loop { if a == 4 { break; } continuing { discard; } }', + pass: true, + }, + continuing_continue_nested: { + src: 'loop { if a == 4 { break; } continuing { loop { if a == 4 { break; } continue; } } }', + pass: true, + }, + continuing_continue: { + src: 'loop { if a == 4 { break; } continuing { continue; } }', + pass: false, + }, + continuing_break: { + src: 'loop { continuing { break; } }', + pass: false, + }, + continuing_for: { + src: 'loop { if a == 4 { break; } continuing { for(;a < 4;) { } } }', + pass: true, + }, + continuing_for_break: { + src: 'loop { if a == 4 { break; } continuing { for(;;) { break; } } }', + pass: true, + }, + continuing_while: { + src: 'loop { if a == 4 { break; } continuing { while a < 4 { } } }', + pass: true, + }, + continuing_while_break: { + src: 'loop { if a == 4 { break; } continuing { while true { break; } } }', + pass: true, + }, + continuing_semicolon: { + src: 'loop { if a == 4 { break; } continuing { ; } }', + pass: true, + }, + continuing_functionn_call: { + src: 'loop { if a == 4 { break; } continuing { _ = b(); } }', + pass: true, + }, + continuing_let: { + src: 'loop { if a == 4 { break; } continuing { let c = b(); } }', + pass: true, + }, + continuing_var: { + src: 'loop { if a == 4 { break; } continuing { var a = b(); } }', + pass: true, + }, + continuing_const: { + src: 'loop { if a == 4 { break; } continuing { const a = 1; } }', + pass: true, + }, + continuing_block: { + src: 'loop { if a == 4 { break; } continuing { { } } }', + pass: true, + }, + continuing_const_assert: { + src: 'loop { if a == 4 { break; } continuing { const_assert(1 != 2); } }', + pass: true, + }, + continuing_loop: { + src: 'loop { if a == 4 { break; } continuing { loop { break; } } }', + pass: true, + }, + continuing_if: { + src: 'loop { if a == 4 { break; } continuing { if true { } else if false { } else { } } }', + pass: true, + }, + continuing_switch: { + src: 'loop { if a == 4 { break; } continuing { switch 2 { default: { } } } }', + pass: true, + }, + continuing_switch_break: { + src: 'loop { if a == 4 { break; } continuing { switch 2 { default: { break; } } } }', + pass: true, + }, + continuing_loop_nested_continuing: { + src: 'loop { if a == 4 { break; } continuing { loop { if a == 4 { break; } continuing { } } } }', + pass: true, + }, + continuing_inc: { + src: 'loop { if a == 4 { break; } continuing { a += 1; } }', + pass: true, + }, + continuing_dec: { + src: 'loop { if a == 4 { break; } continuing { a -= 1; } }', + pass: true, + }, + while: { + src: 'while a < 4 { continuing { break if true; } }', + pass: false, + }, + for: { + src: 'for (;a < 4;) { continuing { break if true; } }', + pass: false, + }, + switch_case: { + src: 'switch(1) { default: { continuing { break if true; } } }', + pass: false, + }, + switch: { + src: 'switch(1) { continuing { break if true; } }', + pass: false, + }, + continuing: { + src: 'continuing { break if true; }', + pass: false, + }, + return: { + src: 'return continuing { break if true; }', + pass: false, + }, + if_body: { + src: 'if true { continuing { break if true; } }', + pass: false, + }, + if: { + src: 'if true { } continuing { break if true; } }', + pass: false, + }, + if_else: { + src: 'if true { } else { } continuing { break if true; } }', + pass: false, + }, + continuing_continuing: { + src: 'loop { if a == 4 { break; } continuing { continuing { break if true; } } }', + pass: false, + }, + no_body: { + src: 'loop { if a == 4 { break; } continuing }', + pass: false, + }, + return_in_continue: { + src: 'loop { if a == 4 { break; } continuing { return vec4f(2); } }', + pass: false, + }, + return_if_nested_in_continue: { + src: 'loop { if a == 4 { break; } continuing { if true { return vec4f(2); } } }', + pass: false, + }, + return_for_nested_in_continue: { + src: 'loop { if a == 4 { break; } continuing { for(;a < 4;) { return vec4f(2); } } }', + pass: false, + }, +}; + +g.test('placement') + .desc('Test that continuing placement is validated correctly') + .params(u => u.combine('stmt', keysOf(kTests))) + .fn(t => { + const code = ` +fn b() -> i32 { + return 1; +} + +@fragment +fn frag() -> @location(0) vec4f { + var a = 0; + ${kTests[t.params.stmt].src} + return vec4f(1); +} + `; + t.expectCompileResult(kTests[t.params.stmt].pass, code); + });