Hello,
I implemented double buffering and I have a synchronization problem (flickering, rogue triangles) with buffers who are frequently updated (particles, grass, water waves…).
There are no validation layer errors.
- Vertex buffers usage:
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
- Index buffers usage:
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
- Memory property is
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
The synchronization works correctly if the vkQueueWaitIdle
is executed (see code).
I don’t see the point of adding barriers if a vkQueueWaitIdle
must is done.
If I understand well the barrier prevents commands form accessing vertices/indices until they are available to the GPU.
All the buffers requiring a double buffering synchronization are placed in a list (lstCopies
in the code).
This code is executed after vkBeginCommandBuffer
and before vkCmdBeginRenderPass
on cmdPrimary
.
void vk_sync_buffers(){
if(!lstCopies.n) return;
//util_log(LL_MSG, "%d buffer copies", lstCopies.n);
BUFCPY *cp;
VkMappedMemoryRange vkrange{};
VkBufferCopy vkcopy{};
VkBufferMemoryBarrier vkbarrier{};
vkbarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
vkbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkrange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
for(int i = 0; i < lstCopies.n; i++){
cp = lstCopies.atp(i);
vkrange.size = cp->sze;
vkrange.memory = cp->mem;
vkFlushMappedMemoryRanges(vkdevice, 1, &vkrange);
if(cp->vks != cp->vkd){
vkcopy.size = cp->sze;
vkCmdCopyBuffer(cmdPrimary, cp->vks, cp->vkd, 1, &vkcopy);
}
vkbarrier.buffer = cp->vkd;
vkbarrier.size = cp->sze;
vkbarrier.srcAccessMask = VK_ACCESS_2_NONE;
vkbarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
vkCmdPipelineBarrier( cmdPrimary,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_DEPENDENCY_BY_REGION_BIT,
0, NULL,
1, &vkbarrier,
0, NULL);
}
lstCopies.reset();
//vkQueueWaitIdle(glGraphicsQueue); //flickering without this wait
}