Требование единообразных регистров для Nvidia с сэмплером в вершинном шейдере - PullRequest
0 голосов
/ 15 ноября 2018

Проблема, о которой я собираюсь написать, может быть воспроизведена только с некоторыми аппаратными средствами и драйверами.

Мне удалось воспроизвести его на GeForce GTX 760 с драйвером 399.24 и GeForce 950M с 416.34. Эта проблема не отображается на GTX650 с драйвером 390.87. Все эти графические процессоры возвращают 1024 для GL_MAX_VERTEX_UNIFORM_VECTORS, поэтому я жестко закодировал 1000 как размер массива vec4 в вершинном шейдере.

Я пытаюсь скомпилировать и связать следующую шейдерную программу.

Вершинный шейдер:

#version 330

uniform vec4 vs[1000];
uniform sampler2D tex;

void main()
{
    gl_Position = vs[42];
    //gl_Position += texture(tex, vs[0].xy); // (1)
}

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

#version 330

out vec4 outFragColor;


void main()
{
    outFragColor = vec4(0.0);
}

Все в порядке, пока строка (1) закомментирована, и, таким образом, сэмплер tex оптимизирован. Но если мы раскомментируем его, произойдет сбой связи со следующим журналом:

-----------
Internal error: assembly compile error for vertex shader at offset 427:
-- error message --
line 16, column 9:  error: invalid parameter array size
line 20, column 16:  error: out of bounds array access
line 22, column 30:  error: out of bounds array access
-- internal assembly text --
!!NVvp5.0
OPTION NV_internal;
OPTION NV_gpu_program_fp64;
OPTION NV_bindless_texture;
Error: could not link.
# cgc version 3.4.0001, build date Oct 10 2018
# command line args:
#vendor NVIDIA Corporation
#version 3.4.0.1 COP Build Date Oct 10 2018
#profile gp5vp
#program main
#semantic vs
#semantic tex
#var float4 gl_Position : $vout.POSITION : HPOS : -1 : 1
#var float4 vs[0] :  : c[0], 1000 : -1 : 1
#var ulong tex :  : c[1000] : -1 : 1
PARAM c[2002] = { program.local[0..2001] };
TEMP R0;
LONG TEMP D0;
TEMP T;
PK64.U D0.x, c[1000];
TEX.F R0, c[0], handle(D0.x), 2D;
ADD.F result.position, R0, c[42];
END
# 3 instructions, 1 R-regs, 1 D-regs

Здесь мы видим, что массив принимает регистры 0..999, а сэмплер принимает регистр 1000. Элементы выше 1000 нигде не указаны, кроме строки PARAM c[2002] = { program.local[0..2001] };.

Дальнейшие эксперименты с размером массива показали, что 2002 год не является константой, но требуется вдвое больше регистров.

Я помню , что

Реализациям OpenGL разрешено отклонять шейдеры для причины, зависящие от реализации.

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

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

Это неверная оптимизация в шейдерном компиляторе?

UPD: пример быстрого воспроизведения - здесь .

UPD2: Webgl repro с описанием обходного пути.

...