ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
MetalFX Upscalingでパフォーマンスを向上させる
MetalFXは、プラットフォーム用に最適化されたMetal App向けのグラフィックスエフェクトを提供する新しいAPIです。MetalFX Upscalingを使用すると、ご利用のAppで、レンダリング品質を損なうことなく低解像度でフレームをレンダリングできるようになり、レンダリング時間も短縮されます。また、こうした2つの効果(空間的な拡張によるパフォーマンスの大幅な向上と、時間的なAAや拡張による最高品質のレンダリング)の利用方法とタイミングについても解説します。
リソース
関連ビデオ
Tech Talks
WWDC23
WWDC22
-
ダウンロード
皆さん ようこそ Apple GPU Software TeamのKelvin Chiuです 本日はMetalFX Upscalingを 利用しMetalApp性能を 向上させる方法についてお話します MetalFXはMetalApp向けに最適化された グラフィックス効果を提供する新しいAPIです 高性能なアップ-スケーリングが可能で レンダリング品質を維持したままAppの パフォーマンスを向上できます 高解像度レンダリングは GPU処理時間を消費します その時間を短縮するため通常解像度を下げて レンダリングするのが効果的です しかし代償でレンダリング品質が低下します MetalFXUpscalingを使用するとAppは レンダリング品質を損なうことなく 低い解像度でフレームをレンダリングし 時間を短縮することができるようになりました MetalFX UpscalingはApple社のデバイスで 快適に動作するよう最適化されています ゲームに採用しやすいのも特徴です MetalFXには2つアップ- スケーリングエフェクトが 用意されているのでその詳細を説明します スペイシャルアップ-スケーリングは 使い方が簡単で性能も大きく向上します Temporal anti-aliasingと アップスケーリングは 複数フレームの情報を統合 より高画質出力を実現します
そしてこれらの効果を利用するための 最善の方法についてお話します 最後に実際に使っている様子をデモで紹介し セッションを終了します
まずSpatial upscalingについて説明します MetalFX Spatial upscaling は入力の空間情報を解析 新しいアップ-スケーリングサンプルを 生成します Spatial upscalingの統合は簡単です アンチエイリアスのかかった入力色だけで 空間的アップスケールされた カラー出力が得られます 一般的なゲームレンダリングパイプラインでは anti-aliased renderや様々な後処理効果など 様々なレンダリングパスが存在します ゲームのトーン-マッピング処理が 完了した直後にMetalFXの 空間アップスケーリングを追加する 入力がトーンマッピングされ 知覚的な色空間である場合に 最適なパフォーマンスを発揮します ではMetalFXの空間アップ- スケーリングを確認します
このチェスのシーンは4K解像度の高品質な リファレンスレンダラーで制作されています パストレースされレイトレースによる 反射や影などの複雑なグラフィック効果を持つ 並べて比較するとこんな感じです 左側が540p入力で右側が1080p出力で
MetalFXによる空間アップスケーリング済です
左のクイーンを拡大するとディテールに欠け 解像度の低い画像になっています 右側の空間的にアップスケールされた出力は よりシャープな反射と洗練されたエッジです
次にアップスケーリングの 実装方法を説明します
Metalでは通常コマンド-バッファにコマンドを エンコードしエフェクトの入力を生成する コマンドエンコーダを作成することになります 同様にMetalFXエフェクト- オブジェクトを作成して コマンドをエンコードし エフェクトを実行できます MetalFXの出力を利用する コマンドをエンコードする 3つ目のコマンド-エンコーダーを作成します 空間スケーラーオブジェクト は作成にコストがかかるため Appの初回起動時や ディスプレイの解像度が 切り替わったときにのみ 新規作成するようにしましょう
まずMTLFXSpatialScaler- Descriptorを作成し 設定します 次にmakeSpatialScaler()メソッドを呼び出し スケーラーオブジェクトを作成します 初期化コードでは ディスクリプタから始めます 入力と出力のテクスチャの幅と 高さの両方を埋めます 次に後でスケーラー-オブジェクトに設定する テクスチャのフォーマットを設定します 色処理モードを設定します これは入力と出力がどの色空間であるかを APIに伝えるものである 知覚的色空間線形色空間 HDR色空間の いずれかの値を設定することができます ディスクリプタが埋まったら スケーラーオブジェクト作成
その後プロパティを変更することができます 好きな回数作成しencode()メソッドを呼び出し アップスケーリング処理を開始します 描画コードではスケーリング 効果をコマンドバッファに エンコードする前にスケーラーオブジェクトに 正しい入力および出力- テクスチャ設定されたか確認 空間アップスケーリングは 簡単に性能を向上させます
さらに高品質なレンダリングが必要な場合は MetalFXのテンポラル-アンチエイリアスと アップスケーリングの出番となるわけです Temporal AAとアップ- スケーリングは前フレームの データを使い高品質のアップ- スケーリング出力生成します つまり前フレームのアップスケーリング出力が 現フレームの入力の一つに 使われることになります
なぜTemporal AAやアップスケーリングに前の フレームのデータが必要かを理解するために スーパーサンプリングの 概念をおさらいしましょう
スーパーサンプリングでは 1画素あたり複数のサンプルを計算し それを1画素の値として積算する 1画素あたりの積算サンプル数が多いほど より良い結果が得られます しかし1フレーム内で画素ごとに 複数のサンプルを計算するためには 大きなコストがかかります 1フレームで1画素あたり複数の場所を サンプリングする代わりに時間的な サンプリングを行うことができます テンポラルサンプリングとはあるフレーム内の 全ピクセルに対して 異なるサンプル位置を レンダリングする概念です 複数フレームでのスーパー- サンプリングクオリティを 低コストで実現することができます 複数フレームからサンプルを 蓄積しサンプルの位置を 考慮しより多くのサンプルを 得ることができます 一時的なAAとアップスケーリングは ターゲット解像度ピクセルに サンプルを適切に統合し 高品質なアンチエイリアス- アップスケーリング出力を実現します しかしコンテンツはフレーム間で変化するため 変化を検出するため 多くの入力データが必要です Temporal AAとアップスケーリングには 前フレーム出力のほかにジッター処理された カラー入力とシーンの動きや 深度データも必要です なぜ必要なのかひとつひとつ解説していきます
まずはジッターカラーの入力から
ジッター無でレンダリング済 赤い三角形がこちらです 白い輪郭はレンダリング中の 三角形を表しています 小さな四角の1つ1つが画素を表しています 中央のグレーのドットは ピクセルのサンプリング箇所
同じ三角形を小さなジッターで レンダリングしたときの出力です グレーの点はある画素の サンプリング位置を示します ジッターオフセットは所望の サンプル数を収集するため 設定されたフレーム数に対し 一意である必要があります ジッターシーケンスについて 後ほど詳しく説明します
次にシーンからのモーション情報です シーンから得られるモーションデータは 前のフレームから物体がどれだけ どの方向に移動したかを示すものです Temporal AAとUpscalingは動き情報を使って バックトラックを行い 前フレームで対応する場所を 見つけ正しくサンプルを 収集するために使用される
もう一つの入力はシーンからの深度情報である シーンの深度データは手前に何があり 奥に何があるのかを示しています これは前景のエッジのanti- aliasingを優先する際 重要で 前フレームからサンプルを 収集時 他のオブジェクトが 新たに露出する可能性がある という手がかりを提供します 最後の入力データは前フレームの出力です
前フレームの出力には以前に 統合された全サンプルが 含まれておりピクセルあたりのサンプル数を 増やすために現フレームの ジッターカラー入力と ブレンドされることになる 前後のフレーム 両方の情報を 組み合わせることで より詳細な画像を得ることができます MetalFXはアップ-スケールされた出力を 追跡しているので現在の レンダリングフレームから 色 動き 深度を渡すだけでよいのです 一般的なゲームレンダリング パイプラインに話を戻します MetalFXのTemporal AAとアップスケーリングは アップスケーリングの結果に干渉するため ポスト処理エフェクトの前に 実行する必要があります
ここで再びMetalFX Temporal AAと アップスケーリングを使い レンダリングをします 左側が1080p入力右側が 4Kアップスケーリング出力 サイドバイサイドの比較です
クイーンにズームインすると入力は低解像度で エイリアスが発生しているのに対し 右側の時間的アップスケール された出力は高解像度で 輪郭は滑らかで反射もより細かくなっています
空間スケーラと同様に新しい 時間スケーラを作成するのは コストがかかるのでAppの最初の起動時か ディスプレイの解像度が 切り替わったときにのみ行うべきです まずMTLFXTemporal- ScalerDescriptorを 割り当てて記入する必要があります makeTemporalScaler()methodを 呼出しオブジェクトを作成
初期化コードではディスクリプタから始めます 入力と出力のテクスチャの 幅と高さの両方を記入する スケーラーオブジェクトに後でバインドされる テクスチャのジッター-カラー デプス モーションテクスチャの フォーマットを入力し設定
最後にMetalFXがアップ-スケールした出力を 保存する出力テクスチャの形式を設定します ディスクリプタが埋まったら スケーラーオブジェクト作成 scaler objectにmotion scale- プロパティを設定後 モーションデータをAPIに 合わせスケーリング可能 MetalFXはレンダリング- 解像度のピクセル空間で 現在のフレームの位置から前の フレームの位置に向かう方向の モーションデータを想定しています 例として レンダリング解像度を1080pとします クリップスペース座標(-0.75, -0.75)から (0.25, 0.25)に移動する オブジェクトがあるとする モーションデータは(1,1)として格納される
モーションベクターのscaleプロパティを (-960, 540)に設定し MetalFXにモーション- データを正しく解釈させる
スケーラーオブジェクトのプロパティは 何度でも変更できます encode()メソッドを呼び出し アップスケーリング処理開始
フレームごとの描画コードでは まずresetHistoryプロパティを設定します Appが最初のフレームをロードするとき またはシーンカットがある時 この値をtrueに設定します 次にエフェクトの入力となる テクスチャを設定し 次に出力となるテクスチャを設定します 次に深度値が逆Zマッピング であるかどうかを示す reversedDepthプロパティを設定する
スケーリング効果のエンコード前に設定すべき 最後のプロパティはジッターオフセットです
ジッターを正しくオフセットすることは 出力の質を高めるために不可欠です ジッターオフセットの設定 方法を簡単に説明します
左側はジッターでレンダリングされた三角形
右側はピクセルを拡大したものです サンプルは(0.625, 0.78)に位置しています 画素の中心はオレンジの ドットで表されています これは(0.5, 0.5)に位置します
この例では ジッターオフセットは(-0.125,-0.28)です ジッターオフセットは常に-0.5から0.5の 範囲であることに注意してください 正しいジッターオフセットが 提供されてるかの確認は カメラとオブジェクトの モーションのないシーンを 異なるjitter offsetsのシーケンス を使いレンダリングします 左は誤ったジッターオフセットが 指定された場合の例ですオブジェクトが ずれる可能性があり細かい線があいまいになる 右側は正しいジッターオフセットを 指定した場合の出力です オブジェクトはその場にとどまり 小じわは徐々に解消されます MetalFXのtemporal AAとupscaling効果は Appのパフォーマンスを向上させ ネイティブのターゲット 解像度レンダリングの品質に 匹敵するアップスケーリング品質を提供します 両方のアップスケーリング効果を使用する際に 最適な品質とパフォーマンスを得るために ここでは実装のベスト- プラクティスを説明します
空間アップスケーリングから スタートしましょう 空間アップスケーリングの 高品質を得るためには カラー入力がanti-aliasedで ノイズフリーが望ましいです これはノイズの影響やエイリアス画像によって エッジ判定がうまくいかず 空間アップスケーリングの 品質が悪化するためです 最高のパフォーマンスを得るには 知覚的色彩処理モードを使用してください つまり入力色はsRGB色空間において0~1の値で トーンマッピングされている必要があります 最後により高いテクスチャー ディテールを得るために 適切な負のミップ-バイアスを設定します 空間アップスケーリングの 推奨ミップバイアス計算は レンダリング解像度幅のlog2を ターゲット解像度幅で割ったものを 適用することである
例えばレンダリング解像度の各次元を 2倍に拡大すると-1mipの偏りが生じ 各次元を1.5倍に拡大すると -0.58mipの偏りが生じます なおミップレベルが低いと 高周波のパターンを持つ テクスチャの場合ちらつきが 発生することがあります これらアーチファクトを 発見した場合テクスチャの ミップバイアスを調整する必要があります 次にTemporalAAとアップスケーリングの ベストプラクティスについてお話します Temporal AAとアップ- スケーリングで品質を保つ為 優れたジッターシーケンスを 選択することが重要です アップスケーリングされたターゲット解像度の 全ピクセルに渡ってサンプルの 良い分布が得られるような ジッターシーケンスを探してみてください 通常1画素あたり8個の ジッターサンプルが出力され 高画質なanti-aliased- upscaled出力が得られます 2倍速アップスケーリングの場合32ジッターの ハルトン(2,3)シーケンスを使用し ジッターカラー入力を 生成することを推奨します これはHalton(2,3)シーケンスの最初の32個の サンプル位置をプロットしたもので 1出力ピクセルあたり 約8個のサンプルを生成する また高いテクスチャー-ディテールを得るには 適切な負のミップバイアスを 設定することが重要です 時間的AAとアップ-スケーリングのための 推奨ミップバイアス計算は レンダリング解像度幅log2 ターゲット解像度幅で 割ったものを1減算して適用します 例えばレンダリング解像度の各次元を2倍に スケーリングすると-2mipの偏りが生じ 各次元を1.5倍にスケーリングすると -1.58mipの偏りが生じることになります 次にミップバイアスが出力に どのような影響を与えるか 状況別に例を挙げて説明します 同シーンでミップバイアスを0,-1,-2にして MetalFXのテンポラルAAと アップスケーリングの出力を示します
ミップバイアスを-2にすると 最もシャープでクリアな出力になり ミップバイアス0にすると 最もソフトでぼやけた出力になります
ここでは時間的なアップ- スケーリング効果を利用した 回路基板のレンダリング画像を3点ご紹介します 上から順にテクスチャ- サンプリング時に適用される ミップバイアスの値が0 -1,-2であることを示しています 回路基板のテクスチャは微小なトレース線など 高周波のパターンを持つため -2のミップバイアスはちらつきや モアレ効果を発生させる しかしミップバイアスを-1にすると これらの影響が大きく軽減され ミップバイアスを0にすると完全に解消されます ミップレベルが低いと ディテールが細かくなります ミップバイアスの目安ですが 高周波のパターンを持つ テクスチャーの場合 ミップバイアスを選択する際に注意が必要です MetalFX Temporal AAと アップスケーリングによる anti-aliasedで高品質な アップスケーリング出力を 確保するために以下のプラクティスに従います
最後にMetalFX Upscalingを使用する際の パフォーマンスのベスト- プラクティスを説明します MetalFX Upscalingでベスト- パフォーマンスを得るには 2 つの非依存的なレンダー またはコンピュートパスで 同じリソースを読み取りと書き込みに バインドしないよう注意する必要があります そうすると誤った従属関係を作ってしまいます Metalでは誤った従属性を避けることは 常に重要でしょう これは次に説明するように MetalFX Upscalingで特に重要です この例では2つのフレームがあります シャドウと後処理のパスは全く無関係であり リソースの従属関係もない Metalは次のフレームの シャドウパスと現フレームの ポストプロセッシングパスを オーバーラップさせます
しかしポスト処理パスが Metalバッファに書き込み シャドウパスも同じバッファから読み取る場合 Metalは同じリソースへの読取りと書込みを 同時に行う潜在的な危険を避けるために GPUがこれら2つのパスを並行して 実行するのを阻止します フレーム間の誤った従属関係は MetalFX Upscalingのパフォーマンスに 悪影響を及ぼす可能性があります フレーム間に誤った従属性がない場合 次のフレームのシャドウ-パスは前フレームの MetalFX Upscalingと重なっている 可能性があることに注意してください しかしフレーム間に誤った 従属性があるため パフォーマンスの損失には MetalFX Upscalingが 処理を終了するまでの 時間も含まれるようになりました 理想はフレーム間に 誤った従属性がないことを確認し 異なるフレーム間でワークロードの オーバーラップを可能にすることで MetalFX Upscalingの使用時に 最適な性能を確保することです この例では 代わりに後処理とシャドウパス用に 別々のバッファを作成することで 誤った従属性を防ぎ 結果として独立した パスの並列実行を可能にします
MetalFX Upscalingを採用する際に常に 念頭に置きたいのが誤った従属性の回避です この2つの効果のうちどちらを選ぶかを決める際 いくつかの注意点があります シェーディングコストと ピクセル数が増加し続ける中 Temporal AAとUpscalingが必要とされています 画素を時間的にアモルティ化することで 視覚的な忠実度を高め パフォーマンスを上げます もしまだ優れたtemporal- AA solutionを持っておらず ジッターカラー モーション 深度バッファをレンダリングできる場合 MetalFXのtemporal- AA solutionは 検討すべき説得力のある プラットフォーム最適化 ソリューションを提供します 必要な入力がない場合やすでによく調整された AAsolutionを持っている場合はMetalFX空間- アップスケーリングの利用を検討ください どのアップスケーリング効果を選べばいいのか これでご理解いただけたと思います 次にこの2つの効果をMetalAppで ライブに動作させた例を紹介します ambient occlusionやvolumetric fogなどの real-time rendering algorithmsを 搭載したサンプルコード Modern Rendering with MetalのBistroシーンを 横に並べて比較してみました 左が1080pでのネイティブレンダリング 右がMetalFX Spatial アップスケーリングによる4K出力 このサンプルは独自の temporal anti-aliasing solutionを InputNfor MetalFXの空間 アップスケーリングとし使用
スクーターにズームインしてみると...
左は少しぼやけた画像右は空間的に アップスケーリングされた出力のため エッジがきれいなシャープな 画像になっています ハンドルバーの直線は アンチエイリアスされてます
ボディーのカーブもより滑らかになりました 性能比較をしてみましょう 左は4Kでのネイティブレンダリングです 右側がMetalFX- Spatial upscalingの 4K出力
カメラが動くと左側の ネイティブレンダリングは 途切れたフレームレートで動作していますが 右側の空間的にアップスケールされた 出力ははるかにスムーズです
次に反射や影を多用したレイトレースによる シーンを並べて比較してみます 左は1080pのネイティブレンダリングです 右はMetalFX- Temporal AAと アップスケーリングによる4K出力です
シャンデリアを拡大してみると...
左のネイティブ出力はエイリアス感があり右の タイムアップスケーリング 出力はエッジがシャープで より細かいディテールが表現されています 影がぼやけた感じではなく メリハリのありいい感じです シャンデリアの細かい装飾も 認識できるようになりました
またMetalFX Temporal AAと アップスケーリングによる 性能向上も明らかです 左が4Kでのネイティブ-レンダリングです 右はMetalFX- Temporal AAと アップスケーリングによる4K出力です カメラが動くと左側の ネイティブレンダリングは 非常に低いフレームレートで動作していますが 右側の時間的にアップスケールされた 出力はよりスムーズになっています
第一線のゲーム開発者は MetalFX Upscalingの能力に期待を寄せており Grid:Legends Resident Evil:Village No Man’s Skyを 今年後半にMacで提供する予定です 次にフレームワークを使った 初期の作業を紹介します
MetalFX Temporal AAとUpscalingを 使用したNo Man’s Skyの驚くべきビジュアルと 流動的なゲームプレイを見ることができます
おさらいするとMetalFXは アップスケーリングに特化した新しいAPIです Spatial upscalingは簡単に導入でき 大幅な性能向上を実現します またTemporal AAとアップスケーリングを使用し より高品質なレンダリングを 行うことができます 先に説明したベスト-プラクティスに従うことで MetalFX Upscalingを最大限に活用できます ご視聴ありがとうございます
-
-
3:39 - Spatial upscaling (initialization)
// Spatial upscaling (initialization) let desc = MTLFXSpatialScalerDescriptor() desc.inputWidth = 1280 desc.inputHeight = 720 desc.outputWidth = 2560 desc.outputHeight = 1440 desc.colorTextureFormat = .bgra8Unorm_srgb desc.outputTextureFormat = .bgra8Unorm_srgb desc.colorProcessingMode = .perceptual spatialScaler = desc.makeSpatialScaler(device: mtlDevice)
-
9:16 - Spatial upscaling (per frame)
// Spatial upscaling (per frame) // Encode Metal commands to draw game frame here... // Begin setting per frame properties for effect spatialScaler.colorTexture = currentFrameColor spatialScaler.outputTexture = currentFrameUpscaledColor // Encode scaling effect into command buffer spatialScaler.encode(commandBuffer: cmdBuffer) // Encode Metal commands for particle/noise effects and game UI drawing for frame here...
-
9:16 - Temporal antialiasing and upscaling (initialization)
// Temporal antialiasing and upscaling (initialization) let desc = MTLFXTemporalScalerDescriptor() desc.inputWidth = 1280 desc.inputHeight = 720 desc.outputWidth = 2560 desc.outputHeight = 1440 desc.colorTextureFormat = .rgba16Float desc.depthTextureFormat = .depth32Float desc.motionTextureFormat = .rg16Float desc.outputTextureFormat = .rgba16Float temporalScaler = desc.makeTemporalScaler(device: mtlDevice) temporalScaler.motionVectorScale = CGPoint(x: 1280, y: 720)
-
10:35 - Temporal antialiasing and upscaling (per frame)
// Temporal antialiasing and upscaling (per frame) // Encode Metal commands to draw game frame here... // Setup per frame effect properties temporalScaler.resetHistory = firstFrameOrSceneCut temporalScaler.colorTexture = currentFrameColor temporalScaler.depthTexture = currentFrameDepth temporalScaler.motionTexture = currentFrameMotion temporalScaler.outputTexture = currentFrameUpscaledColor temporalScaler.reversedDepth = reversedDepth temporalScaler.jitterOffset = currentFrameJitterOffset // Encode scaling effect into commandBuffer temporalScaler.encode(commandBuffer: cmdBuffer) // Encode Metal commands for post processing/game UI drawing for frame here...
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。