GPURenderBundleEncoder

实验性: 这是一个 实验性技术
在生产环境中使用此功能之前,请仔细查看 浏览器兼容性表.

安全上下文: 此功能仅在 安全上下文(HTTPS)中可用,在一些或所有 支持的浏览器中。

GPURenderBundleEncoderWebGPU API 的一个接口,用于预先录制命令包。

命令包通过调用 GPURenderBundleEncoder 的方法进行编码;一旦编码了所需的命令,就会使用 GPURenderBundleEncoder.finish() 方法将它们记录到 GPURenderBundle 对象实例中。然后,这些渲染包可以通过将 GPURenderBundle 对象传递到 GPURenderPassEncoder.executeBundles() 调用中,在多个渲染通道中重复使用。

实际上,这就像一个部分渲染传递 - `GPURenderBundleEncoder` 与 GPURenderPassEncoder 具有相同的全部功能,只是它们不能开始和结束遮挡查询,也不能设置剪切矩形、视口、混合常量和模板参考。`GPURenderBundle` 将从执行它的 GPURenderPassEncoder 继承所有这些值。

注意:目前,在执行渲染包之前和之后,所有已设置的顶点缓冲区、索引缓冲区、绑定组和管道都会被清除。

在 JavaScript 绘制调用开销成为瓶颈的情况下,重用预先编码的命令可以显著提高应用程序性能。在将一批对象以相同的方式绘制到多个视图或帧中时,渲染包最为有效,唯一的区别是使用的缓冲区内容(例如更新的矩阵一致)。VR 渲染就是一个很好的例子。将渲染录制为渲染包,然后调整视图矩阵并为每个眼睛重放,是一种更高效地为场景的两种渲染发出绘制调用的方法。

通过 GPUDevice.createRenderBundleEncoder() 属性创建 `GPURenderBundleEncoder` 对象实例。

注意:`GPURenderBundleEncoder` 的方法在功能上与 GPURenderPassEncoder 上的等效方法相同,除了 GPURenderBundleEncoder.finish(),它的用途类似于 GPUCommandEncoder.finish()

实例属性

label 实验性

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

实例方法

draw() 实验性

基于 setVertexBuffer() 提供的顶点缓冲区绘制图元。

drawIndexed() 实验性

基于 setVertexBuffer()setIndexBuffer() 提供的顶点和索引缓冲区绘制索引图元。

drawIndirect() 实验性

使用从 GPUBuffer 读取的参数绘制图元。

drawIndexedIndirect() 实验性

使用从 GPUBuffer 读取的参数绘制索引图元。

finish() 实验性

完成当前渲染传递命令序列的录制。

insertDebugMarker() 实验性

使用标签标记一系列编码命令中的特定点。

popDebugGroup() 实验性

结束一个调试组,调试组由 pushDebugGroup() 调用开始。

pushDebugGroup() 实验性

开始一个调试组,用指定的标签标记,并将包含所有后续的编码命令,直到调用 popDebugGroup() 方法。

setBindGroup() 实验性

为给定的索引设置后续渲染包命令要使用的 GPUBindGroup

setIndexBuffer() 实验性

设置当前的 GPUBuffer,它将为后续的绘制命令提供索引数据。

setPipeline() 实验性

设置此渲染包要使用的 GPURenderPipeline

setVertexBuffer() 实验性

设置或取消设置当前的 GPUBuffer,它将为后续的绘制命令提供顶点数据。

示例

在 WebGPU 示例 Animometer 示例 中,许多类似的操作同时在许多不同的对象上进行。使用以下函数编码命令包

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`,调用函数,并将命令包记录到 GPURenderBundle 中,使用 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

浏览器兼容性

BCD 表格仅在浏览器中加载

参见