微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对 VK_SUBPASS_EXTERNAL 和 VkSemaphore 感到困惑

如何解决对 VK_SUBPASS_EXTERNAL 和 VkSemaphore 感到困惑

我正在阅读 Vulkan Tutorial "Rendering and Presentation" chapter,“Subpass 依赖项”部分让我很困惑。

它说:VK_SUBPASS_EXTERNAL 是对渲染通道之外的命令的引用,但是,问题是,在那个 Hello-Triangle 示例中,渲染通道之外没有命令,我没有看到规范或某处说它会通过信号量自动创建命令块,我现在很困惑,如果渲染通过之前没有命令,VK_SUBPASS_EXTERNAL是什么意思?

解决方法

VK_SUBPASS_EXTERNAL 引用在 vkCmdBeginRenderPass 之前或 vkCmdEndRenderpass 之后记录\提交的命令。


在 101 示例的情况下,相邻使用只是交换链,这需要在获取时使用信号量,在当前使用信号量。在 7.4.2. Semaphore Waiting 的末尾,在规范中实际上有关于这个用例的具体说明。

现在,信号量信号(在您出现之前)已经覆盖了设备上所有先前的内存访问,因此您无需任何进一步的同步即可设置。但是出于教育目的和代码可读性,无论如何明确添加该依赖项并没有什么坏处:

VkSubpassDependency presentDependency{
    0,// srcSubpass
    VK_SUBPASS_EXTERNAL,// dstSubpass
    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,// srcStageMask
    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,// dstStageMask
    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,// srcAccessMask
    0,// dstAccessMask
    0,// dependencyFlags
};

注意 dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,这实际上意味着“无同步”。 srcStageMask 涵盖您的商店操作,但即使您未列出任何依赖项,它也会被隐式涵盖。

现在信号量等待(为您的交换链图像获取信号量)是偷偷摸摸的。有一个偷偷摸摸的 vkQueueSubmit 参数,pWaitDstStageMask。该参数表示信号量不会早于 pWaitDstStageMask 中的管道阶段等待。因此,您实际上必须在那里放置一个依赖项,以便在信号量等待之后从渲染通道中推送布局转换:

pWaitDstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

VkSubpassDependency acquireDependency{
    VK_SUBPASS_EXTERNAL,// srcSubpass
    0,// srcStageMask
    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,// dstStageMask
    0,// srcAccessMask
    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,// dstAccessMask
    VK_DEPENDENCY_BY_REGION_BIT,// dependencyFlags
};

注意 pWaitDstStageMask = srcStageMask,因此 execution dependency chain 与信号量等待一起形成。这种依赖性还迫使布局转换远离 initialLayout 发生在信号量等待和渲染通道加载操作之间。

请参阅 this diagram 了解同步,以及需要同步的内容和原因:

enter image description here


对于更复杂的应用,它实际上变得更简单。请参阅official synch. examples。您只需在那里添加一个适用于图像上一次\下一次使用的依赖项。

例如如果您在渲染过程之后执行计算 (vkCmdDispatch),那么您只需使用 VK_SUBPASS_EXTERNAL 添加一个 dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT 依赖项。

,

源操作定义了依赖项的源命令范围,即与目标范围内的命令具有“先发生”关系的命令集。

范围通常是队列范围的(从技术上讲,它们还包括基于信号量等的队列内依赖链中的内容,但现在不要介意)。因此,当源范围讨论某个点之前的所有命令时,这意味着队列在该点之前按命令顺序执行的所有命令

外部作为子通道依赖项中的源“子通道”意味着渲染通道之前的所有内容。这就是渲染过程之前的一切。由该队列处理的每个命令直到它处理 vkCmdBeginRenderPass 命令为止。

如果队列处理的第一个命令恰好是开始渲染通道命令,则外部源范围是一个空集。但这并没有错。同步本质上是一个空操作。所以一切照常进行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。