GPURenderBundleEncoder
注意:此功能在 Web Workers 中可用。
GPURenderBundleEncoder 介面是 WebGPU API 的一部分,用於預先錄製命令包。
命令包是透過呼叫 GPURenderBundleEncoder 的方法來編碼的;一旦所需的命令被編碼完成,它們就會透過 GPURenderBundleEncoder.finish() 方法錄製到一個 GPURenderBundle 物件例項中。然後,這些渲染包可以透過將 GPURenderBundle 物件傳遞給 GPURenderPassEncoder.executeBundles() 呼叫來在多個渲染通道中重複使用。
實際上,這就像一個部分的渲染通道 — GPURenderBundleEncoder 擁有與 GPURenderPassEncoder 相同的功能,只是它們不能開始和結束遮擋查詢,也不能設定裁剪矩形 (scissor rect)、視口 (viewport)、混合常量 (blend constant) 和模板參考值 (stencil reference)。GPURenderBundle 將繼承執行它的 GPURenderPassEncoder 的所有這些值。
注意: 在執行渲染包之前,當前設定的頂點緩衝區、索引緩衝區、繫結組和管線都會被清除,並在渲染包執行完畢後再次清除。
在 JavaScript 繪製呼叫開銷成為瓶頸的情況下,重用預先錄製的命令可以顯著提高應用程式的效能。在同一批物件將在多個檢視或幀中以相同方式繪製,而唯一不同之處在於正在使用的緩衝區內容(例如更新的矩陣統一變數)的情況下,渲染包最為有效。一個很好的例子是 VR 渲染。將渲染過程錄製為渲染包,然後為每個眼睛調整檢視矩陣並重放它,是為場景的兩次渲染髮出繪製呼叫的更有效方法。
GPURenderBundleEncoder 物件例項是透過 GPUDevice.createRenderBundleEncoder() 屬性建立的。
注意: GPURenderBundleEncoder 的方法在功能上與其在 GPURenderPassEncoder 上可用的相應方法是相同的,除了 GPURenderBundleEncoder.finish(),它的目的與 GPUCommandEncoder.finish() 相似。
例項屬性
例項方法
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 示例中,許多類似的操作同時在許多不同的物件上進行。命令包使用以下函式進行編碼:
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() 將命令包錄製到 GPURenderBundle 中。
const renderBundleEncoder = device.createRenderBundleEncoder({
colorFormats: [presentationFormat],
});
recordRenderPass(renderBundleEncoder);
const renderBundle = renderBundleEncoder.finish();
然後使用 GPURenderPassEncoder.executeBundles() 在多個渲染通道中重用該工作以提高效能。請參閱示例程式碼列表以獲取完整上下文。
// …
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 |
瀏覽器相容性
載入中…