在 Metal 中同步统一缓冲区更新

Synchronize uniform buffer updates in Metal

假设我有以下代码(简化):

id<MTLBuffer> uniforms = ...;
MTLRenderCommandEncoder encoder = ...;

[uniforms contents] = some_data;
[encoder setVertexbuffer: uniforms ...];

DrawSomethingWithShader("myshader");

[uniforms contents] = some_other_data;    // WRONG! overwrites previous draw call's uniforms
[encoder setVertexbuffer: uniforms ...];

DrawSomethingElseWithShader("myshader");

在 Vulkan 中,有一种称为 vkCmdPipelineBarrier() 的机制。然而,我在 Metal 中找不到类似的东西(MTLFence 是一个候选,但似乎它被用于其他种类的东西)。

所以我的问题是如何同步这个缓冲区更新?

(ps.: 我目前的想法是跟踪对缓​​冲区的修改并将 "second uniform data" 复制到另一个位置,但是在健壮的方式)

您需要确保编码到命令缓冲区中的每个绘制调用的统一数据不仅在您结束编码之前而且在命令缓冲区本身完成之前都可以访问。

这意味着您应该向缓冲区的内容指针添加一个偏移量,并将连续绘制调用的统一数据写入缓冲区的连续部分。在完成之前,您不应写入与该帧对应的缓冲区区域。

由于您可能会在正在编码的帧完成之前获得绘制下一帧的回调,因此您应该使用缓冲区池并在它们之间循环,使用计数信号量控制访问。此建议在 Metal Best Practices Guide.

中有详细说明