I'm currently working on a Vulkan implementation which would let me feed a vertex and index buffer with new data prior to each draw, which is very useful for rendering primitive lists and UI. However, since the vkCmdUpdateBuffer cannot be done within a render pass, I though I would do something akin to the good old glFenceSync method.
So I have a thread which waits for the GPU to finish, then I do my work (memcpy to coherent buffer), then I want to signal my GPU to continue. Sounds easy enough, but no matter what I supply to vkCmdWaitEvents, my driver crashes.
In my scenario, I perform vkCmdWaitEvents to a secondary command buffer, ran within a render pass, I supply it with srcStageMask = VK_PIPELINE_STAGE_HOST_BIT and dstStageMask = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, event count is 1, and the event array is a pointer to a single event allocated at application start. In order to also ensure events run in order, I insert a memory barrier with srcAccessMask = VK_ACCESS_MEMORY_READ_BIT and dstAccessMask = VK_ACCESS_HOST_WRITE_BIT.
However, no matter what type of barrier I use, or what stage masks I am using for the actual call, the driver resets. Vulkan driver version is 1.2.
Edit: I think I found my answer, the last requirement for vkCmdWaitEvents is: "If
pEvents includes one or more events that will be signaled by
commandBuffer has been submitted to a queue, then
vkCmdWaitEvents must not be called inside a render pass instance." which is exactly what I am doing, so my way is invalid usage.
But then the question becomes how this issue is to be solved? Is it perhaps better to just allocate a big chunk of vertices and indices and hope we won't render more than we can handle? I don't see any other way unless we can work in lockstep somehow.