Memory buffer masks and stages

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.

Which validation layer? The SDK comes with several.

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.
Untitled%20Diagram%20(1)

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);