在 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 一次?的主要内容,如果未能解决你的问题,请参考以下文章