この記事は、Metal Advent Calendar2016の9日目です。
これまで、MetalのGPUコンピューティングについて解説記事を書いてきました。
[iOS] MetalでGPUコンピューティング (1) 最小限のコードの記述と特性の把握
[iOS] MetalでGPUコンピューティング (2) 群知能
[iOS] MetalでGPUコンピューティング (3) MTLDevice
[iOS] MetalでGPUコンピューティング (4) MTKView
[iOS] MetalでGPUコンピューティング (5) MTLLibrary
本記事では、前回に引き続きAppleが提供するサンプルコードの解説を行います。
扱うサンプルコードは、前回と同じライフゲームのアプリ、MetalGameOfLifeです。
MetalGameOfLife
今回は、サンプルコード内のMTLCommandQueueについて解説を行います。
MTLCommandQueueはコマンドバッファ(MTLCommandBufferのオブジェクト)のキューです。また、MTLCommandBufferのオブジェクトの生成にも用いられます。
コマンドバッファはGPUに引き渡されるエンコードされた命令を格納しています。
MTLCommandQueueはクラスではなくプロトコルです。
コマンドキューはスレッドセーフで、複数のコマンドバッファを同時にエンコードすることができます。
繰り返しになるのですが、このサンプルコードは、主に以下のファイルで構成されています。
AAPLRender.h
AAPLRender.m
AAPLViewController.h
AAPLViewController.m
Sharder.metal
このうち、AAPLRender.mには並列コンピューティング及び描画のCPU側のロジックが、Shader.metalには頂点シェーダー、フラグメントシェーダー、GPUコンピューティング用のシェーダーが書かれています。
ここからは、サンプルコード内におけるMTLCommandQueueの使用箇所を解説していきます。
AAPLRender.mに以下の記述があります。
@property (nonatomic, strong) id<MTLCommandQueue> commandQueue;
...
_commandQueue = [_device newCommandQueue];
MTLDeviceのnewCommandQueueメソッドにより、コマンドキューオブジェクトが生成されています。コマンドキューはmakeCommandQueue(maxCommandBufferCount:)メソッドでも生成することができますが、この場合は格納される未実行のコマンドバッファ数の上限が設定されます。
コマンドバッファはその都度何度も生成しますが、コマンドキューの生成はアプリの起動時に一回行えば十分です。
また、以下のコードでは、コマンドバッファからコマンドキューの生成を行なっています。
id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
コマンドバッファの生成は、commandBufferメソッド、もしくはcommandBufferWithUnretainedReferencesメソッドで行います。commandBufferメソッドは、内部で使われるリソースに対して強参照であるに対して、commandBufferWithUnretainedReferencesメソッドは強参照ではありません。たいていの場合は、commandBufferメソッドが用いられます。
コマンドバッファの生成後、これに対してGPUコンピューティングの設定、及びレンダリングの設定が為されて、コマンドバッファが実行(commit)されます。
[self encodeComputeWorkInBuffer:commandBuffer];
[self encodeRenderWorkInBuffer:commandBuffer];
[commandBuffer commit];
このように、MTLCommandQueueはコマンドバッファを管理する役割を担っています。
今回はライフゲームのサンプルコード内におけるMTLCommandQueueの解説を行いました。
次回以降、さらに他の箇所についての解説を行なっていきます。