export async function runComputeTest()

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));
}