ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Metal Game Performance Optimization
Realize the full potential of your Metal-based games by tackling common issues that cause frame rate slowdowns, stutters, and stalls. Discover how to clear up jitter and maintain a silky-smooth frame rate with simple changes in frame pacing. Get introduced to new tools for analyzing rendering passes and pinpoint expensive or unexpected work. Learn how to avoid thread stalls and get specific advice about handling thermal notifications.
リソース
- Analyzing resource dependencies
- Debugging the shaders within a draw command or compute dispatch
- Optimizing GPU performance
- プレゼンテーションスライド(PDF)
関連ビデオ
WWDC23
WWDC18
-
ダウンロード
(音楽)
(拍手) おはようございます 私はGPUソフトウェア パフォーマンスチームのギエムです 我々の使命は iOSで ゲームデベロッパを― 手助けすることです そこで 人気のゲームを調べ 共通する問題を探しました その膨大なデータの 解析結果をご説明しましょう
本日のテーマは “すごいゲームの開発”
ただし 技術的に すごいという意味合いです 始める前にCroteam社に 感謝したいと思います 彼らが開発したゲーム The Talos Principleを使い スライドやデモを お見せします このゲームは 映像が美しいだけでなく パフォーマンスも 犠牲にしていません では本日の議題です まずツールから紹介します そのあとパフォーマンスの 問題を取り上げます フレームペーシングや スレッド優先度など4点です これらは組み合わさって 悪影響が出るため まとめて対処しましょう
ではツールから
大切なのは 早い段階で 頻繁にプロファイリングすること プロファイリングは欠かせません まずはツールの理解が重要です 今日は2つのツールを ご紹介します 1つ目はInstruments メインのプロファイリングツールで パフォーマンスやレイテンシ 総合的なタイミングを確認できます 2つ目は Metalフレームデバッガ GPUの負荷をデバッグするための 非常に強力なツールです
では どこから 始めればよいのでしょうか 今回 我々は皆さんのために 新しいInstrumentsテンプレートを ご紹介します Game Performance テンプレートです これはSystem Traceや Time Profilerなどを 組み合わせたものです 設定済みなので CPUやGPUのデータを― 記録できます
では起動する方法です Instrumentsの中央を見ます 他のテンプレートと同様に 設定が可能です Windowed Modeで実行すれば 好きなだけゲームをプレイでき 最後の数秒だけ記録されます これが そのデータの例です
簡単に全体を見ていきましょう
System Traceと Time Profilerは システムの負荷や CPUの使用量を表示します 例えば User Interactive Loadは アクティブスレッドを全て記録 この場合 オレンジ色の部分は 動作可能なスレッドが 他にも存在することを示しています とても見やすいですね
Instrumentsについて さらに詳しくは別途ご確認ください
次はMetal System Traceです Metalフレームワークから ディスプレイまでの グラフィックスタックを 確認できます 特にGPUの使用時間を 確認する場合は VertexやFragmentなどに 分かれます ディスプレイトラックも 最初に調べるべきです 長いフレームや スタッタリングを見つけ そこから始めましょう
これは強力なツールで 多くの情報がありますから― 他にもセッションが 用意されています
今年 新たにご紹介する Thread Statesビューには ゲーム内の全スレッドの状態が 色別に示されています オレンジ色はスレッドの プリエンプション 赤色はブロックです 我々が このビューを作ったのは 現在のスレッドシステムが 複雑だからです ぜひ ご利用ください
CPUコアごとの トラックもあります コアで処理中のスレッドや スレッドの優先度が カラーで表示されます これでシステムの状態が よく分かりますね
ツールの概要を 簡単に ご説明しました 次はパフォーマンスの 問題についてです 最初はフレームペーシング
まずは映像をご覧ください これはSceneKitを使った Fox 2のデモです
レンダリングが速いのは どちらでしょう?
分からない人も いるかもしれませんね 左側は毎秒60フレームを 目指しましたが 実際は毎秒40フレームです 動きがカクついていますね 一方 右側は毎秒30フレームです 動きに一貫性があり スムーズですね
これは感覚の問題では ありません レンダリングの速度が速く 映像がスムーズでないのは マイクロスタッタリングと 呼ばれる現象です ディスプレイのリフレッシュ間隔と フレーム時間の差で発生します 例えばゲームのレンダリングに 毎秒40フレームかかり ディスプレイが毎秒60フレームで リフレッシュされるとします この場合 見た目の一貫性が 失われてしまいます
これを解決するには 何をすればよいでしょう? 実際には ほとんど 行うことはありません レンダリングのあと ディスプレイリンクから 次のdrawableを受け取り すぐに表示します そして次のリフレッシュまで― drawableを表示して おくよう命令します 目標は毎秒60フレームです
マイクロスタッタリングの 原因は他にもあります
フレームレートを 低くはしていても usleepを使っているゲームが 数多くありました これはiOSでは 非常によくない習慣なので 後ほど修正する方法を お話ししましょう マイクロスタッタリングが 発生する時― システム内で 何が起きているのでしょう 全てのコンポーネントの タイムラインを見ます 通常どおり レンダリングを開始すると 3つのバッファが 確認できます 全てのdrawableは 文字と色で表されています 前提を説明します Bのレンダリング時間は ディスプレイの リフレッシュ間隔より 長くなっています
Bのレンダリング時間は 25ミリ秒で ディスプレイのリフレッシュ間隔は 16.6ミリ秒
こうなるとディスプレイは レンダリングが終わるまで Aを表示し続けなければ なりません そうして待っている間に Bのレンダリングが完了します 表示する準備はできましたが ここで別の問題が起きます 待っている間に Cのレンダリングも終わり― 表示の準備が完了したのです すると一貫性のない フレームペーシングが発生 これ以降のフレームは 一貫性がなくなり マイクロスタッタリングが 発生します
これは いろいろな形で 実際に起こる現象です The Talos Principleを使い デモをお見せします マイクロスタッタリングを 確認できるでしょうか
今からお見せするのは 先ほどお話しした― Game Performance テンプレートです 左側にInstrumentsがあり
中央にスレッドがあります ではマイクロスタッタリングを 探します ディスプレイトラックに注目し 一貫性のないフレームを 見つけます ディスプレイトラックはここです このディスプレイトラックに いくつかのヒントが隠されています このアイコンは 通常の時間よりも 表示が長くなった時に現れます いい例を見つけたので そこを拡大してみましょう optionキーを押したまま ポインタをドラッグします
ディスプレイトラックを見ると マイクロスタッタリングが 確認できますね 表示のタイミングが 全て違います この場合は 50ミリ秒と33ミリ秒と16ミリ秒 50ミリ秒のあと 33ミリ秒 この繰り返しが 見られるということは マイクロスタッタリングです これを修正しましょう
実際に起こり得る問題を ご覧いただきました では どのように 修正すればよいのでしょう
フレームレートを 調整するのが一番です フレーム持続時間の最小値を APIを使って― レンダリング時間より 長く設定します 例えばMTLDrawable addPresentedHandlerは drawableが現れると コールバックし マイクロスタッタリングを 認識できます 他の2つのAPIは 実際に問題を解決し フレームペーシングを コントロールします 今回は下の2つのAPIを 利用します フレーム持続時間の最小値を レンダリング時間より― 長く設定すると どうなるでしょう
レンダリングを始めた時から フレーム持続時間は レンダリング時間より 一貫して長くなりました 全てのフレームが― 一貫性を保っています 思わぬ副次的効果もあります フレームレートが 毎秒40フレームから 毎秒30フレームになり フレーム時間が伸びたのです
どうすればフレームペーシングを このように修正できるでしょうか 必要なのは わずか数行のコードです 先ほどと同じパターンで レンダリングを行い drawableを受け取りました 先ほどと異なるのは フレーム持続時間の最小値が 設定されている点です それだけです これでフレームの 一貫性が保たれます
しかし こんな疑問もあるでしょう “最大値はどうなるのか?” “作業の優先度については どうするのか?” それが次の問題 スレッド優先度です
まずは映像をご覧ください 再びFox 2のデモです
スタッタリングが起こる原因は 数多く存在すると考えられます その中でも極めて基本的で かつ一般的な原因は
スレッドの遅延です
作業の優先度が うまく調整されていなければ 予期せぬ遅延が発生します iOSは他にも 処理を行っているのです
スレッド優先度はシステム全体の 安定性の保証に使われるため 多くの作業を行うスレッドは 優先度が下がり 他が実行されます これが優先度の低下です
また 優先度の逆転も起こります これは非常に似た状況で 現れる別の問題です 優先度の逆転は レンダリングスレッドが 優先度の低いスレッドに 依存している時に起こります 先ほどのタイムラインで 確認しましょう
まず毎秒30フレームで レンダリングを開始 ここでバックグラウンドの 処理が発生 iOSは たくさんの 処理をします スレッドが正しく 設定されていない場合 バックグラウンド作業と入れ替わり スケジューリングされていた 処理が終わりません
フレーム持続時間の最大値は 設定していないので 何百ミリ秒も 表示される可能性も ユーザは スタッタリングを認識します
これは理論上の話ですが 現実でも― 同様の問題が さまざまな形で起きます The Talos Principleを使って デモをお見せしましょう この問題を確認できます
Game Performanceテンプレートを 再び表示しました 注目したいフレームを すでに拡大しています 非常に長いフレームで 233ミリ秒あります ここを見ていきましょう
GPUが正常に動作していないのが 一目で分かります アイドル状態があって あまりよくありませんね
CPUを見ると このように かなりのビジー状態で 絶え間なく動いています
しかし Time Profilerビューを見ると 動いていません なぜスタッタリングが 発生したのでしょう? Thread Statesビューに 切り替えます そのためにはアイコンをクリックし Track Displayを開きます Thread Statesを選択
何か問題が起きていることが 分かります オレンジ色の箇所です スレッドは192ミリ秒間 プリエンプトされているので レンダリングスレッドが その間 動作していません より詳細な情報が知りたいなら 下部を見れば分かります
プリエンプトされた スレッドをクリックすると 何が起きているのか ここに表示されます スレッド優先度26として プリエンプトされたようです バックグラウンド処理より 順位が低く App Storeの更新が優先されました これでは困るので 今はゲームのほうが重要なのだと システムに伝える必要があります その方法をご説明しましょう
一番いいのは レンダリングスレッドを設定し スレッドの優先度を 45に固定することです iOSやmacOSの優先度は 値が大きいほうが上で 優先度31は 4よりも高くなります また 優先度の低下を 避けるため スケジューラの Quality of Serviceを止めます
では見ていきましょう
すでに設定は完了しています レンダリングを開始
バックグラウンドの作業も 実行します 内容はApp Storeの更新です それでもレンダリングは 正しく処理されています バックグラウンドの作業を プリエンプトしているので スタッタリングはありません ゲームは毎秒30フレームで 動いており 負荷は膨大ですが大丈夫です まさに“技術的にすごい”ですね ではコードを 見ていきましょう
必要なのは わずか数行だけです この場合は pthread属性を設定したあとに pthreadを作成しています Quality of Serviceを止め 優先度を45にしています これで必要な pthreadが作成できました シンプルで 技術的にすごいですね
次の問題は もう少し複雑ですよ 温度の状態です
持続可能なパフォーマンスの ためのデザインには
温度管理が大切です これを考えましょう
iOSデバイスは 非常にパワフルですが とても小さいです アプリケーションが 多くのリソースを使えば 低温を維持するために システムは対策を講じます また ユーザが 省電力モードを設定すれば 同じような影響を与えます
最善の方法は システムの状態によって 作業負荷を変えることです システムへの 負荷を調整するための― APIが多数あります NSProcessInfo thermalStateは デバイスの温度状態が 変わった時に通知します 同様に 省電力モードの状況も チェックしましょう 一番下のAPIを使用すると システムの負荷が GPU時間に どう影響しているか分かります
ではコードを見てみましょう これが最善の方法です switchステートメントがあり caseは温度状態に 対応しています 内容は“nominal”“fair”
“serious”“critical”です
これで温度状態が分かり どう対処すればよいかも コマンドが教えてくれます では 低温を保つには どうすれば? いくつか方法を 提案できますが システムのために何を選ぶかは ゲームデベロッパ次第です 最高の状態を保つために 何が必要でしょうか
ゲームを完遂できるような フレームレートを 目標にするとよいでしょう 例えば 毎秒60フレームが無理なら 毎秒30フレームを維持すること GPUの作業の調整も 非常に重要です 中間レンダリングターゲットの 解像度を下げたり シャドウマップを 単純化したりします 後処理を削除してもよいでしょう あなたのゲームにとって 最適な方法を選びましょう
これは次の問題に関係します 不要なGPUの処理です ここからは私の同僚 オハッドにお願いします (拍手) ありがとう
こんにちは 私はゲーム技術チームの オハッドです システムへの適合が大事だと お分かりいただけましたね 温度状態の変化や 省電力モードに対応するためには GPUの作業負荷を 調整する必要があります しかし多くのデベロッパは GPUは複雑な ブラックボックスだと考えています 今日は その中を解明します
気付かずにGPU時間を 無駄にすることは よくあります 技術的にすごいゲームは GPUを有効に利用し 適切な温度管理を行い 電力をセーブします その方法は 著名なゲームからも学べますが 今日はレンダリングについて お話しします CPUの話でもお伝えしたように 最良の方法は GPUのプロファイリングです
GPUには多くの性能が 隠されています 作業時間を測定し レンダリング技術を理解して ゲームを視覚的に 向上させましょう しかし どこが非効率で パイプラインのどこが 過剰なのでしょうか ここでツールに戻ります
Instrumentsを開き Metal System Traceを見ます VertexやFragmentなどの 処理完了のタイミングが分かります
しかし これだけでは不十分です 各パスが何をしているか 理解しましょう
Metalフレームデバッガに 追加された新機能は 依存関係グラフです
1つのフレームに 関してのグラフで
ノードとエッジで 構成されています エッジはパス間の依存関係を 表しています 全体を見ると どのパスと パイプラインが― フレームを形成しているか 分かります 一方でノードは 1つのパスの情報です
主な要素は3つ まずタイトルで パスの名前が示されます 名前は必ず付けましょう ツール全般において 名前は重要です
今見ているパスの種類も ここで分かります 転送パスや計算パスもありますが これはレンダリングパスです
次は このパスで処理された 作業状況の一覧 最後は下部に表示される パスのリソースのリストです ラベルや 作業内容を示すサムネールや それぞれのリソース情報を 示したリストです これらのおかげで パスを理解できます グラフの説明をしたので デモをお見せしましょう
Fox 2のデモを見てみましょう このゲームに さまざまな 効果を追加します
シャドウマップや ブルーム効果― 被写界深度などを駆使し 美しい映像を描きます では依存関係ビューアです Xcodeを開き Capture GPU frameボタンを押し MainPassを選択します
(拍手) 自動モードに変更すると 右側にアシスタントが現れます デバッグナビゲータで 選んだパスが メインビューで 表示されています これは双方向的で グラフは相互に作用するので 別のパスやテキスチャや バッファを選ぶと 左のナビゲータも 右のアシスタントも更新されます フレームの すばらしい操作方法ですね
ズームアウトすると 統計データが隠れ フォーカスが個別のパスから フレーム全体へと移ります さらに縮小すると フレーム全体が確認できます
グラフの結びつきは 依存関係を示しているので
それぞれの処理が グループ化されています 説明しましょう ここにシャドウマップ作成用の ノードがあります
影をレンダリングする3つのパスが 左側に見えます フレーム全体の様子が 分かるだけでなく 2つのレイヤの間にある 階層も見えます レンダリング技術の 大切な要素の1つですが ゲームエンジンを使う際に 常に目立つものではありません 例えば カスケードに 個別のパスが必要なことに― 気付かない場合もあります これら一つ一つについては考えず グループとしてとらえます これにより GPUの作業負荷を調整する時 確かな情報を基に判断できます
以上が依存関係ビューアです スライドに戻って ギエムを呼びましょう ありがとう (拍手) ありがとう すばらしいデモでした
今 オハッドがご説明した 依存関係ビューアは GPUの作業負荷の調査に 適しています 例えば このように小さく シンプルなパイプラインから 後処理などが必要な複雑なものに 変える場合がよくあります
これらはオブジェクトに プロパティを追加することが 必要です コードの変更は 最小限で済みますが レンダリングの複雑さは 10倍単位で増えます
そこで最初に お話しした内容に戻ります プロファイリングです ゲームを理解することが大切です 開発に時間をかけるだけでなく プロファイリングの時間も必要です 今日お話しした問題は 数分で見つけられます 探し回る必要はありません スタッタリングや 長いフレームを記録し そこから調整を始めるのです 簡単なことです 問題を認識するための 情報を得るために ツールを使いましょう
このことを忘れないでください さまざまな解決法と共に 見てきた問題は― プロファイリングで 発見できます 我々も多くのゲームを解析して 問題を見つけたのです ソースコードに アクセスしたら フレームペーシングと スレッド優先度を設定しましょう コードは ほんの数行です そのうえで 温度を適切に管理し 不要なGPUの処理を避けましょう これらを確実に実行すれば 技術的にすごいゲームを 開発できます より詳細な情報は ラボでご確認ください 皆様からのご質問も お待ちしております あなたのゲームの プロファイリングも行いますよ Metalでのゲーム開発については 他にもセッションがあります
ありがとうございました よい一日を (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。