GLSL produced by SPIRV-cross from SPIR-V breaks std140 rules?

Viewed 365

I've put my snippet HLSL code here: https://shader-playground.timjones.io/d9011ef7826a68ed93394792c2edb732

I compile HLSL with DXC to SPIR-V and then use SPIRV-Cross to get the GLSL code. The GLSL constant buffer is tagged with std140 and it contains vec3 and float. This according to my knowledge will not work. Shouldn't the GL_EXT_scalar_block_layout be used here? The constant block should be tagged with scalar instead of std140. Am I missing something obvious here? Thanks.

1 Answers

For an arbitrary input buffer, there isn't a generic OpenGL memory layout that is exactly equivalent to the DX constant buffer layout.

DX constant buffers will add padding needed to stop single variables spanning 16 byte boundaries, but variables themselves are only 4 byte aligned.

GL std140 uniform buffers will always align vec3 on a 16 byte boundary. This has no equivalent in DX.

GL std430 uniform buffers (if supported via GL_EXT_scalar_block_layout) will always align vec3 on a 16 byte boundary. This has no equivalent in DX.

GL scalar uniform buffers (if supported via GL_EXT_scalar_block_layout) will only pad to component element size, and don't care about 16 byte boundaries. This has no equivalent in DX.

Things get even more fun if you start throwing around struct and array types ...

TLDR, if you want a fixed binary memory layout that is portable between DX and GL/GLES and Vulkan you take some responsibility for designing a portable memory layout for your constant buffers. You can't throw arbitrary layouts around and expect it to work.

Related