Существует ли снижение производительности для 3-байтовых атрибутов вершин в шейдере?

#graphics #vulkan

Вопрос:

Я хочу иметь формат ввода вершин, такой как:

 layout (location = 0) in vec3 position; // Format VK_FORMAT_R8G8B8_SFLOAT layout (location = 1) in vec3 normal; // Format VK_FORMAT_R8G8B8_UNORM layout (location = 2) in vec3 tangent; // Format VK_FORMAT_R8G8B8_UNORM  

Позиция в буфере вершин будет составлять 3 поплавка, поэтому занимает 12 байт. Обычный атрибут будет состоять из трех символов, от -127 до 127, и glsl будет считывать их как нормализованные поплавки (от -1 до 1). Так же будет и с касательной. Насколько я понимаю, «vec3» в glsl не говорит о том, что тип считывается, если 3 плавает, а скорее зависит от формата, заданного при создании описания входного макета и заданного конвейеру шейдеров. Это, по сути, означает, что нормаль занимает три байта, а затем касательная vec3 начинается на границе байтов, не выровненной по 4 байтам. Я не хотел использовать vec4, потому что тогда это было бы пустой тратой места.

Для того, чтобы использовать vec4s, я могу сделать:

 layout (location = 1) in vec4 normal; // Format VK_FORMAT_R8G8B8A8_UNORM layout (location = 2) in vec4 tangent; // Format VK_FORMAT_R8G8B8A8_UNORM  

Тогда компонент w нормального может иметь компонент x касательной, а компоненты x и y касательной могут иметь компоненты y и z касательной, оставляя мне два дополнительных байта для использования для других вещей, но тогда у меня возникает проблема с возможностью хранения, например, 16-разрядного числа в последних двух байтах, поскольку шейдер считывает байты в виде нормализованного поплавка.

Есть ли снижение производительности, чтобы упаковать нормальную и касательную более тесно вместе, как это, в виде двух vec3, каждый из которых занимает по 3 байта?

Ответ №1:

Прежде всего, зависит от реализации.

Во-вторых, наказание, вероятно, было бы незначительным для большинства случаев.

В-третьих, предположение, я бы сказал, что ГВ будет загружать весь кэш содержит необходимые данные, и если данные не выровнены должным образом его готов быть трансформированы (например, если поток может работать только на 4 выровненным данным и неприсоединившихся бы порезать его на кусочки) его бы просто сделать некоторые bitshifting и уплотнительное кольцо, добавив некоторые вычисления над головой.

Так что, вероятно, это компромисс между памятью(пространством, пропускной способностью) и вычислениями(fl/iops).