Can one subpass' bottom of pipe be synchronized with another subpass' top of pipe?

#1

In a framework I am developing, I want to create default subpass dependencies if none are specified. These default subpass dependencies shall be safe, i.e. ensure the correctness of the application and potentially sacrifice on the performance a bit.

I am thinking of the following default dependencies:

VkSubpassDependency incomingDependency = {
    .srcSubpass = VK_SUBPASS_EXTERNAL;
    .dstSubpass = firstSubpass; 
    .srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    .dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;;
    .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    .dependencyFlags = 0;
};

VkSubpassDependency outgoingDependency = {
    .srcSubpass = lastSubpass;
    .dstSubpass = VK_SUBPASS_EXTERNAL;
    .srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    .dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    .dependencyFlags = 0;
};

In words, they would mean (or at least that’s what I want them to mean):

  1. Sync whatever comes before with my firstSubpass for the most common operations (i.e. access masks.
  2. Sync whatever comes after with my lastSubpass for the most common operations (i.e. access masks)

The first questions would be: Are these two dependencies a good idea? What about the access masks? They would synchronize any of the stated operations, right?

What bothers me the most is a note from the specs which goes like this:

An execution dependency with only VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT in the destination stage mask will only prevent that stage from executing in subsequently submitted commands. As this stage does not perform any actual execution, this is not observable - in effect, it does not delay processing of subsequent commands. Similarly an execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage mask will effectively not wait for any prior commands to complete.

What does this mean? Does this mean, that the dependencies like I have specified them, would actually NOT synchronize anything? If it doesn’t mean that, what else is meant by “in the source stage mask will effectively not wait for any prior commands to complete”?

If I really can not achieve synchronization with the two dependencies stated above, how else do they have to be configured?

#2

Aren’t subpasses already implicitly synchronized? If I’m not mistaken, the writes in one subpass are guaranteed to be visible in subsequent subpasses.

I linked this article in your other post(Confusion about the implicit subpass dependencies):
https://www.jeremyong.com/c++/graphics/gpu/vulkan/2018/11/23/vulkan-synchonization-primer-part-ii.html
In fact, the author states that the primary reason that renderpasses exist is for “providing synchronization between draw calls over a shared set of render targets”.

#3

Not without an explicit subpass dependency.

#4

You must have read it wrong. It provides synchronization (of output attachments) between draw calls within single subpass. Rest still needs to be synced.

Well, one does not pick Vulkan to be “safe”. But it is good idea to have those in some debug build. Basically use VK_PIPELINE_STAGE_ALL_COMMANDS_BIT and VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT everywhere. (Render passes might complain and require instead VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT).

Nope, as we established in the other thread. Also write things explicitly; colleagues will thank you. srcStage = TOP and dstStage = BOTTOM means least restrictive synchronization.