Given that I have two different shaders, thus I've got two different VkPipeline
s. They'll work together to render on the same color attachment and depth attachment. (I'm using dynamic rendering so no render pass/subpass here). The second pipeline may rely on the first pipeline's output.
My current renderFrame
records command buffer like this:
vkCmdBeginRendering (with attachments load op = clear, store op = ?)
vkCmdBindPipeline - bind the first pipeline
vkBindVertexBuffers
vkCmdDraw
vkCmdEndRendering
vkCmdBeginRendering (with same attachments, load op = ?, store op = store/don't care)
vkCmdBindPipeline - bind the second pipeline
vkBindVertexBuffers
vkCmdDraw
vkCmdEndRendering
And here are my questions:
storeOp
should I use for the first vkCmdBeginRendering
, and what loadOp
should I use for the second vkCmdBeginRendering
?Till now I'm
storeOp
= VK_ATTACHMENT_STORE_OP_STORE
, depth attachment storeOp
= VK_ATTACHMENT_STORE_OP_DONT_CARE
for the first vkCmdBeginRendering
loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
, depth attachment loadOp
= VK_ATTACHMENT_LOAD_OP_DONT_CARE
for the second vkCmdBeginRendering
And that works on my platform (Windows 10/Linux + AMD GPU) without validation layers complaining about anything. But I want to be safe here, so posting this question.
My original project is a little big and the tech stack is a little bit weird, so I'm not posting real code here.
Edit 1: I've found that I don't actually need multiple vkCmdBeginRendering
to use multiple pipelines:
vkCmdBeginRendering
vkCmdBindPipeline - bind the first pipeline
vkBindVertexBuffers
vkCmdDraw
vkCmdBindPipeline - bind the second pipeline
vkBindVertexBuffers
vkCmdDraw
vkCmdEndRendering
And the "synchronization" problem between multiple vkCmdDraw
family commands has already been elaborated here and here. No synchronization is required.
However I still wonder the answer to the original question, since a pipeline can write to multiple attachments, and two pipelines may only share some output attachments (though I've not got a real-world example yet).
Do I need some kind synchronization/barrier between the two pipelines?
As a general rule of thumb, even with dynamic rendering, you are required to manage the synchronization yourself. And when 2 render passes (dynamic or normal) write to same attachment, or one writes and one reads from same attachment, you need pipeline and memory barriers to synchronize the use. This is not needed for 2 simultaneous reads. In the Edit, you removed the vkCmdEndRendering and vkCmdBeginRendering at the end of 1st pass, so you won't need synchronization anymore. But, this means that you cannot read from the results of 1st pipeline from the 2nd pipeline. Because they are now the same pass.
What storeOp should I use for the first vkCmdBeginRendering, and what loadOp should I use for the second vkCmdBeginRendering
You mentioned that your 2nd pass may rely on first pipeline's output. So you may use storeOp Store in 1st pass, and loadOp load in 2nd pass.