Унифицированные явные местоположения и индексация точки привязки - PullRequest
2 голосов
/ 18 апреля 2019

Я испытываю следующую ошибку в GLSL.Вот фрагментный шейдер:

#version 450 core
#define DIFFUSE_TEX_UNIT   0
#define INDEX_UNIFORM_LOC  0

layout(binding  = DIFFUSE_TEX_UNIT)   uniform  sampler2D colorTex;

#ifdef SOME_SPECIAL_CASE

 layout (location = INDEX_UNIFORM_LOC) uniform uint u_blendMode;

 //...more code here related to the case

 #endif
 //... rest of the code(not important)

Теперь, когда я компилирую этот шейдер в программу без объявления SOME_SPECIAL_CASE и все еще устанавливаю u_blendMode равномерно во время выполнения, я получаю следующую ошибку от драйвера:

Сгенерирована ошибка GL_INVALID_OPERATION.значение недействительно;ожидается GL_INT или GL_UNSIGNED_INT64_NV.

Но я ожидаю получить ошибку, подобную этой:

GL_INVALID_OPERATION генерируется ошибка.'location' недопустимо.

Поскольку нет места с таким индексом (0), если я не установлю флаг препроцессора SOME_SPECIAL_CASE.Затем я решил проверить, какую форму я получил, для чего требуется GL_INT или GL_UNSIGNED_INT64_NV, поэтому я запросил имя формы на основе его местоположения (ноль):

 char buff[20];
 GLsizei len = 0;
 glGetActiveUniformName(prog.progHandle, 0, 20, &len, buff);

И получил имя 'colorTex', которое является именем сэмплера2D, имеющего индекс привязки DIFFUSE_TEX_UNIT, который также равен нулю.До сих пор я считал, что единообразное расположение и точки привязки не используют одни и те же индексы, и я все еще верю, что это не так, потому что в противном случае этот шейдер при компиляции с SOME_SPECIAL_CASE active потерпит неудачу, как и многие другие шейдеры, которые я написал через мойИстория работы. Но это выглядит очень странно, почему на единообразный индекс привязки sampler2D влияют, когда я задаю несуществующее унифицированное местоположение, и я также использую определенный тип (GLSL - uint)

glProgramUniform1ui(prog, location, (GLuint)value);

Что также не 'не соответствует типу sampler2D (так что ошибка, по крайней мере, относительно несоответствия типов).Это ошибка драйвера?

Еще одна вещь, я попытался проверить документы , действительно ли индексы привязки и местоположения действительно перекрываются, и обнаружил следующее утверждение:

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

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

Моя настройка:

  • NVIDIA Quadro P2000, драйвер 419.17
  • OpenGL 4.5
  • Windows 10 64-битная

Что касается возможности использовать одинаковую униформу в одном и том же месте, по крайней мере на графическом процессоре NVIDIA следующие компилируются и работают нормально:

Vertex shader

#version 450 core
#define MVP_UNIFORM_LOC 2

layout(location = 0)      in vec2 v_Position;
layout(location = MVP_UNIFORM_LOC) uniform mat4 u_MVP;
smooth out vec2 texCoord;
void main()
{
    texCoord = v_Position;
    gl_Position = u_MVP * vec4(v_Position,0.0,1.0); 
}

Фрагмент шейдера:

#version 450 core
#define MVP_UNIFORM_LOC 2
#define TEX_MAP_UNIT 5

layout(binding  = TEX_MAP_UNIT ) uniform  sampler2D texMap;
layout(location = MVP_UNIFORM_LOC) uniform mat4 u_MVP;
smooth in  vec2 texCoord;
out vec4 OUTPUT;

 void main()
{
    vec4 tex = texture(texMap, texCoord);    
    OUTPUT =  u_MVP * tex; 
}

1 Ответ

3 голосов
/ 18 апреля 2019

Это ошибка драйвера?

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

Нет способа взять единое местоположение и запросить единообразный индекс (или имя) унифицированной переменной.

Но я бы ожидал получить такую ​​ошибку: ... Потому что нет места с таким индексом (0), если я не установлю флаг препроцессора SOME_SPECIAL_CASE.

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

Если SOME_SPECIAL_CASE не определено, то объявление u_blendMode не существует . Поскольку местоположение 0 никогда не использовалось явной унифицированной переменной, теперь оно доступно для неявного назначения местоположения.

Таким образом, реализация может присвоить расположение colorTex нулю (обратите внимание, что это отличается от присвоения binding нулю).

Если вы хотите всегда резервировать местоположение 0, тогда объявление u_blendMode всегда должно быть видимым, даже если вы никогда его не используете. Спецификация позволяет реализациям все еще оптимизировать такие объявления, но само явное местоположение не оптимизируется. Так что если вы используете location = 0 для униформы, которая не используется, то местоположение 0 может быть или не быть действительным местоположением. Но если он действителен, он будет всегда относиться к u_blendMode.


Что касается возможности использовать одинаковую униформу в одном и том же месте, по крайней мере на графическом процессоре NVIDIA следующие компиляции и работают нормально:

Спецификация GLSL проработала это, и теперь нормально иметь два явных однородных местоположения, которые являются одинаковыми , при условии, что эти два объявления сами по себе идентичны. Так что кросс-шейдерные площадки должны работать одинаково.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...