Skip to content

Commit

Permalink
Ignore empty bind group layout when checking setBindGroup against the…
Browse files Browse the repository at this point in the history
… pipeline (#4134)

This patch fixes the tests about checking setBindGroup() against the pipeline with
empty bind group layout item. According to the latest WebGPU SPEC, the empty bind
group layout item should all be ignored when doing such check.
  • Loading branch information
Jiawei-Shao authored Jan 13, 2025
1 parent 3dd1fec commit 3d039b4
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -830,25 +830,37 @@ g.test('bgl_resource_type_mismatch')
);
});

g.test('empty_bind_group_layouts_requires_empty_bind_groups,compute_pass')
g.test('empty_bind_group_layouts_never_requires_empty_bind_groups,compute_pass')
.desc(
`
Test that a compute pipeline with empty bind groups layouts requires empty bind groups to be set.
Test that a compute pipeline with empty bind group layouts doesn't require empty bind groups to be
set as empty bind group layout items should always be ignored.
`
)
.params(u =>
u
.combine('emptyBindGroupLayoutType', ['Null', 'Undefined', 'Empty'] as const)
.combine('bindGroupLayoutEntryCount', [3, 4])
.combine('computeCommand', ['dispatchIndirect', 'dispatch'] as const)
)
.fn(t => {
const { bindGroupLayoutEntryCount, computeCommand } = t.params;
const { emptyBindGroupLayoutType, bindGroupLayoutEntryCount, computeCommand } = t.params;

const emptyBGLCount = 4;
const emptyBGL = t.device.createBindGroupLayout({ entries: [] });
const emptyBGLs = [];
for (let i = 0; i < emptyBGLCount; i++) {
emptyBGLs.push(emptyBGL);
switch (emptyBindGroupLayoutType) {
case 'Null':
emptyBGLs.push(null);
break;
case 'Undefined':
emptyBGLs.push(undefined);
break;
case 'Empty':
emptyBGLs.push(emptyBGL);
break;
}
}

const pipelineLayout = t.device.createPipelineLayout({
Expand Down Expand Up @@ -880,21 +892,23 @@ g.test('empty_bind_group_layouts_requires_empty_bind_groups,compute_pass')
t.doCompute(computePass, computeCommand, true);
computePass.end();

const success = bindGroupLayoutEntryCount === emptyBGLCount;
const success = true;

t.expectValidationError(() => {
encoder.finish();
}, !success);
});

g.test('empty_bind_group_layouts_requires_empty_bind_groups,render_pass')
g.test('empty_bind_group_layouts_never_requires_empty_bind_groups,render_pass')
.desc(
`
Test that a render pipeline with empty bind groups layouts requires empty bind groups to be set.
Test that a render pipeline with empty bind groups layouts doesn't require empty bind groups to be
set as empty bind group layout items should always be ignored.
`
)
.params(u =>
u
.combine('emptyBindGroupLayoutType', ['Null', 'Undefined', 'Empty'] as const)
.combine('bindGroupLayoutEntryCount', [3, 4])
.combine('renderCommand', [
'draw',
Expand All @@ -904,13 +918,23 @@ g.test('empty_bind_group_layouts_requires_empty_bind_groups,render_pass')
] as const)
)
.fn(t => {
const { bindGroupLayoutEntryCount, renderCommand } = t.params;
const { emptyBindGroupLayoutType, bindGroupLayoutEntryCount, renderCommand } = t.params;

const emptyBGLCount = 4;
const emptyBGL = t.device.createBindGroupLayout({ entries: [] });
const emptyBGLs = [];
for (let i = 0; i < emptyBGLCount; i++) {
emptyBGLs.push(emptyBGL);
switch (emptyBindGroupLayoutType) {
case 'Null':
emptyBGLs.push(null);
break;
case 'Undefined':
emptyBGLs.push(undefined);
break;
case 'Empty':
emptyBGLs.push(emptyBGL);
break;
}
}

const pipelineLayout = t.device.createPipelineLayout({
Expand Down Expand Up @@ -966,7 +990,7 @@ g.test('empty_bind_group_layouts_requires_empty_bind_groups,render_pass')
t.doRender(renderPass, renderCommand, true);
renderPass.end();

const success = bindGroupLayoutEntryCount === emptyBGLCount;
const success = true;

t.expectValidationError(() => {
encoder.finish();
Expand Down Expand Up @@ -997,11 +1021,17 @@ const kPipelineTypesAndBindingTypeParams = [
g.test('default_bind_group_layouts_never_match,compute_pass')
.desc(
`
Test that bind groups created with default bind group layouts never match other layouts, including empty bind groups.
* Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto layout
* Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit layout
* Test that an auto layout from one pipeline can not be used with an auto layout from a different pipeline.
Test that bind groups created with default bind group layouts never match other layouts, except
when the default bind group layouts are empty because the empty bind group layouts should all be
treated as null bind group layouts and be ignored when checking setBindGroup() against the current
pipeline.
* Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto
layout except the explicit layout is empty.
* Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit
layout except the layout got from the pipeline is empty.
* Test that an auto layout from one pipeline can not be used with an auto layout from a different
pipeline except the layouts got from the pipeline are empty.
* Test matching bindgroup layouts on the same default layout pipeline are compatible. In other words if
you only define group(2) then group(0)'s empty layout and group(1)'s empty layout should be compatible.
Similarly if group(2) and group(3) have the same types of resources they should be compatible.
Expand All @@ -1014,7 +1044,16 @@ g.test('default_bind_group_layouts_never_match,compute_pass')
.combine('computeCommand', ['dispatchIndirect', 'dispatch'] as const)
)
.fn(t => {
const { pipelineType, bindingType, swap, _success: success, computeCommand, empty } = t.params;
const {
pipelineType,
bindingType,
swap,
_success: successWhenNonEmpty,
computeCommand,
empty,
} = t.params;

const success = empty || successWhenNonEmpty;

t.runDefaultLayoutBindingTest<GPUComputePipeline>({
visibility: GPUShaderStage.COMPUTE,
Expand Down Expand Up @@ -1056,11 +1095,17 @@ g.test('default_bind_group_layouts_never_match,compute_pass')
g.test('default_bind_group_layouts_never_match,render_pass')
.desc(
`
Test that bind groups created with default bind group layouts never match other layouts, including empty bind groups.
* Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto layout
* Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit layout
* Test that an auto layout from one pipeline can not be used with an auto layout from a different pipeline.
Test that bind groups created with default bind group layouts never match other layouts, except
when the default bind group layouts are empty because the empty bind group layouts should all be
treated as null bind group layouts and be ignored when checking setBindGroup() against the current
pipeline.
* Test that a pipeline with an explicit layout can not be used with a bindGroup from an auto
layout except the explicit layout is empty.
* Test that a pipeline with an auto layout can not be used with a bindGroup from an explicit
layout except the layout got from the pipeline is empty.
* Test that an auto layout from one pipeline can not be used with an auto layout from a different
pipeline except the layouts got from the pipeline are empty.
* Test matching bindgroup layouts on the same default layout pipeline are compatible. In other words if
you only define group(2) then group(0)'s empty layout and group(1)'s empty layout should be compatible.
Similarly if group(2) and group(3) have the same types of resources they should be compatible.
Expand All @@ -1078,7 +1123,16 @@ g.test('default_bind_group_layouts_never_match,render_pass')
] as const)
)
.fn(t => {
const { pipelineType, bindingType, swap, _success: success, renderCommand, empty } = t.params;
const {
pipelineType,
bindingType,
swap,
_success: successWhenNonEmpty,
renderCommand,
empty,
} = t.params;

const success = empty || successWhenNonEmpty;

t.runDefaultLayoutBindingTest<GPURenderPipeline>({
visibility: GPUShaderStage.VERTEX,
Expand Down
4 changes: 2 additions & 2 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,8 @@
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:buffer_binding,render_pipeline:*": { "subcaseMS": 1.734 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:default_bind_group_layouts_never_match,compute_pass:*": { "subcaseMS": 1.734 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:default_bind_group_layouts_never_match,render_pass:*": { "subcaseMS": 1.734 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,compute_pass:*": { "subcaseMS": 2.325 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,render_pass:*": { "subcaseMS": 10.838 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_never_requires_empty_bind_groups,compute_pass:*": { "subcaseMS": 2.325 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_never_requires_empty_bind_groups,render_pass:*": { "subcaseMS": 10.838 },
"webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:sampler_binding,render_pipeline:*": { "subcaseMS": 10.523 },
"webgpu:api,validation,encoding,queries,begin_end:nesting:*": { "subcaseMS": 1.101 },
"webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_balance:*": { "subcaseMS": 0.820 },
Expand Down

0 comments on commit 3d039b4

Please sign in to comment.