Vulkan: Is the rendering pipeline executed once per subpass?

Viewed 834

Considering a RenderPass that has multiple Subpasses:

Is the implication of multiple subpasses that the entire rendering pipeline is executed once per subpass? And that the image output of a prior subpass is accessible to subsequent subpasses, assumming correct subpass dependencies? (with the stipulation that reading prior image data happens at the same pixel location, for tile gpu optimation) I understand that hardware may optimize things out; it's more of a way of thinking about how the multi-subpass processing happens.

Extending this to multiple renderpasses, then is it the same thing as subpasses? except that image data from prior renderpasses can be accessed at any location, and that the synchronization between renderpasses uses different mechanisms that between subpasses.

Vulkan Rendering Pipeline

2 Answers

Pipeline is not "executed". Pipeline just exists. That's why it is called a pipeline, and not a state machine. The queue operations are the things that are executed.

With Vulkan's render pass it is good to know how tile-based architectures work. First they need to sort everything into tiles; that means they need to know the position of everything upfront. So, the geometry processing (vertex shader, geometry shader, tesselation shader, and all the relevant fixed-function stages) need to be finished for all the queue operations, before pixel processing (fragment shader, framebuffer writes, and other fixed-function stages) starts for any of them.

From that, the subpass restrictions are derived:

If srcSubpass is equal to dstSubpass and not all of the stages in srcStageMask and dstStageMask are framebuffer-space stages, the logically latest pipeline stage in srcStageMask must be logically earlier than or equal to the logically earliest pipeline stage in dstStageMask

I.e. you cannot have a vertex shader dependency waiting on a fragment shader output of previous ops. But you can have "framebuffer-space" dependencies; e.g. fragment shader waiting on fragment shader of previous ops.

Subpass dependencies are just another abstraction of the Vulkan API of how to express the synchronization between different commands (each of which can run through multiple pipeline stages). W.r.t. render passes, subpass dependencies serve two purposes:

  1. Expressing synchronization between the commands submitted within different render passes (that is when the VK_SUBPASS_EXTERNAL subpass-id is being used, see VkSubpassDependency
  2. Expressing synchronization between the commands submitted within the same or different subpasses. In this case, pairs of (0 and 0), or (0 and 1), and so on are specified for the srcSubpass and dstSubpass i a VkSubpassDependency structure, respectively.

Given the correct synchronization scopes, a subsequent subpass can read the rendered results of a previous subpass. Framebuffer attachments can be passed on via input attachments, which are specified in VkSubpassDescription. You can get an overview of this in this lecture from 43:28 onwards.

Regarding the "rendering pipeline is executed"-thing: The lecture mentioned above explains commands and how they go through pipeline stages in quite some details starting from 22:29. It should make things a lot clearer.

Regarding tiled GPUs: If you are referring to VK_DEPENDENCY_BY_REGION_BIT for VkSubpassDependency::dependencyFlags, the spec says the following:

VK_DEPENDENCY_BY_REGION_BIT specifies that dependencies will be framebuffer-local.

That means, you can only use the following pipeline stages with that flag:

  • VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
  • VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
  • VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
  • VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT

Valuable information about tile-based architectures are given in the other answer by krOoze already.

Related