How to copy SIMD float4x4 to vertex shader?

How can I copy a SIMD float4x4 matrix to a vertex shader by using the setVertexBytes:length:atIndex message of a render command encoder?

Accepted Reply

I'm not sure if you're using Swift or Objective-C, but here's an example for both. We'll assume there's a helper function matrix4x4_rotation that creates a rotation matrix using the angle-axis formula that returns a matrix_float4x4. We'll also assume that BufferIndexModelMatrix is defined as the index you want to bind the matrix to.

In Swift, you'll create your matrix and then use the & operator to get the pointer, and MemoryLayout<simd_float4x4>.size to get the size of the matrix data type.

let rotationAxis = SIMD3<Float>(1, 1, 0)
let modelMatrix: matrix_float4x4 = matrix4x4_rotation(radians: rotation, axis: rotationAxis)

renderEncoder.setVertexBytes(&modelMatrix, length: MemoryLayout<simd_float4x4>.size, index: Int(BufferIndexModelMatrix.rawValue))

And in Objective-C, we can use the normal C & operator to get the pointer, and sizeof(simd_float4x4) to get the size of the matrix data type.

simd_float3 rotationAxis = {1, 1, 0};
simd_float4x4 modelMatrix = matrix4x4_rotation(_rotation, rotationAxis);

[renderEncoder setVertexBytes:&modelMatrix length:sizeof(simd_float4x4) atIndex:BufferIndexModelMatrix]

And in your Metal shader source, you would add a constant parameter at the buffer index and use the matrix you encoded.

vertex ColorInOut vertexShader(Vertex in [[ stage_in ]],
                               constant FrameData & frameData   [[ buffer(BufferIndexFrameData) ]],
                               constant float4x4 &  modelMatrix [[ buffer(BufferIndexModelMatrix) ]])

{
    ColorInOut out;
    float4 position = float4(in.position, 1.0);
    out.position = frameData.projectionViewMatrix * modelMatrix * position;
    out.texCoord = in.texCoord;
    return out;
}

Replies

I'm not sure if you're using Swift or Objective-C, but here's an example for both. We'll assume there's a helper function matrix4x4_rotation that creates a rotation matrix using the angle-axis formula that returns a matrix_float4x4. We'll also assume that BufferIndexModelMatrix is defined as the index you want to bind the matrix to.

In Swift, you'll create your matrix and then use the & operator to get the pointer, and MemoryLayout<simd_float4x4>.size to get the size of the matrix data type.

let rotationAxis = SIMD3<Float>(1, 1, 0)
let modelMatrix: matrix_float4x4 = matrix4x4_rotation(radians: rotation, axis: rotationAxis)

renderEncoder.setVertexBytes(&modelMatrix, length: MemoryLayout<simd_float4x4>.size, index: Int(BufferIndexModelMatrix.rawValue))

And in Objective-C, we can use the normal C & operator to get the pointer, and sizeof(simd_float4x4) to get the size of the matrix data type.

simd_float3 rotationAxis = {1, 1, 0};
simd_float4x4 modelMatrix = matrix4x4_rotation(_rotation, rotationAxis);

[renderEncoder setVertexBytes:&modelMatrix length:sizeof(simd_float4x4) atIndex:BufferIndexModelMatrix]

And in your Metal shader source, you would add a constant parameter at the buffer index and use the matrix you encoded.

vertex ColorInOut vertexShader(Vertex in [[ stage_in ]],
                               constant FrameData & frameData   [[ buffer(BufferIndexFrameData) ]],
                               constant float4x4 &  modelMatrix [[ buffer(BufferIndexModelMatrix) ]])

{
    ColorInOut out;
    float4 position = float4(in.position, 1.0);
    out.position = frameData.projectionViewMatrix * modelMatrix * position;
    out.texCoord = in.texCoord;
    return out;
}