Вопросы производительности низкого уровня OpenGL

Этот вопрос, как и при любой проблеме оптимизации, попадает во много, но я просто не мог найти то, что я (думаю) хочу.

Много учебников, и даже вопросы SO имеют похожие советы; обычно покрывая:

  • Использование GL-отбрасывания (функция OpenGL, а не логика сцены)
  • Отправлять только 1 матрицу в графический процессор (комбинацию projectionModelView), поэтому уменьшать расчеты MVP от каждой вершины до одной модели (как и должно быть).
  • Использование чередующихся вершин
  • Свести к минимуму как можно больше вызовов GL, пакет, где это необходимо

И, возможно, несколько/много других. Я (по соображениям любопытства) представляю 28 миллионов треугольников в своем приложении, используя несколько вершинных буферов. Я пробовал все вышеперечисленные методы (насколько мне известно) и почти не изменил производительность.

Пока я получаю около 40FPS в моей реализации, что ни в коем случае не проблематично, мне все еще интересно, где эти "советы" для оптимизации действительно используются?

Мой процессор работает на холостом ходу около 20-50% во время рендеринга, поэтому я предполагаю, что я GPU привязан для повышения производительности.

Примечание: Я просматриваю gDEBugger в настоящий момент

Перекресток, размещенный в Разработка игр

Ответ 1

Точка 1 очевидна, так как сохраняется скорость заполнения. В случае, если примитивы обратной стороны объектов будут обработаны сначала, это опустит эти лица. Однако современные графические процессоры хорошо переносят переутомление. Я однажды (GeForce8800 GTX) измерил до 20% overdraw, прежде чем достигнет значительных результатов. Но лучше сохранить этот запас для таких вещей, как окклюзия, удаление смешанной геометрии и т.п.

Точка 2, без смысла. Матрицы никогда не были рассчитаны на GPU - ну, если вы не считаете SGI Onyx. Матрицы всегда были всего лишь своего рода глобальным параметром рендеринга, рассчитанным на CPU, а затем помещались в глобальные регистры на графическом процессоре, теперь называемые единообразными, поэтому присоединение к ним имеет очень мало преимуществ. В шейдере, который сохраняет только одно дополнительное умножение векторной матрицы (сводится к 4 инструкциям MAD), за счет меньшей гибкости алгоритма.

Точка 3 касается эффективности кеша. Данные, принадлежащие вместе, должны вписываться в строку кэша.

Точка 4 касается предотвращения изменений состояния, которые уничтожают кеши. Но это сильно зависит от того, какие вызовы GL они имеют в виду. Изменение униформы дешево. Переключение текстуры дорого. Причина в том, что униформа сидит в регистре, а не какая-то часть памяти, которая кэшируется. Переключение шейдера дорого, потому что разные шейдеры демонстрируют различное поведение во время выполнения, тем самым устраняя предварительное выполнение выполнения конвейера, изменяя паттерны доступа к памяти (и, следовательно,) и т.д.

Но это все микро-оптимизации (некоторые из них с огромным влиянием). Тем не менее, я рекомендую искать большие возможности оптимизации, например, реализовать ранний Z-проход; используя запрос окклюзии на раннем Z для быстрой дискриминации целых партий геометрии. Одна большая оптимизация воздействия, которая по существу состоит из суммирования большого количества микро-оптимизаций Point-4, состоит в том, чтобы сортировать партии рендеринга по дорогим состояниям GL. Поэтому группируйте все с помощью общих шейдеров, в пределах этих групп сортируйте по текстуре и так далее. Эта группировка состояний влияет только на видимые проходы визуализации. В начале Z вы только проверяете результаты в буфере Z, поэтому только преобразование геометрии и шейдеры фрагментов просто передают значение Z.

Ответ 2

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

Первое, что вам нужно знать, - это то, где именно ваше узкое место. GPU - это не ответ, потому что это сложная система. Реальная проблема может быть среди них:

  • Обработка шейдеров (вершина/фрагмент/геометрия)
  • Уровень заполнения
  • Набрать номер звонка
  • GPU ↔ VMEM (что помогает чередование и меньшие текстуры)
  • Системная шина (потоковая передача некоторых данных в каждый кадр?)

Вам нужно выполнить серию тестов, чтобы увидеть проблему. Например, нарисуйте все, чтобы увеличить FBO, чтобы увидеть, есть ли проблема с заполнением (или увеличить количество MSAA). Или дважды нарисуйте все, чтобы проверить проблемы перегрузки вызова вызова.

Ответ 3

Просто чтобы добавить свои 2 цента в ответы @kvark и @datenwolf, я бы хотел сказать, что, хотя вы упомянули о "основных" характеристиках производительности GPU, более значительная оптимизация зависит от приложения.

В вашем тестовом примере с геометрией вы уже выбрасываете 28 миллионов треугольников * 40 FPS = 1120 миллионов треугольников в секунду - это уже довольно много: у большинства (не всех, esp Fermi) GPU есть треугольник производительность установки составляет 1 треугольник за тактовый цикл графического процессора. Это означает, что GPU, работающий на частоте 800 МГц, скажем, не может обрабатывать более 800 миллионов треугольников в секунду; это даже без рисования одного пикселя. NVidia Fermi может обрабатывать 4 треугольника за такт.

Если вы нажмете этот лимит (вы не упомянете свою аппаратную платформу), на уровне OpenGL/GPU вы не сможете многое сделать. Все, что вы можете сделать, это отправить меньше геометрии, используя более эффективную отбраковку (усечение или окклюзию) или через схему LOD.

Другое дело, что крошечные треугольники борется с fillrate, поскольку растеризаторы обрабатывают parrallel на квадратных блоках пикселей; см. http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/.

Ответ 4

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