What stages can be set for srcStageMask/dstStageMask
when submitting a vkCmdPipelineBarrier
out of a renderpass, because in such case there is no subpass bind point to graphics pipeline?
The same question for when submitting vkCmdPipelineBarrier
in subpass that has a bind point to a compute pipeline which I guess doesn't have stages like VK_PIPELINE_STAGE_VERTEX_SHADER_BIT and maybe many more.
Thanks
Edit
First, thanks to @Nicol Bolas comment, a compute shader can not be dispatched in middle of subpass.
And I would like to clarify my question:
Say I have an image that after a renderpass will have the layout of VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
After the renderpass, I want to update the image with new data and wish to change its layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
Thus, after recording vkCmdEndRenderPass I record a vkCmdPipelineBarrier command as follows:
const VkImageMemoryBarrier imageMemoryBarrier =
{
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
nullptr,
VK_ACCESS_SHADER_READ_BIT, // srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // oldLayout
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
image,
{ // subresourceRange
VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
0, // baseMipLevel
VK_REMAINING_MIP_LEVELS, // levelCount
0, // baseArrayLayer
VK_REMAINING_ARRAY_LAYERS // layerCount
}
};
vkCmdPipelineBarrier(currentCommandBuffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
This ensures transition waits as long as previous command within renderpass still didn't cross the fragment shader stage.
But what if vulkan executes vkCmdPipelineBarrier after renderpass execution already finished? now there is no bound pipeline , no stages - does it means the barrier will go into an endless wait until a new renderpass will begin and a fragment shader stage will happen?
If I got everything right, then what you want to synchronize is the following:
You would like to ensure that the image is not overwritten with new data before a preceding renderpass has finished reading the image.
To achieve this, you have set up barriers which synchronize
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: SHADER_READ -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
While these synchronization parameters ensure correctness, they are actually a bit more than necessary. The srcAccessMask
is used for memory that needs to be "made available", which means ~transfer into L2 memory, so that it can be accessed afterwards.
This is the part which is unnecessary in your barrier, because the memory already is available (in L2 memory), otherwise it could not have been read properly.
I.e. the optimal barrier would be as follows:
Execution: FRAGMENT_SHADER -> TRANSFER
Memory: 0 -> TRANSFER_WRITE
Layout: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL
Now to the question about
But what if vulkan executes vkCmdPipelineBarrier after renderpass execution already finished?
What a recorded barrier like those above tell your GPU is the following:
FRAGMENT_SHADER
stage to have completed their FRAGMENT_SHADER
stages before continuing with subsequent commands in their TRANSFER
stages.That also means:
FRAGMENT_SHADER
stages, we don't wait for them.src
dependencies of a barrier never refer to something that might be submitted in the future, only to things that have been submitted previously.If you have difficulties with these things, you might want to have a look at the Introduction to Vulkan lecture which covers such synchronization topics from 22:28 onwards.