GPURenderBundle

可用性有限

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

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

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

GPURenderBundle 接口是 WebGPU API 的一部分,它表示一个用于预先录制命令包的容器。

命令包使用 GPURenderBundleEncoder 进行编码;一旦所需的命令被编码,它们就会通过 GPURenderBundleEncoder.finish() 方法录制到一个 GPURenderBundle 对象实例中。

然后,通过将 GPURenderBundle 对象传递给 GPURenderPassEncoder.executeBundles() 调用,可以在多个渲染通道中重用这些命令包。在 JavaScript 绘制调用开销成为瓶颈的情况下,重用预先录制的命令可以显著提高应用程序性能。当一批对象需要在多个视图或帧中以相同方式绘制,而唯一区别是使用的缓冲区内容(例如更新的矩阵 uniform)时,渲染包最为有效。

VR 渲染是一个很好的例子。将渲染录制为渲染包,然后为每只眼睛调整视图矩阵并重放它,是为场景的两个渲染发出绘制调用的更有效方法。

实例属性

label

一个字符串,提供可用于识别对象的标签,例如在 GPUError 消息或控制台警告中。

示例

在 WebGPU 示例的 Animometer 示例 中,许多类似的opertions同时在许多不同的对象上进行。渲染包使用以下函数进行编码:

js
function recordRenderPass(
  passEncoder: GPURenderBundleEncoder | GPURenderPassEncoder
) {
  if (settings.dynamicOffsets) {
    passEncoder.setPipeline(dynamicPipeline);
  } else {
    passEncoder.setPipeline(pipeline);
  }
  passEncoder.setVertexBuffer(0, vertexBuffer);
  passEncoder.setBindGroup(0, timeBindGroup);
  const dynamicOffsets = [0];
  for (let i = 0; i < numTriangles; ++i) {
    if (settings.dynamicOffsets) {
      dynamicOffsets[0] = i * alignedUniformBytes;
      passEncoder.setBindGroup(1, dynamicBindGroup, dynamicOffsets);
    } else {
      passEncoder.setBindGroup(1, bindGroups[i]);
    }
    passEncoder.draw(3, 1, 0, 0);
  }
}

稍后,会创建一个 GPURenderBundleEncoder,调用该函数,并使用 GPURenderBundleEncoder.finish() 录制渲染包。

js
const renderBundleEncoder = device.createRenderBundleEncoder({
  colorFormats: [presentationFormat],
});
recordRenderPass(renderBundleEncoder);
const renderBundle = renderBundleEncoder.finish();

然后使用 GPURenderPassEncoder.executeBundles() 在多个渲染通道中重用该工作以提高性能。请参阅示例代码列表以获取完整上下文。

js
// …

return function doDraw(timestamp) {
  if (startTime === undefined) {
    startTime = timestamp;
  }
  uniformTime[0] = (timestamp - startTime) / 1000;
  device.queue.writeBuffer(uniformBuffer, timeOffset, uniformTime.buffer);

  renderPassDescriptor.colorAttachments[0].view = context
    .getCurrentTexture()
    .createView();

  const commandEncoder = device.createCommandEncoder();
  const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);

  if (settings.renderBundles) {
    passEncoder.executeBundles([renderBundle]);
  } else {
    recordRenderPass(passEncoder);
  }

  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
};

// …

规范

规范
WebGPU
# gpurenderbundle

浏览器兼容性

另见