Разве это не то, что OpenGL делал без геометрического шейдера?
Нет, это не так. GS - необязательный шаг, а не шаг по умолчанию.
Чтобы OpenGL мог выполнить геометрический шейдер , он должен выполнить так называемую « примитивную сборку ». Когда вы визуализируете серию треугольников через GL_TRIANGLE_STRIP
, OpenGL будет выполнять внутреннюю работу для преобразования каждых 3 смежных вершин в отдельный треугольник, соответственно изменяя порядок намотки.
Обычно, когда GS не используется, этот процесс выполняется один раз. Однако, когда вы используете GS, это должно быть выполнено до того, как GS выполнится. Но это также должно быть выполнено после GS, потому что GS может выводить совершенно другой тип примитива (например, четырехугольники).
Так что теперь вы заставляете систему делать кучу дополнительной работы даром. В конце концов, OpenGL не может предположить, что ваш GS ничего не делает (это неразрешимая проблема).
Кроме того, ряд оптимизаций больше не работает в присутствии GS. Рассмотрим индексированный рендеринг.
Каждый индекс из буфера массива элементов будет генерировать одинаковые выходные данные вершинного шейдера. Таким образом , ГПУ будет часто кэшировать эти выходы в кэш пост-T & L . Если он видит индекс, который уже находится в кэше, VS больше не запускается; он просто выбирает данные из кеша.
Что это такое"? «Это» - это ... примитивная сборочная единица . Да, это то, что запускается дважды, когда вы используете GS. Кэширование индекса? Это работает только для входов GS.
Так что же происходит с выходами GS? Ну, это зависит от оборудования. Но это должно войти в какой-то буфер памяти. И в этом заключается проблема: этот буфер вообще не индексируется. Это похоже на ситуацию с glDrawArrays.
Таким образом, если вы отправите индексный буфер в размере 0, 1, 2, 0, 2, 3
, это будет преобразовано в 4 вершины в кэше после T & L. Но буфер вершин после GS теперь имеет 6 вершин. Буфер post-GS занимает больше места. Так что, если вы столкнетесь с проблемой составления должным образом оптимизированных списков или полос треугольников после T & L и включите сквозной GS, такой как ваш, вы в основном убили около половины прироста производительности от этой оптимизации.
Это не было бесполезно, но это больно.
К этому следует добавить тот факт, что многие графические процессоры класса GL 3.x (также известные как DX10) имели довольно небольшие буферы после GS. Чем меньше буфер, тем меньше вызовов GS вы можете иметь одновременно. Таким образом, ваше оборудование эффективно ограничивает возможности GS. Поскольку тесселяция является большой характеристикой оборудования класса 4.x, большинство такого оборудования имеет буферы, достаточные для обеспечения более интенсивного использования GS.
Таким образом, использование GS с большей вероятностью сделает обработку вершин вашего кода узким местом. Конечно, вы всегда можете использовать это в своих интересах, делая ваши вершинные и фрагментные шейдеры более сложными, поскольку в этот момент это просто бесплатная производительность.
Для получения дополнительной информации о замедлении, вызванном GS, прочитайте эту статью .
Вот основное правило о GS: никогда не используйте GS, потому что вы думаете, что это сделает рендеринг быстрее . Вы должны использовать это, когда это делает возможным то, что вы пытаетесь сделать . Если вы пытаетесь оптимизировать, используйте что-то другое.
Общие исключения из этого:
- Точечные-спрайты, главным образом , чтобы обойти ограничения на размер и проблемы отсечения . Возможно , если вы будете осторожны с размером выходных данных.
- Слоистый рендеринг. У NVIDIA даже есть расширение, определяющее цель которого - лишить GS способности делать что-либо, кроме многоуровневого рендеринга . Кроме того, учтите, что AMD разработала расширение, цель которого состоит в том, чтобы позволить VS выполнять большинство функций многоуровневого рендеринга . Который сейчас является расширением ARB .
- Настройка для операций Transform Feedback , особенно для нескольких потоков. Но благодаря вычислительным шейдерам в GL 4 , вам не нужно это очень часто.