ハイライト
Apple は、タイルベースの遅延レンダリング、タイル メモリ、メモリレス レンダー ターゲット、タイル シェーダ、引数バッファ、および間接コマンド バッファを使用して、Metal アプリケーションが帯域幅を削減し、メモリ使用量を削減し、より複雑なレンダリング ループを GPU 側に移動して実行できるようにする方法を説明しています。
主要内容
多くのグラフィックス プログラムのパフォーマンスのボトルネックはメモリ転送に起因することが多く、シェーダ自体が主な原因ではない可能性があります。従来のレンダリング パイプラインは、G バッファ、MSAA サンプリング結果、および一時的なカラー アタッチメントを外部メモリに書き込み、次のパスでそれらを読み取るために使用されます。状況が複雑になればなるほど、帯域幅がボトルネックになりやすくなります。
Apple GPU の前提は異なります。 CPU と GPU はシステム メモリを共有します。 GPU にはオンチップ タイル メモリもありますが、独立したビデオ メモリはありません。 Apple が選択したパスは、タイルベースの遅延レンダリング (TBDR、タイルベースの遅延レンダリング) です。最初にジオメトリをタイルに分割し、次に各タイルでピクセル処理を完了します。中間結果がタイル メモリに保持されている限り、多くの読み取りと書き込みを行う必要はありません。
このセッションの価値は、Metal の API のいくつかをハードウェアのコンテキストに戻すことです。loadAction、storeAction、メモリレス ストレージ、プログラマブル ブレンディング、タイル シェーダー、イメージブロック、引数バッファ、間接コマンド バッファはすべてハードウェア バックグラウンドを持っています。これらは共に、アクセスするシステム メモリを減らし、並列化可能な意思決定を GPU に引き渡すという 1 つの目標を達成します。
詳細
TBDR はレンダリングをタイリングとレンダリングに分割します
(01:50) Apple GPU のレンダー パスは 2 つのステージに分かれています。タイリング フェーズでは、パス全体のジオメトリを処理し、変換されたプリミティブを対応するタイルに配置します。レンダリング フェーズでは、ロード アクション、ラスタライズ、可視性の計算、フラグメント シェーディング、およびストア アクションをタイルごとに実行します。
ワークフローの例:
- レンダー パスに入るときは、まず各添付ファイルが前のラウンドのコンテンツを必要とするかどうかを判断します。
- 古いコンテンツの添付は必要ありません。タイル メモリをクリアで初期化します。
- パスの最後には、後で表示またはサンプリングされる結果のみが保存されます。
- このパスの深度、テンプレート、または中間カラー データのみが提供され、完了後に破棄できます。
キーポイント:
- ロード アクションのコストは、添付ファイルのコンテンツをタイル メモリに移動することから発生します。
- ストア アクションのコストは、タイル メモリの内容をシステム メモリに書き戻すことから発生します。
- この一連の判断は画像の結果を変更しませんが、レンダー パスに必要な外部帯域幅の量を変更します。
(03:57) このスピーチでは、アプリケーションが明示的に制御できるのはロード/ストア アクションであることが繰り返し強調されました。必要なデータのみをロードし、後で使用するデータのみを保存します。 TBDR の場合、これはタイル メモリとシステム メモリ間で発生する転送数を直接決定します。
HSR は最初に可視性を計算し、次にフラグメント シェーダーを実行します
(04:39) 隠面除去 (HSR、隠面除去) は、オンチップ深度バッファーに依存して、フラグメント シェーダーが実行される前に各ピクセルの最前面のプリミティブを記録します。不透明な三角形が後ろから前に送信された場合でも、GPU は最初に可視レイヤーを取得し、その後、最後の可視ピクセルに対してのみシェーダーを実行できます。
ワークフローの例:
- 最初に不透明なジオメトリを送信します。
- アルファ テストを送信し、ジオメトリ関連の破棄または深度フィードバックを再度送信します。
- 最後に半透明のジオメトリを送信します。
- 不透明なメッシュと不透明でないメッシュを交互に送信しないようにします。
キーポイント:
- HSR はまず各ピクセルのフロント プリミティブを記録し、次にフラグメント シェーダーを実行します。
- 半透明のプリミティブは、GPU に上書きされたピクセルを強制的にフラッシュさせ、早期にコミットすると非効果的なシェーディングが増加する可能性があります。
- 不透明メッシュ間には厳密な順序はありません。可視性の状態によるグループ化の方が重要です。
(07:27) ここでのオーバードローとは、各ピクセルがフラグメント シェーダーをトリガーする回数を指します。オーバードローを減らすために、セッションで行われるプラクティスは、可視性の状態 (不透明、アルファ テスト/破棄/深度フィードバック、半透明) ごとにグループ化することです。不透明なメッシュ間には厳密な順序付けは必要ありませんが、不透明でないメッシュをインターリーブしないでください。
プログラマブル ブレンディングとメモリレス ターゲットにより、中間テクスチャの着地を回避
(09:27) フルスクリーンのフォグエフェクトや遅延ライティングなどのアルゴリズムでは、多くの場合カスタムミキシングが必要です。従来のアプローチでは、複数のアタッチメントを書き出し、後続のパスでテクスチャ サンプルとして使用します。 TBDR はプログラム可能なブレンディングを公開し、フラグメント シェーダーがタイル メモリ内のピクセル データに直接アクセスして、複数のレンダー パスをマージできるようにします。
コンセプト例:
- 遅延ライティングは、最初にサーフェス プロパティを取得し、次にこれらのプロパティを使用してライティングを計算します。
- 従来のマルチパス方法では、属性アタッチメントを書き出して、次のパスでサンプリングします。
- プログラマブル ブレンディングにより、フラグメント ステージがタイル メモリ内の同じピクセルのデータに直接アクセスできるようになります。
- このようにして、元々分離されていたパスをマージでき、中間アタッチメントのロード/ストアを軽減できます。
キーポイント:
- セッションは、グローバル フォグと遅延ライティングをカスタム ブレンドが必要なシーンとして明示的に分類します。
- プログラマブル ブレンディングの範囲は現在のピクセルであり、単一ピクセル レベルのブレンディングと光の蓄積に適しています。
- 中間レンダー ターゲットの外部への書き込みとリードバックの必要性がなくなるという利点があります。
(10:28) 一部のレンダー ターゲットがタイル メモリ内でのみ使用される場合は、メモリレス ストレージに設定できます。このようにして、Metal はこれらの一時的な添付ファイルに永続的なシステム メモリを割り当てません。
ワークフローの例:
- 遅延レンダラー内の G バッファー添付ファイルをリストします。
- 現在のレンダー パス内でのみ使用される添付ファイルをマークします。
- これらの添付ファイルはシステム メモリに保持する必要はありません。
- 最終的な色、または後続のパスで読み取る必要がある結果は、保持される必要があります。
キーポイント:
- メモリレス レンダー ターゲットは、タイル メモリ内にのみ存在する一時データをターゲットとします。
- これらの一時的なレンダー ターゲットに外部ストレージが割り当てられなくなるため、削減されるのはメモリ フットプリントです。
- 後続のパスで特定の結果をサンプリングする必要がある場合、それはこのセッションで説明されているメモリレス シナリオには属しません。
MSAA 解決はタイル メモリから完了します
(11:31) Apple GPU の MSAA (マルチサンプル アンチエイリアス) はチップ上に複数のサンプルを保存し、タイル フラッシュ中に解決します。セッションによって得られる結論は非常に単純です。通常、マルチサンプリング テクスチャを保存する必要はなく、解決結果のみを最終テクスチャに書き込む必要があります。
ワークフローの例:
- レンダー パスで MSAA を使用して、複数のサンプルを生成します。
- 複数のサンプルがタイルメモリーに保存されます。
- タイルフラッシュ中に最終結果を直接解決します。
- 完全なマルチサンプル アタッチメントではなく、解決されたテクスチャのみが保存されます。
キーポイント:
- セッションは、MSAA 解決が常にタイル メモリから行われると明示的に示しています。
- マルチサンプリング添付ファイルは、このプロセスにおける一時的なデータです。
- メモリレス ストレージと組み合わせて、帯域幅とフットプリントを同時に節約します。
イメージブロックとタイル シェーダーにより、コンピューティングがレンダー パスの途中に入ることが可能になります。
(15:53) A11 以降、Apple GPU にはオンチップの Imageblock と Tile Compute が追加されました。 Imageblock はタイル メモリ内の 2 次元データ構造であり、フラグメント関数またはカーネル関数によってアクセスできます。タイル シェーダーは、レンダー パスでディスパッチできる計算カーネルであり、API 送信の順序で描画呼び出しとインターリーブされます。
ワークフローの例:
- まず、レンダー パスでタイルに対応する画像データを取得します。
- Imageblock を使用して、タイル メモリ内の 2 次元データを表現します。
- 描画呼び出しの間にタイル シェーダー ディスパッチを挿入します。
- タイル シェーダーは、送信された順序で描画呼び出しとインターリーブされ、前後の描画呼び出しと同期境界が確立されます。
キーポイント:
- Imageblock の値は、GPU が画像データを処理していることを認識していることを示します。
- タイル シェーダーは、レンダリング パスの途中でイメージブロックにアクセスできます。
- これにより、追加の計算パスが必要となる一部のステップを同じレンダー パス内で完了できるようになります。
(19:28) タイル シェーディングを使用すると、ライト カリング、G バッファの使用量、およびライティングを 1 つのパスに蓄積できます。 3 つのパス間の元の外部テクスチャの読み取りと書き込みは、タイル メモリ内でのインターリーブ レンダリングと計算になりました。
引数バッファと間接コマンド バッファは、GPU 上で描画の決定を行います。
(20:47) 従来のレンダリング ループは、CPU がシーンを走査し、前のフレームの GPU によって書き込まれたオクルージョン情報を読み取り、錐台クロッピングと LOD 選択を実行し、描画コマンドをエンコードすることで構成されます。ここには同期ポイントがあります。CPU は GPU の結果を待つ必要があり、GPU は CPU が次の描画バッチを送信するのを待つ必要があります。
ワークフローの例:
- シーン内のメッシュ、マテリアル、モデルの関係を GPU が横断できるデータ構造に編成します。
- GPU は最初にシーンを走査し、オクルーダーをレンダリングします。
- 次に、GPU はシーンを走査し、カリングと LOD 選択を実行します。
- GPU は最終的に、可視オブジェクトの描画コマンドを送信して、最終的なレンダリングを完了します。
キーポイント:
- 引数バッファは、GPU がアクセスできる構造内に複雑なシーン データを保持する役割を果たします。
- 間接コマンド バッファーは、GPU に独自の描画コマンドを生成させる役割を果たします。
- このパスは、CPU が前のフレームのオクルージョン データを読み取り、描画コマンドをエンコードする同期ポイントを削除します。
(22:45) セッションの GPU 主導のレンダリング ループは 3 つのステップです。GPU はシーンを走査してオクルーダーをレンダリングし、次に GPU はシーンを走査してカリングと LOD 選択を行い、最後に GPU が最終シーンをレンダリングします。 CPU は、フレームごとに各描画呼び出しを決定しなくなりました。
重要ポイント
-
やるべきこと: メモリレス G バッファを既存の遅延レンダラーに追加します。 実行する価値がある理由: このセッションでは、遅延レンダリングのコストは中間テクスチャの書き込みとサンプリングから発生し、メモリレス レンダー ターゲットによりフットプリントを削減できることが明確に指摘されています。 開始方法: 各 G-Buffer アタッチメントのライフ サイクルを確認し、同じレンダー パス内で使用されるアタッチメントのみを設定します。
MTLStorageMode.memoryless、最終的なカラーアタッチメントは保持されます。.store。 -
やるべきこと: 表示状態ごとにレンダリング キューをグループ化します。 実行する価値がある理由: HSR は不透明なジオメトリに対して非常に効率的です。透明性と破棄によってフラッシュがトリガーされ、順序が間違っているとオーバードローが増加します。 開始方法: 描画を送信する前に、メッシュを不透明、アルファ テスト/破棄/深度フィードバック、半透明の 3 つのグループに分割します。まず、不透明と非不透明が織り交ぜられていないことを確認します。
-
対処方法: MSAA 中間サンプリング テクスチャを一時リソースに変更します。 実行する価値がある理由: Apple GPU の MSAA 解決はタイル メモリから行われるため、完全なマルチサンプル テクスチャをシステム メモリに書き戻す必要はありません。 開始方法: マルチサンプル テクスチャにメモリレス ストレージを使用させ、レンダー パスに設定します。
resolveTexture、ストアアクションは使用します.multisampleResolve。 -
やるべきこと: マルチライト シーンに対してタイルベースのライト カリングを試してください。 実行する価値がある理由: タイル シェーディングは、レンダー パス内のタイルごとにライト リストを処理し、複数のパスを 1 つのプロセスに結合して帯域幅を節約できます。 開始方法: まず、各タイルに必要なライト インデックス リストを整理し、次にタイル シェーダーを使用してイメージブロック内の G バッファ データを読み取り、ライティングを蓄積します。
-
やるべきこと: 大きなシーンのカリングと LOD 選択を GPU に移行します。 実行する価値がある理由: 引数バッファーを使用すると、GPU は複雑なシーン データをトラバースできるようになり、間接コマンド バッファーを使用すると、GPU が描画コマンドをエンコードできるようになり、CPU/GPU の同期ポイントを減らすことができます。 開始方法: メッシュ、マテリアル、およびモデルのフラット化を引数バッファ配列に変換し、コンピューティング パスを使用して間接コマンド バッファに書き込み、レンダー パスでこれらのコマンドを実行します。
関連セッション
- GPU カウンターを使用して Metal アプリとゲームを最適化する — Xcode 12 の GPU カウンターを使用して、TBDR 最適化によって本当にボトルネックが軽減されるかどうかを検証する方法を学びます。
- Metal アプリを Apple シリコン Mac に導入する - Apple GPU の TBDR アーキテクチャと Metal の適応について、Mac 移植の観点から引き続き説明します。
- Apple シリコン Mac のメタル パフォーマンスを最適化 — Apple シリコン Mac のメタル ワークロードのパフォーマンスをさらに調整します。
- Metal Performance Shaders Graph を使用してカスタマイズされた ML モデルを構築する — Metal のコンピューティング能力が機械学習グラフとテンソルのワークロードにどのように対応できるかを学びます。
コメント
GitHub Issues · utterances