【问题标题】:Can vkQueuePresentKHR be synced using a pipeline barrier?可以使用管道屏障同步 vkQueuePresentKHR 吗?
【发布时间】:2021-06-20 09:49:17
【问题描述】:

vkQueuePresentKHR 得到一个队列参数的事实让我觉得它就像一个被传递到队列执行的命令。如果是这样,可以使用源阶段为 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT 且目标为 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT 的管道屏障使其等待(直到写入要呈现的图像完成)。或者甚至可以通过图像屏障来缓解仅对图像的同步约束。

但是,在每个教程和书籍中,同步都是使用 semaphore 完成的,这让我认为我的假设是错误的。如果是这样,为什么 vkQueuePresentKHR 需要一个队列参数?因为 semaphore 参数似乎就足够了:当它发出信号时,vkQueuePresentKHR 可以根据图像索引参数和交换链句柄参数呈现图像。

【问题讨论】:

    标签: vulkan


    【解决方案1】:

    有几个针对规范的突出问题。值得注意的是KhronosGroup/Vulkan-Docs#1308 正是您的问题。

    与此同时,每个人通常都遵循这种语言:

    演示的处理与其他队列操作按问题顺序进行,但必须使用信号量来确保指定队列中的先前渲染和其他命令在演示开始之前完成。

    这意味着必须使用信号量。鉴于我们不能 110% 确定,这意味着应该使用信号量,直到我们知道更好为止。

    另一个半官方来源是sync wiki,它使用信号量。

    尽管这句话说了什么,我认为有理由相信在vkQueuePresent 之前使用使图像已经可见的其他同步也是允许的,例如栅栏等待。

    但只有管道障碍可能还不够。演示不在排队系统中:

    但是,这组队列操作的范围并不包括展示引擎对图像的实际处理。

    另外它没有VkPipelineStageFlagBit,并且vkQueuePresentKHR不包含在提交顺序中,所以它不能在任何vkCmdPipelineBarrier的同步范围内。

    令人困惑的部分是这个不幸的措辞:

    支持pPresentInfopPresentInfopImageIndicespSwapchains 成员引用的图像的任何写入内存,在执行vkQueuePresentKHR 之前可用,这些写入自动对演示引擎执行的读取访问可见。

    我相信诀窍是“在vkQueuePresentKHR 被执行之前”。如上所述,vkQueuePresentKHR 不是提交顺序的一部分,因此在执行vkQueuePresentKHR 之前,您不知道内存是否通过管道屏障提供。

    【讨论】:

    • 这带来了一个新的理解——可能有一些命令没有通过“管道阶段板”,因此,障碍和子依赖对那些没有帮助。有趣的是,如果有更多类似 vkQueuePresentKHR。
    • @audi02 是的,也是稀疏绑定。
    【解决方案2】:

    演示是一个队列操作。这就是您将其提交到队列的原因。将执行图像呈现的队列。特别是对于一个能够执行当前操作的队列。

    至于如何同步...the specification is a bit ambiguous on this point.

    信号量绝对可以工作;对此有一个特定的标注:

    信号量对于使先前命令的结果对当前可见不是必需的:

    任何支持pPresentInfopImageIndicespSwapchains 成员引用的图像的内存写入,在执行vkQueuePresentKHR 之前可用,是 自动使演示引擎执行的读取访问可见。图像的这种自动可见性操作发生在信号量信号操作之后,并且发生在表示引擎访问图像之前。

    虽然对信号量做了规定,但没有具体说明其他事情。特别是,如果您不等待信号量,则不清楚“在信号量信号操作之后发生”是什么意思,因为没有发生此类信号操作。

    现在,vkQueuePresentKHR 的 API 清楚表明您不需要提供信号量来等待:

    waitSemaphoreCount 是发出当前请求之前要等待的信号量数。

    数字可能为零。

    一个可能的事情是,作为一个队列操作,该队列上的所有先前同步仍然会影响呈现。例如,如果您将交换链图像作为附件写入,则外部子通道依赖项。它可能会......如果不是因为一个小问题。

    看,同步最终是基于阶段之间的依赖关系。和演示...没有舞台。因此,虽然您的外部依赖来源很容易理解,但不清楚 destination 阶段会起作用。即使指定 all-stages 标志也不一定有效。

    所有阶段的集合中是否存在“不是一个阶段”?

    无论如何,最好只使用信号量。反正你可能需要一个,所以就用它吧。

    【讨论】:

    • 所以我知道当前的同步可以通过外部 dst 的子依赖来完成,而无需信号量。这似乎是一种非常优雅的方式,但是从规范 - “图像的这种自动可见性操作发生在信号量信号操作之后” - 可以理解,信号量是必须的,因为这种自动可见性发生在给定信号量发出信号之后。
    • @audi02:如果这是真的,为什么VkPresentInfoKHR::waitSemaphoreCount 可以为零?
    • @NicolBolas 因为它可以被栅栏等待代替。
    • 不管怎样,把这个放在这里:github.com/KhronosGroup/Vulkan-Docs/issues/1308
    • 值得注意。 spec 也有这个 gem 进一步混淆你:“演示的处理与其他队列操作按问题顺序发生,但 必须使用信号量以确保指定队列中的先前渲染和其他命令在演示开始之前完成。”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2015-03-09
    • 1970-01-01
    • 2014-03-12
    • 2021-12-02
    • 1970-01-01
    • 2020-10-04
    相关资源
    最近更新 更多