submit.spec.ts (3586B)
1 export const description = ` 2 Stress tests for command submission to GPUQueue objects. 3 `; 4 5 import { makeTestGroup } from '../../common/framework/test_group.js'; 6 import { iterRange } from '../../common/util/util.js'; 7 import { GPUTest } from '../../webgpu/gpu_test.js'; 8 9 export const g = makeTestGroup(GPUTest); 10 11 g.test('huge_command_buffer') 12 .desc( 13 `Tests submission of huge command buffers to a GPUQueue. Huge buffers are 14 encoded by chaining together long sequences of compute passes, with expected 15 results verified at the end of the test.` 16 ) 17 .fn(t => { 18 const kNumElements = 64; 19 const data = new Uint32Array([...iterRange(kNumElements, x => x)]); 20 const buffer = t.makeBufferWithContents(data, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC); 21 const pipeline = t.device.createComputePipeline({ 22 layout: 'auto', 23 compute: { 24 module: t.device.createShaderModule({ 25 code: ` 26 struct Buffer { data: array<u32>, }; 27 @group(0) @binding(0) var<storage, read_write> buffer: Buffer; 28 @compute @workgroup_size(1) fn main( 29 @builtin(global_invocation_id) id: vec3<u32>) { 30 buffer.data[id.x] = buffer.data[id.x] + 1u; 31 } 32 `, 33 }), 34 entryPoint: 'main', 35 }, 36 }); 37 const bindGroup = t.device.createBindGroup({ 38 layout: pipeline.getBindGroupLayout(0), 39 entries: [{ binding: 0, resource: { buffer } }], 40 }); 41 const encoder = t.device.createCommandEncoder(); 42 const kNumIterations = 500_000; 43 for (let i = 0; i < kNumIterations; ++i) { 44 const pass = encoder.beginComputePass(); 45 pass.setPipeline(pipeline); 46 pass.setBindGroup(0, bindGroup); 47 pass.dispatchWorkgroups(kNumElements); 48 pass.end(); 49 } 50 t.device.queue.submit([encoder.finish()]); 51 t.expectGPUBufferValuesEqual( 52 buffer, 53 new Uint32Array([...iterRange(kNumElements, x => x + kNumIterations)]) 54 ); 55 }); 56 57 g.test('many_command_buffers') 58 .desc( 59 `Tests submission of a huge number of command buffers to a GPUQueue by a single 60 submit() call.` 61 ) 62 .fn(t => { 63 const kNumElements = 64; 64 const data = new Uint32Array([...iterRange(kNumElements, x => x)]); 65 const buffer = t.makeBufferWithContents(data, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC); 66 const pipeline = t.device.createComputePipeline({ 67 layout: 'auto', 68 compute: { 69 module: t.device.createShaderModule({ 70 code: ` 71 struct Buffer { data: array<u32>, }; 72 @group(0) @binding(0) var<storage, read_write> buffer: Buffer; 73 @compute @workgroup_size(1) fn main( 74 @builtin(global_invocation_id) id: vec3<u32>) { 75 buffer.data[id.x] = buffer.data[id.x] + 1u; 76 } 77 `, 78 }), 79 entryPoint: 'main', 80 }, 81 }); 82 const bindGroup = t.device.createBindGroup({ 83 layout: pipeline.getBindGroupLayout(0), 84 entries: [{ binding: 0, resource: { buffer } }], 85 }); 86 const kNumIterations = 500_000; 87 const buffers = []; 88 for (let i = 0; i < kNumIterations; ++i) { 89 const encoder = t.device.createCommandEncoder(); 90 const pass = encoder.beginComputePass(); 91 pass.setPipeline(pipeline); 92 pass.setBindGroup(0, bindGroup); 93 pass.dispatchWorkgroups(kNumElements); 94 pass.end(); 95 buffers.push(encoder.finish()); 96 } 97 t.device.queue.submit(buffers); 98 t.expectGPUBufferValuesEqual( 99 buffer, 100 new Uint32Array([...iterRange(kNumElements, x => x + kNumIterations)]) 101 ); 102 });