Не очевидно, что в любом из описанных вами сценариев есть преимущество. В некоторых архитектурах, если вы выполняете кучу обратных вызовов отрисовки, которые используют атрибуты из одного и того же VkBuffer
, использование firstVertex
вместо необходимости вызывать vkCmdBindVertexBuffers
между каждым отрисовкой может иметь меньшие накладные расходы.
Функциональное отличие состоит в том, что со смещением вы меняете положение "вершины 0", то есть настраиваете логическое начало буфера вершин. Если бы вы использовали vkCmdDrawIndexed
, значение индекса 0 будет относиться к вершине с этим смещением. В вершинном шейдере встроенная переменная VertexId
будет равна 0.
Используя firstVertex, вы говорите, что буфер логических вершин начинается со смещения 0 в VkBuffer
, но вы хотите нарисовать геометрию, начиная с некоторой вершины, а не в начале буфера. Вершинный шейдер будет видеть VertexId
значения в диапазоне [firstVertex
.. firstVertex+vertexCount-1
].
Так что, если у вас есть большой VkBuffer
, к которому вы просто добавляете разные несвязанные / независимые сетки, особенно если они имеют разную компоновку, вы можете просто использовать смещение при привязке каждой: у вас по существу разные Буферы логических вершин хранятся в одном VkBuffer
. Или, альтернативно, если у вас есть вершинный макет с неперемеженными атрибутами (например, положение в одной «привязке», другие атрибуты в другой «привязке»), но вы хотите сохранить их в том же VkBuffer
, вам необходимо связать тот же VkBuffer
как два разных буфера вершин, но с разными смещениями.
С другой стороны, если, например, вы собираете динамически сгенерированную геометрию сетки в буфер вершин каждый кадр, вы можете просто привязать буфер вершин один раз, а затем использовать firstVertex
для вызова вызова отрисовки для каждой сетки. Или, если вам нужно использовать VertexId
для каких-либо вычислений (например, индексирование в буфер хранения), вы должны использовать firstVertex
, чтобы каждая вершина получила ожидаемое значение VertexId
.