Skip to content

Commit

Permalink
Validation tests for early eval errors in subgroup builtins (#4065)
Browse files Browse the repository at this point in the history
* subgroupBroadcast and quadBroadcast id must be in range [0, 128)
* subgroupShuffleUp, subgroupShuffleDown, subgroupShuffleXor mask/delta
  must be less than 128 for const/override
* Add negative value test for subgroupShuffle
  • Loading branch information
alan-baker authored Nov 29, 2024
1 parent fe65191 commit ecb8816
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, number> = {};
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))
Expand Down

0 comments on commit ecb8816

Please sign in to comment.