Вопросы об объектах юниформ-буфера

Гарантируется ли, что если универсальный блок объявлен одинаковым в нескольких шейдерных программах, скажем,

uniform Matrices
{
    mat4 ProjectionMatrix;
    mat4 CameraMatrix;
    mat4 ModelMatrix;
};

Будет ли он иметь тот же индекс блока, что и glGetUniformBlockIndex(program, "Matrices")?

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

Второй вопрос: будут ли ProjectionMatrix, CameraMatrix, ModelMatrix всегда иметь одинаковый порядок компоновки в памяти соответственно? Я спрашиваю об этом, потому что в учебнике, который я прочитал, используются следующие функции

// Query for the offsets of each block variable
const GLchar *names[] = { "InnerColor", "OuterColor",
"RadiusInner", "RadiusOuter" };
GLuint indices[4];
glGetUniformIndices(programHandle, 4, names, indices);
GLint offset[4];
glGetActiveUniformsiv(programHandle, 4, indices,
GL_UNIFORM_OFFSET, offset);

И я не уверен, действительно ли это необходимо, если я знаю порядок униформ внутри блока униформы..?


person Pilpel    schedule 12.11.2015    source источник
comment
Можете ли вы связать учебник, который вы следуете здесь?   -  person legends2k    schedule 12.11.2015
comment
На самом деле это книга. Поваренная книга языка шейдинга OpenGL 4.0   -  person Pilpel    schedule 12.11.2015
comment
Хорошо, у меня первое издание книги, автор молодец.   -  person legends2k    schedule 12.11.2015


Ответы (1)


будут ли ProjectionMatrix, CameraMatrix, ModelMatrix всегда иметь одинаковый порядок компоновки в памяти соответственно?

Нет. Вот что говорится в стандарте (выделено мной):

Если pname равно UNIFORM_BLOCK_DATA_SIZE, то возвращается зависящий от реализации минимальный общий размер объекта буфера в базовых машинных единицах, необходимый для хранения всех активных юниформ в юниформ-блоке, определяемом uniformBlockIndex. . Не гарантируется и не ожидается, что конкретная реализация упорядочит юниформ-значения как плотно упакованные в буферном объекте. Исключением является компоновка std140 юниформ-блоков, которая гарантирует конкретное поведение упаковки и не требует приложение для запроса смещений и шагов.

Я не уверен, действительно ли это необходимо, если я знаю порядок униформы внутри блока униформы..?

Итак, да, автор прав, не предполагая, что макет является непрерывным, и делает то, что разумно (гарантированно работает всегда во всех реализациях): получает единые индексы и соответственно присваивает их значения.

Указание layout(std140) поможет, верно?

Да, вы можете избежать запроса местоположения и загрузки данных каждый раз, используя как объекты юниформ-буфера, так и std140. Однако убедитесь, что вы понимаете его требования к выравниванию. Эта информация подробно описана в ARB_uniform_buffer_object спецификации. Подробное рассмотрение с примерами см. в статье OpenTK об объектах унифицированного буфера (UBO) с использованием спецификации макета std140. .

Гарантируется ли, что если юниформ-блок объявлен одним и тем же в нескольких шейдерных программах, будет ли он иметь один и тот же индекс блока, возвращаемый glGetUniformBlockIndex(program, "Matrices")?

Нет. Я искал спецификацию OpenGL 3.3, которая не дает таких гарантий. С точки зрения стандарта юниформ-блоки (по умолчанию или именованные) связаны с программой, точка. Никакое существование/связь унифицированных блоков вне программы не делается в спецификации.

Поскольку нет гарантии, что юниформ-блоки будут иметь одинаковый индекс в разных шейдерных программах, это означает, что мне нужно вызывать glBindBufferBase() каждый раз, когда я переключаю программы, верно?

Да, см. пример в спецификации ARB_uniform_buffer_object.

person legends2k    schedule 12.11.2015
comment
Указание layout(std140) поможет, верно? (по крайней мере, для трех мат4, как в примере выше). Еще один вопрос: поскольку нет гарантии, что юниформ-блоки будут иметь одинаковый индекс в разных шейдерных программах, это означает, что мне нужно вызывать glBindBufferBase() каждый раз, когда я переключаю программы, верно? - person Pilpel; 12.11.2015
comment
По поводу моего первого вопроса: я знаю, что юниформ-блоки предназначены для совместного использования юниформ-файлов в нескольких программах, но никогда не говорят, что одному и тому же юниформ-блоку будет присвоен один и тот же индекс в разных программах. (кстати, вы изменили свой ответ? Вчера вы сказали обратное!) - person Pilpel; 13.11.2015
comment
Вы точно ответили на мои вопросы, однако похоже, что некий юниформ-блок всегда имеет один и тот же индекс при использовании разных шейдерных программ. Я открыл новый вопрос для этого. Спасибо! ссылка. - person Pilpel; 13.11.2015
comment
Конечно, весь смысл наличия функции glGetUniformBlockIndex(program, name) показывает, что индекс UBO будет меняться между программами. Спасибо за ссылку. - person legends2k; 13.11.2015
comment
Я делаю это следующим образом: когда я создаю объект универсального буфера, я устанавливаю для него индекс привязки, после чего мне больше не нужно проверять его индекс, потому что в каждом шейдере у меня есть layout (binding = 2, std140) uniform perObjBuffer {// Your данные здесь//} Конечно, это работает и никогда не меняет index. - person Zebrafish; 23.09.2017
comment
Да, я думаю, что layout(binding = 2, std140) гарантирует, что индекс привязки всегда равен 2. Хорошая мысль. - person legends2k; 24.09.2017