Understanding subpass dependencies for memory layout transitions

I am trying to understand what is implied by the following subpass dependency. Let me show it first and then state my understanding and confusion:

VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

What I understand from this dependency is this: Subpass 0’s (I have only one subpass) color attachment write operation will wait for the external subpass’es VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage. I think that this understanding is true, however: I do not any earlier command buffer submits – so in this case VK_SUBPASS_EXTERNAL should refer to the implicit memory layout transition subpass which transitions the memory from an UNDEFINED layout to the OPTIMAL one (sorry for not writing the full names – I hope it is clear). If this is the case, what is the meaning of the VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT in this context?

If this was a proper subpass rendering to a color attachment, it would make more sense to me. But for an implicit memory transition subpass COLOR_ATTACHMENT_OUTPUT doesn’t seem right. Maybe they abused the term?

As a related question (and to better clarify my confusion), how many COLOR_ATTACHMENT_OUTPUT stages occur in this case? Are there two with the first one being the output of the memory transition and the second one for the actual color buffer writes of subpass 0?

As one final question, if I have a semaphore waiting for the VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT as follows:

VkSemaphore waitSemaphores[] = {imageAvailableSemaphore};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;

Is this semaphore going to be signaled after the memory transition’s VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT or subpass 0 output’s VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage?

If my undestanding of this concept is totally wrong, I would be happy to know.

The subpass dependency refers to any operations that make memory available to the color attachment output stage. The barrier that provokes the layout transition to the color attachment optimal layout should have the output color attachment as part of its dstStageMask.

A semaphore wait operation waits until a semaphore is signaled. It doesn’t get signaled by waitStages; it gets signaled by some batch that signals the semaphore. So if you want to know when this wait will pass, you need to look at the semaphore signal operation it’s waiting on.

Thank you. Regarding your answer:

A semaphore wait operation waits until a semaphore is signaled. It doesn’t get signaled by waitStages ; it gets signaled by some batch that signals the semaphore. So if you want to know when this wait will pass, you need to look at the semaphore signal operation it’s waiting on.

I am sorry that I confused signaling of a semaphore with waiting on a semaphore. You are right that this semaphore is signaled by another operation, namely vkAcquireNextImageKHR.

But I still do not understand the first part. VkSubpassDependency has two subpasses: source and destination. Because source is EXTERNAL it refers to everything before the subpass. In my case “everything” is only a memory layout transition from UNDEFINED to OPTIMAL.

So when I submit my command buffer that contains only this subpass, the execution of my command buffer waits at the VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage of the pipeline. When the vkAcquireNextImageKHR function signals this semaphore, the pipeline continues. Precisely what happens after this point is my question.

So is the first thing that happens after this point is the memory transition? (It didn’t happen before because the pipeline was stalled at this point?). And when this happens, does it trigger the VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT defined in the dependency (not the semaphore). And then when this happens, can the actual WRITE action of the subpass be performed?

My understanding is that the actions of the subpass other than the memory transition and writing to the color buffer could be actually finished before we obtained the image from the swap chain. As soon as vkAcquireNextImageKHR signals the semaphone these actions can proceed. Among these two actions memory transition is the first one. The finishing of the memory transition is indicated by dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT When this happens the actual color buffer write of the subpass can proceed (because we said dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT and dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT). Would be great to get a confirmation that this undestanding is correct.

Layout transitions do not exist in a vacuum. That layout transition is part of some kind of execution dependency which has a dstStageMask attached. That’s what matches with the external subpass layout transition.

My understanding is that the actions of the subpass other than the memory transition and writing to the color buffer could be actually finished before we obtained the image from the swap chain. As soon as vkAcquireNextImageKHR signals the semaphone these actions can proceed.

Either you’ve set up your dependencies correctly or you haven’t. When you waited on the semaphore, you set a destination stage mask. If you want the acquired image to be used for color attachment output operations, then that stage needs to be included in the mask.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.