Metal #2 レンダリングパイプライン
- Lingheng Tao
- 2024年3月23日
- 読了時間 7 分
Unity Shader Content Table Metal #22 [Appendix] SwiftUI Shader CG Paper #2 KinectFusion: Real-time 3D Reconstruction and Interaction Using a Moving Depth Camera
#ComputerGraphics#TechnicalArt#GameEngine
本稿は Metal のレンダリングパイプライン(Rendering Pipeline)の知識点についてです。
ハードウェア基礎
まず GPU と CPU の違いを理解する。
- GPU(Graphics Processing Unit):グラフィックス処理装置。大量のデータを処理する。高度に並列な構造により、画像や動画などの大規模データを高速処理。
- CPU(Central Processing Unit):中央処理装置。順序付きデータを高速処理。データは1つずつ処理される。
CPU は命令を GPU に渡す。Metal の戦略は、CPU 上でコマンドバッファに複数の CPU 命令を格納し、ブロッキングを防ぐため CPU は次のフレームの命令を継続的に発行する。GPU が現在のタスクを完了するのを待たない。
レンダリングパイプライン
高レベルでは、各 API のレンダリングパイプラインに大きな差はない。Metal 公式ドキュメントでは、Metal のレンダリングパイプラインをアプリケーション段階→頂点段階→ラスタライズ段階→フラグメント段階→ピクセル段階とまとめている。低レベルでは、各ステップを実現するために、使用する抽象概念に対する具体的な制御がプログラムに必要。
初期化
MetalView
SwiftUI では import MetalKit で MTKView を取得。MTKView を UIViewRepresentable (iOS) または NSViewRepresentable (macOS) でラップして使用する。
Renderer クラス
他の API では1フレーム内のライフサイクル(ゲームループ)を何らかの方法で手動実装する必要がある。Metal では、MetalKit がゲームループの実装を簡略化する構造を提供。MetalKit と MTKViewDelegate プロトコルに準拠する自作 Renderer クラスでレンダリング呼び出しを実装する。
MTKViewDelegate の主なメソッド:
- mtkView(_:drawableSizeWillChange:):MTKView の drawable サイズが変化したときに呼ばれる。つまりウィンドウサイズが変わったとき。
- draw(in:):毎フレーム呼ばれる。通常このメソッド内で Metal API を呼んでレンダリングする。
1回だけ設定する変数
初期化の目的は、デバイス、状態、コマンド、バッファなどの参照を取得すること。Metal の利点の1つは、初期化時に多くの変数を事前設定でき、毎フレームで行う必要がないこと。
1回だけ設定すべき変数(シングルトンとみなす):
- MTLDevice:GPU デバイスへの参照
- MTLCommandQueue:CPU がコマンドバッファを投入するキュー
- MTLLibrary:シェーダーコードの関数ライブラリ
複数設定可能な変数:
- MTLBuffer:バッファ。頂点情報などを格納。頂点データを GPU に渡す媒体。
- MTLRenderPipelineState:レンダリング状態の具体的設定。使用するシェーダー、深度設定、色設定、頂点データ読み取り規則など。
これらは Renderer クラスが担当する。
