Vulkan缓冲区内存管理 - 何时需要暂存缓冲区?

12
我阅读了很多有关Vulkan内存管理的文章,它们都建议使用分期缓冲区来向GPU传输数据。 但是我们已经可以创建设备本地和主机可见、主机一致的内存。它既可以从GPU读取,也可以从CPU写入。
我认为比较合理的做法是 - 创建一个绑定到设备本地、主机可见和一致的内存的大缓冲区。现在对于所有动态缓冲区,我们只需从此缓冲区中继续使用内存,并在该偏移处绑定缓冲区。
但在大多数示例中,它们创建一个主机可见的缓冲区和一个GPU可见的缓冲区,并使用copyBuffer操作进行传输。相较于只使用一个可由CPU和GPU访问的缓冲区,这种方式有何优势?我只谈论缓冲区,不包括纹理。
2个回答

13
正如ratchet freak所说,设备不需要具有即可用于设备又可用于主机的记忆类型。虽然大多数设备都是这样的,但其大小可能会受到限制。也许在过去的几年里情况发生了变化,但是基于PCI-E和BIOS的限制意味着你能获得的最大容量只有256 MB或者512 MB。最后,CPU通过PCI-E进行写入的带宽将低于CPU自己的内存。因此,即使使用缓冲区在总带宽上使用的是两倍,如果可以异步地在传输队列上完成,它最小化了CPU和图形流水线花费在该传输上的时间。因此,是否使用缓冲区取决于特定的CPU和GPU组合以及您的应用程序正在做什么。

然而,在像移动设备或集成GPU这样的SOC上,使用缓冲区应该很少用甚至永远不用。移动GPU不应该有受限的可用于设备本地+主机可见的堆大小。查看一些Windows集成GPU在vulkan.gpuinfo.org上,看起来现代的Intel集成GPU也没有这样的限制,但AMD集成GPU仍然有(我只看了几个随机样本,你的情况可能有所不同)。

所有这些都使得难以给出明确的“总是要做X”的建议。个人而言,我通常会这样做:

  • 如果我只想要一个可以在任何地方运行且不必担心性能或内存占用的代码路径,则使用缓冲区。这对于独立GPU来说可能是一个不错的选择,但对于集成式/SOC GPU来说则不是最优的选择。
  • 否则,在大可用的设备本地/主机可见池存在时将缓冲区保留为后备路径。
  • 当我开始尝试获得最后一点性能时,然后根据数据进行调整,优先考虑在离散GPU上使用异步传输的缓冲区,因为数据显示它是有利的。

那么动态缓冲区呢?我们每帧都需要进行复制操作吗?我认为DMA引擎不会像直接访问256MB设备本地主机可见内存那样快速。 - user6522494
1
没错,它不会像使用共享内存那样快。但如果你关心速度,那么你就属于我提到的第二类人,如果可以的话,尽量使用共享内存。 - Jesse Hall

4

创建一个大缓冲区,绑定到设备本地、主机可见和一致的内存。

并非所有设备都具有这样的内存堆。因此,如果要实现可移植性,您需要考虑这一点。

如果您想/必须将缓冲区放入的内存不可见于主机,则除了使用暂存缓冲区外,没有其他选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接