MTLVertexDescriptor's offset -- everybody's doing it wrong

In pretty much every Metal tutorial out there, people use MTLVertexDescriptor like this: they create a struct like

struct Vertex {
    var position: float3
    var color: float3
}

then a vertex array and buffer:

let vertices: [Vertex] = ...

guard let vertexBuffer = device.makeBuffer(bytes: vertices,
                                     length: MemoryLayout<Vertex>.stride * vertices.count,
                                     options: []) else { ... } 

This is all good, we have a buffer with interleaved position and color data. The problem is, when creating a vertex descriptor, they use MemoryLayout<float3>.stride as the offset for the second attribute:

let vertexDescriptor = MTLVertexDescriptor()
vertexDescriptor.attributes[0].format = .float3
vertexDescriptor.attributes[0].offset = 0
vertexDescriptor.attributes[0].bufferIndex = 0

vertexDescriptor.attributes[1].format = .float3
vertexDescriptor.attributes[1].offset = MemoryLayout<float3>.stride // <-- here!
vertexDescriptor.attributes[1].bufferIndex = 0

vertexDescriptor.layouts[0].stride = MemoryLayout<Vertex>.stride

This does not look correct to me. The code happens to work only because the stride of SIMD3<Float> (a.k.a. float3) matches the alignment of the fields in this particular struct.

But if we have something like this:

struct Vertex {
    var attr0: Float
    var attr1: Float
    var attr2: SIMD3<Float>
}

then the naive approach of using stride won't work. Because of padding, attr2 does not start right after the two floats, at offset 2 * MemoryLayout<Float>.stride but at offset = 16.

So it seems to me that the only correct and robust way to set the vertex descriptor's offset is to use offset(of:), like this:

vertexDescriptor.attributes[2].offset = MemoryLayout<Vertex>.offset(of: \.attr2)!

Yet, I'm not able to find a single code example that does this. Am I missing something, or is everybody else just being careless with their offsets?

MTLVertexDescriptor's offset -- everybody's doing it wrong
 
 
Q