在vkCmdBindVertexBuffers vkCmdDraw中使用偏移量有什么好处?

What are the advantages of using offsets in vkCmdBindVertexBuffers vkCmdDraw?

在 vulkan 中,我有一个存储 6 个顶点的顶点缓冲区。前 3 个属于一个三角形,另外 3 个属于另一个三角形。每个顶点都有两个指定 x 和 y 位置的浮点数,另外 3 个指定 rgb。

如果我只想绘制一个三角形,似乎我可以通过将 3*5*sizeof(float) 的偏移量指定为 vkCmdBindVertexBuffers 的偏移量或将 firstVertex 指定为 3 到 vkCmdDraw 来获得相同的结果.

它们对这两种方法有什么优势吗?

(字节)偏移量允许您将顶点数据与其他类型的数据交错,这些数据可能不会在 sizeof(vertex) 处对齐。

在您描述的场景中,这两种方式的优势并不明显。在某些架构上,如果您正在执行一堆 back-to-back 绘制调用,这些调用使用来自相同 VkBuffer 的属性,则使用 firstVertex 而不是必须在每次绘制之间调用 vkCmdBindVertexBuffers开销可能更低。

功能上的区别在于,通过偏移量,您正在更改 "vertex 0" 所在的位置,即调整顶点缓冲区的逻辑起点。如果您使用 vkCmdDrawIndexed,索引值 0 将引用该偏移处的顶点。在顶点着色器中,VertexId 内置变量将为 0。

通过使用 firstVertex,您是说逻辑顶点缓冲区从 VkBuffer 中的偏移量 0 开始,但您想要从某个顶点开始绘制几何图形,而不是在缓冲区的开头。顶点着色器将在 [firstVertex .. firstVertex+vertexCount-1].

范围内看到 VertexId

因此,如果您有一个大的 VkBuffer,您只需将不同的 unrelated/independent 网格附加到其中,尤其是当它们具有不同的布局时,您可能只想在绑定每个网格时使用偏移量:您实际上已经将不同的逻辑顶点缓冲区存储在单个 VkBuffer 中。或者,如果您的顶点布局具有 non-interleaved 属性(例如,位置在一个 "binding" 中,其他属性在另一个 "binding" 中)但想将它们存储在相同的 VkBuffer 中,您需要将相同的 VkBuffer 绑定为两个不同的顶点缓冲区,但具有不同的偏移量。

另一方面,例如,如果您将 dynamically-generated 网格几何体收集到每一帧的顶点缓冲区中,您可能只想绑定顶点缓冲区一次,然后使用 firstVertex 发出为每个网格绘制调用。或者,如果您需要使用 VertexId 进行某些计算(例如索引到存储缓冲区),您需要使用 firstVertex 以便每个顶点获得预期的 VertexId 值。