What is an Argument Buffer?

Hello -

This question may sound rather basic, but I am having a difficult time distinguishing an argument buffer from a “normal” buffer. I thought if I tagged a member of a struct with an id[[]] attribute the struct was effectively an argument buffer. But that does not seem to be the case.

For a point of reference, this is the struct:

typedef struct Mesh {
constant float * bufferA [[ id(0) ]];
constant uint * bufferB [[ id(1) ]];
} Mesh;

The two buffers are just an array of floats/uints. If I try to get an argument encoder to a function that has this struct, the API throws an error and says there is no argument buffer at this index.

So is a struct an argument buffer only if it mixes and matches types (for example a pointer to a buffer type and a texture)? Section 2.11.2 of the MSL Language Specification made this much more confusing for me.

If the error is something like this:

failed assertion `Function fragment_main does not have a buffer argument with buffer index 21'

then that’s because you don’t have a buffer argument at that number.

In Chapter 15 sample code, you can get this message by changing in Model's initializeTextures():

let textureEncoder =
  fragmentFunction.makeArgumentEncoder(
    bufferIndex: Int(BufferIndexTextures.rawValue))

to:

let textureEncoder =
  fragmentFunction.makeArgumentEncoder(
    bufferIndex: 21))

The matching fragment code for this buffer is:

struct Textures {
  texture2d<float> baseColorTexture;
  texture2d<float> normalTexture;
};

fragment float4 fragment_main(VertexOut in [[stage_in]],
        constant Textures &textures [[buffer(BufferIndexTextures)]]

So the fragmentFunction.makeArgumentEncoder buffer index has to match the buffer index of the parameter into the fragment function, not the buffer index inside the struct.

Does that answer your question?

Yes! Thank you. That was the error I received and the change you recommended solved it.

1 Like