GPUComputePassEncoder: dispatchWorkgroupsIndirect() 方法

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

安全上下文: 此功能仅在安全上下文(HTTPS)中可用,且支持此功能的浏览器数量有限。

注意:此功能在 Web Workers 中可用。

GPUComputePassEncoder 接口的 dispatchWorkgroupsIndirect() 方法会分派一个由 GPUBuffer 的参数定义的、工作组的网格,以执行当前 GPUComputePipeline 所执行的工作(即通过 GPUComputePassEncoder.setPipeline() 设置的工作)。

语法

js
dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset)

参数

indirectBuffer

一个 GPUBuffer,其中包含要分派的工作组网格的 X、Y 和 Z 维度。该缓冲区必须包含一个紧凑的、由三个 32 位无符号整数值组成的块,代表维度(总共 12 字节),其顺序与 GPUComputePassEncoder.dispatchWorkgroups() 的参数顺序相同。例如:

js
const uint32 = new Uint32Array(3);
uint32[0] = 25; // The X value
uint32[1] = 1; // The Y value
uint32[2] = 1; // The Z value

// Write values into a GPUBuffer
device.queue.writeBuffer(buffer, 0, uint32, 0, uint32.length);
indirectOffset

indirectBuffer 中维度数据开始位置的偏移量(以字节为单位)。

注意: 传递给 GPUComputePassEncoder.dispatchWorkgroups()dispatchWorkgroupsIndirect() 的 X、Y 和 Z 维度值是每个维度要分派的工作组数量,而不是每个维度要执行的着色器调用数量。这与现代原生 GPU API 的行为一致,但与 OpenCL 的行为不同。这意味着,如果一个 GPUShaderModule 定义了一个入口点,其 @workgroup_size(4, 4),并且使用 dispatchWorkgroupsIndirect(indirectBuffer); 调用(其中 indirectBuffer 指定 X 和 Y 维度分别为 8 和 8)将其分派给该入口点,那么入口点将总共调用 1024 次 — 沿着 X 和 Y 轴各分派 4x4 的工作组 8 次。 4 * 4 * 8 * 8 = 1024

返回值

无 (Undefined)。

验证

调用 dispatchWorkgroupsIndirect() 时必须满足以下条件,否则将生成 GPUValidationError,并且 GPUComputePassEncoder 将变为无效

  • indirectBufferGPUBuffer.usage 包含 GPUBufferUsage.INDIRECT 标志。
  • indirectOffset + 由 XYZ 维度指定的总大小小于或等于 indirectBufferGPUBuffer.size
  • indirectOffset 是 4 的倍数。

示例

js
// Set global buffer size
const BUFFER_SIZE = 1000;

// Compute shader; note workgroup size of 64
const shader = `
@group(0) @binding(0)
var<storage, read_write> output: array<f32>;

@compute @workgroup_size(64)

...

`;

// …

// Create GPUCommandEncoder to encode commands to issue to the GPU
const commandEncoder = device.createCommandEncoder();

// Initiate render pass
const passEncoder = commandEncoder.beginComputePass();

// Issue commands
passEncoder.setPipeline(computePipeline);
passEncoder.setBindGroup(0, bindGroup);

const uint32 = new Uint32Array(3);
// Note workgroupCountX is set based on the global buffer size and the shader workgroup count.
uint32[0] = Math.ceil(BUFFER_SIZE / 64);
uint32[1] = 1;
uint32[2] = 1;

const workgroupDimensions = device.createBuffer({
  size: 12,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDIRECT,
});
device.queue.writeBuffer(workgroupDimensions, 0, uint32, 0, uint32.length);

passEncoder.dispatchWorkgroupsIndirect(workgroupDimensions, 0);

// End the render pass
passEncoder.end();

// Copy output buffer to staging buffer
commandEncoder.copyBufferToBuffer(
  output,
  0, // Source offset
  stagingBuffer,
  0, // Destination offset
  BUFFER_SIZE,
);

// End frame by passing array of command buffers to command queue for execution
device.queue.submit([commandEncoder.finish()]);

// …

规范

规范
WebGPU
# dom-gpucomputepassencoder-dispatchworkgroupsindirect

浏览器兼容性

另见