计算通道
ComputePass 是一种帧通道,在单个物理计算通道中按顺序派发一组计算实例。它将计算工作放到一帧中的指定位置,例如相机渲染之后,以在同一帧处理场景深度和颜色贴图。
如果希望调用时立即派发计算实例,使用 GraphicsDevice#computeDispatch。
计算着色器仅在 WebGPU 上受支持,参见 GraphicsDevice#supportsCompute。其他设备上通道仍执行,但不会派发任何任务。
创建通道
使用要派发的计算实例创建通道。实例保存在 computes 数组中,之后仍可添加或移除。请设置名称,以便在 GPU 性能分析中标识派发任务:
const compute = new Compute(app.graphicsDevice, shader, 'Histogram');
compute.setParameter('bins', histogramBuffer);
const pass = new ComputePass(app.graphicsDevice, [compute]);
pass.name = 'HistogramPass';
将通道添加到帧
将通道添加到相机的 beforePasses 或 afterPasses,可在相机渲染之前或之后派发;也可添加到其他通道的前置或后置列表。使用自定义 framePasses 的相机还可将它包含在列表中,在对应位置派发,例如放在将场景渲染到纹理的通道和使用计算结果的通道之间。相机后置列表中的通道可读取同帧相机的渲染结果:
cameraEntity.camera.afterPasses.push(pass);
每个通道在一帧内最多执行一次。
读取相机渲染结果
相机后置列表中的计算通道可读取该相机同帧渲染的深度和颜色贴图。先在相机上通过 requestSceneDepthMap 和 requestSceneColorMap 请求贴图,再通过 setSceneDepthMap 和 setSceneColorMap 将它们附加到计算实例:
cameraEntity.camera.requestSceneColorMap(true);
compute.setSceneColorMap(cameraEntity.camera.sceneColorMapHandle);
关于在使用 CameraFrame 的相机上请求贴图,以及在计算着色器中读取贴图,参见场景深度和颜色贴图。
派发
各计算实例按其设置的派发尺寸和参数执行。可在帧渲染前设置,也可在紧邻派发前的 onBefore 中设置。还可以通过 onBefore 准备着色器写入的缓冲区,例如清空缓冲区。
按上述方式附加场景颜色贴图后,逐纹素处理它的着色器应按颜色贴图尺寸派发。句柄保存相机最近一次渲染的贴图尺寸;使用渲染缩放或独立渲染目标时,它与画布尺寸不同。深度贴图句柄也具有相同的 width 和 height 属性:
pass.onBefore = () => {
// a thread for each texel of the color map the camera just rendered
const { width, height } = cameraEntity.camera.sceneColorMapHandle;
compute.setupDispatchThreads(width, height);
histogramBuffer.clear();
};
回读结果
在 onAfter 中读取结果,因为其中请求的读取会紧接着派发记录。数据会在数帧后到达:
pass.onAfter = () => {
histogramBuffer.read().then((data) => {
// the histogram, a few frames after it was computed
});
};
XR 视图
一帧渲染多个 XR 视图时,xrViewIndex 选择通道在哪个视图中、按其在该视图内的位置执行。设为 -1 可在所有视图之前执行一次。计算实例每帧最多派发一次,因此若要为多个视图派发,需要每个视图具有独立的 ComputePass 和计算实例。相机后置列表中的通道在所有视图之后执行一次。
通道所有权
通道不会销毁计算实例,相机也不会销毁通道。不再需要时,应移除通道,并销毁它及计算实例:
const passes = cameraEntity.camera.afterPasses;
passes.splice(passes.indexOf(pass), 1);
pass.destroy();
compute.destroy();
示例
相机之后的计算通道为渲染颜色构建直方图,回读后绘制到屏幕。
相机之后的计算通道读取场景深度和颜色贴图,绘制扫过场景的扫描脉冲。