RenderBundle是什么
通常情况下,WebGPU每次绘制时都需要向RenderPassEncoder注册渲染命令。处理此绘图命令比 WebGL 内部执行的类似处理更快。但是,如果可以省略此命令注册过程,则可以能够更快地绘制。RenderBundle 就是实现这一点的。
RenderBundle 允许预先注册的绘图命令稍后重用。 命令可以重复使用,这减少了为每个绘制调用注册命令的成本。
由于注册的绘图命令在内部被转换为GPU可以理解的命令格式, 比绘制时每次都用RenderPassEncoder进行转换效率更高。
程序实现
1. 创建RenderBundle
首先,使用device
的createRenderBundleEncoder
函数创建一个RenderBundleEncoder。 此时用作参数的描述符是一个名为 GPURenderBundleDescriptor 的类型, 注意创建RenderPassEncoder时与GPURenderPassDescriptor不同。
该描述符有一个名为 colorFormats
的属性,用来指定纹理格式。 由于这次我们要渲染到 Canvas,因此我们将使用 navigator.gpu.getPreferredCanvasFormat()
的值。
javascript
function buildRenderBundle(pipeline: GPURenderPipeline): void {
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
const renderBundleDescriptor: GPURenderBundleDescriptor = {
colorFormats:[presentationFormat],
};
const encoder = g_device.createRenderBundleEncoder(renderBundleDescriptor);
encoder.setPipeline(pipeline);
encoder.draw(3, 1, 0, 0);
g_renderBundle = encoder.finish();
}
创建 RenderBundleEncoder 后,像注册 RenderPassEncoder 一样注册绘图命令。
完成后,调用 finish()
(而不是像 RenderPassEncoder 中那样的 end())。 这个 finish()
函数返回一个 RenderBundle 对象。
2. 使用RenderBundle进行绘制
接下来使用 RenderBundle 进行绘制。照常使用 createCommandEncoder
和 beginRenderPass
函数, 创建一个 RenderPassEncoder。
这个RenderPassEncoder有一个函数叫executeBundles()
,RenderBundle以数组的形式传递给这个函数。
javascript
const commandEncoder = g_device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor: GPURenderPassDescriptor = {
colorAttachments: [
{
view: textureView,
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
loadOp: 'clear',
storeOp: 'store',
},
],
};
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.executeBundles([g_renderBundle]);
passEncoder.end();
g_device.queue.submit([commandEncoder.finish()]);
结果
在线示例查看。