diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index fb5e451b32a0..acce2b1e2465 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -2278,6 +2278,7 @@ "webgpu:shader,validation,expression,call,builtin,quadBroadcast:early_eval:*": { "subcaseMS": 63.825 }, "webgpu:shader,validation,expression,call,builtin,quadBroadcast:id_constness:*": { "subcaseMS": 15.347 }, "webgpu:shader,validation,expression,call,builtin,quadBroadcast:id_type:*": { "subcaseMS": 26.268 }, + "webgpu:shader,validation,expression,call,builtin,quadBroadcast:id_values:*": { "subcaseMS": 7.315 }, "webgpu:shader,validation,expression,call,builtin,quadBroadcast:must_use:*": { "subcaseMS": 41.658 }, "webgpu:shader,validation,expression,call,builtin,quadBroadcast:requires_subgroups:*": { "subcaseMS": 42.565 }, "webgpu:shader,validation,expression,call,builtin,quadBroadcast:requires_subgroups_f16:*": { "subcaseMS": 44.998 }, @@ -2370,6 +2371,7 @@ "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:early_eval:*": { "subcaseMS": 1.254 }, "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:id_constness:*": { "subcaseMS": 7.026 }, "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:id_type:*": { "subcaseMS": 24.703 }, + "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:id_values:*": { "subcaseMS": 7.763 }, "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:must_use:*": { "subcaseMS": 232.030 }, "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:requires_subgroups:*": { "subcaseMS": 47.231 }, "webgpu:shader,validation,expression,call,builtin,subgroupBroadcast:requires_subgroups_f16:*": { "subcaseMS": 38.503 }, @@ -2404,6 +2406,7 @@ "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:data_type:*": { "subcaseMS": 115.093 }, "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:early_eval:*": { "subcaseMS": 110.489 }, "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:must_use:*": { "subcaseMS": 7.628 }, + "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:param2_early_eval:*": { "subcaseMS": 133.389 }, "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:param2_type:*": { "subcaseMS": 88.305 }, "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:requires_subgroups:*": { "subcaseMS": 102.779 }, "webgpu:shader,validation,expression,call,builtin,subgroupShuffle:requires_subgroups_f16:*": { "subcaseMS": 13.121 }, diff --git a/src/webgpu/shader/validation/expression/call/builtin/quadBroadcast.spec.ts b/src/webgpu/shader/validation/expression/call/builtin/quadBroadcast.spec.ts index 6988f17b9ede..f96d46aad7d7 100644 --- a/src/webgpu/shader/validation/expression/call/builtin/quadBroadcast.spec.ts +++ b/src/webgpu/shader/validation/expression/call/builtin/quadBroadcast.spec.ts @@ -246,6 +246,38 @@ fn foo() { t.expectCompileResult(kIdCases[t.params.value].valid, wgsl); }); +g.test('id_values') + .desc('Validates that id must be in the range [0, 4)') + .params(u => + u + .combine('value', [-1, 0, 3, 4] as const) + .beginSubcases() + .combine('type', ['literal', 'const', 'expr'] as const) + ) + .beforeAllSubcases(t => { + t.selectDeviceOrSkipTestCase('subgroups' as GPUFeatureName); + }) + .fn(t => { + let arg = `${t.params.value}`; + if (t.params.type === 'const') { + arg = `c`; + } else if (t.params.type === 'expr') { + arg = `c + 0`; + } + + const wgsl = ` +enable subgroups; + +const c = ${t.params.value}; + +fn foo() { + _ = quadBroadcast(0, ${arg}); +}`; + + const expect = t.params.value >= 0 && t.params.value < 4; + t.expectCompileResult(expect, wgsl); + }); + g.test('stage') .desc('Validates it is only usable in correct stage') .params(u => u.combine('stage', ['compute', 'fragment', 'vertex'] as const)) diff --git a/src/webgpu/shader/validation/expression/call/builtin/subgroupBroadcast.spec.ts b/src/webgpu/shader/validation/expression/call/builtin/subgroupBroadcast.spec.ts index fd76cd419b7f..33e5fd8622af 100644 --- a/src/webgpu/shader/validation/expression/call/builtin/subgroupBroadcast.spec.ts +++ b/src/webgpu/shader/validation/expression/call/builtin/subgroupBroadcast.spec.ts @@ -246,6 +246,38 @@ fn foo() { t.expectCompileResult(kIdCases[t.params.value].valid, wgsl); }); +g.test('id_values') + .desc('Validates that id must be in the range [0, 128)') + .params(u => + u + .combine('value', [-1, 0, 127, 128] as const) + .beginSubcases() + .combine('type', ['literal', 'const', 'expr'] as const) + ) + .beforeAllSubcases(t => { + t.selectDeviceOrSkipTestCase('subgroups' as GPUFeatureName); + }) + .fn(t => { + let arg = `${t.params.value}`; + if (t.params.type === 'const') { + arg = `c`; + } else if (t.params.type === 'expr') { + arg = `c + 0`; + } + + const wgsl = ` +enable subgroups; + +const c = ${t.params.value}; + +fn foo() { + _ = subgroupBroadcast(0, ${arg}); +}`; + + const expect = t.params.value >= 0 && t.params.value < 128; + t.expectCompileResult(expect, wgsl); + }); + g.test('stage') .desc('Validates it is only usable in correct stage') .params(u => u.combine('stage', ['compute', 'fragment', 'vertex'] as const)) diff --git a/src/webgpu/shader/validation/expression/call/builtin/subgroupShuffle.spec.ts b/src/webgpu/shader/validation/expression/call/builtin/subgroupShuffle.spec.ts index 62ffb5af36dd..b46f90c545b4 100644 --- a/src/webgpu/shader/validation/expression/call/builtin/subgroupShuffle.spec.ts +++ b/src/webgpu/shader/validation/expression/call/builtin/subgroupShuffle.spec.ts @@ -94,6 +94,60 @@ g.test('early_eval') t.expectCompileResult(t.params.stage === 'runtime', code); }); +g.test('param2_early_eval') + .desc('Ensures id/delta/mask parameters must be in the range [0, 128) for const and override') + .params(u => + u + .combine('op', kOps) + .combine('value', [-1, 0, 127, 128] as const) + .filter(t => { + // Only subgroupShuffle supports an i32 parameter. + return t.op === 'subgroupShuffle' || t.value !== -1; + }) + .beginSubcases() + .combine('stage', ['constant', 'override', 'runtime'] as const) + ) + .beforeAllSubcases(t => { + t.selectDeviceOrSkipTestCase('subgroups' as GPUFeatureName); + }) + .fn(t => { + let arg = `const_param`; + if (t.params.stage === 'override') { + arg = `override_param`; + } else if (t.params.stage === 'runtime') { + arg = `let_param`; + } + + const type = t.params.value === -1 ? `i32` : `u32`; + + const wgsl = ` +enable subgroups; + +const const_param : ${type} = ${t.params.value}; +override override_param : ${type} = 0; + +fn foo() { + let let_param : ${type} = ${t.params.value}; + _ = ${t.params.op}(0, ${arg}); +}`; + + const value_ok = t.params.value >= 0 && t.params.value < 128; + const compile_expect = value_ok || t.params.stage !== 'constant'; + const pipeline_expect = value_ok || t.params.stage !== 'override'; + t.expectCompileResult(compile_expect, wgsl); + if (compile_expect) { + const constants: Record = {}; + constants['override_param'] = t.params.value; + t.expectPipelineResult({ + expectedResult: pipeline_expect, + code: wgsl, + constants, + reference: [], + statements: ['foo();'], + }); + } + }); + g.test('must_use') .desc('Tests that the builtin has the @must_use attribute') .params(u => u.combine('must_use', [true, false] as const).combine('op', kOps))