1

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.

matoek
  • 21
  • 2

1 Answers1

0

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.

solidpixel
  • 10,688
  • 1
  • 20
  • 33
  • 2
    "*GL std140 uniform buffers will always pad vec3 to vec4 in terms of storage.*" That's not quite how it works. They align to vec4, but they don't actually take up 16 bytes. So a `vec3` followed by a `float` will only take up 16 bytes. – Nicol Bolas Dec 15 '21 at 19:50
  • @NicolBolas Thanks. So, there's some imprecise info here I think: https://www.oreilly.com/library/view/opengl-programming-guide/9780132748445/app09lev1sec2.html They state there that for vec3 both alignment and the size is 4N. After what you said I do believe that in my case both HLSL and GLSL versions will read proper data from the buffer. – matoek Dec 16 '21 at 09:44
  • Again, not generically. {float1, float3} is 16 bytes in HLSL and 32 bytes in GLSL – solidpixel Dec 16 '21 at 10:08
  • 1
    @solidpixel Yes, not generically, I understand :D. I asked about this particular case because I didn't understand why SPIRV-cross produced the GLSL it produced. The one thing I was missing was that O'Reilly imprecisely described std140. BTW for {float, float3} SPIRV-cross outputs: "SPIRV-Cross threw an exception: Buffer block cannot be expressed as any of std430, std140, scalar, even with enhanced layouts. You can try flattening this block to support a more flexible layout." Which is awesome. – matoek Dec 16 '21 at 10:25