in src/webgpu/shader/execution/expression/call/builtin/subgroup_util.ts [325:425]
export async function runComputeTest(
t: GPUTest,
wgsl: string,
wgSize: number[],
outputUintsPerElement: number,
inputData: Uint32Array,
checkFunction: (metadata: Uint32Array, output: Uint32Array) => Error | undefined
) {
// Compatibility mode has lower workgroup limits.
const wgThreads = wgSize[0] * wgSize[1] * wgSize[2];
const {
maxComputeInvocationsPerWorkgroup,
maxComputeWorkgroupSizeX,
maxComputeWorkgroupSizeY,
maxComputeWorkgroupSizeZ,
} = t.device.limits;
t.skipIf(
maxComputeInvocationsPerWorkgroup < wgThreads ||
maxComputeWorkgroupSizeX < wgSize[0] ||
maxComputeWorkgroupSizeY < wgSize[1] ||
maxComputeWorkgroupSizeZ < wgSize[2],
'Workgroup size too large'
);
const inputBuffer = t.makeBufferWithContents(
inputData,
GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE
);
t.trackForCleanup(inputBuffer);
const outputUints = outputUintsPerElement * wgThreads;
const outputBuffer = t.makeBufferWithContents(
new Uint32Array([...iterRange(outputUints, x => kDataSentinel)]),
GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE
);
t.trackForCleanup(outputBuffer);
const numMetadata = 2 * wgThreads;
const metadataBuffer = t.makeBufferWithContents(
new Uint32Array([...iterRange(numMetadata, x => kDataSentinel)]),
GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE
);
const pipeline = t.device.createComputePipeline({
layout: 'auto',
compute: {
module: t.device.createShaderModule({
code: wgsl,
}),
},
});
const bg = t.device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [
{
binding: 0,
resource: {
buffer: inputBuffer,
},
},
{
binding: 1,
resource: {
buffer: outputBuffer,
},
},
{
binding: 2,
resource: {
buffer: metadataBuffer,
},
},
],
});
const encoder = t.device.createCommandEncoder({ label: 'runComputeTest' });
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bg);
pass.dispatchWorkgroups(1, 1, 1);
pass.end();
t.queue.submit([encoder.finish()]);
const metadataReadback = await t.readGPUBufferRangeTyped(metadataBuffer, {
srcByteOffset: 0,
type: Uint32Array,
typedLength: numMetadata,
method: 'copy',
});
const metadata = metadataReadback.data;
const outputReadback = await t.readGPUBufferRangeTyped(outputBuffer, {
srcByteOffset: 0,
type: Uint32Array,
typedLength: outputUints,
method: 'copy',
});
const output = outputReadback.data;
t.expectOK(checkFunction(metadata, output));
}