Confusion about uniform buffer binding binary format

I have experienced a great deal confusion about the alignment of uniform structs in GLSL bound to a Vulkan pipeline. For context, note that throughout I am using Vulkan 1.3 and the latest version of glslangValidator to compile GLSL to SPIR-V (using the -V flag).

I had assumed (it now appears mistakenly) that all structs bound this way would adhere to the binary layout described by the Vulkan spec here (). The spec explicitly states that the Uniform storage class (which I assumed corresponded to the uniform struct in GLSL but later started to question) uses the “scalar” alignment rules (this effectively means “packed” in most cases) for GPU’s with the scalarBlockLayout attribute (which mine has). This conforms with my intuition and expectations as it usually matches the layout of C and C++ structs and does not require any padding to be inserted into array buffers which should match the native array layout of nearly all languages.

I quickly observed that this was not the layout actually being used, but only corresponded to it in some special cases (e.g. 4\times 4 matrices). By trial and error I determined that, for example, 2\times2 matrices require padding of the columns.

On later investigation I found that this page () in the OpenGL wiki states that uniform cannot use the std430 layout which the Vulkan spec claims to be describing. For the hell of it I tried explicitly annotating my block as std430 and it indeed gives an error message informing me that I’m not allowed to do that for uniform. I started adding the std140 annotation which should guarantee that it matches the layout described in the OpenGL spec (). So far this seems to work.

So, in summary, I think I have found that when compiling for Vulkan uniform block types use a format described in the OpenGL spec, while I still assume buffer and other struct types use a format that matches what I am seeing in the Vulkan spec.

I would like to verify from anyone who would be kind enough to confirm that I am understanding this correctly, but I also feel like I’m still missing something because of the Vulkan specs explicit mention of Uniform blocks. My current theory is that Vulkan is that the Vulkan spec is describing SPIR-V but that the relationship between GLSL abstractions and the underlying SPIR-V output is far less obvious than I had assumed. Any additional context to clarify the situation would be appreciated. Thanks.

(Note: I had originally included a lot of helpful links but discourse is telling me “you can’t include links in your post”)

Do your drivers offer support for:

(Vulkan 1.2+) If so, you can use std430 layout on UBOs.

The base Vulkan GLSL customization indicates that the default layouts are std140 for UBOs and std430 for SSBOs and Push Constants:

For more detail, see:

1 Like