Когда VBO быстрее, чем «простые» примитивы OpenGL (glBegin ())? - PullRequest
36 голосов
/ 10 января 2009

После многих лет слушаний об объектах Vertex Buffer (VBO) я наконец решил поэкспериментировать с ними (мои вещи обычно не критичны по производительности, очевидно ...)

Я опишу свой эксперимент ниже, но, короче говоря, я вижу неразличимую производительность между «простым» прямым режимом (glBegin () / glEnd ()), массивом вершин (сторона ЦП) и VBO ( GPU сторона) режимы рендеринга. Я пытаюсь понять, почему это так, и при каких условиях я могу ожидать, что VBO значительно затмевают своих примитивных предков (каламбур).

Детали эксперимента

Для эксперимента я создал (статическое) трехмерное гауссовское облако с большим количеством точек. С каждой точкой связана информация о вершине и цвете. Затем я вращал камеру вокруг облака в последовательных кадрах, что-то вроде «орбитального» поведения. Опять же, точки статичны, движется только глаз (через gluLookAt ()). Данные генерируются один раз перед любым рендерингом и сохраняются в двух массивах для использования в цикле рендеринга.

Для прямого рендеринга весь набор данных отображается в одном блоке glBegin () / glEnd () с циклом, содержащим один вызов glColor3fv () и glVertex3fv ().

Для рендеринга массива вершин и VBO весь набор данных отображается одним вызовом glDrawArrays ().

Затем я просто запускаю его в течение минуты или около того в тесном цикле и измеряю средний FPS с помощью высокопроизводительного таймера.

Результаты производительности ##

Как упоминалось выше, производительность была не различима как на моем настольном компьютере (XP x64, 8 ГБ ОЗУ, 512 МБ Quadro 1700), так и на моем ноутбуке (XP32, 4 ГБ ОЗУ, 256 МБ Quadro NVS 110). Тем не менее, он масштабировался, как и ожидалось, с количеством очков. Очевидно, я также отключил vsync.

Конкретные результаты запуска ноутбука (рендеринг с GL_POINTS):

glBegin () / glEnd (): * * тысяча двадцать-один

  • 1K pts -> 603 FPS
  • 10K pts -> 401 FPS
  • 100K pts -> 97 FPS
  • 1M pts -> 14 FPS

Вершинные массивы (на стороне процессора):

  • 1K pts -> 603 FPS
  • 10K pts -> 402 FPS
  • 100K pts -> 97 FPS
  • 1M pts -> 14 FPS

Объекты буфера вершин (сторона GPU):

  • 1K pts -> 604 FPS
  • 10K pts -> 399 FPS
  • 100K pts -> 95 FPS
  • 1M pts -> 14 FPS

Я рендерил те же данные с GL_TRIANGLE_STRIP и получил аналогично неразличимые (хотя и медленнее, чем ожидалось из-за дополнительной растеризации). Я могу опубликовать эти цифры тоже, если кто-то хочет их. .

Вопрос (ы)

  • Что дает?
  • Что мне нужно сделать, чтобы реализовать обещанный прирост производительности VBO?
  • Что мне не хватает?

Ответы [ 6 ]

27 голосов
/ 10 января 2009

Существует множество факторов для оптимизации 3D-рендеринга. обычно есть 4 узких места:

  • CPU (создание вершин, вызовы APU, все остальное)
  • Шина (передача процессора <-> GPU)
  • Vertex (вершинный шейдер поверх выполнения конвейера с фиксированной функцией)
  • Пиксель (заливка, фрагмент выполнения шейдера и кадры)

Ваш тест дает искаженные результаты, потому что у вас много ЦП (и шины) при максимизации пропускной способности вершин или пикселей. VBO используются для понижения ЦП (меньше вызовов API, параллельных передач ЦП DMA). Поскольку вы не связаны с процессором, они не дают вам никакой выгоды. Это оптимизация 101. Например, в игре процессор становится ценным, так как он необходим для других вещей, таких как ИИ и физика, а не только для выдачи множества вызовов API. Легко видеть, что запись данных вершин (например, 3 числа с плавающей запятой) непосредственно в указатель памяти происходит намного быстрее, чем вызов функции, которая записывает 3 числа с плавающей запятой в память - по крайней мере, вы сохраняете циклы для вызова.

10 голосов
/ 14 февраля 2009

Возможно, не хватает нескольких вещей:

  1. Это дикое предположение, но на карте вашего ноутбука может вообще отсутствовать этот тип операции (т.е. ее эмуляция).

  2. Вы копируете данные в память графического процессора (через glBufferData (GL_ARRAY_BUFFER с параметром GL_STATIC_DRAW или GL_DYNAMIC_DRAW) или используете указатель на основной (не графический) массив в памяти? ( это требует копирования каждого кадра и, следовательно, производительность низкая)

  3. Передаете ли вы индексы в качестве другого буфера, отправляемого через параметры glBufferData и GL_ELEMENT_ARRAY_BUFFER?

Если эти три вещи выполнены, выигрыш в производительности велик. Для Python (v / pyOpenGl) это примерно в 1000 раз быстрее для массивов, превышающих пару на 100 элементов, C ++ до 5 раз быстрее, но для массивов с вершинами 50k-10m.

Вот мои результаты теста для c ++ (Core2Duo / 8600GTS):

 pts   vbo glb/e  ratio
 100  3900  3900   1.00
  1k  3800  3200   1.18
 10k  3600  2700   1.33
100k  1500   400   3.75
  1m   213    49   4.34
 10m    24     5   4.80

Так что даже с 10-метровыми вершинами это была нормальная частота кадров, в то время как с glB / e она была вялой.

4 голосов
/ 13 января 2009

В качестве примечания:
«Прямой режим» (glBegin / glEnd) не поддерживается в:

OpenGLES. OpenGL 3.x.

Так что, если вы когда-нибудь планируете портировать приложение на мобильную платформу (например, iPhone), даже не привыкай к этому.

Я преподаю OpenGL в университете, и на слайде, объясняющем glBegin / glEnd, есть большое красное поле вокруг это с дополнительным жирным заголовком «НЕ ИСПОЛЬЗОВАТЬ».

Использование массивов вершин занимает всего две строки, и вы сохраняете циклы с самого начала.

2 голосов
/ 13 января 2009

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

1 голос
/ 20 ноября 2009

14Mpoints / s это не много. Это подозрительно. Можем ли мы увидеть полный код, выполняющий рисование, а также инициализацию? (сравните эти 14 м / с с 240 м / с (!), которые получает Слава Вишняков). Еще более подозрительно, что он падает до 640K / s для дро 1K (по сравнению с его 3.8M / s, который выглядит ограниченным ~ 3800 SwapBuffers, в любом случае).

Я бы сказал, что тест не измеряет то, что вы думаете, что он измеряет.

0 голосов
/ 13 января 2009

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

...