Reputation: 13918
In vertex input layouts you're allowed for example a vec3 followed by a vec2 packed closely together, however in things like uniform blocks and storage buffers a vec3 is packed to 16 bytes. I'd like to know what the reason for this is. But also, I'd like to know that if my vertices are in layout vec3 instead of vec4, and I want to eventually read those vertices from a storage buffer or using the buffer device address, can I? It essentially means that vec3s will be enlarged/padded out to 16 bytes and the layout is no longer good, the shader won't read the right data. How can you have such a layout and read it from anything other than the input attributes? For example can you read something like the following from a storage buffer or from device buffer pointer?
vec3 position;
vec2 tex_coords;
uint normal;
Ordinarily in buffers Vulkan would pad the position out to 16 bytes.
Upvotes: 0
Views: 106
Reputation: 473447
I'd like to know what the reason for this is.
The vertex input process is, on some hardware, a specific hardware feature. On such hardware, it has its own decompression logic, its own caches, etc. Since it is not using the same technology as SSBOs, it is not restricted the way SSBOs are.
Hardware that doesn't have dedicated vertex input hardware simply emulates this. It generates specialized vertex shader code (which is why the vertex input is not able to be separated from a pipeline) that can read and process the data in the format. This shader logic reads the data from a single buffer binding as a single read of X bits, then extracts the individual inputs for each attribute that uses that binding. It also does any normalization work as required by the format for that attribute.
This is what allows a vec3
input (which in the VS is 3 floats) to be fed by binary data that is in the VK_FORMAT_A2R10G10B10_UNORM_PACK32
format (32-bytes per data value).
If you want, you can emulate this behavior by just treating the data as an array of uint
s, accessing the right set of 32-bit integers with the index gl_VertexIndex*sizeof(datum)
and then filling in the values by reading and processing that block of data.
But if you're looking for something simpler, a lot of GPUs support scalar layout, which is a more granular form of storage block layout.
Upvotes: 0