Reputation: 85
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.
Upvotes: 5
Views: 3888
Reputation: 51
To answer your questions: Normaly you clear when the frame begins, before you render something. beginRenderpass can only be called by the primary commandbuffer, secondary commandbuffer must not invoke this call. Basically you are starting a renderpass instance in the primary commandbuffer(only commandbuffer that you can submit to the queue), This is what you will be doing on each frame.
but you can clear one or more regions of color and depth/stencil attachments inside a render pass instance, by calling vkCmdClearAttachments regardless whether it is LOAD_OP_CLEAR / LOAD_OP_DONT_CARE, or if you want to do it out side the renderpass you use vkCmdClearColor/DepthStencilImage. this can be called by either the primary command buffer or secondary commandbuffer.
Tip: using LOAD_OP_DONT_CARE may optimized on some drivers, if you are sure that you will overwrite the entire the screen written by the previous frame. so the drivers don't have to load/copy the memory from the presenation buffer for the current renderpass to clear it.
you can use vkCmdClearAttachment command in the secondary comandbuffer to clear any attachment. But you cannot submit them by itself, it has to be put inside the primary commandbuffer.
So does that mean that every submitted command buffer starts a new renderpass and so clears the attachments? is it a misunderstanding of vkCmdBeginRenderPass? yes every submit commandbuffer starts the renderpass and clear the fbo attachments.
Does it not actually begin a new render pass when there is one running already? Renderpass contains the executation order of the framebuffer. it has states. the states are reused on each frame. you can use another renderpass (different state) with the same fbo. so the first renderpass can clear it and the second renderpass don't clear at the beginning of the frame.
you cannot call another renderpass inside renderpass instance. what you see below is invalid
Commandbuffer.beginRenderpass(renderpass1, fbo, ClearValues);
Commandbuffer.beginRenderpass(renderpass2, fbo, ClearValues);// ERROR
Commandbuffer.end;
you have to end the renderpass1 instance before you begin the second renderpass. should be like this
Commandbuffer.beginRenderpass(renderpass1, fbo, ClearValues);
// draw scene
Commandbuffer.end;// renderpass is ended
Commandbuffer.beginRenderpass(renderpass2, fbo, ClearValues);
// draw full screen quad
Commandbuffer.end;
Commandbuffer.beginRenderpass(renderpass3, fbo, ClearValues);
// draw full screen quad
Commandbuffer.end;
let say that in the above example the fbo has 3 attachment. we are using 3 renderpass here. First: Render the scene in to the attachment 1 using the renderpass1. Second: Read from the attachment 1 and do a Vertical Blur and write into attachment 2 using renderpass2. third: Read from the attachment 2 and do a Horinzontal blur and write in to the swapchain image using renderpass3. (Note: for this particular techniqueue we cannnot use multiple subpass thats why I'm using 3 renderpasses for the same fbo.)
Upvotes: 0
Reputation: 3457
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.
Upvotes: 5