ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Macへのゲーム展開 Part 2:シェーダーをコンパイルする
HLSLシェーダをMetalに変換するプロセスを合理化するMetal Shader Converter について、ゲームをMacに移植するための3部構成のシリーズの2つ目としてご紹介します。すべてのシェーダステージをサポートし、Apple GPUの高度な機能を活用できるDXILの高速なエンドツーエンドのShader Pipelineを構築する方法をご覧ください。また、オフラインコンパイラを使ってGPUバイナリを生成することで、アプリの起動時間とスタッタを短縮する方法もご紹介します。 このセッションを最大限に活用するには、まず「Bring your game to Mac, Part 1: Make a game plan」 をご覧ください。
関連する章
- 0:00 - Intro
- 0:49 - New Metal compiler tools
- 1:54 - Convert your shaders
- 12:27 - Finalize GPU binaries
- 18:20 - Wrap-Up
リソース
- Download the game porting toolkit
- Download the Metal shader converter (Mac and Windows)
- Get started with Metal shader converter
- Metal
関連ビデオ
Tech Talks
WWDC23
WWDC22
WWDC21
WWDC20
-
ダウンロード
♪ ♪
こんにちは ようこそ 私Varun Subramanianは AppleのGPU Graphicsと Display Softwareグループの エンジニアです
本セッションは ハイエンドゲームを Macで楽しむための 3部構成のうちの第2部です 最初のセッションではゲームを評価し 「Make a game plan」方法を伝えました 本セッションではシェーダーに焦点を当て シェーダーをMetal中間表現に 変換する新しい方法や ゲームのビルド時に GPUバイナリを確定することで オンデバイスコンパイルを回避する方法など 新しいMetalコンパイラーツールの 一部を使用して シェーダーの柔軟性と 速度を向上させる方法を紹介します Metalコンパイラツールチェーンは ゲームのパワーとなる シェーダーのコンパイルを支援します
デバイス上でMetal IRを作成することは GPUが必要な作業を行う前に コンパイルのオーバーヘッドを追加するため 最適とはいえません MetalはMetalシェーディング言語から Metal IRを 前もって生成する際に 必要なツールを提供します このメタルIRは Metalライブラリの一部として保存されます 常にMetalコンパイラ ツールチェーンを使用して Metalライブラリを 生成することを目指すべきです
しかし ほかのAPIや シェーディング言語から来た場合は それらをMetalに取り込む方法が必要です もしあなたがMacの初心者なら Metal Shader Converterがあります これにより シェーダーパイプラインが 簡素化され 生成されたMetalライブラリを直接 バンドルにパッケージすることができるため デバイス上でのMetal IRの生成を 避けることができます 生成されるMetalライブラリはMetal コンパイラから生成されるものと同じなので 変換されたシェーダーはMetal APIと ネイティブに統合できます この新しいツールを使用して 既存のシェーダーをMetalライブラリに 変換して ゲームに同梱することができます Metal Shader Converterは シェーダーを Metalに変換する際のエクスペリエンスを 向上させる堅牢な機能セットを提供します DXILを消費してMetal IRを生成します オープンソースのDXCコンパイラツールと ともに使用することで エンドツーエンドのシェーダーパイプラインを 構築できます Metal Shader Converterは バイナリレベルで変換を実行するため DXILからMetal IRへの変換は 非常に高速です その結果 シェーダー資産の ビルド時間が短縮されます また Apple GPUの高度な機能を 活用することもできます これが可能なのは既存のDXILシェーダーの 従来および最新のシェーダーステージを すべてサポートする Metal Shader Converterの 豊富な機能セットのおかげです Metal Shader Converterを使用すると テッセレーションや ジオメトリシェーダーを含む従来の グラフィックスパイプライン用シェーダーを Metalライブラリに変換できます また コンピュートシェーダーや 最近導入されたレイトレーシングの ステージやシェーダー 増幅シェーダー メッシュシェーダーもサポートしています では Metal Shader Converterの 使い方を説明します
コマンドラインでシェーダーを変換する場合 2つのシナリオがあります ターミナル経由でコマンドラインツールを 使用するのは 一度に1つの シェーダーを変換する際に 適したメカニズムです 複数のシェーダーがある場合は Metal Shader Converterを呼び出す シェルスクリプトを作成し 複数のシェーダーを自動的に 変換することができます コマンドラインツールを使った シェーダーの変換は非常に簡単です DXCとシェーダーコンバータを セットアップしたら HLSLシェーダーをDXILに コンパイルすることから始めます DXCではコンパイルする エントリーポイントやシェーダーのタイプ 出力ファイルを指定する必要があります 次に 作成したDXILファイルに対して Shader Converter を呼び出し 作成する出力Metalライブラリを 指定します デフォルトではShader Converterは 最新バージョンの macOS用のMetalライブラリと 有用なリフレクションデータを含む JSONファイルを生成します 実行時に このMetalライブラリを Metalデバイスに渡してロードし パイプライン状態オブジェクトを構築します コマンドラインインターフェイスが ワークフローに 最適でない場合のシナリオが ほかに2つあります ゲームエンジンによっては カスタムアセットビルドプログラムがあり シェーダーをコンパイルしてゲーム固有の フォーマットにパッケージ化します また 状況によってはMetal用に ゲームをブートストラップする際に Metalライブラリに完全に変換する前に プラットフォーム上で シェーダーがどの程度動作するか 確認したい場合もあります これら最後の2つのケースでは ワークフローにMetal Shader Converter を うまく統合する方法が必要です Metal Shader Converter ダイナミックライブラリを使用してこれを実現します CLIツールと同じ機能をすべて公開し Metalライブラリの生成を支援します ライブラリは純粋な Cインターフェイスを提供し CLIと同様にmacOSとWindowsの 両方で利用できるため 既存のワークフローに簡単に統合できます シェーダーをMetal IRに変換した後 ゲームに統合するために パイプラインステートを作成し リソースをバインドします
シェーダーでは通常リソースを グローバル変数として定義し 「レジスタ」宣言を割り当てます API側では ゲームはリソースを これらのスロットに直接バインドするか 「ルートシグネチャ」を介して 明示的なメモリレイアウトを定義します シェーダーコンバータは Metalが非常に柔軟な バインディングモデルを持つため このモデルを持ち込む際に役立ちます このツールはこれらのリソースを 引数バッファにレイアウトします このモデルでは1つの引数バッファを パイプラインに直接バインドし それを介してリソースを参照します この 「トップレベル」引数バッファには 2つのレイアウトモードがあり ゲームに最適なものを選択できます
最も単純なレイアウトは自動レイアウトで シェーダーコンバータが リソースを次々に配置します シェーダーを含む パイプラインステートを作成したら 1つの引数バッファをバインドし それを通してすべてのリソースを参照します あるいはシェーダーコンバータは ルートシグネチャに一致するレイアウトの 明示的な定義もサポートしています このモードはゲームが独自のリソース テーブルに別々のテクスチャとサンプラーを 指定する必要がある場合やバインドレス リソースを使用する場合に使います また この図では0と1として示されている― 生のバッファと32ビット定数を トップレベルの引数バッファに 直接埋め込むこともできます
最上位引数バッファは CPUとGPU間で 共有されるリソースなので そこに書き込む際は 視覚的な破損を引き起こす可能性のある レースコンディションを 避けるため メモリへのアクセスを 調整する必要があります これを避けるためにCPU とGPUの 作業をシリアライズする必要はありません これを避ける方法の一つが バンプアロケータの使用です これは大きな メタルバッファにすることができ そこからフレームごとに 異なるリソースをサブアロケートします そして ゲームが処理する飛行中の フレームごとに バッキングバッファをシャドウします バンプアロケータ実装の詳細については サンプルコードを参照してください Argumentバッファ管理の ベストプラクティスについては 昨年のバインドレスセッションと Metalドキュメントを確認してください Metal Shader Converter が シェーダーをMacに取り込む際に バインディングモデルだけが 役立つわけではありません グラフィックスAPIの違いにより 特定のシェーダーステージの マッピングが難しい場合があります 例えば 従来のジオメトリや テッセレーションステージを活用する パイプラインがあるかもしれません Metalは最新のAPIであり ビューポートIDや 増幅などの機能を提供しているため ほかのグラフィックスAPIにあるような 古くて効率の悪いステージは不要になります
しかし この画像でレンダリングされた 芝のようにいくつかのサーフェスを強化する 伝統的なエフェクトのためゲームがこれらの パイプラインに依存している場合 手作業で変換するのはコストがかかります Metal Shader Converterは これらのパイプラインを メッシュシェーダーに マッピングすることで Metalへの変換を支援します
このツールは 各ステージを Metal IR表現に マッピングすることで これらの複雑なパイプラインを簡単に Metalに移行するための力仕事を行います これには従来は固定関数操作であった テッセレータも含まれます このワークフローをサポートするために 今年のMetalはMeshシェーダーの 「オブジェクトとメッシュ」ステージに 可視関数をリンクする機能を追加しました シェーダーをコンパイルしたあと それを使って 「Metal Mesh RenderPipelineDescriptor」を 構築し 「Metal Render Pipeline state」に コンパイルします Metalはこのパイプライン状態の 構築要求を受け取ると すべてのMetal IRを コンパイルしてリンクし すべての関数を 単一のパイプラインにベイクすることで 関数呼び出しのオーバーヘッドを 完全に回避し 実行時のパフォーマンスを最大化します Metalの可視関数のパワーと柔軟性により これらのシェーディングステージと その補助関数を含む この精巧なレンダーパイプラインを 構築できることに注目してください これらのメッシュパイプラインの 構築は簡単ですが すべてのパイプラインは正確な順序で 一連のステップに従わなければなりません
シェーダーコンバータランタイムは 複雑なパイプラインの構築を支援します メッシュシェーディング作業のディスパッチにより 描画呼び出しもエミュレートします 詳細は Metal Shader Converterの ドキュメントを参照してください シェーダーがMetal上にあり パイプラインの状態を実行している今 素晴らしいパフォーマンスと視覚的な 正しさを得る際に役立つヒントを紹介します
シェーダーコンバータでコンパイルされた シェーダーはMetalリソースを参照します 「useResource」を呼び出して Metalへのリソース常駐にフラグを立てます しかし useResourceは過剰に使用すると 高価な呼び出しになります 複数のuseResourcesを使用して 一度に複数のリソースを提供するか useHeapを使用してMetalヒープを 使用し 1回の呼び出し複数のリソースの 常駐をフラグすることを検討してください パイプラインオブジェクトはMetalが 初めてコンパイルするときにキャッシュされ それ以降のゲーム実行におけるコンパイル ベースのヒッチングを自動的に減らします バイナリアーカイブもここで役立ちます GPUをより活用し Metal IRを カスタマイズしてより高いパフォーマンスを 実現するために シェーダーコンバータは オプションを提供します 互換性やGPUファミリー 頂点フェッチ動作 エントリポイントの命名 リフレクションなどの カスタマイズがあります ここで さらなる最適化の機会を 1つ紹介します
シェーダーコンバータは 既存のシェーダーIRから 「Metal Libraries」を生成する もう1つのメカニズムとして Metalコンパイラに 加わることを先に述べました 様々なグラフィックパイプラインステージに Metalはこれらを使用して供給します すべてがMetal IRであるため Metal Shader Converterと Metalコンパイラからの 「Metal Libraries」を単一のアプリや 単一のパイプラインで混ぜ合わせられます Metalシェーディング言語では プログラマブルブレンディングのような 独自の機能にもアクセスできます このアプローチを使って AppleのGPUを最大限に活用してください タイルシェーディングのような ユニークなシェーディング機能を 利用することもできます これによりゲームをMetalで実現する方法に 非常に大きな柔軟性が得られます パフォーマンスは重要ですが ゲームの ビジュアルが正しいことが最も重要です HLSLではテクスチャを1つの要素の 配列としてシームレスに扱うことができます
この動作に依存する シェーダーを導入するには テクスチャをテクスチャ配列として 作成するか テクスチャに 「テクスチャ配列ビュー」を作成します 「MetalKit Texture Loader」を 使用している場合は ファイルをテクスチャ配列として 読み込むこともできます サンプラーオブジェクトをセットアップし これらのテクスチャから 読み取るには MTLサンプラーディスクリプタの supportsArgumentBuffers プロパティを使用して 引数バッファで サンプラーを参照する予定であることを 事前にMetalに知らせてください シェーダーコンバータを ワークフローに統合することについては ご理解いただけたと思います Metal Shader Converterはdeveloper. apple.comからダウンロードできます Macで作業している場合は Metal Shader Converter for Mac パッケージを入手してください Windowsで作業している場合は Metal Developer Tools for Windows パッケージに含まれています このツールのベータ版は現在入手可能です どちらのパッケージにも スタンドアロンおよび ライブラリ形式の Metal Shader Converterと ランタイムコンパニオンヘッダーが 含まれています 完全なドキュメンテーションとMetal C++ コードサンプルは現在入手可能です サンプルコードを使用してジオメトリと テッセレーションのエミュレーション インスタンス化された描画 コンピュートシェーダーを探求してください ゲームに同梱するシェーダーを Metalライブラリに変換することで ゲーム実行時にライブラリを 生成する手間を省くことができます さらに実行できる可能性のある最適化として GPUバイナリの事前コンパイルがあります ゲームをビルドするとき シェーダーを Metalライブラリにコンパイルしますが それらもGPUバイナリに ファイナライズする必要があります 通常 ゲームは起動時にこれを行うため ローディング画面が長くなります 実行時にGPUバイナリのファイナライズを 延期すると ゲームが新しいパイプラインを オンデマンドでコンパイルするため フレームが低下する可能性があります Metal GPU Binaryコンパイラは ゲームビルド時に シェーダーバイナリを生成できるため この問題の解決に役立ちます ゲームプレイ中にシェーダーバイナリを 生成する必要性をなくすことで プレイヤーにはGPUの追加的な 不具合を発生させることなく アプリのロード時間が短縮されるという メリットがあります
これを活用するために ワークフローに別のステップを追加して ビルド時に MetalライブラリをMetalバイナリ アーカイブにファイナライズできます オンデバイスGPUバイナリのコンパイルは descriptorからパイプラインステートを 作成するときに行われます このdescriptorは、Metalライブラリの 関数を参照するだけでなく レンダーアタッチメントの カラーフォーマットや 頂点レイアウトdescriptorなど そのほかの重要な情報もMetalに提供します GPUバイナリはPSO作成の一部として ジャストインタイムに生成されます バイナリアーカイブを使用すると コンパイルがいつ行われるかを制御できます GPUバイナリを前もって生成するには 既存のMetalライブラリと それらのライブラリを参照するパイプライン 設定スクリプトの両方を提供します そして その両方をmetal-ttに提供し GPUバイナリを含む バイナリアーカイブを作成します パイプラインスクリプトを開発するには Metal APIと 同様のパイプライン設定を持つ JSONスクリプトを作成します この Metal コードは レンダーパイプラインdescriptorを生成し そのJSON相当の表現も一緒に生成します パイプラインスクリプトには Metalライブラリのパスと フラグメントおよび頂点関数名を追加します また その他のパイプライン状態の 設定も指定します これで使用可能な Metalスクリプトが完成しました JSONスキーマの詳細については Metalのデベロッパ向け ドキュメントを参照してください 前もってシェーダーを コンパイルするワークフローは パイプラインスクリプトファイルの生成を 意図していないかもしれません このような場合は別の方法で スクリプトを生成することができます デバイス上でゲームを実行しながら Metalのバイナリアーカイブを記録できます これらのアーカイブには対応する パイプラインスクリプトが含まれます これらのアーカイブをデバイスから 取り出したら「metal-source」で 埋め込まれているパイプラインスクリプトを 取り出すことができます その後 抽出したスクリプト内の Metalライブラリへのパスを更新します 詳細については 「GPUバイナリをビルドする」方法と 「コンパイルワークフローを発見する」 方法の講演を参照してください GPUバイナリは GPUごとに調整されるため 「metal-tt」は プレーヤーのデバイスに応じて 異なるバージョンのバイナリを作成し プレーヤーに配布します Metal-ttは すべての異なるGPUバイナリを Metalバイナリアーカイブに カプセル化することで この複雑さを管理するのに役立ちます こうすることで アプリが バイナリアーカイブを読み込むと Metalがプレーヤーに 適切なバイナリを自動的に選択します 複数のバイナリセットを1つのバイナリ アーカイブにカプセル化することもできます
バイナリアーカイブを 事前に作成できるようになったので ベストプラクティスをいくつか紹介します プレーヤーがコンパイル済みのGPU バイナリを含むMetalアプリを実行すると パッケージ化されたバイナリアーカイブから Metalは必要なGPUバイナリを検索します Metalがアーカイブの中に 一致するものを見つけられなかった場合 自動的にオンデバイスコンパイルに フォールバックします アプリは正しく見えますが GPUへの提出が遅れる可能性があります 「FailOnBinaryArchiveMiss」 オプションでバイナリアーカイブに 期待するパイプラインが 含まれているかどうかテストできます FailOnBinaryArchiveMissオプションは Metalパイプラインステートオブジェクトを 作成するときに簡単に指定できます バイナリアーカイブが見つからない場合 このオプションを設定すると Metalはオンデバイスコンパイルを飛ばし パイプライン状態をnilとして返します すべてのターゲットデバイスをサポートする バイナリアーカイブの準備ができたら デプロイの準備は完了です すべてのプレーヤーが 最新のOSを使用しているとは限りません すべてのユーザーがバイナリアーカイブの 恩恵を受けられるようにするには 主要な OS バージョンごとに アーカイブを生成してアプリに保存します そのためにはプレーヤーのデバイスの OSバージョンを確認し 適切なバイナリ アーカイブを選択して Pipeline Descriptorsに関連付けます プレーヤーがOSをアップデートした場合 バイナリアーカイブの互換性を保つために 再コンパイルが必要になることがありますが Metalなら大丈夫です Metalはプレーヤーのデバイス上の アプリバンドル内の パッケージ化されていない バイナリアーカイブを識別し OSのアップデートやゲームの インストール後 バックグラウンドで 自動的にアップグレードします 要約するとMetalコンパイラと Metal Shader Converterは Metalライブラリを事前に作成し ゲームに同梱するためのツールです MSLソースをコンパイルする場合は Metalコンパイラを使用し シェーダーがHLSLである場合は Metal Shader Converterを使います metal-ttを使用すると Metal エコシステム内の様々なGPUに合わせて MetalライブラリをGPUバイナリに 最終調整できます 最後に metal-sourceは 既存のMacOSゲームから パイプラインスクリプトを 採取する際に役立ちます これらのツールの大部分と GPUバイナリーコンパイラー ツールチェインの残りは macOSに加えて Windowsもサポートするようになり 既存のワークフローへの統合が これまで以上に容易になりました まとめとして Metal Shader Converterは ほかのシェーディング言語で 開発されたシェーダーをMetalに 取り込むための新しいツールです GPUバイナリコンパイラと そのツールチェーンは 現在Windowsで利用可能であり MetalライブラリをGPUバイナリに ファイナライズすることができます これらのツールにより シェーダーをMetalに取り込むために 必要なものがすべて揃いました まだまだお伝えしたいことがあります シリーズのパート3はハイエンドのMetal アプリケーションの最適化に焦点を当てます ぜひご覧ください ご視聴ありがとうございました ♪ ♪
-
-
14:28 - Json Metal Script
{“libraries": { "paths": [ {"path": “ba.metallib”, "label": "myMetalLib"} ] }, "pipelines": { "render_pipelines": [{ "vertex_function": "alias:myMetalLib#v", "fragment_function": "alias:myMetalLib#f", "raster_sample_count": 2, "color_attachments": [{ "pixel_format": "BGRA8Unorm" }], "depth_attachment_pixel_format": "Depth32Float" }] } }
-
16:30 - Testing Binary Archive hit
// Create Pipeline Descriptor MTLComputePipelineDescriptor *computeDesc = [MTLComputePipelineDescriptor new]; computeDesc.binaryArchives = @[existingBinaryArchive]; computeDesc.computeFunction = computeFn; id<MTLComputePipelineState> computePS = [device newComputePipelineStateWithDescriptor:computeDesc options:MTLPipelineOptionFailonBinaryArchiveMiss error:&err]; if(computePS == nil) { // Binary archive is missing compiled shader. }
-
17:03 - Loading appropriate Binary Archive
// Load OS-specific binary archives MTLComputePipelineDescriptor *computeDesc = [MTLComputePipelineDescriptor new]; if (@available(macOS 14, *)) { computeDesc.binaryArchives = @[binaryArchive_macOS14]; } else { computeDesc.binaryArchives = @[binaryArchive_macOS13_3]; } computeDesc.computeFunction = computeFn; id<MTLComputePipelineState> computePS = [device newComputePipelineStateWithDescriptor:computeDesc options:nil error:&err];
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。