Либо чередование в VBOs ускоряет работу при использовании VAO

Обычно вы получаете ускорение, когда используете VBO с чередованием вместо использования нескольких VBOs. Это также справедливо при использовании VAO?

Потому что гораздо удобнее иметь VBO для позиций, а другой для нормалей и т.д. И вы можете использовать один VBO в нескольких VAO.

Ответ 1

VAOs

  • Для совместного использования больших наборов данных специальный буфер, содержащий один массив вершин (атрибут), безусловно, способ пойти, в то время как все еще можно чередовать определенные массивы в другом буфере и объединить их с помощью VAO.

  • VAO обрабатывает привязку всех этих буферов и состояний массива вершины (атрибута), таких как привязки буфера массива и атрибутов записей с указателями (буфера) и флаги включения/выключения. Помимо удобства, он предназначен для быстрого выполнения этой задачи, не говоря уже о простом вызове API, который сразу меняет все состояния, без утомительного включения и отключения массивов атрибутов. Это в основном делает то, что мы должны были делать вручную раньше. Тем не менее, с моей собственной реализацией, подобной VAO, я не мог измерить потерю производительности даже при выполнении большого количества привязок. С моей точки зрения, основным преимуществом является его удобство.

Таким образом, VAO не принимает решения о производительности в плане glDraw *, но может повлиять на накладные расходы изменений состояния.

Форматы данных с чередованием...

  • ... вызывают меньшее давление кеша GPU, поскольку координаты вершин и атрибуты одной вершины не разбросаны по всей памяти. Они последовательно помещаются в несколько строк кеша, в то время как разбросанные атрибуты могут вызвать больше обновлений кеша и, следовательно, выселения. В худшем случае сценарий может быть одним (атрибутом) элементом на каждую строку кэша за раз из-за отдаленных мест памяти, в то время как вершины вытягиваются не детерминированным/несмежным образом, где, возможно, не прогнозируется и не предваряется. Графические процессоры очень подобно процессорам в этом вопросе.

  • ... также очень полезны для различных внешних форматов, которые удовлетворяют устаревшим чередующимся форматам, где наборы данных совместимых источников данных может считываться прямо в карту памяти GPU. Я в конечном итоге перепрограммировал эти чередующиеся форматы с текущим API по этим причинам.

  • ... должен быть совместим с выравниванием, как простые массивы. Для микширования различных типов данных с различными требованиями к размеру/выравниванию может потребоваться отступы для обеспечения совместимости с графическим процессором и ЦП. Это единственный недостаток, о котором я знаю, из более сложной реализации.

  • ... не мешает вам указывать на отдельные массивы атрибутов в них для совместного использования.

Чередование, скорее всего, улучшит производительность при рисовании.

Вывод:

Из того, что я испытал, лучше всего иметь чисто разработанные интерфейсы для источников данных вершин и "скомпилированных" VAO, где можно инкапсулировать VAO factory соответствующим образом. Этот factory может быть изменен для инициализации перемежающихся, отдельных или смешанных вершинных макетов буфера из источников данных, не нарушая ничего. Это особенно полезно для профилирования.

После всего, что лепит, мой совет прост: правильная и достаточно абстрактная конструкция до и для оптимизации.

Ответ 2

В VAO не содержатся данные атрибутов вершин. Это контейнерный объект для набора вершинных массивов, который описывает, как извлекать данные из нуля, одного или нескольких объектов буфера (это фактические массивы вершин, которые вы определяете с помощью VertexAtrribPointer() (pre-GL43) или VertexAttribFormat(), VertexAttribBinding() и BindVertexBuffer() (GL43 +)), разрешить состояния для вершинных массивов и, возможно, ELEMENT_ARRAY_BUFFER_BINDING. Подробности см. В таблицах 23.3 и 23.4 спецификации GL 4.4.

ARRAY_BUFFER_BINDING записывается отдельно для каждого массива вершин, т.е. каждого VertexAttribPointer() вызова для каждого индекса атрибута. Таким образом, вы можете связать индекс атрибутов VAO с несколькими объектами буфера и переключиться между буферами, чтобы извлечь из него использование {Enable|Disable}VertexAttribArray() или путем распределения буферов по индексам атрибутов и выбора соответствующих мест назначения для ваших шейдеров - либо с помощью glBindAttribLocation(), либо используя явные атрибуты места в вашем шейдере (последний превосходит).

Почему все это связано с VAO? Поскольку не существует отрицательного эффекта использования VAO и компоновки хранилища буферов VBOs, а также то, как быстро вытягиваются вершины, не имеет ничего общего с VAO. VAO - это государственные контейнеры, не более, не что иное. Вы все еще нуждаетесь в буферном хранилище, чтобы поддержать любое перемещение вершин, вы можете чередовать свои данные так же, как и без VAO. Все, что вам нужно сделать, это отобразить перемеженный макет памяти с массивами вершин. Таким образом, по сути, кроме записи состояния массива вершин, ничего не меняется.

То, что вы получаете с помощью VAO, - это способ более или менее быстрого переключения между наборами состояний и связанных объектов буфера без настройки массивов вершин при каждом переключении объекта буфера. Поэтому вы сохраняете вызовы API. Кроме того, при связывании VAO каждый массив вершин все еще имеет свой ARRAY_BUFFER_BINDING, и нет необходимости снова вызывать BindBuffer(), тем самым сохраняя дальнейшие вызовы API. Это.

Вы не получаете и не теряете ничего в отношении вытягивания вершин из-за VAO, по крайней мере, не теоретически. Однако вы теряете общую производительность, когда вы бесцеремонно переключаете VAO вокруг, как сумасшедшие.

Кстати, использование VAO также является обязательным при использовании GL32 и более высоких базовых контекстов, поэтому ваш вопрос является спорным, если вы не собираетесь на совместимость.

В общем, когда вы не уверены в производительности: не угадайте, всегда профиль! Это особенно актуально при использовании OpenGL.