Weird behavior of vulkan Image layout transition for swapchain image while using a seperate command buffer

I can not past code snapshot here, because of too many codes. I will describe my problem by Vulkan validation error and renderdoc.

What I do

I create a render pass, initial/final layouts of the render target attachment(swapchain image) both are VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL . So I need to make some image layout transitions.

  • While creating swapchain: transite the layouts of swapchain images from VK_IMAGE_LAYOUT_UNDEFINED to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
  • At begining of a frame: transit the current layout of current render target to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
  • Before submiting rendering command buffer prior to the call of vkQueuePresentKHR: transite the current layout of current render target to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.

Also, I create two seperate command buffer, one for recording rendering command which will be submitted before vkQueuePresentKHR, another for recording vkCmdPipelineBarrier to transite the image layout which will be submitted before submitting render command buffer.

Validation Error

First validation error pops up after submitting rendering command buffer, second validation error pops up after the call vkQueuePresentKHR.

see image 1

It is weird that the first validation error is in submitting rendering command buffer instead of the command buffer for transiting image layout.

The first frame recorded by Renderdoc

The first frame is presenting swapchain image 157 as showed in renderdoc recording.

  • The image layout transition while creating swapchain

see image 2

My two command buffers are allocated from same command pool. Does anyone know what’s happening here?

Upadate:

if I use rendering command buffer to record vkCmdPipelineBarrier, no validation error appears. But I don know why a seperate trainsition command buffer can not work normally.

image1:

image2:

Crossposted at stack overflow.

Seems pretty obvious what the validation errors say. Your image is not in the expected layout for draw resp. present. Either you did not transition the layout before the subsequent image access, or you did not synchronize the transition with the access properly.

Yes, sorry for copying from stack overflow which is posted by me.

I understand what validation error means. However I don’t know why when I use a seperate command buffer to record and submit vkCmdPipelineBarrier, the validation error appears. And I use the same buffer as that for recording render commands, no validation error.

But from specification, vkCmdPipelineBarrier works on the whole queue, which means the commands after the barrier wiil be executed after finishing the execution of the commands before the barrier. So, using the seperate command buffer to submit vkCmdPipelineBarrier shold work same as using only one command buffer.

Or, maybe it’s related to the synchronization with the image layout tansition of insider the render pass. I would appreciate for any suggestion.

Annoying aspect of many software engineers is they are taking mental shortcuts. Most bugs\problems are obvious and facepalmy in retrospect…

Your mental shortcut is you are doing some refactoring of your code, and based on the nature of the refactor you expect certain behavior.

When we eliminate the impossible what remains will probably be true. Either your refactor is significantly different, or it simply triggers different codepath in Validation Layers or the coverage of the invalid usage checking is not reliable (and the code was incorrect before the refactor, just the error was not reported). In the end, that is nice mental gymnastics, but to get anywhere we are gonna have to do it the hard way anyway to figure out the problem.

Either way, if you want specific answer, you are gonna have to show specific code. I already gave you generic answer: either you misjudged your layout changing, or the sync gonna be incorrect (semaphores, fences, stage and acess flags) leading to the layout state to be ambiguous at some point in time.

My advice (if you prefer to figure stuff for yourself) is for you to take ol’ pen and paper and draw yourself a sync proof. What you are looking for is if your dependencies and sync of the problematic image forms a neat unbroken chain. It could look something like this (at page “Synchronization”).

The VK_LAYER_LUNARG_api_dump could also be useful to evaluate if Vulkan is being fed what you think you are feeding it. Most annoying bug is if you make a command buffer, but forget to ever submit it and stuff of this sort.

Also it is worth noting if the error happens at the first “frame” (resp. first iteration of the loop), or if it happens at later frames. Judging from the error I would guess it is from second frame and the layout state from previous frame is the problem (present layout). That points to a problem with synchronization across frames.

Thanks a lot for your experienced suggestions and explanation. I post this question for I’m not sure whether I correctly understand the barrier mechanism. Finally, I found the validation error is caused by a stupid logical mess.

This error is caused by the incorrect usage of separate command buffer. I submit the command buffer recording barrier before rendering command buffer. I think the execution barrier is ensuring the command execution sequence consistent with the recording order relative to barrier commands. My way will have the following execution results

vkCmdPipelineBarrier

vkBeginRenderpass
vkBindVertexBuffer
vkDraw
vkEndRenderpass

I set up barrier for transiting the layout of the image genreated by renderpass to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR. However, my wrong practice results in executing transition before executing a render pass. I’m so stupid.