Как я могу создать плотно упакованный однородный буфер из неподписанных байтов? - PullRequest
0 голосов
/ 29 февраля 2020

В основном название. Это массив, содержащий миллионы чисел, поэтому я хочу минимизировать пространство, занимаемое графической картой. К сожалению, массивы в компоновке std140 имеют базовое выравнивание 16 байтов, а GLSL не имеет встроенного типа unsigned char, поэтому я не уверен, как я могу сделать это эффективно.

1 Ответ

3 голосов
/ 01 марта 2020

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 или буферную текстуру.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...