Home > Enterprise >  Issue with indexing Metal buffers
Issue with indexing Metal buffers

Time:02-22

When setting a buffer with Metal, you do so by associating a certain index with it, here at index 0:

renderCommandEncoder.setVertexBuffer(someBuffer, offset: 0, index: 0)

Then from your Metal shading language code, you access to these buffers using arguments such as constant float4x4* projectionMatrix [[ buffer(0) ]].

The issue I have is that libraries and tutorials seem to encourage setting the index "automatically" in some cases, for instance, when loading a Model I/O mesh, you are provided with an array of buffers that store the data of the mesh.

I see these buffers are sometimes set this way:

for (index, buffer) in mesh.vertexBuffers.enumarated() {
    renderCommandEncoder.setVertexBuffer(buffer, offset: 0, index: index)
}

My issue with this is that contrary to a case where you know upfront how many buffers you will have (say one buffer for your mesh data (index 0), one for the mesh world transform (index 1), one for camera (index 2)) now the indexes of your own buffers may be offsetted in function of the mesh you are loading with Model I/O.

For instance if Model I/O loads a mesh that has two buffers to represent its data, you now have to offset your own buffers, but then your Metal Shading Language code cannot know about it at compile time.

Is it just that Model I/O would never load more buffers than you expected (since you can specify it a certain layout for your vertices in memory?). My issue is that I am using the procedural mesh generation functions (such as the ones to generate a sphere) and these functions have no way to customize this so I wonder how stable the memory layout is for those.

CodePudding user response:

You can use vertex descriptors to work around this. One option is to put all the vertex buffers at the higher buffer binding slots. Kinda like this:

You can calculate vertex buffer binding start as let vertexBufferIndexStart = 31 - bufferLayouts.count where bufferLayouts is an array of vertex buffer layouts for your model. I think you can go higher than 31 also, but you'd have to check feature tables.

Then, just offset bufferIndex on MTLVertexAttributeDescriptor on each attribute in the MTLVertexDescriptor. This way, all the buffers starting from 0 up to the max buffer bind slots minus number of vertex buffers are gonna be available for you to bind your other buffers.

  • Related