2
\$\begingroup\$

As with most projects working in a graphics library, I need to dynamically send draw calls to the command buffers, but what is the best way to do this? Currently, for every frame, I rebuild my command buffers, specify the objects I wish to render, then destroy the command buffer. Am I doing it the right way? I thought there might be a clear command for the buffer but I still need to find it.

One other way I thought I could get it to work is when an object is needed to be displayed/removed, then and only then, I rebuild the command buffer. But again I'm not sure how to handle this properly.

Any help is really appreciated.

\$\endgroup\$
2
  • \$\begingroup\$ I'm pretty sure you're supposed to keep the command buffer and reuse it (that's the whole point of a buffer IMO), but then again it probably depends on how much changes. If we're talking about a few different frames only, I'd certainly try to keep them and then compare performance. Don't think this is something you can answer in general. \$\endgroup\$
    – Mario
    Jul 16, 2017 at 7:08
  • \$\begingroup\$ @Mario You seem to be right, now when I need to draw one or more new objects to the screen, I rebuild my command buffers then use it for all rendering requirements. Thanks! \$\endgroup\$
    – 0xen
    Jul 20, 2017 at 21:05

2 Answers 2

1
\$\begingroup\$

A good way is to keep several sets of resources, each set for a single frame. Each set should contain a command buffer (or more), a fence and two semaphores.

Now You record a command buffer (or more), potentially with ONE_TIME_SUBMIT flag, and submit it to a queue. During submission You wait for "image acquired" semaphore that was provided to vkAcquireNextImageKHR() function. You also provide the second semaphore and the fence to be signaled. Semaphore is used for vkQueuePresentKHR() function.

For the next frame You take another set of the above resources until You run out of all sets. Then You just take the set that is the oldest (least recently used). You check if the fence from this set is already signaled. If it is, You record the command buffer and perform all the usual job. If the fence is not signaled, You wait for it. But if You have 3 or 4 such sets there is a small chance that the fence isn't already signaled.

You can't re-record a command buffer while it still being processed, so You need to wait. But this approach lets minimize waiting. You don't need to use functions like vkDeviceWaitIdle() and thus stalling graphics hardware pipeline. It's also easier to balance memory consumption, input lag and performance. The more sets, the less wait and better performance, but more memory is used and potentially You increase input lag. Typically 2, 3, maybe 4, sets should be enough.

Example of such approach is described in the Vulkan Cookbook and presented on Github:

Increasing the performance through increasing the number of separately rendered frames

\$\endgroup\$
0
\$\begingroup\$

Currently, for every frame, I rebuild my command buffers, specify the objects I wish to render, then destroy the command buffer. Am I doing it the right way?

Assuming you're not just rendering the exact same content over and over again, you're most likely going to have to do some command buffer creation and recording on a per-frame basis.

However, you can look into the use of secondary command buffers to contain many of the individual drawing commands. These secondary command buffers would not need to be re-recorded each frame, but could be updated only when the rendering for some item in the command buffer is actually modified.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .