Source code
Revision control
Copy as Markdown
Other Tools
export const description = `
Stress tests covering behavior around shader entry points.
`;
import { makeTestGroup } from '../../common/framework/test_group.js';
import { range } from '../../common/util/util.js';
import { GPUTest } from '../../webgpu/gpu_test.js';
export const g = makeTestGroup(GPUTest);
const makeCode = (numEntryPoints: number) => {
const kBaseCode = `
struct Buffer { data: u32, };
@group(0) @binding(0) var<storage, read_write> buffer: Buffer;
fn main() { buffer.data = buffer.data + 1u; }
`;
const makeEntryPoint = (i: number) => `
@compute @workgroup_size(1) fn computeMain${i}() { main(); }
`;
return kBaseCode + range(numEntryPoints, makeEntryPoint).join('');
};
g.test('many')
.desc(
`Tests compilation and usage of shaders with a huge number of entry points.
TODO: There may be a normative limit to the number of entry points allowed in
a shader, in which case this would become a validation test instead.`
)
.fn(t => {
const data = new Uint32Array([0]);
const buffer = t.makeBufferWithContents(data, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC);
// NOTE: Initial shader compilation time seems to scale exponentially with
// this value in Chrome.
const kNumEntryPoints = 200;
const shader = t.device.createShaderModule({
code: makeCode(kNumEntryPoints),
});
const layout = t.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.COMPUTE,
buffer: { type: 'storage' },
},
],
});
const pipelineLayout = t.device.createPipelineLayout({
bindGroupLayouts: [layout],
});
const bindGroup = t.device.createBindGroup({
layout,
entries: [{ binding: 0, resource: { buffer } }],
});
const encoder = t.device.createCommandEncoder();
range(kNumEntryPoints, i => {
const pipeline = t.device.createComputePipeline({
layout: pipelineLayout,
compute: {
module: shader,
entryPoint: `computeMain${i}`,
},
});
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(1);
pass.end();
});
t.device.queue.submit([encoder.finish()]);
t.expectGPUBufferValuesEqual(buffer, new Uint32Array([kNumEntryPoints]));
});