Intel TuT 4 uses a SubpassDependency but why?

Hello guys,
i have read part 4 of the Intel Tut (his tutorials are awesome! -> u can find it here: API without Secrets: Introduction to Vulkan* Part 4: Vertex Attributes) and
i am asking myself, why is he doing a Subpass-Dependency for only one Subpass?

std::vector<VkSubpassDependency> dependencies = {
  {
    VK_SUBPASS_EXTERNAL,                            // uint32_t                       srcSubpass
    0,                                              // uint32_t                       dstSubpass
    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,           // VkPipelineStageFlags           srcStageMask
    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags           dstStageMask
    VK_ACCESS_MEMORY_READ_BIT,                      // VkAccessFlags                  srcAccessMask
    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,           // VkAccessFlags                  dstAccessMask
    VK_DEPENDENCY_BY_REGION_BIT                     // VkDependencyFlags              dependencyFlags
  },
  {
    0,                                              // uint32_t                       srcSubpass
    VK_SUBPASS_EXTERNAL,                            // uint32_t                       dstSubpass
    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags           srcStageMask
    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,           // VkPipelineStageFlags           dstStageMask
    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,           // VkAccessFlags                  srcAccessMask
    VK_ACCESS_MEMORY_READ_BIT,                      // VkAccessFlags                  dstAccessMask
    VK_DEPENDENCY_BY_REGION_BIT                     // VkDependencyFlags              dependencyFlags
  }
};

VkRenderPassCreateInfo render_pass_create_info = {
  VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,        // VkStructureType                sType
  nullptr,                                          // const void                    *pNext
  0,                                                // VkRenderPassCreateFlags        flags
  1,                                                // uint32_t                       attachmentCount
  attachment_descriptions,                          // const VkAttachmentDescription *pAttachments
  1,                                                // uint32_t                       subpassCount
  subpass_descriptions,                             // const VkSubpassDescription    *pSubpasses
  static_cast<uint32_t>(dependencies.size()),       // uint32_t                       dependencyCount
  &dependencies[0]                                  // const VkSubpassDependency     *pDependencies
};

if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) {
  std::cout << "Could not create render pass!" << std::endl;
  return false;
}

I fully understand what the code means, but i am asking myself why i never saw this so far in other code-samples. Is this really necessary?
i dont doing anything like this in my engine and it works fine. Rendering/Presenting is syncronized with two semaphores (He is actually doing the same thing).

They’re dependencies between the subpass and the world outside of the renderpass instance. Hence the use of VK_SUBPASS_EXTERNAL for the source/destination subpasses.

Yea i know, i understand what this code does. But why i never seen anything like that in other tutorials / code samples? Basically this dependencies say’s that the presentation engine should not read until the color-writes are complete and vice versa that the application should not write until the reads are complete. At least i think that is what he is intented to do. But aren’t the two semaphores already does this kind of synchronization?

The External to 0 is necessary if you want to use semaphores for syncing acquire with render as otherwise the transition from present/undefined to color_attachment is could begin before the semaphore is signaled (it only blocks specific stages and transitions don’t have a stage).

The post render dependency is not necessary as the semaphore itself has enough implicit memory dependency to be correct…

At least for my examples I plan on using subpass dependencies in different places. The reason that most people (including myself) are using semaphores instead of subpass dependencies is because subpasses are a concept new to Vulkan. And the LunarG API examples didn’t use them (upon release) anyway, and I guess that’s where most people that wrote examples and tutorials started with :wink:

But after playing around with sub pass dependencies I’d prefer them in several places and plan on adding them at some point.

Thanks for the explanations, i think i got it now :slight_smile: