Buffer Alignment in Instancing Chapter

Hello everyone -

Could someone help me understand one of the concepts explained in the chapter on instancing?

In the part on morphs, we initially render the rocks with an incorrect struct and see the vertices out it order.

We then go on to fix this problem by updating the stride in the vertex layout and switching from float3 to packed_float3.

The thing I don’t understand is why removing the stage_in attribute introduces this issue.

The original vertex layout has a stride and offsets that match the struct yet the image renders fine. No changes are made to the buffer to fix the bug. We only change the layout.

Since the vertex data is “incorrect” when using the original stage in/vertex layout, how does it render properly? Wouldn’t the shader look at bytes 0 to 40, then 40 to 80, which would overshoot the actual offset which is 32?

stage_in and vertex descriptors is are behind-the-scenes magical. I’ll try and describe it.

You stated that you’re only removing stage_in. But you are also changing the size of the buffer to fix it. In Nature.swift, you change mdlVertexDescriptor to have a stride of 32 instead of 40.

The GPU knows about the vertex descriptor through the pipeline state, and knows that each vertex has three attributes of float3 (which is actually a packed_float3).

The float3 in the Metal buffer is actually stored as a packed_float3, which is size 12. But when I wrote the book, I chose to use the stride of a float3 which is size 16. I should have used 12 because it would save on buffer space. But because the GPU knows about the vertex descriptor through the pipeline state, it can match it up with the attributes that you described in the original VertexIn struct and stage_in. So the padding didn’t matter.

But when you can’t use stage_in you have to read the data in the buffer as is.

So you change mdlVertexDescriptor's .float3 attributes to be 12 long, which is packed, total length of the vertex descriptor is now 32. And you change the struct in the shader to match that.

Btw, you don’t have to change mdlVertexDescriptor. You could create the struct in the shader to look like this:

struct VertexIn {
  packed_float3 position;
  float pad1;
  packed_float3 normal;
  float pad2;
  float2 uv;
};

That now has a stride of 40.

1 Like

Thank you! Now it clicks for me. The example with the struct padding helped a lot. I didn’t know you could do something like that.

1 Like