T.TAO
Back to Blog
/4 min read/Others

Metal #2 Rendering Pipeline

Metal #2 Rendering Pipeline

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 の主なメソッド:

  1. mtkView(_:drawableSizeWillChange:):MTKView の drawable サイズが変化したときに呼ばれる。つまりウィンドウサイズが変わったとき。
  2. draw(in:):毎フレーム呼ばれる。通常このメソッド内で Metal API を呼んでレンダリングする。

1回だけ設定する変数

初期化の目的は、デバイス、状態、コマンド、バッファなどの参照を取得すること。Metal の利点の1つは、初期化時に多くの変数を事前設定でき、毎フレームで行う必要がないこと。

1回だけ設定すべき変数(シングルトンとみなす):

  • MTLDevice:GPU デバイスへの参照
  • MTLCommandQueue:CPU がコマンドバッファを投入するキュー
  • MTLLibrary:シェーダーコードの関数ライブラリ

複数設定可能な変数:

  • MTLBuffer:バッファ。頂点情報などを格納。頂点データを GPU に渡す媒体。
  • MTLRenderPipelineState:レンダリング状態の具体的設定。使用するシェーダー、深度設定、色設定、頂点データ読み取り規則など。

これらは Renderer クラスが担当する。