Using Vulkan dynamic uniform buffer

Alignment

Dynamic offsets can only be read correctly when aligned. The alignment usually lead to paddings between the required data structures. E.g.,

minUniformBufferOffsetAlignment = 0x100 // 256

a 192-byte uniform struct will be padded and takes 256 bytes.

Struct array

Struct arrays are usually used in storage buffers. The length of the array does not need to be specified.

struct Mtl {
    int indices[4];
    // ...
};

layout (set = 1, binding = 0) readonly buffer Mtl_buffer{
    Mtl data[];
};
}

To use it in a uniform buffer, the struct above needs to be reformatted.

Buffer content:

0 1 2 3 4 5 6 7 ...
layout (constant_id = 0) const uint NUM_MATERIALS = 1;

struct Mtl {
    ivec4 indices;

    // same as:
    // int a;
    // int b;
    // int c;
    // int d;
};

layout (binding = 0) uniform Mtl_properties{
    Mtl data[NUM_MATERIALS];
} mtl_props;

// This will read:

mtl_props.data[0].indices.x == 0;
mtl_props.data[0].indices.y == 1;
mtl_props.data[0].indices.z == 2;
mtl_props.data[0].indices.w == 3;

Using a int[] in this case however does not work as commonly intended:

struct Mtl {
    int indices[4];
}

// This will read:

mtl_props.data[0].indices[0] == 0;
mtl_props.data[0].indices[1] == 4;
mtl_props.data[0].indices[2] == 8;
mtl_props.data[0].indices[3] == 12;

, in which the index of data[] is accessed as column index, and int[] index as row index, if we lay down the buffer content into a row-first matrix.