Consider the following MSL:
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
float3 color [[attribute(2)]];
};
// Void just for demonstration
vertex void vertexFunc(const VertexIn vIn [[stage_in]]) {}
The concept of MTLBuffer
objects and MTLVertexDescriptor
objects is clear: the latter describes how data for a Metal struct (VertexIn
in this case) is distributed among different MTLBuffer
objects. Then, adding the [[stage_in]]
attribute to the argument into a vertex function with the struct's type, an instance is created with the struct's members matched to the data.
I have one question: does [[stage_in]]
automatically offset the buffer by the total size of all attributes using a particular buffer (totalSize
) by totalSize * [[vertex_id]]
within each MTLBuffer
before binding the struct's members to the data with the attribute layout information? I figure this must happen, but I haven't yet found anything mentioning if/how/when this occurs with [[stage_in]]
.
For example, if we used
let descriptor = MTLVertexDescriptor()
// Position
descriptor.attributes[0].format = .float3
descriptor.attributes[0].bufferIndex = 0
descriptor.attributes[0].offset = 0
// Normal
descriptor.attributes[1].format = .float3
descriptor.attributes[1].bufferIndex = 0
descriptor.attributes[1].offset = MemoryLayout<vector_float3>.stride
// Color
descriptor.attributes[2].format = .float3
descriptor.attributes[2].bufferIndex = 1
descriptor.attributes[2].offset = 0
descriptor.layouts[0].stride = 2 * MemoryLayout<vector_float3>.stride
descriptor.layouts[1].stride = MemoryLayout<vector_float3>.stride
and set two buffers, one with the interleaved position and normal data and the other with color data, would the vertex shader receive the nth vertex's data at (buffer0Start) + n * (sizeof(float3) + sizeof(float3))
in buffer 0 and (buffer1Start) + n * (sizeof(float3))
in buffer 1 with [[stage_in]]
?