[iOS, GPU] Metalの描画パイプラインを図解してみる
Apple製のGPUシェーダー言語Metalにて、初学者には中々掴みにくい描画の仕組みについて図示しながら概説してみたいと思います.
はじめに
ざっくりと、Metalでは以下のような手順で描画が行われます。
- 描画情報の設定 (頂点や色の設定など)
- 描画コマンドの生成と送信
- Shader (.Metal拡張子に書かれた描画関数) の通り描画を実行.
以下、これらそれぞれの概説を図とともに見ていきたいと思います.
描画情報の設定
まずは図に記載の
- MTLRenderPipelineDescriptor
- MTLRenderPassDescriptor
の2つのオブジェクトに描画情報をセットし、これを描画コマンドへと渡すようにします.
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
let depthStencilDescriptor = MTLDepthStencilDescriptor()
MTLRenderPipelineDescriptor
主に、
・頂点描画用の関数 (VertexFunction)
・頂点描画設定 (VertexDescriptor)
・頂点の色情報決めるための関数 (FragmentFunction)
等を、MTTLRenderPipelineDescriptor
オブジェクトのattributesに設定します.
その後、MTLPipelineState
オブジェクトがMTTLRenderPipelineDescriptor
から生成されます.
このように、MTLPipelineState (描画設定を保持し、情報をGPUへのコマンド受け渡しに使用する) を作ります.
またDepth情報については、MTLDepthStencilDescriptor
オブジェクトで設定します. 設定手法は、パラメータは違えど上記と同様なので割愛します.
詳しくはこちらの公式で紹介されているソースコードを参照.
MTLRenderPathDescriptor
主に出力先の設定が行われます. 出力としてMTLTexture
をセットすることで、GPU計算をしてCPUへ結果のMTLTexure
を返すこともできます.
以下のように、ベースとなる mtkView から毎フレーム取得して設定も実施します. MTLRenderPathDescriptor
は毎フレームで初期化されるため絵、毎フレーム設定しなければなりません.
let renderPassDescriptor = mtkView.currentRenderPassDescriptor
描画コマンドの生成と送信
基本の流れ
先ほどの描画設定は下図の通り、MTLCommandBuffer
に渡され、これを用いてMTLRenderCommandEncoder
クラスオブジェクトを生成します.
この...CommandEncoderは、GPUが解釈可能なデータになっているものと思われます.
commandQueue = device.makeCommandQueue()
let commandBuffer = commandQueue.makeCommandBuffer()
このcommandBufferに、必要な画像等のデータをセットしてGPU描画が実行されます.
他の流れ
描画をカスタムして実行する場合は、上記のMTLCommandBuffer
の設定が必要ですが、カスタムの描画でなければMTLCommandBuffer
を飛ばす場合もあります. (上図中の紫の矢印)
例えばビルトインの画像フィルター郡は、基本この仕様になっています.
let filter = MPSImageGaussianBlur(device: device!, sigma: 5)
filter.encode(commandBuffer: commandBuffer,
sourceTexture: secTex, destinationTexture: dstTex)
Shader
最後はShaderです.
Shader関数は先述のMTLRenderPipelineDescriptor
の時点で文字列にて設定された関数を用いることになります.
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
// (MTLTextureを順にセットする等、必要な処理を実行)
renderEncoder.endEncoding()
commandBuffer.present(currentDrawable) // 描画
commandBuffer.commit() // 描画完了
まず、MTLComanndBuffeer
からMTLRenderEncoder
が生成されます.
このMTLRenderEncoderには、先述のMTLRenderPipelineStateオブジェクトも入力されます. (コードは割愛)
(Shaderの仕組みは本稿に追記する、もしくは別記事にて形で後日説明します)
参考
Metalの各種Tipsについて、こちらの記事にまとめていますので併せてご参考にいただけますと幸いです。
終わりに
改善点やご意見などあれば、どしどしコメント下さい!
Author And Source
この問題について([iOS, GPU] Metalの描画パイプラインを図解してみる), 我々は、より多くの情報をここで見つけました https://qiita.com/Susumu0417/items/fc2b46fb66a4240dee6f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .