Получить мусор только из шейдерного хранилища?

Я связал shader storage buffer к shader storage block вот так

GLuint index = glGetProgramResourceIndex(myprogram, GL_SHADER_STORAGE_BLOCK, name);
glShaderStorageBlockBinding(myprogram, index, mybindingpoint);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mybuffer)
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, mybindingpoint, mybuffer, 0, 48);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 48, &mydata);

mydata указывает на std::vector содержащий 4 glm::vec3 объекты.

Потому что я связан 48 bytes в качестве диапазона буфера я ожидаю lights[] держать 48/(4*3) = 4 vec3s,

layout(std430) buffer light {
    vec3 lights[];
};

Элемент в индексе 1 в моем std::vector содержит данные x=1.0, y=1.0, z=1.0,

Но просматривая вывод, делая

gl_FragColor = vec4(lights[1], 1.0);

Я вижу желтый (x=1.0, y=1.0, z=0.0) пикселей. Это не то, что я загрузил в буфер.

Может кто-нибудь сказать мне, что я делаю не так?

РЕДАКТИРОВАТЬ

Я просто изменяю блок хранения шейдера на

layout(std430) buffer light {
    float lights[];
};

и вывод

gl_FragColor = vec4(lights[3],lights[4],lights[5],1.0);

и это работает (белые пиксели).

Если кто-то может объяснить это, это все равно будет здорово.

1 ответ

Решение

Это потому, что люди не принимают этот простой совет: никогда не используйте vec3 в UBO / SSBO.

Базовое выравнивание vec3 16 байтов. Всегда. Следовательно, при его массиве шаг массива (количество байтов от одного элемента к следующему) всегда равен 16. Точно так же, как vec4,

Да, std430 макет отличается от std140, Но это не так уж и отличается. В частности, он только предотвращает округление базового выравнивания и шага элементов массива (и выравнивания базовых структур) до такового у vec4, Но так как базовое выравнивание vec3 всегда равно тому из vec4, это ничего не меняет в них. Это влияет только на скаляры и vec2 "S.

Другие вопросы по тегам