[iOS]MetalでGPUコンピューティング(12) MTLRenderPipelineState


この記事は、Metal Advent Calendar2016の17日目です。

これまで、MetalのGPUコンピューティングについて解説記事を書いてきました。
[[iOS] MetalでGPUコンピューティング (1) 最小限のコードの記述と特性の把握](http://qiita.com/yuky_az/items/ece9b64befc635e89f1a)
[[iOS] MetalでGPUコンピューティング (2) 群知能](http://qiita.com/yuky_az/items/ce5920f28c08e743418b#_reference-cc4434da198d861bba61)
[[iOS] MetalでGPUコンピューティング (3) MTLDevice](http://qiita.com/yuky_az/items/1992daff208223468e70)
[[iOS] MetalでGPUコンピューティング (4) MTKView](http://qiita.com/yuky_az/items/a2556edcfa417b7d912c)
[[iOS] MetalでGPUコンピューティング (5) MTLLibrary](http://qiita.com/yuky_az/items/fd777dfde0bdef85861e)
[[iOS] MetalでGPUコンピューティング (6) MTLCommandQueue](http://qiita.com/yuky_az/items/e40b8a36035a409d08db)
[[iOS] MetalでGPUコンピューティング (7) MTLCommandBuffer](http://qiita.com/yuky_az/items/b557850ae9dc317f1570)
[[iOS] MetalでGPUコンピューティング (8) MTLComputeCommandEncoder](http://qiita.com/yuky_az/items/4c4e384b1f7a399a2320)
[[iOS] MetalでGPUコンピューティング (9) MTLComputePipelineState](http://qiita.com/yuky_az/items/2a59f9530410b734cb5b)
[[iOS] MetalでGPUコンピューティング(10) Metal Shading Languageで記述されたライフゲームのロジック](http://qiita.com/yuky_az/items/a2aba547c02b879d7b29#_reference-9d4b6788a293fae54af5)
[[iOS] MetalでGPUコンピューティング(11) MTLRenderCommandEncoder](http://qiita.com/yuky_az/items/59fa00e1dc826cb714af)
 本記事では、前回に引き続きAppleが提供するサンプルコードの解説を行います。

扱うサンプルコードは、前回と同じ[ライフゲーム](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0)のアプリ、MetalGameOfLifeです。
 [MetalGameOfLife](https://developer.apple.com/library/content/samplecode/MetalGameOfLife/Introduction/Intro.html)

![IMG_5933.PNG](https://qiita-image-store.s3.amazonaws.com/0/35297/fa9b4e62-91a6-83fb-c60c-3666fc44fdf1.png "IMG_5933.PNG")
（実行画面）

今回は、サンプルコード内の[MTLRenderPipelineState](https://developer.apple.com/reference/metal/mtlrenderpipelinestate)について解説を行います。
MTLRenderPipelineStateは、グライフィックのレンダリング用のパイプラインに描画用の関数や頂点の設定などの状態をエンコードするために用いられます。
コンピューティング用のMTLComputePipelineStateと対をなしています。
MTLRenderPipelineStateはクラスではなくプロトコルで、MTLDeviceのオブジェクトにより生成されます。
MTLRenderPipelineStateのオブジェクトの生成はコストが高いので、アプリ起動時に一度生成すれば十分です。

繰り返しになるのですが、このサンプルコードは、主に以下のファイルで構成されています。

AAPLRender.h
AAPLRender.m
AAPLViewController.h
AAPLViewController.m
Sharder.metal

このうち、AAPLRender.mには並列コンピューティング及び描画のCPU側のロジックが、Shader.metalには頂点シェーダー、フラグメントシェーダー、GPUコンピューティング用のシェーダーが書かれています。

ここからは、サンプルコード内におけるMTLRenderPipelineStateの使用箇所を解説していきます。
AAPLRender.mに以下の記述があります。

```Objective-C:AAPLRender.m
@property (nonatomic, strong) id<MTLRenderPipelineState> renderPipelineState;
...
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.label = @"Fullscreen Quad Pipeline";
pipelineStateDescriptor.vertexFunction = vertexProgram;
pipelineStateDescriptor.fragmentFunction = fragmentProgram;
pipelineStateDescriptor.vertexDescriptor = vertexDescriptor;
pipelineStateDescriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
_renderPipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];                                                                   
```

MTLRenderPipelineStateのオブジェクトの生成時には、MTLRenderPipelineDescriptorを介して頂点シェーダーの関数、フラグメントシェーダーの関数、頂点の設定、ピクセルフォーマットを指定します。

頂点シェーダーの関数、フラグメントシェーダーの関数は以下のようにMTLLibraryのオブジェクトを介してMTLFunctionのオブジェクトvertexProgram、fragmentProgramに格納されています。

```Objective-C:AAPLRender.m
    id<MTLFunction> vertexProgram = [_library newFunctionWithName:@"lighting_vertex"];
    id<MTLFunction> fragmentProgram = [_library newFunctionWithName:@"lighting_fragment"];
```

@"lighting_vertexと@"lighting_fragment"がシェーダー内に記述された関数名です。

MTLRenderPipelineStateオブジェクトは、以下の箇所でコマンドエンコーダーに設定されます。

```Objective-C:AAPLRender.m
[renderEncoder setRenderPipelineState:self.renderPipelineState];
```

このように、MTLRenderPipelineStateは描画用の様々な設定をエンコードし格納する役割を担っています。

今回はライフゲームのサンプルコード内におけるMTLRenderPipelineStateの解説を行いました。
次回以降、さらに他の箇所についての解説を行なっていきます。