Подтвердить что ты не робот

OpenGL лучше выполнять партийный розыгрыш или статические VBOs

Что предпочтительнее, с точки зрения эффективности (или, если это важно, другая точка зрения)?

Ситуация
Приложение OpenGL, которое рисует много строк в разных положениях каждого кадра (60 кадров в секунду). Допустим, есть 10 строк. Или 100 000 строк. Будет ли ответ другим?

  • # 1 У вас есть статический VBO, который никогда не изменяется, содержащий 2 вершины строки

Каждый кадр будет иметь один вызов glDrawArrays в строке для рисования, а между ними будут матричные преобразования для размещения нашей одной строки

  • # 2 Обновите VBO с данными для всех строк в каждом кадре

Каждый кадр будет иметь один вызов рисования

4b9b3361

Ответ 1

Вторая невероятно эффективна.

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

Обновление геометрии, однако, просто включает перезапись буфера.

С современным видеооборудованием на довольно массивных шинах с пропускной способностью, отправка нескольких поплавков через тривиальную. Они предназначены для быстрого перемещения тонны данных, что является побочным эффектом работы. Обновление буферов вершин - это именно то, что они делают часто и быстро. Если мы принимаем точки по 32 байта каждый (позиция и цвет float4), 100000 сегментов линии меньше 6 МБ, а PCIe 2.0 x16 составляет около 8 ГБ/с, я полагаю.

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

Хорошим примером этого, который ранее был решен, является концепция дозирования, сводящая к минимуму изменения состояния, поэтому между ними может быть проведена большая геометрия. Это используется для более эффективного рисования больших объемов геометрии.

В качестве очень ясного примера рассмотрим наилучший вариант для # 1: преобразовать триггеры без дополнительных вычислений и буфферы драйвера усердно и отлично. Чтобы нарисовать 100000 строк, вам нужно:

  • 100000 наборов матриц (в системной памяти)
  • 100000 матричных вызовов с функцией служебных вызовов функций (к видеодрайверу, копирование матрицы в буфер там)
  • 100000 матриц, скопированных в видеопамять, выполняются в одном куске
  • 100000 вызовов рисования линии

Одна только функция служебного вызова функции будет убивать производительность.

С другой стороны, пакетная обработка включает в себя:

  • 100000 точек вычислений и наборов, в системном ОЗУ
  • 1 копия vbo в видеопамять. Это будет большой кусок, но один непрерывный кусок и обе стороны знают, чего ожидать. Его можно обработать хорошо.
  • 1 вызов набора матрицы
  • 1 копия матрицы в видеопамять
  • 1 вызов вызова

Вы копируете больше данных, но есть хороший шанс, что содержимое VBO по-прежнему не так дорого, как копирование данных матрицы. Кроме того, вы сохраняете огромное количество процессорного времени в вызовах функций (200000 до 2). Это упрощает жизнь для вас, водителя (который должен буферизировать все и проверять избыточные вызовы, оптимизировать и обрабатывать загрузку) и, возможно, и видеокарту (что, возможно, пришлось пересчитать). Чтобы это было ясно, визуализируйте для него простой код:

1

for (i = 0; i < 100000; ++i)
{
    matrix = calcMatrix(i);
    setMatrix(matrix);
    drawLines(1, vbo);
}

(теперь разворачиваем это)

2

matrix = calcMatrix();
setMatrix(matrix);
for (i = 0; i < 100000; ++i)
{
    localVBO[i] = point[i];
}
setVBO(localVBO);
drawLines(100000, vbo);