【问题标题】:Vulkan: Concurrent host-writes and device reads to separate parts of same VkMemoryVulkan:并发主机写入和设备读取到同一 VkMemory 的不同部分
【发布时间】:2017-01-18 22:47:34
【问题描述】:

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

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

为了实现上述目标,一旦线程的数据被完全写入/刷新到暂存,我希望它能够立即提交 GPU 传输命令。

但是,这意味着 GPU 将从 VkMemory 的一部分读取,而其他线程可能正在写入/刷新。

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

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

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


问题:

  1. 这样可以吗?
  2. 是否需要将每个单独的对象与页面边界对齐?或者别的什么。
  3. 我是否正确假设图像内存屏障(上图)不需要设备写入到暂存内存。

【问题讨论】:

  • "为了实现上述目标,一旦线程的数据完全写入/刷新到暂存,我希望它能够立即提交 GPU 传输命令。" 我会强烈建议不要这样做。将 GPU 命令提交到队列,即使只是副本,也是一个重量级操作。最好将命令批量化并在帧结束时一次性提交。一个好的多写并发队列就足够了。

标签: multithreading memory vulkan memory-mapping


【解决方案1】:
  1. 是的,规范中提到必须同步读取和写入的区域。

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

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

vkMapMemory 不检查设备内存当前是否在 在返回主机可访问指针之前使用。应用程序必须 保证任何先前提交的写入此命令的命令 范围在主机读取或写入之前完成 范围,以及从该范围读取的任何先前提交的命令 范围在主机写入该区域之前完成(请参见此处 有关履行此类保证的详细信息)。如果设备内存是 在没有VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 集的情况下分配,这些 必须为扩展范围做出保证:应用程序必须 将范围的开始向下舍入到最接近的倍数 VkPhysicalDeviceLimits::nonCoherentAtomSize,并在结尾处舍入 范围最接近的倍数 VkPhysicalDeviceLimits::nonCoherentAtomSize.

  1. 布局转换可能会写入内存,但屏障会根据之前和之后的内存访问自行同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 2019-03-04
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多