GLSL не имеет типа, эквивалентного байту. Но поскольку все его типы состоят из определенного c байтов, вы можете просто извлечь нужный байт из большего типа. Например, uint
, размер которого должен быть 32-разрядным.
И, конечно, проблема порядка байтов будет проблемой. Указывается, что порядковый номер GPU совпадает с порядковым номером процессора, который его передает. Но вы должны принять это во внимание, когда вы go извлекаете байт из указанного c uint
.
. Конечно, макет std140
не позволит вам создать плотно упакованный массив uint
. Так что не надо; создать плотно упакованный массив uvec4
. Это 4 целых числа.
Итак, чтобы получить указанный c неподписанный байт из такого UBO, вы должны сделать следующее:
layout(binding = #, std140) uniform BlockName
{
uvec4 byte_array[NUM_BYTES / 16]; //NUM_BYTES must be a multiple of 16.
};
uint get_byte(uint byte_ix)
{
uint byte_in_uint = byte_ix % 4;
uint uint_in_vec = (byte_ix / 4) % 4;
uint vec_ix = byte_ix / 16;
uint bytes = byte_array[vec_ix][uint_in_vec];
return (bytes >> ((4 - byte_in_uint) * 8)) && 0xFF; //Little-endian. For Big-endian, remove the "4 -" part.
}
При этом:
Это массив, который содержит миллионы чисел
Что ж, большинство карт не позволят вам получить доступ к миллионам чего-либо, хотя это будет единый блок. Гарантируется, что предел для одинакового размера блока составляет не менее 16 КБ, а размеры обычно составляют около 64 КБ. Вряд ли «миллионы» чего-либо. Сам буферный объект может содержать все, что вы можете заставить систему выделить, но любой конкретный вызов glBindBufferRange(GL_UNIFORM_BUFFER, ...)
должен быть ограничен единым размером блока.
Если вам нужен один шейдер для потенциального доступа к большему количеству данных, тогда вам придется использовать SSBO или буферную текстуру.