Search code examples
renderervulkan

What is the relation between render passes, command buffers and clearing of attachments in vulkan?


I am currently learning vulkan and came across above question that I can't seem to answer by reading the spec.

When looking at the spec and code samples, it's always the same simplified workflow:

begin commandbuffer 
    begin renderpass
        bind stuff (pipeline, buffers, descriptor sets)
        draw
    end renderpass
end commandbuffer

create_submit_info
submit_to_graphics_queue

Now the first thing that's a little unclear to me is when to clear the attachments. If I create my attachments with LOAD_OP_CLEAR then I have to supply clear values for VkRenderPassBeginInfo, but every command buffer contains a vkBeginRenderpass. So does that mean that every submitted command buffer starts a new renderpass and so clears the attachments? That does not sound right.

If I specify LOAD_OP_DONT_CARE then I have to use vkCmdClear which kind of asks for a seperate command buffer just for clearing the attachments. Which can't be right either.

So can someone please clearify the relation between command buffers and render passes for me?

Or is it a misunderstanding of vkCmdBeginRenderPass? Does it not actually begin a new render pass when there is one running already?!

Thank you for helping.


Solution

  • Command buffers are responsible for storing commands that later get submitted to queue(s) and processed by the hardware. It is the only way to perform operations in Vulkan - record them and then submit. But the important thing is that each command buffer is totally independent from all other command buffers. If You want to perform a specific job, You need to record all the necessary commands that set appropriate state into the command buffer. If You want to perform similar job in another command buffer, You need to record the same set of commands in this other command buffer because there is no state sharing between command buffers. They are all independent. (There are some exceptions but they are not relevant for this discussion as they involve only secondary command buffers).

    Next, in Vulkan rendering can only occur inside render passes. Render pass is a general definition of steps (called subpasses) drawing commands are divided into and of rendering resources (and relationships between them) needed for these drawing commands (attachments). But this is just description, metadata. You define how these attachments are used (as color attachments, as depth attachment, as input attachments) and what are their layouts in each subpass. You also define what to do with each attachment before the render pass (load op) and after the render pass (store op).

    Now the actual resources used for these attachments are defined through framebuffers. This way You can perform similar rendering operations on various sets of images (by using various but compatible framebuffers) without the need to recreate render passes. And which framebuffer should be used during rendering is defined when You start a render pass.

    Now when we combine the above information, render pass and command buffer, we get this: each command buffer is independent, so rendering must start and end during a single command buffer (excluding secondary command buffers). So that also means that You need to start and end a render pass within a single command buffer (but of course You can also start and end multiple render passes in a single command buffer).

    So does that mean that every submitted command buffer starts a new renderpass and so clears the attachments?

    If You want a command buffer that only performs math calculations by executing compute shaders, then You don't need render passes. So such command buffer doesn't need to start and end any render pass and it doesn't need to clear any attachments. But if You want to render in a command buffer, then yes, each such command buffer must start (and end) a render pass. If rendering involves clearing, then each command buffer that needs to perform such operation will also need to clear attachments.

    Or is it a misunderstanding of vkCmdBeginRenderPass? Does it not actually begin a new render pass when there is one running already?!

    vkCmdBeginRenderPass() starts a new render pass, yes, but in a single command buffer You cannot start another render pass until previous render pass is ended. You must explicitly start a render pass and end it. Only after that You can start another render pass (in the same command buffer).

    As for clears, they are also defined during beginning of a render pass, which allows You to clear attachments with different colors. This way You don't have to create a separate render pass every time You want to change "background" color.

    And one more thing about attachment clearing: unless really necessary, use render pass clears (LOAD_OP_CLEAR) instead of explicit clears (vkCmdClear()) as they may hurt performance (render pass clears are recommended by most of the vendors as far as I know).

    I hope this hope clarifies this topic.