entry_points.spec.ts (2422B)
1 export const description = ` 2 Stress tests covering behavior around shader entry points. 3 `; 4 5 import { makeTestGroup } from '../../common/framework/test_group.js'; 6 import { range } from '../../common/util/util.js'; 7 import { GPUTest } from '../../webgpu/gpu_test.js'; 8 9 export const g = makeTestGroup(GPUTest); 10 11 const makeCode = (numEntryPoints: number) => { 12 const kBaseCode = ` 13 struct Buffer { data: u32, }; 14 @group(0) @binding(0) var<storage, read_write> buffer: Buffer; 15 fn main() { buffer.data = buffer.data + 1u; } 16 `; 17 const makeEntryPoint = (i: number) => ` 18 @compute @workgroup_size(1) fn computeMain${i}() { main(); } 19 `; 20 return kBaseCode + range(numEntryPoints, makeEntryPoint).join(''); 21 }; 22 23 g.test('many') 24 .desc( 25 `Tests compilation and usage of shaders with a huge number of entry points. 26 27 TODO: There may be a normative limit to the number of entry points allowed in 28 a shader, in which case this would become a validation test instead.` 29 ) 30 .fn(t => { 31 const data = new Uint32Array([0]); 32 const buffer = t.makeBufferWithContents(data, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC); 33 34 // NOTE: Initial shader compilation time seems to scale exponentially with 35 // this value in Chrome. 36 const kNumEntryPoints = 200; 37 38 const shader = t.device.createShaderModule({ 39 code: makeCode(kNumEntryPoints), 40 }); 41 42 const layout = t.device.createBindGroupLayout({ 43 entries: [ 44 { 45 binding: 0, 46 visibility: GPUShaderStage.COMPUTE, 47 buffer: { type: 'storage' }, 48 }, 49 ], 50 }); 51 const pipelineLayout = t.device.createPipelineLayout({ 52 bindGroupLayouts: [layout], 53 }); 54 const bindGroup = t.device.createBindGroup({ 55 layout, 56 entries: [{ binding: 0, resource: { buffer } }], 57 }); 58 59 const encoder = t.device.createCommandEncoder(); 60 range(kNumEntryPoints, i => { 61 const pipeline = t.device.createComputePipeline({ 62 layout: pipelineLayout, 63 compute: { 64 module: shader, 65 entryPoint: `computeMain${i}`, 66 }, 67 }); 68 69 const pass = encoder.beginComputePass(); 70 pass.setPipeline(pipeline); 71 pass.setBindGroup(0, bindGroup); 72 pass.dispatchWorkgroups(1); 73 pass.end(); 74 }); 75 76 t.device.queue.submit([encoder.finish()]); 77 t.expectGPUBufferValuesEqual(buffer, new Uint32Array([kNumEntryPoints])); 78 });