View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

WWDC23に戻る

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • Metalレイトレーシングのガイド

    Metalレイトレーシングでゲームやアプリのビジュアルクオリティを向上させる方法を紹介します。MetaレイトレーシングAPIの基本を確認しましょう。よりスケールが大きく複雑なシーンの作成、メモリ使用量とビルドの時間の削減、髪や毛皮などのビジュアルコンテンツの効率良いレンダリングなどを可能にする、最新の改善点やテクニックについて解説します。

    関連する章

    • 0:09 - Intro
    • 1:50 - Build your scene
    • 9:48 - Scale with instancing
    • 17:34 - Build with parallelization
    • 18:34 - Refitting
    • 19:47 - Compaction
    • 21:14 - Intersect rays
    • 26:16 - Debug and profile
    • 30:42 - Wrap-Up

    リソース

    • Accelerating ray tracing using Metal
    • Metal for Accelerating Ray Tracing
    • Rendering reflections in real time using ray tracing
      • HDビデオ
      • SDビデオ

    関連ビデオ

    Tech Talks

    • M3とA17 ProでのGPUの進化
    • M3とA17 Proの新しいMetalプロファイリングツール
    • Metalシェーダのパフォーマンスを改善するベストプラクティス

    WWDC22

    • Metalレイトレーシングのパフォーマンスを最大限に高める

    WWDC21

    • Metalレイトレーシングによるハイブリッドレンダリング
    • MetalレイトレーシングによるAppの強化

    WWDC20

    • Metalを使用したレイトレーシング
  • このビデオを検索

    ♪ ♪

    こんにちは Pawel Szczerbukです 私はGPUソフトウェアエンジニアです Metalはレイトレーシングアプリの より複雑で 詳細なシーンを拡張するのに役立ちます レイトレーシングはプロダクションの レンダリングにおける画像の再現度合いが 基本となりますが、 ゲームでは画質の向上に加え 高フレームレートに焦点が当てられます これはMetalレイトレーシングでレンダリングされた ディズニーのモアナ島の画像です 今日はMetalレイトレーシングの 使用方法についてお話しします ゲームとプロダクションレンダラーで レイトレーシングを加速する 新機能に焦点を当てます

    レイトレーシングアプリは シーン内を反射する 個々の光線をシミュレートします Metalレイトレーシングでは まずシーンのジオメトリの定義が 第一ステップです 次にMetalはジオメトリを含んだ Acceleration Structureを作成し GPUアクセラレーションで 効率よく交差点を照会します GPU functionで シーンと交差するレイを作成し シェーダーでIntersectorを作成し レイとacceleration structureと共に 供給します こうしてピクセルに影が必要か さらに処理が必要か などの情報とともに intersection resultが戻ります これらが一緒に働いてシーンを作成し インスタンスで視覚的複雑性を加え レイの交差を実行します またレイトレーシングアプリでの 作業に役立つ 数々の素晴らしいツールがあります まずはシーンの構築からです MetalレイトレーシングAPIは いくつかのジオメトリタイプに対応します これらのジオメトリは acceleration structureに保存されています

    Acceleration structureは ジオメトリを再帰的に分割して レイトレーシング過程を スピードアップします これによりレイと交差しないジオメトリを 素早く削除することができます Acceleration structureの セットアップには3ステップあります Acceleration structure descriptorで 実際のジオメトリを供給します Descriptorができれば Acceleration structureを割り当てし ビルドします Acceleration structure descriptorには 1つ以上のジオメトリdescriptorがあります Metalには3タイプのdescriptorがあります トライアングルは周知のプリミティブであり コンピュータグラフィックの ほぼすべてに使用されます バウンディングボックス・プリミティブは レイがバウンディングボックスに 当たる時にMetalが呼び出す カスタム交差機能により定義されます 今年はカーブが加わります 髪や毛皮のレンダリングに最適です トライアングルを使って acceleration structureを作るには 個々のジオメトリにトライアングル ジオメトリdescriptorを作ります Vertex bufferとindex buffer そしてtriangle countを供給します バウンディングボックス・ジオメトリも よく似ていますが verticesの代わりに ジオメトリを取り囲む バウンディングボックスを供給します 更にレイがバウンディングボックスに 当たる時に Metalが呼び出す intersection functionを供給します

    Intersection functionの セットアップについては WWDC20のDiscover ray tracing with Metalをご覧ください

    髪や毛皮や草木などのジオメトリには 何百万にも及ぶプリミティブが あるかもしれません これらは通常細いスムーズなカーブを かたどっています トライアングルで このカーブに近づける代わりに Metalの新しいカーブ・プリミティブを 使用できます これらのカーブはカメラがズームしても スムーズさを保ちます トライアングルと比べて カーブのメモリ・フットプリントは小さく より速いacceleration structure buildsが可能です

    カーブはいくつもつながった 曲線分から成り立っています その一分一分がプリミティブで Metalは各曲線分にユニークな プリミティブIDを割り当てます 各曲線分はカーブの形を制御する いくつもの制御点で定義されています これらの制御点は基底関数のセットで 補間されています 基底関数によって 各曲線分には2・3・4か所の 制御点があります Metalは4つのカーブ基底関数を提供します ベジェ キャットムル-ロム B-スプライン リニアです 各基底関数にそれぞれの利点がありますので 最適のものをお選びください Metalはまた制御点の index bufferが必要です 各曲線分にindex bufferが一つあり 曲線分の最初の制御点を示します 例えば制御点が4つあるとします 最初の制御点のインデックスを使って 曲線分を定義するため index bufferに0を加えます この例ではキャットムル-ロム基底関数を 使用しており 実際の曲線分は 制御点1と2の間に定義されます 別の曲線分をつなぐには 制御点をもう1つ加えるだけです この曲線分は制御点1から4を使用するため index bufferに1を足します Index bufferのために 2つの曲線分が3つの制御点を共有するため カーブはメモリの使用を抑制できます カーブが完成するまでこれを繰り返します 新しいカーブを始めるには それまでの制御点に交わらず さらなる制御点を足せばいいだけで index bufferに 対応するインデックスを足します 今のところこのカーブは 抽象な数学的なオブジェクトです これらをレンダリングするには 何らかの3次元形状が必要です 各制御点には半径があり カーブの長さ中を補間しています 既定としてカーブは 3次元円筒形の横断面と共にレンダリングされます クローズアップになるカーブには最適です 遠くからしか見られないカーブの場合 Metalはフラットカーブもサポートします 3次元ジオメトリが必要でない時の パフォーマンスが向上します

    トライアングルなどと同様に カーブジオメトリは curve geometry descriptorで定義されます controlPointBufferと 対応するradiusBuffer及び indexBufferを取り付けます 制御点バッファの制御点の数と 曲線分の実際の数をセットします Index bufferの インデックス数と同じはずです カーブのタイプを指定します この例では各曲線分に4つの制御点を持つ ラウンドベジェカーブです Curve geometry descriptorの 設定に必要なのはそれだけです

    ジオメトリdescriptorを作ったところで acceleration structure descriptorを セットアップできます トライアングルなどの プリミティブジオメトリに PrimiticAcceleration StructureDescriptorを使います AccelerationStructureDescriptorに geometryDecriptorを足します ジオメトリを結合するため 1つのAccelerationStructureに いくつものgeometryDesciptorを 足せます Acceleration structure descriptorが 用意できれば acceleration structureに メモリを割り当てできます Metalでその時と場所を完全制御できます

    これは二部構成の作業です まずビルドに必要な オブジェクトのサイズを計算します MetalデバイスはAcceleration structureに 必要なアロケーションサイズを 計算するメソッドを提供します Metalデバイスから直接ストレージを 割り当てすることができますが Heapからすることで 後にリソース管理のオーバーヘッドを 減らすことができます それには更なるサイズや配置条件を 要するかもしれませんが Metalデバイスの別のメソッドで 照会できます このサイズならacceleration structureを 保管するメモリを割り当てできます このストレージは MTLAccelerationStructureで示されます これらを割り当てするには HeapかMetalデバイスでサイズをパスし makeAccelerationStructureメソッドを 呼び出します またMetalがacceleration structureを 作る間に使うスクラッチメモリも 割り当てします このメモリへのアクセスは GPUだけでいいため Metalデバイスからprivate storage mode bufferを割り当てするだけです

    これでacceleration structureを ビルドする準備ができました ビルドをスケジュールすれば MetalがGPUでaccelerationをビルドします Acceleration Structure Command Encoderを使用します

    このエンコーダには acceleration structureを作成し 改良するためのメソッドが 幾つかあります この場合 destination acceleration structureとdescriptor 及びscratch bufferで buildメソッドを呼びます Metalがジオメトリの primitive acceleration structureを作成し 後のGPU commandsで使用可能になります このようにして primitive acceleration structureで シーンにジオメトリを描写できます 大きいシーンのスケーリングに Metalはinstance acceleration structures をサポートしています 1つのprimitive acceleration structureでは モアナ島のような複雑で詳細な環境の保管に 莫大なメモリが必要になります しかしこの複雑なシーンには 何千の木々や 何百万もの葉やそれ以外の 繰り返し構造物があり シーンを効率よく レンダリングすることができます 山やサンゴや木々など シーンのユニークな物すべては primitive acceleration structuresとして 描写できます これらをinstance acceleration structureにまとめて シーン全体を描写できます つまりprimitive acceleration structureがジオメトリを含むのに対し instance acceleration structureには シーン全体の構成のため 位置やサイズや向きが変えられた ほかのacceleration structuresへの参照が 含まれています 各インスタンスにシーンで参照される acceleration structureを配列する 変換行列があります Instance acceleration structureの作成は primitive acceleration structureの 作成と似ています まずdescriptorの作成から始まります この場合はジオメトリの代わりに 参照されたacceleration structureや シーンに配置される transformation matrixなど 各インスタンスの情報を含む バッファを供給します そしてprimitive acceleration structureと同様に GPUでacceleration structureを ビルドします

    Descriptorの作成にはMTL Instance Acceleration Structure Descriptorを築き 含まれるインスタンスの数をセットします そしてインスタンスに参照される primitive acceleration structuresの 配列を供給し instance bufferに含まれる instance descriptorのtypeを特定します ユースケースによって選べる instance descriptor typesを Metalは提供します acceleration structureでの インスタンスの設定は2ステップです

    まずper-instance dataを 保管するバッファを割り当てします このバッファのサイズはインスタンスの数と instance descriptorのサイズ次第ですが ほかのMetalバッファ同様に 割り当てできます バッファーを割り当てたら それをinstance acceleration structure descriptorに割り当てます

    次にacceleration structureにある すべてのinstanceの情報を instance bufferに詰め込みます Instance毎にdescriptorを作り このinstanceが参照する acceleration structureを特定します Instance acceleration structure descriptorでセットした acceleration structure index配列を 確認します また使用する instance descriptorのtypeによって 各instanceには transformation matrixや visibility maskなどの プロパティがあります

    最後のステップは acceleration structureのビルドで primitive acceleration structureと 同じプロセスです ビルドまでのステップはすべて CPUで実行可能です しかしinstancesの数が大きいと instance bufferの書き込み処理に 多大な負荷がかかります Instance descriptorsは 通常のMetal bufferに格納されているため GPUからdescriptorsを書き込むことで このステップを加速できます GPUに作業を手渡す前に acceleration structureにinstancesが 幾つあるかわかっている限り これはGPUアクセラレーションの いい機会です しかしinstance cullingなどを 行いたい場合は descriptorで 最終Instance countができるよう CPUでinstancesをcullしなければいけません 今年から新しいindirect instance acceleration structure descriptorで この処理がGPUで可能になりました このindirect descriptorで instancesのcullや instance bufferの書き込みや 最終instance countのセットが すべてGPUで行えます GPUによる acceleration structureビルドを行うには indirect instance acceleration structure descriptorを作成します descriptorの maximum instance countと GPUからの最終instance countを書く bufferをセットします そしてinstance descriptor bufferをセットし GPUでのinstancesの設定が可能になります

    Instance bufferで 違ったdescriptor typeを使用します Indirect instance descriptorは direct instance descriptorに似ていますが descriptorに単に割り当てるだけで acceleration structureが 例証されているか確認できます こうしてinstance acceleration structureを作成します これまで2レベルモデルの インスタンスに触れてきました このモデルではモアナ島シーンの森林が 何千もの種類の木々のインスタンスで 構成されています しかし掘り下げて見ると 木は葉のコピーを幹に取り付けたものです この構造の場合 新機能である マルチレベルインスタンスを 利用することができます マルチレベルインスタンスで instance acceleration structureは primitive acceleration structuresだけでなく ほかのinstance acceleration structuresも含めます このシーンの例ではシーン全体としては ヤシの木のインスタンスを含む一方 ヤシの木は幹と葉のインスタンスを含む instance acceleration structure として表現できます モアナ島はマルチレベルインスタンスの パワーを示す非常にいい例です 2レベルインスタンスの場合 シーンに1つのタイプの木を足すのは 何百または何千もの木のパーツのコピーを 足すということです マルチレベルインスタンスでは パーツの繰り返しインスタンスで定義された 複雑な木のインスタンスを 足せるということです つまりモアナ島シーンで 何百万ものインスタンスを省けるのです しかしマルチレベルインスタンスは プロダクションのためだけではありません ゲームのような リアルタイムアプリでも貴重です 2レベルacceleration structure patternは ゲームオブジェクトのインスタンスから 世界を作り出すなど ゲーム制作でも使用されています しかしゲームは プロダクションレンダラーとは違います プロダクションはオブジェクトの再利用に 深い階層を使用しますが ゲームはゲームオブジェクトインスタンスの 長いリストを使用します またゲームは動的コンテンツのために instance acceleration structureを フレーム毎に再建するため インスタンスの数が多いと GPUの処理時間が増加します

    しかしゲームでは多くのコンテンツが静的で フレームの更新は必要ありません acceleration structureの更新を 変化があるコンテンツだけに限定するため acceleration structuresを 静的と動的に分けることができます つまり動的コンテンツだけを処理するため 通常 静的コンテンツより少なく済みます 静的と動的コンテンツに分ける時 ray traversalコストを追加して 階層の深さの バランスをとることが重要です Acceleration structureのビルドと レイトレーシングのあるフレームでは 3レベルのインスタンスの使用で トレーシングに最小限の影響だけで ビルドの時間を削減できるため フレーム全体での時間が削減できます マルチレベルインスタンスは メモリ使用量を減少させ リビルドの時間短縮に最適です またMetalレイトレーシングアプリを 最適化できる方法があります その一つがBuild parallelizationです

    通常アプリは違うシーンや そのパーツを描写する 多くのacceleration structuresを ビルド及び更新する必要があります これらのビルドを並行に行うことで 起動時間を減少できます

    可能であれば並行に実行できるよう 複数のビルドを同じ command encoderにエンコードし ビルドをバッチするようにします メモリ容量を超えないよう確認しながら できるだけ多くのビルドを 並列化するようにしましょう またacceleration structureの ビルドが終了すると scratch bufferは不要になります つまりscratch buffersを 一束のacceleration structureビルドから 次のものに使用できるのです Acceleration structureのリビルドの時間を 削減するのにリビルドを避けることが 最善策であることもあります Acceleration structure refittingが 役に立ちます Metalがacceleration structureを作る時 近辺のプリミティブを箱の階層に グループ分けします もしプリミティブが動くと これらの箱はシーンを正確に描写できず acceleration structureは 更新されねばなりません でもジオメトリの変化が少しだけなら この階層はまだ道理が合うかもしれません 新しいacceleration structureを 一から作り直す代わりに Metalはプリミティブの 新しい位置を反映するため 既存のacceleration structureを リフィットできます Acceleration structureを 一から作り直すより簡単です Refitはbuild operationのような scratch bufferが必要です Refit scratch bufferのサイズは 先ほどacceleration structureを アロケートするのに使った 同じ構造体にあります RefitはGPUで実行され acceleration structure command encoderでエンコードされます Refitは所定の場所か別の acceleration structureで実行できます

    最後にcompactionはメモリにおける acceleration structuresの サイズの減少に最適です 最初にacceleration structureを作る時 Metalはどれだけメモリが必要かわからず 控えめな見積もりを出さねばなりません いざacceleration structure作ったら Metalはそれを描写するための 必要最小限のサイズを計算します Compactionは必要最小限サイズの acceleration structureを アロケートし GPUを使って 現在のacceleration structureから 新しいものにコピーします これは特にprimitive acceleration structuresに役立ちます Compactionを使うにはGPUにある acceleration structureのcompacted sizeを 計算するコマンドをエンコードします このコマンドを実行すると Metalはcompacted sizeを 供給されたbufferに書き込みます いざcompacted sizeを読めば そのサイズの新しい acceleration structureをアロケートし 古いものから 新しいacceleration structureに copy and compact処理をエンコードします このcommand bufferが完了すれば 元のacceleration structureを リリースできます Metalレイトレーシングアプリの 最適化については WWDC22のMaximizing your Metal ray tracing performanceをご覧ください このセクションでは インスタンスのセットアップと マルチレベルインスタンス機能の利用と インスタンスのスケールについて話しました ではレイをシーンに交差させる時です Metalではコマンドの一部として実行する GPU Functionでレイを交差します Apple Siliconではcomputeと renderコマンドの両方でレイを交差でき AMDとIntelでは computeコマンドでレイを交差できます レイを交差させるために command encoderで acceleration structureをバインドします これでGPU Functionで このacceleration structureとレイを 交差できます acceleration structure parameterで functionを宣言し intersector objectを作成します 最高のパフォーマンスでの レイ交差の設定のため このintersectorに プロパティをセットできます レイをシーンと交差させるため レイを作成し intersector objectに intersect methodを呼び出し レイとacceleration structureを パラメータとしてパスします これによりintersectionの 情報すべてが返ってきます レイが交差するプリミティブの種類や intersectionの距離や プリミティブのIDなどです

    Triangle intersection pointの 情報が知りたいなら triangle dataタグをintersectorと intersection result typesに足します これにより triangle barycentric coordinatesが intersection resultで得られます Primitive acceleration structureとの レイの交差については以上です Instance acceleration structureと レイの交差もよく似ています Primitive acceleration structureの バインド同様に instance acceleration structureを バインドします GPUのinstance acceleration structureで acceleration structuresが参照されるよう useResourceかuseHeapを 必ずコールしてください レイとinstance acceleration structureを 交差させるにはGPU functionに 少し変更を与えるだけです まずacceleration structure typeに instancingタグを足します そしてintersectorと intersection resultに instancingとmax levelsタグを付けます Max levelsタグは acceleration structureでの インスタンスレベルの数を指定します 例えばモアナ島シーンを描写する acceleration structureは 3レベルacceleration structureです 最初のレベルはシーン全体を含んだ instance acceleration structureです 2つ目のレベルにはサンゴや木々 そして地形のインスタンスがあります 3つ目のレベルは葉や花や幹など 木のパーツのインスタンスです レイがシーンと交差する時は プリミティブと交差するだけでなく プリミティブを含む インスタンスとも交差します もしレイがこの木の葉と交差したら 木のインスタンスや木にある葉の インスタンスとも交差するのです Metalは交差したインスタンス 一つ一つのIDを記録して これを監視しています この場合 最初に交差したインスタンスは 6のIDを持つ木で 2つ目に交差したインスタンスは 1のIDを持つ葉です 交差するインスタンスが 一つの時もあります 例えばレイが地形と交差したら Metalは地形インスタンスのIDしか 記録しません Intersection resultで 交差したインスタンスの数とIDを 見つけることができます Primitive acceleration structuresと instance acceleration structuresに こうしてレイを交差できます カーブプリミティブの場合 注意すべきことが幾つかあります 既定ではレイの交差を実行する時 Metalはカーブプリミティブを 使用していないと仮定しています Metalにカーブの使用を伝えるには intersector objectで geometry typeを設定します Geometry typeを設定すれば カーブに交差できます 以前と同様 intersection resultで intersectionの情報を得られます もしcurve dataタグを使えば intersection resultも curve parameterを含みます これはカーブがレイと交差する点を算出する カーブの基底関数に挿入される値です これらの関数はMetal Shading Languageに 実装されています 詳細はMetal Shading Language仕様書を ご覧ください 多くのアプリでカーブジオメトリは 一種のカーブだけで描写されています 例えば シーンのカーブすべてが 円形横断面の3次ベジェ曲線と 表現されているかもしれません この場合 intersector objectで カーブのプロパティを設定して どのようなカーブが使用されているか Metalに指定できます カーブプリミティブを使用する際 これで最高の性能が得られます このようにしてレイを交差させます レイトレーシングの作業負荷はXcodeで デバッグ及びプロファイルできます

    デバッグにおける困難な問題には Shader Validationを 使用できます シェーダーのランタイムチェックを行い クラッシュや破損に つながる問題を発見します Shader Validationは 最新のレイトレーシング機能を含む すべてのMetal APIをカバーします さらにShader Validationにより シェーダーコンパイルの時間が削減されます これはレイトレーシングアプリに よく見られる 長く複雑なシェーダーの使用時に便利です また役に立つもう一つのツールは最新式の Acceleration Structure viewerです 交差テストに使用するシーンの検査を 可能にします Acceleration Structure viewerを開けると ジオメトリプリミティブに及ぶまでの acceleration structureにおける ビルディングブロックの概要が 左側に表示されます トライアングルジオメトリを構成する 各トライアングルがここに表示されています 右側のビューポートでは 数々のハイライトモードにおける acceleration structureを点検できます 例えばAxis-Aligned Bounding Box Traversalsハイライトモードでは 負荷がより大きい intersection testingに該当する トラバーサルの深いエリアを 視覚化することができます ポインタを動かすと そのポイントで示された方向において レイが交差する数をinspectorが更新します 別の例がAcceleration Structure ハイライトモードです Acceleration structuresを 違う色で視覚化できます Acceleration Structure viewerは 新機能のマルチレベルインスタンスと カーブジオメトリをサポートします ビューポートでカメラを動かすと 木々のinstance acceleration structuresや 葉のカーブを見つけることができます Acceleration structureの確認には ビューポートでクリックすると アウトラインが現れます このヤシの木の葉の acceleration structureを 詳しく見てみましょう このacceleration structureでは 葉はカーブで構成されています プリミティブハイライトモードに変えると 曲線分を視覚化できます 曲線分をさらに視察するため 少し拡大してみます 先程シーンで acceleration structuresを選んだように 各曲線分をクリックして選択できます レイトレーシング作業量の検査に便利な もう一つのツールが Shader Debuggerです シェーダーコードでの問題解決に役立ちます これはシェーダーで intersection testingを行う compute dispatchです シェーダーのデバッグを始めるには Shader Debuggingボタンをクリックし ポップオーバーでスレッドを選び Debugボタンをクリックします

    データの収集後 シェーダー実行中どの時点でも 変数値を確認することができます プリミティブIDの値を見てみましょう さらなるデバッグコンテキストに Shader Debuggerは 近辺のスレッドからのデータを示します ポインタをvalueビューにかざすと 同じスレッドグループからの プリミティブIDを確認できます

    どのアプリにおいても その性能はもう一つの重要な要素です Profiling timelineは レイトレーシング作業性能の概要を示し あらゆる性能メトリックを並べて確認 及び関係付けることが可能になります さらにDebug navigatorを すべての作業量のpipeline statesに 変えることも出来ます またshader profiling dataで 最も負荷量の大きいpipeline statesを 上からリストすることも出来ます さらにpipeline stateを拡張すると shader codeが表示されます シェーダーを開いたあと 各シェーダーがどこでどう 実行時間を費やすか行毎の shader profiling insightsが得られます サイドバーの円グラフにポインタをかざすと コードのその行での作業負荷の詳細が ポップオーバーに表示されます これらのツールはMetalレイトレーシングの 新機能をすべてサポートし Metalアプリ作成の デバッグやプロファイルの 素晴らしい手助けとなります

    またMetalレイトレーシングは さらなる機能をサポートします プロダクションレンダラーでの動画での primitive及びinstance motionや alpha testingなどの改善を含む ray intersectionの カスタム化のための custom intersection functions そしてクエリベースAPIからの 移植性のためのintersection queryなどです MetalレイトレーシングAPIや 言語及びツールは ゲームやプロダクションレンダラーなど リアルタイムレンダリングアプリに対応します 最新MetalレイトレーシングAPIで カーブのようなジオメトリを含む primitive acceleration structuresを 使ってシーンを構築できます インスタンス 特に新しい マルチレベルインスタンス機能で さらに大きく複雑なシーンに スケールできます MetalレイトレーシングAPIは GPU functionsで直接呼び出せます 最後にアプリのデバッグとプロファイルに Xcodeが役に立ちます これらのトピックの詳細をカバーし サンプルコードや書類にアクセスできる 以前のセッションもぜひご視聴ください ありがとうございました ♪ ♪

    • 3:06 - Create triangle geometry descriptor

      // Create geometry descriptor:
      let geometryDescriptor = MTLAccelerationStructureTriangleGeometryDescriptor()
      
      geometryDescriptor.vertexBuffer = vertexBuffer
      geometryDescriptor.indexBuffer = indexBuffer
      geometryDescriptor.triangleCount = triangleCount
    • 3:20 - Create bounding box geometry descriptor

      // Create geometry descriptor:
      let geometryDescriptor = MTLAccelerationStructureBoundingBoxGeometryDescriptor()
      
      geometryDescriptor.boundingBoxBuffer = boundingBoxBuffer
      geometryDescriptor.boundingBoxCount = boundingBoxCount
    • 6:42 - Create curve geometry descriptor

      let geometryDescriptor = MTLAccelerationStructureCurveGeometryDescriptor()
        
      geometryDescriptor.controlPointBuffer = controlPointBuffer
      geometryDescriptor.radiusBuffer = radiusBuffer
      geometryDescriptor.indexBuffer = indexBuffer
      
      geometryDescriptor.controlPointCount = controlPointCount
      geometryDescriptor.segmentCount = segmentCount
      geometryDescriptor.curveType = .round
      geometryDescriptor.curveBasis = .bezier
      geometryDescriptor.segmentControlPointCount = 4
    • 7:29 - Create primitive acceleration structure descriptor

      // Create acceleration structure descriptor
      let accelerationStructureDescriptor = MTLPrimitiveAccelerationStructureDescriptor()
      
      // Add geometry descriptor to acceleration structure descriptor
      accelerationStructureDescriptor.geometryDescriptors = [ geometryDescriptor ]
    • 8:08 - Query for acceleration size and alignment requirements

      // Query for acceleration structure sizes
      let sizes: MTLAccelerationStructureSizes
      sizes = device.accelerationStructureSizes(descriptor: accelerationStructureDescriptor)
      
      // Query for size and alignment requirement in a heap
      let heapSize: MTLSizeAndAlign
      heapSize = device.heapAccelerationStructureSizeAndAlign(size: sizes.accelerationStructureSize)
    • 8:39 - Allocate acceleration structure and scratch buffer

      // Allocate acceleration structure from heap
      var accelerationStructure: MTLAccelerationStructure!
      accelerationStructure = heap.makeAccelerationStructure(size: heapSize.size)
      
      // Allocate scratch buffer
      let scratchBuffer = device.makeBuffer(length: sizes.buildScratchBufferSize,
                                            options: .storageModePrivate)!
    • 8:40 - Encode the acceleration structure build

      let commandEncoder = commandBuffer.makeAccelerationStructureCommandEncoder()!
      
      commandEncoder.build(accelerationStructure: accelerationStructure,
                           descriptor: accelerationStructureDescriptor,
                           scratchBuffer: scratchBuffer,
                           scratchBufferOffset: 0)
      
      commandEncoder.endEncoding()
    • 11:30 - Create instance acceleration structure descriptor

      var instanceASDesc = MTLInstanceAccelerationStructureDescriptor()
      
      instanceASDesc.instanceCount = ...
      instanceASDesc.instancedAccelerationStructures = [ mountainAS, treeAS, ... ]
      instanceASDesc.instanceDescriptorType = .userID
    • 12:07 - Allocate the instance descriptor buffer

      let size = MemoryLayout<MTLAccelerationStructureUserIDInstanceDescriptor>.stride
      let instanceDescriptorBufferSize = size * instanceASDesc.instanceCount
      
      let instanceDescriptorBuffer = device.makeBuffer(length: instanceDescriptorBufferSize,
                                                       options: .storageModeShared)!
          
      instanceASDesc.instanceDescriptorBuffer = instanceDescriptorBuffer
    • 12:33 - Populate instance descriptors

      var instanceDesc = MTLAccelerationStructureUserIDInstanceDescriptor()
      
      instanceDesc.accelerationStructureIndex = 0    // index into instancedAccelerationStructures
      instanceDesc.transformationMatrix = ...
      instanceDesc.mask = 0xFFFFFFFF
    • 14:06 - Configure indirect instance acceleration structure descriptor

      var instanceASDesc = MTLIndirectInstanceAccelerationStructureDescriptor()
      
      instanceASDesc.instanceDescriptorType = .indirect
      instanceASDesc.maxInstanceCount = ...
      instanceASDesc.instanceCountBuffer = ...
      instanceASDesc.instanceDescriptorBuffer = ...
    • 14:29 - Populate indirect instance descriptor

      device MTLIndirectAccelerationStructureInstanceDescriptor *instance_buffer = ...;
      // ...
      acceleration_structure<> as = ...;
      instance_buffer[i].accelerationStructureID = as;
      instance_buffer[i].transformationMatrix[0] = ...;
      instance_buffer[i].transformationMatrix[1] = ...;
      instance_buffer[i].transformationMatrix[2] = ...;
      instance_buffer[i].transformationMatrix[3] = ...;
      instance_buffer[i].mask = 0xFFFFFFFF;
    • 19:22 - Update geometry using refitting

      // Allocate scratch buffer
      let scratchBuffer = device.makeBuffer(length: sizes.refitScratchBufferSize,
                                            options: .storageModePrivate)!
      
      // Create command buffer/encoder ...
      
      // Refit acceleration structure
      commandEncoder.refit(sourceAccelerationStructure: accelerationStructure,
                           descriptor: asDescriptor,
                           destinationAccelerationStructure: accelerationStructure,
                           scratchBuffer: scratchBuffer,
                           scratchBufferOffset: 0)
    • 20:24 - Use compaction to reclaim memory

      // Use compaction to reclaim memory
      
      // Create command buffer/encoder ...
      
      sizeCommandEncoder.writeCompactedSize(accelerationStructure: accelerationStructure,
                                            buffer: sizeBuffer,
                                            offset: 0,
                                            sizeDataType: .ulong)
      
      // endEncoding(), commit command buffer and wait until completed ...
      
      // Allocate new acceleration structure using UInt64 from sizeBuffer ...
      
      compactCommandEncoder.copyAndCompact(sourceAccelerationStructure: accelerationStructure,
                                   destinationAccelerationStructure: compactedAccelerationStructure)
    • 21:36 - Set acceleration structure on the command encoder

      encoder.setAccelerationStructure(primitiveAccelerationStructure, bufferIndex:0)
    • 21:48 - Intersect rays with primitive acceleration structure

      // Intersect rays with a primitive acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<> i;
      
        ray r(origin, direction);
      
        intersection_result<> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
      
      
          // shade triangle...
        }
      }
    • 22:24 - Use triangle_data tag to get triangle barycentric coordinates

      // Intersect rays with a primitive acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<triangle_data> i;
      
        ray r(origin, direction);
      
        intersection_result<triangle_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
          float2 coords = result.triangle_barycentric_coord;
      
          // shade triangle...
        }
      }
    • 22:51 - Set instance acceleration structure on the command encoder

      encoder.setAccelerationStructure(instanceAccelerationStructure, bufferIndex:0)
      encoder.useHeap(accelerationStructureHeap);
    • 23:07 - Intersect rays with instance acceleration structure

      // Intersect rays with an instance acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<instancing> as, /* ... */) {
        intersector<instancing, max_levels<3>> i;
      
        ray r(origin, direction);
      
        intersection_result<instancing, max_levels<3>> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
      
          // shade triangle...
        }
      }
    • 24:43 - Find intersected instance information in the intersection result

      // Intersect rays with an instance acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<instancing> as, /* ... */) {
        intersector<instancing, max_levels<3>> i;
      
        ray r(origin, direction);
      
        intersection_result<instancing, max_levels<3>> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
          for (uint i = 0; i < result.instance_count; ++i) {
            uint id = result.instance_id[i];
            // ...
          }
          // shade triangle...
        }
      }
    • 25:02 - Intersect rays with curve primitives

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
      
        ray r(origin, direction);
      
        intersection_result<> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          // shade curve...
        }
      }
    • 25:26 - Find curve parameter in the intersection result

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<curve_data> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
      
        ray r(origin, direction);
      
        intersection_result<curve_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          float param = result.curve_parameter;
          // shade curve...
        }
      }
    • 26:04 - Set geometry type on the intersector for better performance

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<curve_data> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
        i.assume_curve_type(curve_type::round);
        i.assume_curve_basis(curve_basis::bezier);
        i.assume_curve_control_point_count(3);
      
        ray r(origin, direction);
      
        intersection_result<curve_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          float param = result.curve_parameter;
          // shade curve...
        }
      }

Developer Footer

  • ビデオ
  • WWDC23
  • Metalレイトレーシングのガイド
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン