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

  • 0
    いいね
  • 0
    コメント

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

    これまで、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
    [iOS] MetalでGPUコンピューティング (6) MTLCommandQueue
    [iOS] MetalでGPUコンピューティング (7) MTLCommandBuffer
    [iOS] MetalでGPUコンピューティング (8) MTLComputeCommandEncoder
    
本記事では、前回に引き続きAppleが提供するサンプルコードの解説を行います。

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

    IMG_5933.PNG
    (実行画面)

    今回は、サンプルコード内のMTLComputePipelineStateについて解説を行います。
    MTLComputePipelineStateはMTLFunction内のコンピューティング用の関数をコンパイルするのに用いられます。
    MTLComputePipelineStateはクラスではなくプロトコルで、MTLDeviceのオブジェクトにより生成されます。
    MTLComputePipelineStateのオブジェクトの生成はコストが高いので、アプリ起動時に一度生成すれば十分です。

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

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

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

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

    AAPLRender.m
    @property (nonatomic, strong) id<MTLComputePipelineState> simulationPipelineState;
    @property (nonatomic, strong) id<MTLComputePipelineState> activationPipelineState;
    ...
       MTLComputePipelineDescriptor *descriptor = [MTLComputePipelineDescriptor new];
        descriptor.computeFunction = [_library newFunctionWithName:@"game_of_life"];
        descriptor.label = @"Game of Life";
        _simulationPipelineState = [_device newComputePipelineStateWithDescriptor:descriptor
                                                                          options:MTLPipelineOptionNone
                                                                       reflection:nil
                                                                            error:&error];
    ...
        descriptor.computeFunction = [_library newFunctionWithName:@"activate_random_neighbors"];
        descriptor.label = @"Activate Random Neighbors";
        _activationPipelineState = [_device newComputePipelineStateWithDescriptor:descriptor
                                                                          options:MTLPipelineOptionNone
                                                                       reflection:nil
                                                                            error:&error];                                                                     
    

    MTLComputePipelineStateのオブジェクトの生成時には、MTLComputePipelineDescriptorを介してコンピューティング用の関数を指定します。@"game_of_life"と@"activate_random_neighbors"が関数名です。このサンプルコードでは、毎フレームごとに実行される関数と、画面タップ時に実行される関数があり、それぞれ異なるMTLComputePipelineStateオブジェクトでエンコードされます。

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

    AAPLRender.m
    [commandEncoder setComputePipelineState:self.simulationPipelineState];
    ...
    [commandEncoder setComputePipelineState:self.activationPipelineState];
    

    このように、MTLComputePipelineStateはコンピューティング用の関数をエンコードし格納する役割を担っています。

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