More than 1 year has passed since last update.

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

これまで、MetalのGPUコンピューティングについて解説記事を書いてきました。
[iOS] MetalでGPUコンピューティング (1) 最小限のコードの記述と特性の把握
[iOS] MetalでGPUコンピューティング (2) 群知能
[iOS] MetalでGPUコンピューティング (3) MTLDevice
[iOS] MetalでGPUコンピューティング (4) MTKView

本記事では、前回に引き続きAppleが提供するサンプルコードの解説を行います。

扱うサンプルコードは、前回と同じライフゲームのアプリ、MetalGameOfLifeです。
MetalGameOfLife

IMG_5933.PNG
(実行画面)

今回は、サンプルコード内のMTLLibraryについて解説を行います。
MTLLibraryを用いることでGPU側の言語Metal shading languageの関数を、CPU側の言語Objective-CやSwiftで扱うことが可能になります。

MTLLibraryはクラスではなくプロトコルです。
MTLLibraryに従うオブジェクトは、Metal shading languangeのソースコードを含んでいます。
シェーダーファイル内にあるソースコードはビルド時にコンパイルされ、文字列で書かれたMSLのコードはランタイム時にコンパイルされます。
MTLLibraryのオブジェクトを生成するためには、MTLDeviceのメソッドを用います。

コンパイル済みのバイナリからライブラリを作る場合は、以下のメソッドのどれかを用います。

  • newDefaultLibrary()
  • makeLibrary(filepath:)
  • makeLibrary(data:)

また、ランタイムでテキストからコンパイルしライブラリを作る場合は、以下のメソッドのどれかを用います。

  • makeLibrary(source:options:completionHandler:)
  • makeLibrary(source:options:)

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

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

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

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

Objective-C: AAPLRender.m
@property (nonatomic, strong) id<MTLLibrary> library;
...
_library = [_device newDefaultLibrary];

MTLDeviceのnewDefaultLibraryメソッドにより、ライブラリが生成されています。
このサンプルコードでは、コンパイル済みのバイナリからライブラリの生成を行なっている訳です。

以下のコードでは、頂点シェーダー及びフラグメントシェーダーのコンパイル済みの関数を、MTLFunctionに従うオブジェクトに格納しています。

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

@"lighting_vertex"、及び@"lighting_fragment"はShader.metal内に記述されている関数名です。

また、以下のコードでは、コンピューティング用のコンパイル済みの関数を、MTLComputePipelineDescriptorクラスのオブジェクトのプロパティに設定しています。

AAPLRender.m
descriptor.computeFunction = [_library newFunctionWithName:@"game_of_life"];
...
descriptor.computeFunction = [_library newFunctionWithName:@"activate_random_neighbors"];

@"game_of_life"、及び@"activate_random_neighbors"はShader.metal内に記述されている関数名です。

このように、MTLLibraryはMetal shading languageの関数を扱うためのインターフェイスの役割を果たしているのです。

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