【问题标题】:vulkan barriers and multi-threadingvulkan屏障和多线程
【发布时间】:2018-09-15 11:27:44
【问题描述】:

我想分享我对如何在多线程渲染中保持内存屏障同步的想法。如果我对 Vulkan 内存屏障的想法是错误的,或者我目前的计划是否有意义,请告诉我。我在工作中没有人可以讨论,所以我会在这里寻求帮助。

对于 Vulkan 中的资源,当我在 drawcalls 中为它们设置内存屏障时,我需要同时设置 srcAccessMask 和 dst AccessMask。这对于单线程渲染很简单。但是对于多线程渲染,它变得复杂。 dst AccessMask 不是问题,因为我们总是知道资源将用于什么。但是对于 srcAccessMask,当一个命令缓冲区尝试读取某个资源的当前访问掩码时,可能会有其他命令缓冲区将其更改为其他内容。所以我目前解决它的想法是:

每个资源都有自己的状态,我只会在将命令缓冲区提交到命令队列之前更新状态,我稍后会描述。每个命令缓冲区都维护着它内部资源状态如何变化的跟踪记录。这样做,在同一个命令缓冲区内,每个资源的访问状态是明确的,唯一的问题是每个命令缓冲区的资源的开始状态。

在提交多个命令缓冲区执行时,由于命令缓冲区的顺序现在是固定的,我检查所有命令缓冲区中每个资源的跟踪记录,根据每个命令缓冲区中资源的结束状态更新资源的状态,并使用它来更正每个命令缓冲区的跟踪记录中相同资源的开始状态。

然后我需要插入一个新的命令缓冲区以具有额外的内存屏障以将资源转换为第一个命令缓冲区的正确状态,或者将内存屏障插入到先前的命令缓冲区以用于其余命令缓冲区。当所有这些都完成后,我终于可以批量提交命令缓冲区了。

这些对你有意义吗?有没有更好的解决方案来解决它?还是我们甚至需要解决每个资源访问状态的“同步”问题?

感谢您的宝贵时间

【问题讨论】:

    标签: multithreading 3d rendering vulkan


    【解决方案1】:

    您所说的只有在这些渲染操作都不知道其他地方发生了什么的世界中才有意义。图像的消费者不知道图像中的数据是如何到达那里的。这可能意味着它并不真正知道该图像在概念上的含义。

    Vulkan 是一个低级 API。这个想法是您可以将渲染系统的高级概念直接连接到 Vulkan。所以在高层次上,你知道资源 X 具有 Y 的含义,并且在这个框架中,它的数据将从操作 Z 生成。不是因为资源 X 中存储的东西,而是因为它资源 X;这就是资源 X 的用途。所以生成它的操作和使用它的操作都知道发生了什么以及它是如何到达那里的。

    例如,如果您正在执行延迟渲染和 SSAO,那么您的 SSAO 渲染通道会知道包含深度缓冲区的纹理的值是通过渲染生成的。深度缓冲区不需要存储在其中的内容来说明这一点;这就是你渲染的本质。以这种方式工作是硬编码的。

    您的大部分资源依赖项都是(或应该是)这种方式。

    如果您通过帧缓冲区执行一些渲染到纹理的操作,那么消费者可能甚至不需要了解依赖关系。您可以为渲染通道和生成它的子通道设置适当的外部依赖项。而且您可能知道为什么要进行渲染到纹理操作,并且您可能知道它的去向。如果您正在为反射进行 RTT,您知道目标将是某种着色器阶段纹理提取。如果您不知道如何使用它,那么您可以安全地设置所有目标阶段位。

    如果您正在处理流式对象,那么您所谈论的内容在一定程度上是有道理的,其中对象以某种规律性地进出内存。但即便如此,这并不是每个资源的真正属性。

    当您加载流式块时,您通过生成命令缓冲区并提交它们来上传其数据。这就是我们存在特定于实现的分歧的地方。您最好的性能选择是在专用于传输操作的队列上执行这些 CB。但由于 Vulkan 不能保证所有实现都具有这些,因此您需要能够将这些传输 CB 交付到主渲染队列。

    因此,当渲染线程可以预期开始使用资源时,您需要一种与渲染线程进行通信的方法。但即使这样也不需要基于每个资源;他们可以被告知“来自区块 X 的东西可用”,然后他们就可以开始使用它了。

    此外,实现差异变得很重要。看,如果它是在另一个队列上完成的,那么屏障不是正确的同步原语。您的渲染 CB 现在必须让其提交的批次在 信号量 上等待。并且该信号量应该处理内存的所有同步需求(即:目标位是一切)。因此,在传输 CB 与渲染 CB 在同一队列上执行的实现中,您不妨省去一些麻烦,并在传输 CB 结束时发出一个屏障,使所有给定资源可用于所有阶段.

    如前所述,这种自动化系统只有在您无法真正控制渲染的结构时才有用。如果您正在编写某种中间件,这主要是正确的,其中更高级别的代码定义了呈现的结构。但是,如果是这样的话,Vulkan 可能不是适合这项工作的工具。

    【讨论】:

    • 我目前正在开发的引擎封装了渲染任务,并调用特定于平台的低级函数将渲染任务转换为绘图调用。因此,对于每个渲染任务,将其转换为 Vulkan API 的低级函数并不知道其他地方发生了什么,正如您在开始时指出的那样。也许我应该让渲染任务告诉我更多信息,这样我就不用做太多的工作来猜测发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 2010-12-06
    相关资源
    最近更新 更多