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 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(async 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])); });