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

瀏覽器相容性

另見