Memory buffer masks and stages

#1

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?

#2

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.

#3

You cannot use a pipeline barrier to synchronize between queues. The only tool for inter-queue sync is a semaphore.

#4

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?

#5

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?

#6

I realized that a single VkSubmitInfo can contain multiple command buffers.

This brings me back to square one: My memory barriers are not working.

#7

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.

#8

Which validation layer? The SDK comes with several.

#9

VK_LAYER_LUNARG_standard_validation

#10

I also just tried VK_LAYER_KHRONOS_validation and was found and produced no errors.

#11

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.

#12

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.

#13

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