Я пытаюсь передать массив int во фрагментный шейдер через единый блок (все в соответствии с GLSL «#version 330») на GeForce 8600 GT.
На стороне приложения у меня есть:
int MyArray[7102];
…
//filling, binding, etc
…
glBufferData(GL_UNIFORM_BUFFER, sizeof(MyArray), MyArray, GL_DYNAMIC_DRAW);
В моем фрагментном шейдере я объявляю соответствующий блок следующим образом:
layout (std140) uniform myblock
{
int myarray[7102];
};
Проблема в том, что после успешного выполнения glCompileShader программа glLinkProgram возвращает ошибку, говоря, что она не может привязать соответствующий ресурс хранения.
Несколько дополнительных фактов:
1) GL_MAX_UNIFORM_BLOCK_SIZE вернул значение 65536
2) Если я уменьшу количество элементов до 4096, он будет работать нормально и не имеет значения, использую ли я «int» или «ivec4» в качестве типа массива. Все, что выше 4096, дает мне ту же «ошибку хранения».
3) Если я использую «общий» или «упакованный», все работает как предполагалось.
Посоветовавшись со спецификацией GLSL 3.3 для std140, я предполагаю, что существует проблема с выравниванием / заполнением в соответствии с:
«1) Если элемент является скаляром, потребляющим N основных машинных единиц, базовое выравнивание равно N.
...
4) Если член является массивом скаляров или векторов, базовое выравнивание и шаг массива устанавливаются в соответствии с базовым выравниванием одного элемента массива в соответствии с правилами (1), (2) и (3) и округляются. до базового выравнивания vec4. В конце массива может быть заполнение; базовое смещение элемента, следующего за массивом, округляется до следующего числа, кратного базовому выравниванию ».
Мои вопросы:
1) Правда ли, что «myblock» занимает в 4 раза больше, чем 7102 * 4 = 28408 байт? Т.е. std140 расширяет каждый член myarray до vec4, а реальное использование памяти составляет 7102 * 4 * 4 = 113632 байта, что является причиной проблемы?
2) Причина, по которой он работает с «общим» или «упакованным», связана с устранением этих пробелов из-за оптимизации?
3) Может это ошибка драйвера? Все факты указывают на то, что причиной является «… и округление до базового выравнивания vec4», но довольно сложно согласиться с тем, что такая простая вещь, как массив целых чисел, оказывается в 4 раза менее эффективной с точки зрения ограничений памяти.
4) Если это не ошибка, то как мне организовать массив и получить к нему доступ в случае std140? Я могу использовать «ivec4» для оптимального распределения данных, но тогда вместо простого x = myarray [i] мне приходится жертвовать производительностью, делая что-то вроде x = myarray [i / 4] [i% 4] для ссылки на отдельные элементы каждого ivec4 ? Или я чего-то упускаю и есть очевидное решение?