I get occasional flickers in my renderer where part of the scene disappears for an instant. This should not happen, ever. I think it is due to memory being used as it is being written to.
I have data being uploaded in a few buffers and then accessed for indirect drawing instructions, vertex and index data, and object matrices. My memory barriers are set up with the following values:
memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
memoryBarriers.push_back(memoryBarrier);
And then they are submitted like this:
vkCmdPipelineBarrier(commandbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, memoryBarriers.size(), memoryBarriers.data(), 0, nullptr);
Am I missing a mask or other value I need to add to make these work correctly?
In fact, the only way I can get these glitches to go away is inserting a call to vkDeviceWaitIdle() after the transfer queue is submitted, before the drawing queue is sent.
You cannot use a pipeline barrier to synchronize between queues. The only tool for inter-queue sync is a semaphore.
Sorry, I think I have my terminology wrong.
I mean they are two different command buffers in the same queue. I can submit them in two calls to vkQueueSubmit() or a single call like this:
vkQueueSubmit(environment->devicequeue[0], 2, &submits[0], inFlightFences[currentFrame]);
Two command buffers are used. The first handles data transfer and is re-recorded each frame. The second other handles rendering and is reused several times before the set of visible objects changes.
Hmmmm, looking over my other code, I am guessing the transfer command buffer should have a signal semaphore it marks when completed, and that signal semaphore is then used as a wait semaphore for the second command buffer?
No. Semaphores are for signaling the completion of batches to other queues. If you have stuff in the same queue, you shouldn’t use a semaphore.
Also:
accessed for indirect drawing instructions, vertex and index data, and object matrices
So why does your dstAccessMask
only include indirect commands and vertex attributes? Indices are a separate bit.
Oh, and what validation layers are you using? And what of the contents of the memory barrier used in this pipeline barrier?
I realized that a single VkSubmitInfo can contain multiple command buffers.
This brings me back to square one: My memory barriers are not working.
I’m using the LunarG validation layer.
I’m confident the buffer data is correct. There are two buffers being uploaded each time a new visibility set occurs. One is full of objects IDs, which is accessed by the vertex shader, and the other is full of IndirectDraw data.
I reversed the order of the command buffer array the VkSubmitInfo object contains and it made the problem worse, which is good for testing.
VK_LAYER_LUNARG_standard_validation
I also just tried VK_LAYER_KHRONOS_validation and was found and produced no errors.
I wonder if the memory write is being interfered with a write that a previous frame is still performing? Each image in the swap chain has one command buffer for data transfer, and they use a pool of staging buffers to copy data into a single shared buffer.
I set up a series of semaphores inbetween frames and in between the transfer and draw command buffers, and I still get occasional objects disappearing. If it happens even once there is something seriously wrong.
Here is what I am doing. Blue arrows are semaphores. Green arrows are buffer writes. Red arrows are buffer reads.

The staging buffers are mapped and copied to before the command buffer begins, so I don’t think those need a memory barrier. I do need a memory barrier after the staging buffer is copied to the storage buffer, before it is read from. The data being sent is a list of object IDs, which indicate a position to lookup the object’s 4x4 matrix.
What are the correct settings for this? By my understanding, I should only need this:
memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(commandbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &memoryBarrier, 0, nullptr);