1

I have a uniform buffer which has a mix of doubles and floats, and I'm attempting to use the scalar layout specifier to match the cpu side buffer layout. My understanding from here is that scalar layout:

  • uses the largest scalar size to determine required alignment (presumably this is recursive, so any sub-struct is also inspected?)
  • requires manual padding only when going from scalars of a smaller to a larger type

My code seems to obey these rules, and everything "seems to work", but I'm getting validation errors:

Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x1dda0a68700, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: Structure id 446 decorated as Block for variable in Uniform storage class must follow relaxed uniform buffer layout rules: member 1 is an improperly straddling vector at offset 8
  %ShapeUniforms = OpTypeStruct %double %v3double %v3double %rpose3 %v4float %v3float %float %float %uint %uint %uint %uint

So my question is this:

  • What does "must follow relaxed uniform buffer layout rules" mean? Is "relaxed" equivalent to "scalar" layout or is my qualifier even working? (and can it apply to uniform blocks?)
  • Why is member 1 (k_surface_basis_x) improperly aligned if this is scalar?

The code is:

struct rpose3 {
    dvec3  pos;
    double scale;
    vec4   rot;

    // This padding seems to be needed since the struct is aligned to scalar double?
    vec4  pad;
};

layout(binding = 0, scalar) uniform ShapeUniforms {
    double u_show_grid;
    dvec3  k_surface_basis_x;
    dvec3  k_surface_basis_y;
    rpose3 u_world_from_camera;
    vec4   world_from_camera_rot ;
    vec3   world_from_camera_pos;
    
    float u_tan_half_y_fov_rad;
    float u_time;
    uint  u_frame;

    bool  u_flatten; 
    uint  u_show_map;

    bool  u_show_steps;
};

Oddly enough, if I switch the layout qualifier to std430, nothing works (understandably) but the validation errors are gone...which makes me suspect validation with respect to these things?

antovsky
  • 11
  • 1
  • 2
    Is the scalar block layout supported by your driver (it's an optional feature), and have you enabled it when creating the device? – solidpixel May 26 '23 at 07:53
  • Yes, I enabled "VK_EXT_scalar_block_layout" extension during device creation and got no errors back. – antovsky May 27 '23 at 17:55
  • Is the base memory address 8 byte aligned? Scalar layout requires all types to be naturally aligned, so all doubles need 8 byte aligned address. – solidpixel May 29 '23 at 08:19
  • P.S. using doubles for this is unusual - they are much slower than floats on most GPU implementations, if supported at all. – solidpixel May 29 '23 at 08:20
  • Yes indeed, it's nearly 16x slower to use doubles here, but the use case requires the massive dynamic range. The memory allocated by Vulkan I believe is guaranteed to be "properly aligned for the usage", so I don't believe I'm able to specify manual alignment anywhere. However, when I map the memory, I can see that at least that (and the memory I copy from) are both 8 byte aligned. – antovsky May 30 '23 at 08:00

0 Answers0