The meaning of buffer index

Hi, I proceed to chapter 5

vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal,

format: .float3, offset: offset, bufferIndex: 0)

offset += MemoryLayout<float3>.stride

I want to make sure the meaning of bufferIndex, I always see this word. My understand is this is the id where you can find in the shader. But the bufferIndex:0 is same as the bufferIndex of position attribute. I am a little confused about that

The context of buffer index is slightly different here.

When you want to send a buffer to the GPU, you create a command on the command encoder to (for example) setVertexBuffer. You assign a buffer index. This is the index into the command encoder’s argument table. The argument table has at least 31 slots for buffers.

However, when you want to layout your vertex buffers for the vertex descriptor, you can assign your own layout.

For example, if you have Position §, Normal (N) and Color ©, you can layout a buffer like this:

PPPPNNNNCCCPPPPNNNNCCCPPPP....

That describes an interleaved layout in one buffer. (Index 0). You describe the offset for each from the start of the buffer. PPPP has offset 0, NNNN has offset float4.stride and CCC has offset float4.stride * 2.

You set up the vertex descriptor layout with the stride between each vertex PNC. Here it’s float4.stride * 2 + float3.stride:

At the end of defaultVertexDescriptor:

 vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: offset)

Or

PPPPPPPPPPPP...
NNNNNNNNNNNN....
CCCCCCCCC...

That describes a layout over three buffers. (Indexes 0 to 3) The offset for each from the beginning of the buffer is 0. This is how you’d describe the layout to the vertex descriptor:

vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<float4>.stride)
vertexDescriptor.layouts[1] = MDLVertexBufferLayout(stride: MemoryLayout<float4>.stride)
vertexDescriptor.layouts[2] = MDLVertexBufferLayout(stride: MemoryLayout<float3>.stride)

In Chapter 5, even though vertexBuffers is an array, you only send the first vertex buffer to the GPU in draw(in:):

let vertexBuffer = mesh.mtkMesh.vertexBuffers[0].buffer
   renderEncoder.setVertexBuffer(vertexBuffer, offset: 0,
                                      index: 0)

However, when you get to chapter 8, you’ll be sending tangents and bi tangents. These will be laid out in different vertex buffers and you’ll change the vertex descriptor layout as I’ve described above. Then in draw(in:), you’ll send all the vertex buffers in the mesh’s vertex buffer array to the GPU:

for (index, vertexBuffer) in mesh.mtkMesh.vertexBuffers.enumerated() {
    renderEncoder.setVertexBuffer(vertexBuffer.buffer,
                                  offset: 0, index: index)
}

You noted that we’re using buffer index 0 for both the command encoder’s index and the vertex descriptor’s layout index. But they are independent, and you could be using differently numbered indices.

thank you for detailed explain, I appreciate! :+1:
So for now all we do only set one buffer , I’m looking forward to learn other 31 buffers
Thank you

1 Like