Можно ли объявить слишком большой выходной массив в шейдере фрагментов и оставить некоторые индексы неиспользуемыми?


Некоторый контекст:

Я ищу простой способ запустить "старые" шейдеры (скажем, #version 120) на "новом" GLSL (скажем, #version 150 core).

До сих пор я придумал добавить следующий заголовок к моим шейдерам фрагментов при таргетинге #version 150:

#version 150 core
#define texture2D texture
out vec4 _gl_FragData[gl_MaxDrawBuffers];
#define gl_FragData _gl_Fragdata
#define gl_FragColor gl_Fragdata[0]

Вопрос:

Я немного сосредоточен на этой строке:

// In a fragment shader
out vec4 _gl_FragData[gl_MaxDrawBuffers];

В большинстве шейдеров, _gl_FragData[1 ... gl_MaxDrawBuffers-1] не используется, т. е. не записывается шейдером, и не хватает вложений буфера кадров для получения значений. Я беспокоюсь, если присутствие этих неиспользуемых элементов делает мои шейдеры плохо сформированными (или имеет какие-либо нежелательные эффекты или накладные расходы).

Спецификация GLSL 1.50 говорит, что существует неявно определенный устаревший out vec4 gl_FragData[gl_MaxDrawBuffers];, поэтому предположительно то, что я делаю, прекрасно и не несет никаких накладных расходов.
Но я также знаю, что builtin gl_FragData в некотором смысле "волшебный", и аналогичное пользовательское объявление может иметь другой эффект.

TL; DR:

Если мой фрагмент шейдера выход-это массив, могу ли я не записывать некоторые элементы в конце массива, учитывая, что значения этих элементов отбрасываются (не принимаются ни одной точкой присоединения буфера кадров) ?

Немного слишком широко, но: имеет ли присутствие этих неиспользуемых индексов какие-либо незначительные эффекты или накладные расходы на общие реализации?

1 3

1 ответ:

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

Вам всегда разрешено не писать ни в какие выходные переменные, независимо от того, используются они или нет.

Поскольку вы используете #version 150, я имею в видуGLSL 1.50 spec . Раздел 4.3.6" результаты " гласит (Курсив мой):

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

Если вы объявляете переменную и никогда не записываете в нее, у вас будет неопределенное значение, но не неопределенное поведение. Это также подкрепляется спецификацией профиля ядра OpenGL 3.2 , раздел 3.9 " шейдеры фрагментов", Подраздел "Выходные Данные Шейдера"

Любые цвета или компоненты цвета, связанные с фрагментом, которые не записаны фрагментом шейдеры не определены.

Более современные версии спецификации GL, например OpenGL 4.6 core profile , еще более ясны в этом пункте (раздел 17.4 "операции полного буфера кадров"):

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

Спецификация GLSL 1.50 продолжает:

Необходимо записать только выходные переменные, которые считываются на следующем этапе конвейера; разрешается имеют избыточные объявления выходных переменных.

Совершенно нормально не писать в выходные переменные, которые все равно не будут использоваться.

Ваш второй вопрос немного сложнее:

Оказывает ли присутствие этих неиспользуемых индексов какое-либо незначительное влияние или накладные расходы на общие реализации?

Спецификация GL никогда не дает таких гарантий. Я могу сказать только две вещи:

  1. я никогда не замечал никаких негативных последствий наличия некоторых дополнительных неиспользуемых выходов FS (но я также не делал этого очень часто). Я также не ожидал бы, что разумная реализация приведет к заметным накладным расходам в таком случае.
  2. Если вам действительно нужно быть уверенным, вы должны проверить/профайл на реальных реализациях, которые вас интересуют.