Hello community,
this is my scenario:
- graphics queue: draw world-space positions into an image (gbuffer)
- move ownership of image to compute queue to read the image data
- compute queue: process data (write into SSBO)
I get this callback error message:
Cannot submit cmd buffer using image (0xa) [sub-resource: aspectMask 0x1 array layer 0, mip level 0], with layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL when first use is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
Now some details, first approach:
The gbuffer image is created with the VK_SHARING_MODE_EXCLUSIVE
flag. Its supposed first time usage is in a render pass transitioning from VK_IMAGE_LAYOUT_UNDEFINED
to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
for rendering and stays in the latter layout after the pass.
At the end of the command buffer using that render pass I use an image memory barrier with the following pipeline barrier command:
VkImageMemoryBarrier image_to_compute_barrier = {
srcAccessMask : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
dstAccessMask : VK_ACCESS_SHADER_READ_BIT,
oldLayout : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
newLayout : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
srcQueueFamilyIndex : graphics_queue_family_index,
dstQueueFamilyIndex : compute_queue_family_index,
image : gbuffer_image,
subresourceRange : gbuffer_subresource_ange,
};
vkCmdPipelineBarrier( graphics_cmd_buffer,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, nullptr, 0 nullptr, 1, &image_to_compute_barrier );
The same barrier and command is used at the beginning of the compute command buffer later.
In the submit info I use a semaphore to signal the completion of the graphics command buffer:
VkSubmitInfo graphics_submit_info = {
waitSemaphoreCount : 0, // this submit shall happen first
pWaitSemaphores : nullptr,
pWaitDstStageMask : nullptr,
commandBufferCount : 1,
pCommandBuffers : &graphics_cmd_buffer,
signalSemaphoreCount : 1,
pSignalSemaphores : &gbuffer_semaphore,
};
As mentioned already, and as per spec for exclusive resource ownership transition, the same image memory barrier as above is used at the beginning of the compute command buffer. Next is binding of a compute pipeline, descriptors and the dispatch command. After that command the image is not used until the frame fence. In the compute submit info I wait on the gbuffer semaphore:
VkPipelineStageFlags gbuffer_wait_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo compute_submit_info = {
waitSemaphoreCount : 1,
pWaitSemaphores : &gbuffer_semaphore,
pWaitDstStageMask : &gbuffer_wait_stage_mask,
commandBufferCount : 1,
pCommandBuffers : &compute_cmd_buffer,
signalSemaphoreCount : 1,
pSignalSemaphores : &compute_done_semaphore, // some additional work is supposed to happen afterwards
};
The command buffers are recorded once and submitted multiple times to the corresponding queues, the order here should be irrelevant:
vkQueueSubmit( graphics_queue, 1, &graphics_submit_info, VK_NULL_HANDLE );
vkQueueSubmit( compute_queue, 1, &compute_submit_info, VK_NULL_HANDLE );
Stepping into the code with a debugger the error message happens right after the second submit command. My guess is that the compute queue does not wait on the gbuffer image transition and ownership release from the graphics queue, so (hope I gave enough info) what’s wrong with my setup?
My second approach was to transit the image to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
in the render pass. That got me a different error message which I don’t understand fully:
Source AccessMask 256 [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT] must contain at least one of access bits 48 [VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT] when layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, unless the app has previously added a barrier for this transition.
This error message comes only twice, once per pipeline barrier command. Why shouldn’t the transition from access VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
to access VK_ACCESS_SHADER_READ_BIT
be possible?
When I add VK_ACCESS_SHADER_READ_BIT
to the image memory barrier:
VkImageMemoryBarrier image_to_compute_barriere = {
srcAccessMask : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
dstAccessMask : VK_ACCESS_SHADER_READ_BIT,
oldLayout : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
newLayout : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
...
};
I get this message which I understand even less:
Additional bits in Source accessMask 0x120 [VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT] are specified when layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.