Почему OpenGL> = 3 допускает только VBO?

21

Я вижу, что OpenGL версии 3 и выше исключают использование рендеринга на стороне клиента. Немедленный режим был исключен, и массивы вершин, похоже, устарели. Вместо этого, если я правильно понимаю, VBO являются основным способом рендеринга вершин.

Хотя я вижу логику в том, чтобы иметь единый способ рендеринга всего, разве в том случае, если у VBO нет больших недостатков по сравнению с массивами вершин? Я думал, что VBO должны быть большими буферами, содержащими> 1 МБ данных, как правило. Что если у меня есть сцена, которая имеет меньшую геометрию? У меня есть граф сцены с большим количеством узлов, каждый из которых нуждается в своем собственном преобразовании и т. Д. Каждый узел также должен иметь возможность удалять отдельно, добавляться отдельно и т. Д. Я использовал массивы вершин раньше. Итак, мой первый вопрос заключается в том, будет ли, если я переключусь на VBO, увеличивать издержки на мои объекты графа сцены сейчас, потому что VBO необходимо выделить для каждого объекта.

Другая проблема заключается в том, что рендеринг геометрии может быть очень динамичным. В худшем случае могут быть моменты, когда всю геометрию необходимо повторно отправлять каждый кадр в течение некоторого периода времени. В этом случае производительность VBO будет хуже, чем у вершинных массивов, или в худшем случае VBO будет выполнять столько же работы, сколько и у вершинных массивов, но не больше?

Итак, в более кратком формате, мои вопросы:

1) Существуют ли существенные накладные расходы на распределение / освобождение VBO (я имею в виду простой акт настройки буфера)?

2) Если я обновляю данные из CPU каждый кадр, может ли это быть значительно хуже, чем если бы я использовал массивы вершин?

И, наконец, я хотел бы знать:

3) Если ответ на любой из приведенных выше вопросов «да», зачем отказываться от других режимов рендеринга, которые могут иметь преимущества перед VBO? Есть ли что-то, чего я здесь упускаю, например, методы, которые я должен использовать, чтобы смягчить некоторые из этих потенциальных затрат на распределение и т. Д.?

4) Существенно ли меняются ответы на эти вопросы в зависимости от того, какую версию OpenGL я использую? Если я сделаю рефакторинг своего кода, чтобы он был совместим с OpenGL 3 или 4, используя VBO таким образом, чтобы он был эффективным, будут ли те же самые методы работать хорошо с OpenGL 2, или вероятно, что некоторые методы будут намного быстрее с OpenGL 3 + и другие с OpenGL 2?

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

Сила тяжести
источник
1
Зачем закрывать голосование? Это дуп? Если да, могу ли я увидеть ссылку, чтобы извлечь из нее выгоду?
Гравитация

Ответы:

23

Существуют ли существенные накладные расходы для распределения / освобождения VBO (я имею в виду простой акт настройки буфера)?

Определите «существенный». Как правило, не рекомендуется создавать их в середине кадра; они должны быть установлены во время инициализации или где угодно. Но это верно для большинства объектов OpenGL, таких как текстуры, рендер-буферы или шейдеры.

Если я обновляю данные из процессора каждый кадр, может ли это быть значительно хуже, чем если бы я использовал массивы вершин?

Может это? Да. OpenGL определяет функциональность, а не производительность . Вы действительно можете сделать вещи намного медленнее. Или вы можете сделать вещи быстрее. Все зависит от того, как вы его используете.

В OpenGL Wiki есть хорошая статья о том, как правильно передавать данные .

Если ответ на любой из приведенных выше вопросов «да», зачем отказываться от других способов рендеринга, которые могут иметь преимущества перед VBO? Есть ли что-то, чего я здесь упускаю, например, методы, которые я должен использовать, чтобы смягчить некоторые из этих потенциальных затрат на распределение и т. Д.?

Во-первых, они не просто устарели. Устаревание означает пометку чего-либо как «подлежащего удалению» в будущих версиях. Они устарели в версии 3.0 и удалены в ядре версии 3.1 и выше.

Во-вторых, ARB обычно объясняет причину, по которой они удалили материал из OpenGL. Это делает спецификацию меньше и проще. Это делает API меньше и более упорядоченным. Это помогает узнать, какие API вы должны использовать; 2.1 было 4 способа предоставления данных вершин; 3.1+ имеет 1. Это избавляет от большого количества беспорядка. И т.п.

Существенно ли меняются ответы на эти вопросы в зависимости от того, какую версию OpenGL я использую? Если я сделаю рефакторинг своего кода, чтобы он был совместим с OpenGL 3 или 4, используя VBO таким образом, чтобы он был эффективен, будут ли те же самые методы работать хорошо с OpenGL 2, или вероятно, что некоторые методы будут намного быстрее с OpenGL 3 + и другие с OpenGL 2?

Более или менее нет. Только на MacOSX разница между версиями 3.1 + core и pre-3.0 действительно очевидна. Профиль совместимости реализован всеми драйверами для Linux и Windows, поэтому вы можете предположить, что профиль ядра из этих драйверов на самом деле просто добавляет проверки, чтобы не вызывать функции совместимости.

Под Mac OSX 10.7 доступно ядро ​​GL 3.2, но нет профиля совместимости. Это не обязательно что-то значит для техник исполнения одного против другого. Но это означает, что если есть различия, то на этой платформе вы их увидите.

