Макет OpenGL Uniform Buffer std140

Я пытаюсь передать массив 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 ? Или я чего-то упускаю и есть очевидное решение?


person Vitaly83    schedule 28.05.2012    source источник


Ответы (1)


1) (…) округлить до базового выравнивания vec4? (…)

да.

2) Причина, по которой он работает с «общим» или «упакованным», связана с устранением этих пробелов из-за оптимизации?

Да; только то, что это не связано с производительностью оптимизации.

3) Может это ошибка драйвера?

РЕДАКТИРОВАТЬ Нет. Графические процессоры обычно работают с векторизованной типизацией. Упаковка типов требует добавления дополнительных инструкций для де- / мультиплексирования векторов. За время, прошедшее с момента написания этого ответа, произошли значительные изменения в архитектуре графического процессора. Все графические процессоры, производимые в наши дни, представляют собой односкалярную архитектуру с упором на сильную суперскалярную векторизацию.

4) Если это не ошибка, то как мне организовать массив и получить к нему доступ в случае std140?

Не используйте однородные буферные объекты для таких больших данных. Поместите данные в одномерную текстуру и используйте texelFetch для индексации в ней.

person datenwolf    schedule 28.05.2012
comment
Спасибо, хотя я не хочу тратить силы на распаковку. Я посмотрю на texelFetch, но вот еще один вопрос - «общий» / «упакованный» отлично работает на моем ПК, и похоже, что UBO имеет отличную производительность. Можно ли предположить, что «совместно используемый» / «упакованный» макет будет иметь точно такой же «беспрерывный» шаблон памяти для всего оборудования, совместимого с GLSL 3.3? Спецификация GLSL немного двусмысленна в этом отношении - она ​​сообщает о запросе смещения для каждой формы в блоке, но означает ли это, что пробелы в массиве (в данном случае - единственном члене блока) также могут быть оптимизированы по-другому? - person Vitaly83; 28.05.2012
comment
@ Vitaly83: Могут остаться зазоры, в зависимости от оборудования и ограничений на его выравнивание. Но на самом деле БЛО не для этого. Они предназначены для таких вещей, как данные скелетной анимации, которые обычно намного меньше 100 элементов. - person datenwolf; 29.05.2012
comment
Спасибо за разъяснения, тогда я воспользуюсь TBO. - person Vitaly83; 29.05.2012