4
votes

The vulkan docs mention that moving image layouts in render passes (see VkAttachmentDescription structure) is preferred compared to moving them using barriers (i.e. vkCmdPipelineBarrier). I can understand that since the latter introduce sync points which constrain parallel execution.

Now consider a typical example: A transition from VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. In this case the resource is going to be read in the shader, but in order to do that safely it is necessary to synchronize the writing of the color attachment with the reading in the shader. In other words we need to use a barrier anyway and moving the layout in the render pass doesn't seem to give any advantage at all.

Can somehow explain how all this works in detail? In which situations does one have a real advantage of moving layouts in render passes? Are there (practical) layout changes which do not require further synchronization?

1
It is called "transitioning" not "moving". - krOoze
May I have the quote where the recommendation is in the spec. I can't seem to find it. - krOoze
I see, it's indeed not in the specs. I got this from the Vulkan Programming Guide. That book is also using 'moving' instead of 'transitioning'. - S. Jordan
Instead of a pipeline barrier, You can (and even should) synchronize operations inside and after a render pass using render pass dependencies. They are designed exactly for this purpose. - Ekzuzy

1 Answers

4
votes

Firstly, you are not given a choice. The API forces you to provide finalLayout, and intermediate VkAttachmentReference::layouts. You can use vkCmdPipelineBarrier inside the render pass conditionally (aka subpass self-dependency), but one of the rules is you are not allowed to change the layout of an attached image:

If a VkImageMemoryBarrier is used, the image and image subresource range specified in the barrier must be a subset of one of the image views used by the framebuffer in the current subpass. Additionally, oldLayout must be equal to newLayout, and both the srcQueueFamilyIndex and dstQueueFamilyIndex must be VK_QUEUE_FAMILY_IGNORED.

So during a render pass, you can only change layout using the render pass mechanism, or you must be outside the render pass. That leaves only the "outside render pass" case to discuss:

Good way to think of a render pass is that it (potentially, based on platform) copies the resource (using loadOp) to specialized memory, and when done copies it back (using storeOp) back to general-purpose memory.

That being said, it is reasonable to assume you may get the layout transition to finalLayout for free as part of the storeOp. (And similarly the transition from initialLayout to first VkAttachmentReference::layout as part of the loadOp.) So, it makes sense to have the layout transition as part of the renderpass, if possible\convenient enough.