在 Metal 中,将顶点和片段缓冲区设置为相同的 MTLBuffer 是不是仅将其复制到 GPU 一次?

Posted

技术标签:

【中文标题】在 Metal 中,将顶点和片段缓冲区设置为相同的 MTLBuffer 是不是仅将其复制到 GPU 一次?【英文标题】:In Metal, does setting vertex and fragment buffer to same MTLBuffer copies it to GPU only once?在 Metal 中,将顶点和片段缓冲区设置为相同的 MTLBuffer 是否仅将其复制到 GPU 一次? 【发布时间】:2017-05-05 05:32:18 【问题描述】:

我将统一缓冲区传递给顶点和片段着色器。

let uniformBuffer = device.makeBuffer(length: 4096, options: [])
renderEncoder.setVertexBuffer(uniformBuffer, offset: 0, at: 1)
renderEncoder.setFragmentBuffer(uniformBuffer,offset:0, at: 1)

这会将uniformBuffer从CPU复制到GPU两次吗?然后,我会将缓冲区从顶点着色器传递到片段着色器,这发生在 GPU 内部。

【问题讨论】:

【参考方案1】:

没有特别涉及setVertexBuffer()setFragmentBuffer() 的副本。这些只是将缓冲区的引用放入渲染编码器的缓冲区表中。

您的代码和 Metal 只需要确保缓冲区的内容在 GPU 上是最新的,然后就会从那里引用它。正如 Matthjis 提到的,你如何做到这一点取决于storageMode。如果您使用托管模式,如果您修改 CPU 上的缓冲区内容,则需要使用 didModifyRange() 告知 Metal。一旦你这样做了,Metal 知道下次需要时将修改后的范围复制到 GPU。无论编码器缓冲区表引用缓冲区多少次,这个单一副本就足够了。

请注意,setVertexBytes()setFragmentBytes() 的工作方式不同。每次调用它们时,它们都必须(并且确实)立即复制传入的字节数组。

【讨论】:

我从未使用过storageMode统一矩阵VertexBuffer总是会随着顶点VertexBuffer保持不变【参考方案2】:

我认为这取决于平台。在 ios 上,内存在 CPU 和 GPU 之间共享,因此根本不执行复制。在 macOS 上,是否涉及复制取决于缓冲区或纹理的storageMode(但我不知道在您的情况下它是复制缓冲区两次还是只复制一次)。

【讨论】:

以上是关于在 Metal 中,将顶点和片段缓冲区设置为相同的 MTLBuffer 是不是仅将其复制到 GPU 一次?的主要内容,如果未能解决你的问题,请参考以下文章

何时可以安全地重写和重用 MTLBuffer 或其他 Metal 顶点缓冲区?

为啥在 Metal 中不允许从片段着色器中写入缓冲区?

METAL顶点/片段着色器“拦截”结果的最佳方法

在 Metal 中从顶点缓冲区渲染四边形

一个 VBO 可以绑定多个 VAO 吗?

具有多个缓冲区的片段着色器颜色错误