2.4K Views
February 05, 23
スライド概要
グラフィックスのローレベルAPIがリリースされた当初に、その存在意義などをざっくり解説するライトニングトーク用のスライド。もはや大昔だけど、今でもさほど状況は変わってなさそうなので、上げてみます。
ローレベルAPIに触れて GPUの気持ちになる 正確にはドライバ作る人の気持ちかもしれない rita
自己紹介 • rita(@rita0222) • 大学院博士課程を経て、ゲームミドルウェアの会社に入社 • その後、とあるゲームディベロッパーのR&Dに • 大学在学中から FK ToolKit というライブラリを共同開発 • http://gamescience.jp/FK/ • C++ネイティブでWin/Mac対応なのに加えて、 最近.NET版もできました(C#,F#で開発可能)
ローレベルAPIとは • CPUの負荷低減を主目的とした新たなAPI • Metal(iOS/Mac) • DirectX12(Win) • Vulkan(Win/Linux/Android) • 新しい表現が可能になるといったものではない • これまでドライバがやってきたことを使う側が やらなきゃいけないやれるAPI
ドライバがやっている仕事 • APIを叩いた先には GPUドライバの実装がある • これが良くも悪くも 抽象的かつ汎用的 • 多彩な環境で様々な要求に 応える必要があるため • ユーザープログラムで 最適化できる余地が少ない • ドローコール減らす • ステート切り替え減らす ユーザープログラム これまでのAPI (DirectX9/10/11,OpenGL) GPUドライバ
そこでローレベルAPI • これまでドライバ内でやって いた処理も最適化対象になる • ドローコールを増やしても 重くなりにくい処理が書ける ユーザープログラム • うまくやれば • 今までマルチスレッドに できなかった部分もできる • うまくやれば • 最適化の選択肢が増える • うまくやれば ローレベルAPI (Metal,DirectX12,Vulkan) GPUドライバ
比べてみよう これまでのAPI ローレベルAPI ユーザープログラム ユーザープログラム これまでのAPI (DirectX9/10/11,OpenGL) ローレベルAPI (Metal,DirectX12,Vulkan) GPUドライバ GPUドライバ
やること増えてる…… これまでのAPI(オートマティック車) ローレベルAPI(マニュアル車) ユーザープログラム ユーザープログラム これまでのAPI (DirectX9/10/11,OpenGL) しかも結構たいへん ローレベルAPI (Metal,DirectX12,Vulkan) GPUドライバ GPUドライバ
オートマ(旧API)だと重かった点 • これまで最適化として減らしてきた要素 • ドローコール • レンダーステート切り替え • テクスチャサンプラー切り替え • これらをローレベルAPIで記述してみると、 何故重かったのかが理解できるはず
ドローコールの作り方 これまでのAPI(GL系想定) ローレベルAPI 1. 頂点バッファやテクスチャ・ シェーダをロードしておく 2. それらをグローバルなステー トに対してバインドしておく 3. 深度ステンシルやブレンドの ステートもセットしておく 4. 描画APIを呼ぶ 1. 2. 3. 4. 5. 6. 7. 頂点バッファやテクスチャ・ シェーダをロードしておく コマンドバッファを作る コマンドバッファに使用する頂点 バッファ・テクスチャ・シェーダな どをセットする 各種ステートオブジェクトを作る ステートオブジェクトも コマンドバッファにセット 描画命令をバッファに書く コマンドバッファを コマンドキューに提出する
コマンドバッファと ステートオブジェクト • 描画指示をGPUネイティブ命令に変換してプールするバッファ • どのような描画要求が来るか分からないので、 基本的には一度作ったら毎回破棄して作り直し • 重くない訳がない! • レンダーステートをGPUのレジスタに変換したオブジェクト • 何か1つでもステートが変更されると作り直し • APIによっては部分的な作り直しで済む場合も • OpenGLの場合、描画APIが呼ばれるたびに • その時点の値をコピーしてステートオブジェクトを作る • 無駄すぎる
もちろんドライバベンダーも頑張ってる • 馬鹿正直に前スライドのようなことはやってない • が、多彩な環境下で、様々な要求に応える必要がある以上、 ある程度のオーバーヘッドは必要経費になる • これがゲームコンソールだと、ターゲットが限定されるため、 以前からローレベルに相当するようなAPIが提供されていた • 特にOpenGLはステートマシンなので、 マルチスレッドと壊滅的に相性が悪く、打てる手が少ない • DX11の場合は、ディファードコンテキストを使うことで、 マルチスレッド化しやすい
ローレベルAPIでできる最適化 • コマンドバッファの作り置き • コンスタントバッファを更新してSRTやアニメーションは操作可能 • ステートオブジェクトの作り置き • 定番の設定はプールしておいて複数のコマンドバッファで使い回す • コマンドバッファ構築のマルチスレッド化 • コマンドキューに突っ込むまでの作業は並列化可能 • コマンドキュー自体を多重化すれば、あるキューの描画待ち中に 次のキューに対するコマンドバッファ構築が可能 • キューの多重化に合わせて使用するバッファも種類によっては多重化が必要
まとめ • ローレベルAPIはマニュアルトランスミッション • うまく使えばGPUの性能を余さず引き出せる • 逆に言えば最適化しないならローレベルAPIは無用 • 直接ローレベルAPIを叩かなくても、その構造を知ることで、 これまでのAPIやゲームエンジンに対しても優しくなれるはず
おしまい 初LTでした ありがとうございました