具有可变实例计数的 Vulkan vkCmdDraw

问题描述

当我定义命令缓冲区时,我需要事先指定顶点数和实例数。这是否意味着如果我想动态更新实例的数量,我需要重新编译整个命令缓冲区?只是改变这个单一的数字似乎是一个小而无害的调整。应该有一种更有效的方法来做到这一点。

解决方法

vkCmdDrawIndirect 允许从 VkBuffer 获取参数的分派操作。这允许您更改该缓冲区对象中的存储,这将反映在 CB 使用的间接绘制调用中...

无论如何,假设您进行了适当的同步。

毕竟,当可能使用该存储的命令正在执行时,您无法修改与 VkBuffer 关联的存储中的值。因此,如果要更改该内存中的数据,则需要在从缓冲区读取的最终间接绘制命令与写入数据的任何进程之间进行某种同步。如果它是一个 GPU 上的进程(例如来自映射内存的副本),那么就相当容易了。

然而,事件设置不是你可以在渲染过程中做的事情,所以设置必须等到整个渲染过程结束。

处理此问题的最有效方法是对您的绘图间接缓冲区进行双缓冲。在一帧中,您写入一块内存并执行从中读取的命令。在下一帧中,当 GPU 执行写入前一帧的命令时,您将写入另一块内存。在第三帧,你回到第一块内存(使用你设置的同步来确保 GPU 完成)。

当然,如果您坚持使用静态命令缓冲区,这意味着命令缓冲区自身也必须是双缓冲的。一个 CB 从一个缓冲区读取间接数据,另一个 CB 从另一个缓冲区读取。