Skip to content

Commit

Permalink
Test creating pipeline with pipeline layout created with null bind gr… (
Browse files Browse the repository at this point in the history
gpuweb#4110)

* Test creating pipeline with pipeline layout created with null bind group layout

* Address reviewer's comments
  • Loading branch information
Jiawei-Shao authored Dec 19, 2024
1 parent 8be4ce7 commit 321b94d
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 additions & 0 deletions src/webgpu/api/validation/createPipelineLayout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,127 @@ g.test('bind_group_layouts,null_bind_group_layouts')
t.device.createPipelineLayout({ bindGroupLayouts });
}, kShouldError);
});

g.test('bind_group_layouts,create_pipeline_with_null_bind_group_layouts')
.desc(
`
Tests that it is valid to create a render pipeline or compute pipeline with a pipeline layout
created with null bind group layouts as long as the pipeline layout matches the declarations in
the shaders.
`
)
.params(u =>
u
.combine('pipelineType', ['Render', 'Compute'] as const)
.combine('emptyBindGroupLayoutType', ['Null', 'Undefined'] as const)
.combine('emptyBindGroupLayoutIndex', [0, 1, 2, 3] as const)
.combine('emptyBindGroupLayoutIndexMissedInShader', [true, false])
)
.fn(t => {
const {
pipelineType,
emptyBindGroupLayoutType,
emptyBindGroupLayoutIndex,
emptyBindGroupLayoutIndexMissedInShader,
} = t.params;

const bindGroupLayouts: (GPUBindGroupLayout | null | undefined)[] = [];
for (let i = 0; i < 4; ++i) {
if (i === emptyBindGroupLayoutIndex) {
switch (emptyBindGroupLayoutType) {
case 'Null':
bindGroupLayouts.push(null);
break;
case 'Undefined':
bindGroupLayouts.push(undefined);
break;
}
} else {
const nonEmptyBindGroupLayout = t.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUConst.ShaderStage.COMPUTE | GPUConst.ShaderStage.FRAGMENT,
buffer: {
type: 'uniform',
},
},
],
});
bindGroupLayouts.push(nonEmptyBindGroupLayout);
}
}
const layout = t.device.createPipelineLayout({ bindGroupLayouts });

let declarations = '';
let statement = '_ = 1';
for (let i = 0; i < 4; ++i) {
if (emptyBindGroupLayoutIndexMissedInShader && i === emptyBindGroupLayoutIndex) {
continue;
}
declarations += `@group(${i}) @binding(0) var<uniform> input${i} : u32;\n`;
statement += ` + input${i}`;
}

const shouldError = !emptyBindGroupLayoutIndexMissedInShader;

switch (pipelineType) {
case 'Render': {
const code = `
${declarations}
@vertex
fn vert_main() -> @builtin(position) vec4f {
return vec4f(0.0, 0.0, 0.0, 1.0);
}
@fragment
fn frag_main() -> @location(0) vec4f {
${statement};
return vec4f(0.0, 0.0, 0.0, 1.0);
}
`;
const shaderModule = t.device.createShaderModule({
code,
});

t.expectValidationError(() => {
t.device.createRenderPipeline({
layout,
vertex: {
module: shaderModule,
},
fragment: {
module: shaderModule,
targets: [
{
format: 'rgba8unorm',
},
],
},
});
}, shouldError);
break;
}

case 'Compute': {
const code = `
${declarations}
@compute @workgroup_size(1) fn cs_main() {
${statement};
}
`;
const shaderModule = t.device.createShaderModule({
code,
});
t.expectValidationError(() => {
t.device.createComputePipeline({
layout,
compute: {
module: shaderModule,
},
});
}, shouldError);
break;
}
}
});

0 comments on commit 321b94d

Please sign in to comment.