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

Организация шейдеров GLSL в OpenGL-движке

Что лучше?

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

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

4b9b3361

Ответ 1

Большинство современных движков, которые я знаю, имеют "шейдерный кеш" и используют второй вариант, потому что, по-видимому, он быстрее.

Также вы можете взглянуть на ARB_shader_subroutine, который обеспечивает динамическую связь. Но я думаю, что он доступен только на аппаратном уровне DX11.

Ответ 2

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

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

Ответ 3

Я бы склонен полагать, что это зависит от конкретного приложения. И да, так как было бы более эффективно говорить, что запустить 100 программ, где каждый из них может иметь около 2-16 униформ; может быть, лучше иметь компромисс между ними. Я бы склонен думать, что, может быть, 10-20 программ для ваших наиболее распространенных методов затенения будут достаточными или еще несколькими. Например, вы можете захотеть, чтобы одна программа/шейдер выполняла все ваши сопоставления с ударами, одна для выполнения всех ваших эффектов тумана, одна - для отражения, одна - для преломления.

Теперь, вне сферы вашего вопроса, я думаю, что это будет иметь место и здесь, одна вещь, которую нужно включить в ваш движок, - это установка класса BatchProcess и BatchManager для уменьшения количества вызовов CPU - GPU по шине, поскольку это доказывает также эффективны. Я не думаю, что в вашем вопросе есть одно подходящее решение, так как я считаю, что он будет специфичным для приложения, так же как установить соотношение между количеством партий (ведер) вершин (примитивов) вашего движка и сколько вершины каждой из этих партий.

Чтобы попытаться сделать это более понятным: в одной игре может быть 4 контейнера или партии, где каждая партия может содержать до 10000 вершин, которые считаются заполненными до того, как BatchManager решит очистить это ведро, отправив все эти вершины в графическую карту для проводки рендеринга, которую нужно обработать и нарисовать, где у другой игры могут быть 10 ведер с 5000 вершин, или другая игра может иметь 8 ведер с 12 0000 вершинами.

Таким образом, может возникнуть компромисс между попытками совместить эти два в соответствии с вашими потребностями. Если у вас 1 единственная программа с 100-ю формами; единственная программа легче управлять внутри конвейера, но шейдеры были бы громоздки для чтения и управления. Затем снова есть шейдеры с очень небольшим количеством форматов, которые легко читаются и управляются, но при этом 100% программ немного сложнее управлять на процессоре, прежде чем связывать и отправлять их для правильной обработки. Я лично попытался бы найти среднюю почву для того, где у меня достаточно программ для выполнения каждой конкретной задачи, которая полностью уникальна друг от друга, например, с плотностью тумана на одном и с отображением объемной тени на другой, где у каждой программы есть достаточно формы, чтобы сделать требуются расчеты.

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