我有一个永久映射的内存。它既是HOST_VISIBLE又是HOST_COHERENT,但不是DEVICE_LOCAL。 (我的物理设备不提供专门用于HOST_VISIBLE的内存,而不同时提供HOST_COHERENT。)

此内存包含顶点缓冲区。我每帧发送命令以绘制这些缓冲区。其中一些,我会每帧更改内容,而其他情况则很少。

我相信驱动程序需要某种方式将缓冲区转移到GPU上才能绘制缓冲区,是吗?在这里,因为内存为HOST_COHERENT,所以我不需要使任何内容无效/刷新。驾驶员如何知道何时更新/转移?它是否有必要检测我更换零件的部件,还是强制性地每帧重新传输数据?

#1 楼


驱动程序如何知道何时更新/转让?


不知道。没有以这种方式进行的传输或更新。

通过Vulkan设备分配的所有内存代表某些设备操作可以直接读取的内存。如果Vulkan设备宣传其可以使用可见/相干内存作为渲染操作的源顶点数据,则并不意味着某种上传正在继续进行。设备正在从您写入的内存中读取该数据。 vkFlushMappedRange函数仅清除CPU高速缓存行中的写操作,以便它们实际到达内存。

主机一致且主机可见的内存将代表以下任一内存:


没有被CPU缓存,因此GPU可以按原样查看内存。这也意味着CPU的读写速度往往会变慢。
GPU可以直接访问CPU的缓存,可以达到某种程度。

通常,在GPU开启时发生#2 -与CPU一起死。这也意味着这将是设备本地内存。由于您已经说过它不是设备本地的,所以很可能根本就不缓存它。它可以使用写合并(这可以提高顺序写的效率),但是CPU写则按原样传递。鉴于内存的描述中似乎没有包含“已缓存”,因此我认为最有可能出现#1。

请注意,仅仅因为您不需要显式刷新内存就不会更改以下事实:您仍然需要在写入数据的CPU操作与读取数据的GPU命令之间建立依赖关系。这通常是事件的一部分,具有内存依赖性。

#2 楼

我认为这种底层数据传输不应在Vulkan等低级API中进行。 GPU能够通过PCIe互连直接从主机内存读取。因此,当您从主机内存缓冲区进行渲染时,它应该动态地“拉” draw调用所引用的顶点。

我不确定主机一致性如何精确地工作,但是我的猜测是CPU的内存控制器可能足够聪明,可以监听PCIe读取请求,并对CPU缓存进行正确的处理。

如果您想先将数据传输到GPU内存中,我想您应该通过分配一些设备本地内存并将其复制到其中来自己实现。 (对于每帧线性消耗一次的顶点缓冲区,这样做可能没有任何好处,但对于更新很少或具有随机访问模式的缓冲区来说,这可能是值得的。)