GPURenderBundleEncoder
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Secure context: This feature is available only insecure contexts (HTTPS), in some or allsupporting browsers.
Note: This feature is available inWeb Workers.
TheGPURenderBundleEncoder interface of theWebGPU API is used to pre-record bundles of commands.
The command bundles are encoded by calling the methods ofGPURenderBundleEncoder; once the desired commands have been encoded, they are recorded into aGPURenderBundle object instance using theGPURenderBundleEncoder.finish() method. These render bundles can then be reused across multiple render passes by passing theGPURenderBundle objects intoGPURenderPassEncoder.executeBundles() calls.
In effect, this is like a partial render pass —GPURenderBundleEncoders have all the same functionality available asGPURenderPassEncoders, except that they can't begin and end occlusion queries, and can't set the scissor rect, viewport, blend constant, and stencil reference. TheGPURenderBundle will inherit all these values from theGPURenderPassEncoder that executes it.
Note:Currently set vertex buffers, index buffers, bind groups, and pipeline are all cleared prior to executing a render bundle, and once the render bundle has finished executing.
Reusing pre-recoded commands can significantly improve app performance in situations where JavaScript draw call overhead is a bottleneck. Render bundles are most effective in situations where a batch of objects will be drawn the same way across multiple views or frames, with the only differences being the buffer content being used (such as updated matrix uniforms). A good example is VR rendering. Recording the rendering as a render bundle and then tweaking the view matrix and replaying it for each eye is a more efficient way to issue draw calls for both renderings of the scene.
AGPURenderBundleEncoder object instance is created via theGPUDevice.createRenderBundleEncoder() property.
Note:The methods ofGPURenderBundleEncoder are functionally identical to their equivalents available onGPURenderPassEncoder, except forGPURenderBundleEncoder.finish(), which is similar in purpose toGPUCommandEncoder.finish().
In this article
Instance properties
Instance methods
draw()Draw primitives based on the vertex buffers provided by
setVertexBuffer().drawIndexed()Draw indexed primitives based on the vertex and index buffers provided by
setVertexBuffer()andsetIndexBuffer()drawIndirect()Draw primitives using parameters read from a
GPUBuffer.drawIndexedIndirect()Draw indexed primitives using parameters read from a
GPUBuffer.finish()Completes recording of the current render pass command sequence.
insertDebugMarker()Marks a specific point in a series of encoded commands with a label.
popDebugGroup()Ends a debug group, which is begun with a
pushDebugGroup()call.pushDebugGroup()Begins a debug group, which is marked with a specified label, and will contain all subsequent encoded commands up until a
popDebugGroup()method is invoked.setBindGroup()Sets the
GPUBindGroupto use for subsequent render bundle commands, for a given index.setIndexBuffer()Sets the current
GPUBufferthat will provide index data for subsequent drawing commands.setPipeline()Sets the
GPURenderPipelineto use for this render bundle.setVertexBuffer()Sets or unsets the current
GPUBufferthat will provide vertex data for subsequent drawing commands.
Examples
In the WebGPU SamplesAnimometer example, a lot of like operations are done on many different objects simultaneously. A bundle of commands is encoded using the following function:
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); }}Later on, aGPURenderBundleEncoder is created, the function is invoked, and the command bundle is recorded into aGPURenderBundle usingGPURenderBundleEncoder.finish():
const renderBundleEncoder = device.createRenderBundleEncoder({ colorFormats: [presentationFormat],});recordRenderPass(renderBundleEncoder);const renderBundle = renderBundleEncoder.finish();GPURenderPassEncoder.executeBundles() is then used to reuse the work across multiple render passes to improve performance. Study the example code listing for the full context.
// …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()]);};// …Specifications
| Specification |
|---|
| WebGPU> # gpurenderbundle> |
Browser compatibility
See also
- TheWebGPU API