Николь Болас
источник
1
Поскольку вы только что опубликовали этот вопрос , я просто добавлю свой ответ.
Никол Болас
Еще одним преимуществом краткости API является то, что он облегчает реализацию API OpenGL. Это было большое соображение в оригинальной спецификации OpenGL ES.
notlesh
@stephelton: имеет смысл. Мой вопрос «почему не рекомендуется все, кроме VBO», был основан на том, что, несмотря на то, что имеет смысл поддерживать API, не имеет смысла отказываться от функций, которые могут быть лучше, чем VBO для многих вариантов использования. Из того, что я слышу, кажется, что нет никаких недостатков в использовании VBO, хотя, поэтому тогда есть смысл осудить все остальное.
гравитация
@ Gravity Вам не нужно использовать VBO. Вы также можете использовать массив вершин.
Notlesh
18

Как работает OpenGL, всякий раз, когда вы используете данные, не относящиеся к VBO, драйвер должен сделать их копию - на практике создавая временный VBO - поскольку ничто не мешает вам изменять ваши голые массивы пользовательского пространства между вызовами OpenGL.

Может быть некоторая хитрость на стороне водителя, чтобы ускорить выделение времени, но вы ничего не можете сделать, чтобы избежать копирования.

Так что да, пока вы - и разработчики драйверов - все делаете правильно, VBO должны (tm) всегда просто ускорять процесс.

Яри ​​Комппа
источник
6
Мне больше нравится этот ответ. Это короче и ближе к делу, имо.
TravisG
@JariKomppa: Это звучит как очень разумное объяснение. У меня все еще есть одна проблема: VBO должны быть достаточно большими объектами, часто выделяемыми как буферы 1 МБ - 4 МБ в прошлый раз, когда я проверял. Что если мои геометрические объекты не такие большие, но я все еще беспокоюсь о производительности, потому что у меня много объектов? Я боюсь, что VBO могут быть просто для другого случая использования, чем у меня. Должен ли я объединить несколько объектов вместе в одном VBO, а затем использовать glDrawRangeElementsдля рисования каждого отдельного объекта, или это неэффективно, как массивы вершин?
гравитация
Я сомневаюсь, что это будет иметь какое-то значение, но если вы чувствуете, что это проблема, сравните это.
Яри ​​Комппа
@JariKomppa: Как вы думаете, что изменит ситуацию? Использовать glDrawRangeElementsнесколько раз на каждом VBO с несколькими VBO вместо того, чтобы давать каждому объекту свое собственное VBO?
Гравитация
1
В точку. Я сомневаюсь, что вы увидите большую разницу, но профилирование некоторых тестовых примеров должно дать вам больше информации. Я также не стал бы беспокоиться об этом сейчас, поскольку подобное изменение может быть применено позже, если потребуется.
Яри ​​Комппа
9

и массивы вершин кажутся устаревшими. Вместо этого, если я правильно понимаю,

Не совсем. Вершинные массивы являются основой для буферных объектов вершин. Только хранилище перемещено от клиента к стороне сервера.

Что если у меня есть сцена, которая имеет меньшую геометрию?

Объедините меньшие наборы геометрии в большие VBO. Нет необходимости иметь один VBO для каждой партии геометрии. Вы можете идеально обратиться к подмножествам VBO для рендеринга. Используйте ненулевое смещение для параметра данных gl… Pointer.

2) Если я обновляю данные из CPU каждый кадр, может ли это быть значительно хуже, чем если бы я использовал массивы вершин?

Для этого есть флаги использования буфера GL_DYNAMIC_DRAW и GL_STREAM_DRAW.

Если ответ на любой из приведенных выше вопросов «да», зачем отказываться от других способов рендеринга, которые могут иметь преимущества перед VBO?

Потому что нет никаких преимуществ. Данные геометрии должны быть переданы в графический процессор в любом случае. Использование обычного клиентского массива вершин по-прежнему будет вызывать передачу DMA в GPU, а в режиме немедленной обработки будет также создан пакет для первой передачи.

Нет абсолютно никакой пользы в том, чтобы не использовать VBO.

datenwolf
источник
Таким образом, моя производительность, как правило, не должна быть хуже с VBO, чем с массивами вершин, но только если я правильно установил режим GL_STREAM_DRAW?
гравитация
@Gravity: Действительно. Однако режим буфера - это всего лишь подсказка для ожидаемого использования, но, конечно, этот совет должен быть верным тому, что вы собираетесь делать. Также не забывайте, что вы можете отображать буферы в адресное пространство вашего процесса для обновлений (glMapBuffer, glUnmapBuffer).
datenwolf
но тогда буфер не может быть в VRAM, верно? Или это все еще будет в VRAM, но просто адресуется через адреса пространства процесса? Будет ли произвольный доступ дешевым при использовании этой методики, или я все же должен попытаться обновить только небольшое количество смежных диапазонов?
Гравитация
@Gravity: буфер может отображаться только для чтения, только для записи или для чтения и записи. Для обновлений вы бы выбрали только запись. Теперь важно знать, как современные ОС управляют виртуальным адресным пространством, а именно с помощью выгружаемой памяти. В случае карты только для записи вы отображаете часть памяти передачи DMA, и ваши записи в этот сопоставленный диапазон будут более или менее напрямую поступать в память GPU (содержимое сначала записывается в ОЗУ ЦП, но затем передается DMA в GPU перечислить). Важно, что это более прямой путь, чем если бы данные проходили через массив вершин на стороне клиента:
обычная