单个子通道的子通道依赖性。如何?

Subpass dependencies for a single subpass. How to?

所以我有一个渲染通道和一个直接绘制到帧缓冲区的子通道。规范不强制我使用依赖项——如果我省略它们,实现会隐式插入它们(尽管我不明白为什么它使用 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT 作为第一个子通道——这个阶段意味着最开始,即不要不要等待任何事情)。

但与 Vulkan 一样 - 最好是明确的。这就是混淆 - 多个来源使用不同的子通道。

  1. Sdk 的立方体示例根本没有使用它们。

  2. Vulkan 教程只使用一个:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = 0;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    这里为什么srcAccessMask为零?

  3. API 没有秘密使用两个:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    dependency.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    dependency.srcSubpass = 0;
    dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    

    不太清楚为什么 srcStageMask VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT 在第一个子通道中 - 不是 这个阶段应该用于执行依赖,但在这里我们 需要内存依赖?关于为什么 dstStageMask 的相同问题 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT在第二个subpass中吗?

  4. Khronos同步实例使用一个:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = 0;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    为什么srcAccessMask是0?

  5. 这是我对两个依赖项的尝试:

        dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
        dependency.dstSubpass = 0;
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // need to wait until
    presentation is finished reading the image
        dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // we are writing to
    the image in this stage
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    
    and
    
        dependency.srcSubpass = 0;
        dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // we are writing to
    the image in this stage
        dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // presentation reads
    image in this stage (is it?)
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
    

这一切都非常令人困惑。如您所见,多个有能力的消息来源有不同的看法。使用哪一个?如何理解这些依赖?

天哪,这是一个大多数人都不太了解的话题。许多错误信息被假定并扩散开来。规范示例的适当位置是 wikipage in the github repo

可以找到关于交换链图像 acquire/present 的相关部分 here

  1. 这是许多同步细节被正确确定之前的旧示例。

  2. 目的是同步信号量使用以等待 vkAcquireNextImage 的结果与渲染。这是一个读后写的危险,信号量将包括内存可见性同步。所以 srcAccessMask 是没有必要的。

  3. 同样,障碍是为了与信号量同步。将命令缓冲区提交到队列时,您可以设置哪些阶段等待哪些信号量。在这种情况下,他们使用管道底部而不是 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT

  4. 与 2 相同的答案,唯一不同的是 dstAccessMask

  5. 我在上面链接的 wiki 页面使用了以下内容:

    /* Only need a dependency coming in to ensure that the first
       layout transition happens at the right time.
       Second external dependency is implied by having a different
       finalLayout and subpass layout. */
    VkSubpassDependency dependency = {
        .srcSubpass = VK_SUBPASS_EXTERNAL,
        .dstSubpass = 0,
        // .srcStageMask needs to be a part of pWaitDstStageMask in the WSI semaphore.
        .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
        .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
        .srcAccessMask = 0,
        .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
        .dependencyFlags = 0};
    
    /* Normally, we would need an external dependency at the end as well since we are changing layout in finalLayout,
       but since we are signalling a semaphore, we can rely on Vulkan's default behavior,
       which injects an external dependency here with
       dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
       dstAccessMask = 0. */
    

    您混淆了第二个障碍的子通道索引。尽管如评论中所述,在 renderpass 的末尾已经存在一个隐式屏障,它反过来与您用来与当前同步的信号量或栅栏同步。所以不需要显式依赖。