Компоновка OpenGL Uniform Buffer std140, ошибка драйвера или я неправильно понял спецификацию? - PullRequest
5 голосов
/ 17 сентября 2011

Спецификация OpenGL лежит (или это ошибка?) ... Обращаясь к компоновке для std140, с общими унифицированными буферами, она гласит:

"Набор правил, показанный в Табл. L-1, используется компилятором GLSL для элементы макета в унифицированном блоке с квалификацией std140 Смещения члены в блоке накапливаются на основе размеров предыдущие члены в блоке (те, которые объявлены перед переменной в вопрос) и начальное смещение. Начальное смещение первого член всегда равен нулю.

Тип скалярной переменной (bool, int, uint, float) - Размер скаляра в Основные типы машин "

(http://www.opengl -redbook.com / добавления / AppL.pdf )

Итак, вооружившись этой информацией, я установил в своем шейдере единый блок, который выглядит примерно так:

// Spotlight.

layout (std140) uniform Spotlight
{
    float Light_Intensity;
    vec4  Light_Ambient;
    vec3  Light_Position;   
};

... только чтобы обнаружить, что он не работает с последующей компоновкой std140, которую я настроил на стороне процессора. То есть первые 4 байта представляют собой число с плавающей запятой (размер скалярного типа машины для GLfloat), следующие 16 байтов являются vec4, а следующие 12 байтов являются vec3 (с 4 байтами, оставшимися в конце для учета правила). что vec3 действительно является vec4).

Когда я изменяю сторону ЦП, чтобы указать, что float имеет тот же размер, что и vec4, то есть 16 байт, и с учетом моих смещений и размера буфера, исходя из этого предположения, шейдер работает как задумано.

Итак, либо спецификация неверна, либо я неправильно понял значение слова «скаляр» в этом контексте, либо ATI имеет ошибку драйвера. Кто-нибудь может пролить свет на эту тайну?

1 Ответ

11 голосов
/ 17 сентября 2011

Этот PDF-файл, на который вы ссылались, , а не спецификация OpenGL .Я не знаю, откуда вы это взяли, но это, конечно, не полный список правил.Всегда проверяйте свои источники;спецификация не так нечитабельна, как утверждают многие.

Да, размер переменных базовых типов такой же, как у базового типа машины (то есть: 4 байта).Но один только размер не определяет положение переменной.

Каждый тип имеет базовое выравнивание, и независимо от того, где этот тип находится в однородном блоке, его общее смещение байтов должен соответствовать этому выравниванию.Базовое выравнивание vec4 равно 4 * выравниванию его базового типа (то есть: float).Таким образом, базовое выравнивание vec4 равно 16.

Поскольку Light_Intensity заканчивается через 4 байта, компилятор должен вставить 12 байтов заполнения, потому что Light_Ambient не может находиться на4-байтовая граница.Он должен быть на 16-байтовой границе, поэтому компилятор использует 12 байт пустого пространства.

У ATI есть несколько ошибок драйвера вокруг компоновки std140, но это не одна из них.

Как правило, мне нравится явно добавлять заполнение в мои структуры, и я избегаю vec3 (потому что он имеет 16-байтовое выравнивание).Выполнение этих действий, как правило, сокращает количество ошибок компилятора, а также случайное недопонимание того, куда идут дела и сколько места они фактически занимают.

...