1

In Sascha Willems's offscreen rendering sample, there are 2 VkSubpassDependency for the main renderPass, and 2 for the offscreen renderPass. First, I often see pairs of VkSubpassDependency, and don't understand why.

VkSubpassDependency of the main renderPass:

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

VkSubpassDependency of the offScreen renderPass:

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

In the main renderPass, is the second VkSubpassDependency (dependencies[1]) only here for the presentation to the swapchain? Is it mandatory?

For the offScreen renderPass, in a general way I don't understand the point of dependencies[0]:

As we only need to write into the framebuffer, and tell the main renderPass when it is finished, it seems to me that's what the dependencies[1] do.

What is the meaning of dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; because there is no other pass involved before the offscreen renderPass. Is it just for the offscreen renderpass to wait the main renderPass finish the presentation into the swapchain?

My last question is more specific: if I use these 4 VkSubpassDependency, in a similar way Sasha does in this sample, so in order to do an offscreen renderPass, I've got a validation error "Dependency graph must be specified such that an earlier pass cannot depend on a later pass." I can't find anything about this error on the internet. I just found that this error is triggered because: dependency.srcSubpass > dependency.dstSubpass. Any idea?

Here is the link for Sascha Willems's offscreen rendering sample: https://github.com/SaschaWillems/Vulkan/blob/master/examples/offscreen/offscreen.cpp

Leon
  • 554
  • 4
  • 18

1 Answers1

3

This question is similar to Order of action commands using subpass dependency?, being the same codebase.

The examples are bit dated, as I say in SaschaWillems/Vulkan#665. The specification was massively clarified since then. So there are some unnecesserily confusing arguments there occasionally.


main renderPass, dependencies[1]

Yes, this kind of dependency is typical when it is followed by a semaphore signal. E.g. with presentation to the swapchain.

Now, a dst external dependency with dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT does not do anything. Resp. it is the same as the implicit dependency. Still, it is esthetic choice to be explicit in the case anyway.

VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT has no accesses, so dstAccessMask should just be 0.

VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT is bit confused about which access the last access is. The last access to color attachment is the storeOp, which is just VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT for either STORE or DONT_CARE.


offScreen renderPass, dependencies[0]

The dst side of the dependency should be obvious. It is just the color buffer access. It should match the loadOp, which in the case of CLEAR of color buffer is VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT and VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.

Now, src is VK_ACCESS_SHADER_READ_BIT in VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT. That is the image being accessed as texture in the fragment shader. There seems to be only one offscreen framebuffer. So, without studying the sample too much I would assume this dependency makes sure the "main renderPass" finished reading the offscreen buffer, before it is written by the offscreen renderPass again.


What is the meaning of dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; because there is no other pass involved before the offscreen renderPass.

Of course there is. It goes like this: offscreen, main, offscreen, main, offscreen, main, offscreen, main, ... . So unless it is the first frame, there is always something before a given render pass.


I just found that this error is triggered because: dependency.srcSubpass > dependency.dstSubpass. Any idea?

That's right. Seems you figured it out?

the srcSubpass and dstSubpass must be either VK_SUBPASS_EXTERNAL, or srcSubpass must be less than dstSubpass, as not to accidentally create cycles and deadlocks in the dependency DAG.

krOoze
  • 12,301
  • 1
  • 20
  • 34
  • Thank you for such a complete response. I just don't get why with the same dependencies than the sample, my srcSubpass < dstSubpass. Does the renderPass creation order matter? – Leon May 26 '20 at 17:15
  • No, the order does not matter. Probably some trivial mistake, if you are not aware of the argument values. You can use the `VK_LAYER_LUNARG_api_dump` to see what Vulkan sees. – krOoze May 26 '20 at 20:17
  • I spent 3 hours trying to compile VulkanTools on ubuntu in order to get VK_LAYER_LUNARG_api_dump for android. I suppose I'm not bearded enough for this kind of operation. – Leon May 26 '20 at 22:41
  • @Leon Ah, I didn't know this is Android. Then I guess just print your `srcSubpass` and `dstSubpass` immediately before the `vkCreateRenderPass`, or however else you are debugging on that platform... I would recommend to retain some ability to test run your code on desktop; it massively simplifies things, I think. – krOoze May 27 '20 at 00:18