Chapter 5 : Meaning of stage_in

Hello

I hope you are have spending a nice Monday.
I have a question that is maybe too early in my learning curve of Metal but …

in « fragment float4 fragment_main(VertexOut in [[stage_in]]) { return float4(in.normal, 1); } »
in Shaders.metal

So far (chapter5), I do not really understand what does stage_in mean. Can you provide a short explanation and point out what to read to understand better what it means ?

Regards

Behr

1 Like

[[stage_in]] is an attribute that you can use with one vertex or fragment shader argument.

With the vertex shader, when you use the stage_in attribute, you match the shader struct with the pipeline’s vertexDescriptor. So you might have a vertex descriptor that describes

Position - float3
Normal - float 3

and then in the shader you define a struct with

position: float4
normal: float3

Using the stage_in attribute, the shader can look at the pipeline’s vertex descriptor and see what format the input buffer is in, and then match it with the struct as declared in the argument. Notice here that the position doesn’t match between vertexDescriptor and shader struct, but that doesn’t matter because stage_in will make it match.

You don’t have to use vertexDescriptors or stage_in. As long as your buffer matches what the shader struct expects, then that will work too.

Warren Moore’s answer on this question is great:

Also, become familiar with the Metal Shading Language specification. It’s really daunting at first, but as you use it more, it does start to make more sense:

4 Likes

Hello Caroline,

First, thank you for your answer. Very pedagogical you are.

For ‘stage_in’ … I understand it now!

This made me realize first that stage_in is defined (from the swift point of view) in VertexDescriptor.swift, which was not clear for me at this point.

Your answer made me read more (MBT book) and more especially back to chapter 2, were VertexDescriptors are well, described. But after this reading, I try to figure out why float3 are / can be translated into float4 in the shader…

It seems that it is possible because: the float3 contains less data than destination float4 and so far I can only speculate that the w value is set to 1 or 0 … by the Gremlins inside the computer…

I found a lot of interesting topics in Metal Shading Language Specification.pdf, but not this answer … so far.

Can I put a next question?
VertexDescriptors have an array of 31 attributes: which mean if I understand well that we can set 31 differents type of data description in the struct of the shader. When I call such a line " renderEncoder.setVertexBytes " do these bytes uses the same 31 quota for type of data?

You define the vertex descriptor on the Swift side, a struct on the GPU side, and the [[stage_in]] attribute links the two. This linking means that when the vertex buffer described by the vertex descriptor is transferred from RAM to video RAM, the “gremlins” can automatically make that float3 to float4 conversion.

You don’t have to use vertex descriptors. If you create an MTLBuffer without one, you make sure that the struct in your shaders file exactly matches the layout of the MTLBuffer. The vertex descriptor is a convenience.

A vertex descriptor describes how one or more vertex buffers are laid out. However, as I just said, not all vertex buffers use vertex descriptors. For example uniforms go into an MTLBuffer. That buffer is described by the Uniforms struct in Common.h, which both Swift and the shaders use.

setVertexBytes is a convenience which automatically creates an MTLBuffer so you don’t have to.

With that explanation, I hope that you can see that the 31 attributes for the vertex descriptor are plenty. In chapter 8, you’ll use a few more for joint animation.

I hope you are not getting confused with the 31 slots in the GPU buffer argument table. When you set the index of the vertex buffer on the render command encoder, you are setting the slot into the buffer argument table, and that has nothing at all to do with vertex descriptors.

2 Likes