“This is the 23rd day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”

An overview of the

Using layer selection to select the target slice for each pixel in the vertex shader, primitives can be rendered into multiple layers (slices) of a texture array, cube texture, or 3D texture. A layer is a single 1D, 2D, or 3D pixel block, specified by slice and MIPMap levels in the target texture. Load and store operations apply to each slice of the render channel attachment.

Layer selection is useful when you need to render content to multiple related textures from the same source data, such as when rendering environment cube maps or virtual reality stereoscopic images.

For a specific example demonstrating layer selection, see Render reflection with Fewer Render channels.

Check whether the device object supports layer selection

All Gpus in the macOS family support layer selection. Apple Gpus from series 5 onwards provide layer selection support. Use the following code to test whether layer selection is supported:


- (Boolean) supportsLayerSelection

{

  return

    [_device supportsFamily: MTLGPUFamilyMac1 ] ||

    [_device supportsFamily: MTLGPUFamilyApple5 ];

}

Copy the code

Add Layer selection

To specify which slice to render primitives to, add vertex output with the [[render_target_array_index]] attribute. The vertex shader must set this value so that Metal knows which slice to render to.

The following example uses instantiation rendering to render primitives into multiple output slices. You need to add a layer field in the vertex output phase to specify the target slice. The e target is taken as input as part of each instance property and copied to the vertex output.

typedef struct { ... uint layer [[render_target_array_index]]; } ColorInOut; vertex ColorInOut vertexTransform ( const Vertex in [[ stage_in ]], const uint instanceId [[ instance_id ]], const device InstanceParams* instanceParams [[ buffer ]], { ColorInOut out; out.layer = instanceParams[instanceId].layer; . }Copy the code

A vertex function must return the same index for all vertices that make up any given primitive.

Configure the pipe state object

A rendering pipeline that can be rendered to a layer must specify the primitive type that can be rendered. This requirement is different from a normal render pipeline, where a different primitive can be selected for each draw command.

When MTLRenderPipelineDescriptor for rendering pipeline configuration, set inputPrimitiveTopology attribute to specify the rendering primitive types.

MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];
descriptor.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
descriptor.sampleCount = 1
...
Copy the code

Configuring render channels

When configuring the MTLRenderPassDescriptor, specify a texture array, cube map texture, or 3D texture as a color accessory. You must also set the renderTargetArrayLength property of the render channel descriptor to the maximum number of slices that the shader can select. For example, when rendering to a cube map texture, set the length to 6.

When rendering to texture arrays and cube maps, you can specify multiple attachments and render all of them at the same time. If you specify a 3D texture, you cannot render to multiple attachments. Here is an example of using a cube map texture to set the render channel descriptors, one for color data and one for depth information:

MTLRenderPassDescriptor* reflectionPassDesc = [MTLRenderPassDescriptor renderPassDescriptor]; reflectionPassDesc.colorAttachments[0].texture = _reflectionCubeMap; reflectionPassDesc.depthAttachment.texture = _reflectionCubeMapDepth; reflectionPassDesc.renderTargetArrayLength = 6; .Copy the code

conclusion

This article describes the steps of using Metal to render to multiple textures, first using layer selection to select the target slice for each pixel in the vertex shader, then configuring the rendered pixel type for the rendering pipeline, and finally configuring the rendering channel.