Vulkan:并发主机写入和设备读取以分离同一 VkMemory 的各个部分

Vulkan: Concurrent host-writes and device reads to separate parts of same VkMemory

为了将我的静态数据传输到 GPU,我正在考虑拥有一个暂存 VkMemory 对象(大约 64MB),并将其用作旋转队列。但是,我有多个线程生成内容(例如:渲染字形、加载文件、程序),我希望他们可以完全自己上传数据(即写 plus submit Vulkan传输命令)。

我打算至少在加载期间(但如果我想流式传输数据,可能会更长)永久映射整个暂存 VkMemory(如果这是愚蠢的,请这样说)。

为了实现上述目标,一旦线程的数据完全 written/flushed 到分段,我希望它能够 立即 提交 GPU 传输命令。

然而,这意味着 GPU 将从 VkMemory 的一部分读取,而其他线程可能 writing/flushing 读取它。

AFAIK 我还需要使用图像内存屏障来从 VK_IMAGE_LAYOUT_PREINITIALIZED 过渡到 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL。

我在规范中找不到任何明确说明这是合法还是非法的内容,只是应该注意确保同步。但是,我没有找到足够的细节来确定是哪种方式。

注意:暂存队列需要确保在覆盖任何内容之前传输已完成 - 我打算为此保留一个免费的 VkFences 队列。


问题:

  1. 这样可以吗?
  2. 我是否需要将每个单独的对象与页面边界对齐?或者别的。
  3. 我假设图像内存屏障(上图)不需要设备写入到分段内存,我是否正确。
  1. 是的,规范中谈到必须同步读取和写入的区域。

  2. 如果内存不连贯,那么您必须对齐正在读取或写入的块 NonCoherentAtomSize

来源:Vulkan spec under the note after the declaration of vkMapMemory

vkMapMemory does not check whether the device memory is currently in use before returning the host-accessible pointer. The application must guarantee that any previously submitted command that writes to this range has completed before the host reads from or writes to that range, and that any previously submitted command that reads from that range has completed before the host writes to that region (see here for details on fulfilling such a guarantee). If the device memory was allocated without the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, these guarantees must be made for an extended range: the application must round down the start of the range to the nearest multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize, and round the end of the range up to the nearest multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.

  1. 布局转换可能会写入内存,但屏障将针对之前和后续的内存访问进行自己的同步。