OpenGL: вопросы низкого уровня производительности - PullRequest
19 голосов
/ 09 марта 2011

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

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

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

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

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

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

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

Крест размещен на Разработка игр

Ответы [ 4 ]

25 голосов
/ 09 марта 2011

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

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

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

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

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

3 голосов
/ 11 марта 2011

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

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

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

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

3 голосов
/ 10 марта 2011
  1. Да
  2. Не имеет смысла, так как водитель может объединить эти матрицы для вас (он знает, что они являются униформами, поэтому не изменится во время вызова отрисовки).
  3. Да
  4. только если вы связаны с процессором

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

  • Обработка шейдера (вершина / фрагмент / геометрия)
  • Скорость заполнения
  • Рисование номера вызовов
  • Графический процессор<-> VMEM (здесь помогают чередование и меньшие текстуры)
  • Системная шина (потоковая передача некоторых данных каждый кадр?)

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

1 голос
/ 09 марта 2011

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

...