Команда разрыва GLSL - PullRequest
       3

Команда разрыва GLSL

6 голосов
/ 05 февраля 2011

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

for (int i = 0; i < uNumLights; i++)
{
   ...............
}

Но невозможно заменить это циклом с фиксированным количеством итераций, но содержащим условный оператор, который будетразорвать цикл, если я, в этом случае, больше, чем uNumLights ?.Пример:

for (int i = 0; i < MAX_LIGHTS; i++)
{
    if(i >= uNumLights)
        break;
    ..............
}

Разве это не эквивалент?Должен ли последний работать в старых версиях GLSL?И если так, разве это не более эффективно и легко реализовать, чем другие методы, о которых я читал, например, использовать другую версию шейдера для разного количества источников света?
Я знаю, что это может быть глупый вопрос, но я новичок, и я не могу найти причину, почему это не должно работать.

Ответы [ 2 ]

12 голосов
/ 05 февраля 2011

GLSL может вводить в заблуждение, поскольку for() предлагает вам, что должно быть условное ветвление, даже если его нет, потому что аппаратное обеспечение вообще не может этого сделать (что относится к if() таким же образом).

Что на самом деле происходит на оборудовании до SM3, так это то, что HAL внутри вашей реализации OpenGL полностью развернет ваш цикл, так что на самом деле скачка больше нет.И это объясняет, почему ему трудно делать это с неконстантами.

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

Это проблема, потому что ... что тогда?Это плохая ситуация.

Если вы укажете слишком большую константу, это приведет к ошибке компилятора «слишком много инструкций» при сборке шейдера.Теперь, если вы предоставляете глупое число в униформе, и, таким образом, HAL должен создавать новый код и работать с этим пределом, что может сделать OpenGL?
Скорее всего, вы проверили свою программу после компиляции и компоновки, и вы, скорее всего,запросил журнал информации о шейдере, и OpenGL продолжал говорить вам, что все в порядке.Это, в некотором смысле, обязательное обещание, оно не может просто решить иначе внезапно.Следовательно, он должен убедиться, что такая ситуация не может возникнуть, и единственное работоспособное решение состоит в том, чтобы не допускать униформы в условиях на поколениях оборудования, которые не поддерживают динамическое ветвление.
В противном случае должна быть некоторая форма проверки внутриglUniform, который отвергает плохие значения.Однако, поскольку это зависит от успешной (или неудачной) перекомпиляции шейдера, это будет означать, что он должен будет выполняться синхронно, что делает его подходом "не уходить".Также учтите, что GL_ARB_uniform_buffer_object предоставляется на некоторых аппаратных средствах SM2 (например, GeForce FX), что означает, что вы можете выбросить буферный объект с непредсказуемым содержимым в OpenGL и все же ожидать, что он будет работать как-то!Реализация должна будет сканировать память буфера на предмет недопустимых значений после того, как вы удалите его, что является безумным.

Подобно циклу, оператор if() не разветвляется на оборудовании SM2, даже если выглядит так,Вместо этого он вычислит обе ветви и сделает условный ход.

2 голосов
/ 05 февраля 2011

(я полагаю, вы говорите о пиксельных шейдерах).
Второй вариант будет работать только на gpu, который поддерживает модель шейдера> = 3. Поскольку динамическое ветвление (например, перевод переменной uNumLights в IF) не поддерживается на модели шейдера gpu <3. </p>

Здесь вы можете сравнить то, что поддерживается и не поддерживается между различными моделями шейдеров.

...