From what I understand there are several methods for storing and transferring vertex data to the GPU.
- Using a temporary staging buffer and copying it to discrete GPU memory every frame
- Using shared buffer (which is slow?) and just update the shared buffer every frame
- Storing the staging buffer for each mesh permanently instead of recreating it every frame and copying it to the GPU
Which method is best for storing animating mesh data which changes rapidly?
It depends on the hardware and the memory types it advertises. Note that all of the following requires you to use vkGetBufferMemoryRequirements
to check to see if the memory type can support the usages you need.
If hardware advertises a memory type that is both DEVICE_LOCAL
and HOST_VISIBLE
, then you should use that instead of staging. Now, you still need to double-buffer this, since you cannot write to data that the GPU is reading from, and you don't want to synchronize with the GPU unless the GPU is over a frame late. This is something you should also measure; your GPU needs may require a triple buffer, so design your system to be flexible.
Note that some hardware has two different heaps that are DEVICE_LOCAL
, but only one of them will have HOST_VISIBLE
memory types for them. So pay attention to those cases.
If there is no such memory type (or if the memory type doesn't support the buffer usages you need), then you need to profile this. The two alternatives are:
- Staging (via a dedicated transfer queue, where available) to a
DEVICE_LOCAL
memory type, where the data eventually gets used.
- Directly using a non-
DEVICE_LOCAL
memory type.
Note that both of these require buffering, since you want to avoid synchronization as much as possible. Staging through a transfer queue will also require a semaphore, since you need to make sure that the graphics queue doesn't try to use the memory until the transfer queue is done with it. It also means you need to deal with chapter 11.7: how to share resources between queues.
Personally though, I would try to avoid CPU animated vertex data whenever possible. Vulkan-capable GPUs are perfectly capable of doing any animating themselves. GPUs have been doing bone weighted skinning (even dual-quaternion-based) for over a decade now. Even vertex palette animation is something the GPU can do; summing up the various different vertices to reach the final answer. So scenes with lots of CPU-generated vertex data should be relatively rare.