Guides and Sample Code


Metal Best Practices Guide

Buffer Bindings

Best Practice: Use an appropriate method to bind your buffer data to a graphics or compute function.

Metal provides several API options for binding buffer data to a graphics or compute function so it can be processed by the GPU.

The setVertexBytes:length:atIndex: method is the best option for binding a very small amount (less than 4 KB) of dynamic buffer data to a vertex function, as shown in Listing 5-1. This method avoids the overhead of creating an intermediary MTLBuffer object. Instead, Metal manages a transient buffer for you.

Listing 5-1Binding a very small amount (less than 4 KB) of dynamic buffer data
  1. float _verySmallData = 1.0;
  2. [renderEncoder setVertexBytes:&_verySmallData length:sizeof(float) atIndex:0];

If your data size is larger than 4 KB, create a MTLBuffer object once and update its contents as needed. Call the setVertexBuffer:offset:atIndex: method to bind the buffer to a vertex function; if your buffer contains data used in multiple draw calls, call the setVertexBufferOffset:atIndex: method afterward to update the buffer offset so it points to the location of the corresponding draw call data, as shown in Listing 5-2. You do not need to rebind the currently bound buffer if you are only updating its offset.

Listing 5-2Updating the offset of a bound buffer
  1. // Bind the vertex buffer once
  2. [renderEncoder setVertexBuffer:_vertexBuffer[_frameIndex] offset:0 atIndex:0];
  3. for(int i=0; i<_drawCalls; i++)
  4. {
  5. // Update the vertex buffer offset for each draw call
  6. [renderEncoder setVertexBufferOffset:i*_sizeOfVertices atIndex:0];
  7. // Draw the vertices
  8. [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:_vertexCount];
  9. }