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?