dugla
dugla

Reputation: 12954

How do I pull the data out of a MDLMeshBufferData to fill a MTKMeshBuffer?

I need to create a MTKMeshBuffer instance from a MDLMeshBufferData instance. Here is a code snippet:

let mdlm = MDLMesh(scnGeometry:sceneGeometry, bufferAllocator:nil)

let mdlSubmesh:MDLSubmesh = mdlm.submeshes?[ 0 ] as! MDLSubmesh

let mdlIndexBufferData:MDLMeshBufferData = mdlSubmesh.indexBuffer as! MDLMeshBufferData

let d:Data = mdlIndexBufferData.data

let mtlIndexBuffer:MTKMeshBuffer = device.makeBuffer(bytes: ???, length: ???, options:MTLResourceOptions.storageModeShared) as! MTKMeshBuffer

The ??? are the bits I need to fill. Can someone please show me the proper API to use to extract the bits from the MDL buffer to fill the MTK buffer?

Upvotes: 3

Views: 1700

Answers (2)

dugla
dugla

Reputation: 12954

The solution is to build the MTLBuffers for each of vertexBuffer and indexBuffer and use them in the draw loop. Works fine.

See: https://github.com/turner/HelloMetal and run the HelloSceneKit target.

Upvotes: 1

rickster
rickster

Reputation: 126167

You're actually making more work for yourself by trying to pull data out of the mesh and stuff it into Metal buffers "manually". Also, an MTKMeshBuffer is not an MTLBuffer — it contains a Metal buffer, along with info that you're likely to need when using that buffer to render with.

What you actually what to do here is have Model I/O allocate MetalKit buffers for you instead of doing it yourself, which means MetalKit allocates Metal buffers for the data so you don't have to copy it. Then use MetalKit to access the meshes and buffers. Something like this (untested):

let allocator = MTKMeshBufferAllocator(device: myMetalDevice)
let mdlMesh = MDLMesh(scnGeometry: sceneGeometry, bufferAllocator: allocator)
let mtkMesh = try! MTKMesh(mesh: mdlMesh, device: myMetalDevice)
//            ~~~~ <- in real code, please handle errors

// then, at render time...
for (index, vertexBuffer) in mtkMesh.vertexBuffers.enumerated() {
    // vertexBuffer is a MTKMeshBuffer, containing an MTLBuffer
    renderEncoder.setVertexBuffer(vertexBuffer.buffer,
                                  offset: vertexBuffer.offset,
                                  at: index)
}
for submesh in mtkMesh.submeshes {
    // submesh is a MTKSubmesh, containing an MTKMeshBuffer
    renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
                                        indexCount: submesh.indexCount,
                                        indexType: submesh.indexType,
                                        indexBuffer: submesh.indexBuffer.buffer,
                                        indexBufferOffset: submesh.indexBuffer.offset)
}

Upvotes: 2

Related Questions