O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
GPU駆動レンダリングへの
取り組み
株式会社カプコン 三嶋仁/ 清水昭尋
今回の内容
•レンダリングパイプライン
•メッシュレンダラ
•ライトカリング
レンダリングパイプライン
•マルチプラットフォーム向け
• 中間描画命令
• ネイティブ描画命令
• リソース管理
レンダリングパイプライン
中間描画命令
描画命令の
ソート
ネイティブ
描画命令
中間描画命令
•プログラマが使用
• 内製の描画命令
• マルチスレッド
• 描画コンテキストで構築
• 命令の再利用
中間描画命令
• 基本の命令はDirectX11風
• DX12世代の機能
• Multi DrawやAsync Compute…
• 32Bit定数の低コスト利用
• 一般命令
• Copy, Update Buffer,
• Draw, D...
描画コンテキスト
•描画命令を作るインターフェイス
• 各スレッドごとに存在
• ユニークなスレッドIDを保持
• 優先順位の設定
• 各種の描画リソースの設定
• シェーダとリソースの整合性のチェック
• 中間描画命令を作成
描画命令のリソースの種類
•グラフィックスに必要な要素
• Texture,
• ShaderBinary,
• ShaderResourceView,
• UnordredAccessView,
• VertexBuffer,
• Index...
描画命令のリソース管理
• オブジェクトの参照状態は参照カウントで管理
• リソースの生存管理
• 描画が完了するまで生存を保証しなければならない
• 参照カウンタとは異なる別の生存保障の管理が必要
• 生存保障の管理は、保障フレームを使用
•...
描画命令のリソース構成
•複数のリソースから構成
• セットアップコストが高い
• リソースの収集
• 収集したリソースに保障フレームの更新
• インゲーム中は大量の描画命令
• セットアップコストは無視できない
Draw
VertexBuff...
描画命令のリソースの再利用
•経験的に描画命令は、前回の描画時と大差がない
• メッシュの描画
• 毎回ほとんど同じ組み合わせのリソースを送る
• 更新されるのはリソースの中身で、ハンドルは固定
• パーティクルの描画
• 使用するリソースは事...
リソースの拡張
• リソースを意味のある単位に集約
• 初期化時に作成
• 複数フレームで再利用
• 内部のリソースの管理
• 作成時
所持するリソースの参照カウンタのみを
作成時に更新
• 解放時
保障を所持するリソースに反映
• 更新チェッ...
送信する描画リソース
•Draw命令なら、4つのリソース
Draw
TargetState
PipelineState
PipelineResourceTable
GeometryState
頂点数など
Draw
VertexBuffer
In...
中間描画命令のマルチスレッド
• ネイティブ描画命令は中間描画命令の優先順に実行
• 中間描画命令の発行は、実際の描画と分離が可能
• 半透明と不透明の命令の実行
スレッド0
スレッド1
不透明
半透明
不透明 半透明
不透明半透明
不透明 不...
中間描画命令のマルチスレッド
•優先順位の応用例
• 描画順番の最適化
• EarlyZを効かせるための、手前順の描画
• 半透明の整合性のための、奥順番の描画
• データのコピータイミングの制御
• コンピュートシェーダの依存リソースの調整
...
コンピュートシェーダの依存リソースの調整
• CSでUAVとSRVがピンポンする箇所はストール
• GPUソートや、シミュレーションなどで問題
• 依存したリソースが連続処理しないように優先順位を調整
• 回避するために、他のCSと混ぜて動かす...
マルチスレッド
•実際のエンジンの動作
•3段階の構成
ライトやメッ
シュの情報更新
描画パスの構築 描画処理
ライトやメッシュの情報更新
•マルチスレッドで実際の描画を行う前の前処理
•ライト
• 影を落とすかの判定し、描画パスの登録/解除
• 影のキャッシュの更新の可否
•メッシュ
• 詳しくは後半に!
描画パスの構築
• 現在のフレームで利用する描画パスの収集
• GBuffer,
• DeferredLighting
• ShadowCast
• PostProcess
• Etc….
• 描画パスの構築は、シングルで動作
• 優先順位の最...
描画処理
•マルチスレッドで処理
• 個々の描画処理は相互依存しない
描画が依存するのは、描画リソースと描画パス(優先順位)
• 各描画処理が収集した描画パスから中間描画命令を作成
命令のキャプチャとプレイ
• 一度作った描画命令を再利用
メモリの設定なども省けるため最速
• 使用例
シャドウキャストメッシュ、ポストプロセス
• キャプチャとプレイの制約
描画パスに依存したリソースは、別の描画パスで使用不可能
• ローカル...
レンダリングパイプライン
中間描画命令
描画命令の
ソート
ネイティブ描
画命令
ソート
•正しい命令順番に並び替える
• 安定したソートを使用
• 同一優先順位、同一スレッドの描画命令は発行順番を維持
•並び替えはマルチスレッド
スレッド0
スレッド1
不透明
半透明
不透明 半透明
不透明半透明
不透明 不透明 半透明不...
レンダリングパイプライン
中間描画命令
描画命令の
ソート
ネイティブ描
画命令
ネイティブ描画命令
•中間描画命令をグラフィックスAPIに渡す
• DirectX11,DirectX12, Mantle, etc…
•マルチスレッドで作成
ゲーム処理
ネイティブ描画コマンド0
メインスレッド
レンダリングスレッド0
ネイテ...
リソースからネイティブ描画命令を支援
•再利用可能な処理は事前に最適化
• 中間描画命令を作成する段階で必要な情報を収集
プラットフォームによって実装が異なる
• DX11ならリソースの単純な配列化
• DX12ならdescriptor tab...
リソースからネイティブ描画命令を支援
• 更新頻度でリソースの処理を分離
• 更新される可能性があるリソース
• ConstantBuffer
• 位置情報やカメラ情報など細かな単位の更新に使用されており、ハンド
ルが可変なため
• プラットフ...
ここまでのまとめ
•マルチスレッドの描画命令の作成
•リソースの集約と再利用
•よりパフォーマンスアップするためには?
メッシュレンダラの目標
•従来よりも多くのジオメトリを高速に処理する
• 描画コール数の削減
• 効果的なカリング
• GPUによるCPU負荷の肩代わり
• CPU SIMDの活用
• CPU,GPUキャッシュフレンドリ
新しいエンジンとしての課題
•汎用設計でも高い性能
•拡張性を閉ざさない
•マルチプラットフォーム
• 最新のAPIに対応できるキャパシティ
• Mantle, DirectX12, etc…
• 下はDirectX11世代までを考慮
•ゼロド...
メッシュレンダラの取り組み
•描画API の Indirect 化
• すべてのメッシュが Indirect 命令による描画
•描画コールの削減
• Multi-Draw, Instancing
• マージメッシュ
•GPUカリング
描画API の Indirect 化
Indirect 命令とは
•描画 API 引数をGPUのバッファで指定
• GPUから引数制御が可能
• 引数データがCPU側の場合GPUへの転送が必要
• バッファのオフセットはCPUから指定
void DrawIndexedInstanc...
Indirect 命令のための引数
•ジオメトリ描画のためのデータ(20byte)
•このデータの管理に注力
struct DrawIndexedInstancedArgs {
uint IndexCountPerInstance;
uint ...
Indirect 引数の管理
•VRAMの一部領域を割り当て
• 割り当てた領域をさらにアロケーターで管理
• 単一リソースとすることでCSアクセスを容易に
•バッファ使用戦略
• メッシュ単位でLOD、影モデル含めた情報を転送
• LOD切替...
Mesh 0 Mesh 3 Mesh 2 Mesh 4
Indirect 引数のメモリ使用図
LOD0 LOD1 LOD2 影LOD0
Mat
A
Mat
A
Mat
B
Mat
B
Mat
C
Mat
A
Mat
B
Mat
B
Mat
D
...
Indirect 命令は使えるか
•CPU負荷に大きな変化は無い?
• PCの場合はドライバ実装による(遅くなることも?)
• バッファ管理のオーバーヘッド
•ポテンシャル
• Multi-Draw の使用
• GPU駆動のメッシュ描画パイプラ...
描画コールの削減
Multi-Draw API とは
•複数の Indirect 描画を一度の描画コールで実行
•DirectX12, OpenGL4.3, 拡張DirectX11[2]は
同様の機能が使用可能
void DrawIndexedInstanced...
メッシュ描画の素朴な実装
Mesh 1
Material A
Material B
Material B
Material C
Mesh 2
Material B
Material B
Material B
Material C
Materia...
Multi-Draw を使用した実装
Mesh 1
Material A
Material B
Material B
Material C
Mesh 2
Material B
Material B
Material B
Material C
M...
Multi-Draw は使えるか
•対応プラットフォームの問題
• DirectX11では複数のIndirect命令に置き換え
•Indirect命令を使用するのであれば必ず考えるべき
• 描画コールをシンプルに削減可能
Instancing に関して
•同一描画可能インスタンスをハッシュマップ管理
• 自動 Instancing
• CPUカリング後のインスタンス数をGPUへ
• Indirect バッファの InstanceCount を CS で制御
•イ...
インスタンス情報の管理
•レンダラが全インスタンス情報を管理
• メッシュ固有オフセットと SV_InstanceID で引く
2
インスタンス情報
へのインデックス
インスタンス情報
SV_InstanceID
8 1 0 5 3 12 7 ...
マージメッシュの検証
•Multi-Draw によりジオメトリ描画が柔軟に
• メッシュを跨いだ描画コールのマージも可能では?
•20byteの Indirect 引数を連結していく
• 必要なリソースの結合
• StartIndexLocat...
マージメッシュの実装?
Mesh 1
Material A
Material B
Material B
Material C
Mesh 2
Material B
Material B
Material B
Material C
Material...
Instancing, マージメッシュの課題
•描画コールは減るがオーバードロー負荷が目立つ
• ピクセル負荷の高いものは致命的
• CPUとGPU負荷のトレードオフ
• シーンによって効果的かどうかの選択が必要
•実装コストに結果が見合うのか...
マージメッシュは使えるか
•マテリアルがユーザーメイドのエンジンでは大変
•リソースの制約等の要件を満たすメッシュは…
→シャドウマップ描画!
•描画不具合時のデバッグが難しくなる?
GPU カリング
エンジン層アプリケーション層
新しいエンジン初期のカリングの流れ
•カリングはすべてCPU処理
疎粒度な
シーンカリング
フラスタムカリング
&
微小面積カリング
中間描画命令
カリング処理の再考
•フラスタムカリング
• それなりのCPU負荷
• GPUの方が得意そうな処理?
•オクルージョンカリング
• 高速なCPU処理の実装難度が高い
• GPUの方が得意そうな処理?
GPU駆動のカリングへ
•理想
• CPUのコストをGPUへオフロード
• メッシュはすべてGPUへ素通し、GPUでカリング
•現実
• 中間描画命令の肥大化、大量の描画コール
• データのGPUへのコピーコスト増
オクルージョンカリングの導入
•アルゴリズムはHiZを利用したものを使用[4]
•GBufferへの描画対象メッシュのみ
• ライトのPreZ処理は無い
•Gbufferパスの前までにCSで実行
•同一フレームのGPUで処理するため遅延無し
GPUオクルージョンカリングの流れ
•PreZでHiZを作成
• これはライトカリング等でも利用
•GBufferパスの頂点、ピクセル負荷を下げる
PreZ Pass
1. 遮蔽物による Z の作成
2. Z から HiZ を作成
GBuffe...
GPUオクルージョンカリングは使えるか
•カリング処理によるGPU負荷増
• 主にジオメトリの頂点負荷とのトレードオフ
• GPUへのデータ転送負荷は最小限に
•描画コールの数は減らない
• CPUで遮蔽情報をリードする必要がある
GPUフラスタムカリングの検証
•CPUでカリングしないため中間描画命令が増加
• マージメッシュを使ったシャドウマップ描画への適用
Shadow Cast Pass
インスタンス数 0 であれば
描画されない
Frustum Culling ...
GPUカリングは使えるか
•CPU, GPUでのカリング処理のオーバーヘッドが
大きくなってしまうと意味がない
•CSカリングによるGPU負荷の増加
• 非同期コンピュートで負荷を隠蔽できるか?
GPUカリングの展望
•フレーム遅延無しでのCPUオクルージョンクエリ
• 非同期コンピュートラスタライザ
• CPU, GPU負荷双方の削減可能性
メッシュレンダラのまとめ
•エンジンで搭載されているもの
• Multi-Draw, Instancing
• GPU オクルージョンカリング
•エンジン搭載を検証中のもの
• マージメッシュ(シャドウマップ描画)
• GPU フラスタムカリン...
ライトカリング
2段階のアプローチ
•GPU上でのオクルージョンカリング
• PreZで作られた深度を利用
• フレーム遅延
•描画時のライトカリング
• GBufferで作られた深度からHiZを作成
• CSで実行
よりよいスポットライトのカリング
ライトカリング
実装
•従来の視線をFrustumからView空間のAABBへ
•ConeをAABBからView空間のFrustumへ
• 対象物を逆にすることで適切なカリングが可能
まとめと課題
•利点
• ライトの照明範囲を任意の凸包体で表現可能
•問題点
• 視推台をAABBにすることで誤った判定が発生
References
1. Approaching Zero Driver Overhead in OpenGL
http://gdcvault.com/play/1020791/
2. GPU-Driven Rendering Pipelin...
Próximos SlideShares
Carregando em…5
×

GPU駆動レンダリングへの取り組み

21.714 visualizações

Publicada em

Game Creators Conference 2016の講演で使用したスライドです。
『GPU駆動レンダリングへの取り組み』 - 三嶋 仁 / 清水 昭尋

Publicada em: Tecnologia
  • Seja o primeiro a comentar

GPU駆動レンダリングへの取り組み

  1. 1. GPU駆動レンダリングへの 取り組み 株式会社カプコン 三嶋仁/ 清水昭尋
  2. 2. 今回の内容 •レンダリングパイプライン •メッシュレンダラ •ライトカリング
  3. 3. レンダリングパイプライン •マルチプラットフォーム向け • 中間描画命令 • ネイティブ描画命令 • リソース管理
  4. 4. レンダリングパイプライン 中間描画命令 描画命令の ソート ネイティブ 描画命令
  5. 5. 中間描画命令 •プログラマが使用 • 内製の描画命令 • マルチスレッド • 描画コンテキストで構築 • 命令の再利用
  6. 6. 中間描画命令 • 基本の命令はDirectX11風 • DX12世代の機能 • Multi DrawやAsync Compute… • 32Bit定数の低コスト利用 • 一般命令 • Copy, Update Buffer, • Draw, Dispatchなどの • 優先順位の指定 Header 96 bit Attribute(32 bit) Command Priority(64bit) Type Id(8bit) Command Size(24bit) Reserve(8bit) Layer(10bit) Segment(6bit) Priority(32bit) Thread Id(8bit)
  7. 7. 描画コンテキスト •描画命令を作るインターフェイス • 各スレッドごとに存在 • ユニークなスレッドIDを保持 • 優先順位の設定 • 各種の描画リソースの設定 • シェーダとリソースの整合性のチェック • 中間描画命令を作成
  8. 8. 描画命令のリソースの種類 •グラフィックスに必要な要素 • Texture, • ShaderBinary, • ShaderResourceView, • UnordredAccessView, • VertexBuffer, • IndexBuffer… Draw VertexBuffer IndexBuffer Texture… Sampler… ConstantBuffer… RenderTargetView DepthStencilView
  9. 9. 描画命令のリソース管理 • オブジェクトの参照状態は参照カウントで管理 • リソースの生存管理 • 描画が完了するまで生存を保証しなければならない • 参照カウンタとは異なる別の生存保障の管理が必要 • 生存保障の管理は、保障フレームを使用 • 保障フレームは、参照時に現在フレーム+nを代入 • 保障フレームが現在のフレームを超えて、かつ、参照カウント が0のものが初めてメモリ上から解放 • 生存保障の管理は描画命令を発行時
  10. 10. 描画命令のリソース構成 •複数のリソースから構成 • セットアップコストが高い • リソースの収集 • 収集したリソースに保障フレームの更新 • インゲーム中は大量の描画命令 • セットアップコストは無視できない Draw VertexBuffer IndexBuffer Texture… Sampler… ConstantBuffer… RenderTargetView DepthStencilView
  11. 11. 描画命令のリソースの再利用 •経験的に描画命令は、前回の描画時と大差がない • メッシュの描画 • 毎回ほとんど同じ組み合わせのリソースを送る • 更新されるのはリソースの中身で、ハンドルは固定 • パーティクルの描画 • 使用するリソースは事前に決まっている •前回と同じとして再利用 • CPUのパフォーマンスを向上
  12. 12. リソースの拡張 • リソースを意味のある単位に集約 • 初期化時に作成 • 複数フレームで再利用 • 内部のリソースの管理 • 作成時 所持するリソースの参照カウンタのみを 作成時に更新 • 解放時 保障を所持するリソースに反映 • 更新チェックは劇手に低下 • 実行時作成 • PipelineResourceTable • 実行時に必要なものが決定されるため • 再利用で描画コストを削減 TargetState Viewports RTVs DSV GeometryState VertexBuffer IndexBuffer PipelineState Shader Binary GPU States PipelineResourceTable Constant Buffers ShaderResourceViews UnorderedAccessViews Samplers
  13. 13. 送信する描画リソース •Draw命令なら、4つのリソース Draw TargetState PipelineState PipelineResourceTable GeometryState 頂点数など Draw VertexBuffer IndexBuffer Texture… Sampler… ConstantBuffer… RenderTargetView DepthStencilView
  14. 14. 中間描画命令のマルチスレッド • ネイティブ描画命令は中間描画命令の優先順に実行 • 中間描画命令の発行は、実際の描画と分離が可能 • 半透明と不透明の命令の実行 スレッド0 スレッド1 不透明 半透明 不透明 半透明 不透明半透明 不透明 不透明 半透明不透明 半透明 半透明 中間描画命令 ソート後の命令
  15. 15. 中間描画命令のマルチスレッド •優先順位の応用例 • 描画順番の最適化 • EarlyZを効かせるための、手前順の描画 • 半透明の整合性のための、奥順番の描画 • データのコピータイミングの制御 • コンピュートシェーダの依存リソースの調整 • チェック処理の遅延
  16. 16. コンピュートシェーダの依存リソースの調整 • CSでUAVとSRVがピンポンする箇所はストール • GPUソートや、シミュレーションなどで問題 • 依存したリソースが連続処理しないように優先順位を調整 • 回避するために、他のCSと混ぜて動かす スレッド0 スレッド1 Priority 0 BufA 書き出し Priority 0 BufB 読み込み Priority 1 BufB書き込み 中間描画命令 ソート後の命令 BufA 読み込み BufB 読み込み BufA 書き出し BufB 書き込み Priority 1 BufA読み込み
  17. 17. マルチスレッド •実際のエンジンの動作 •3段階の構成 ライトやメッ シュの情報更新 描画パスの構築 描画処理
  18. 18. ライトやメッシュの情報更新 •マルチスレッドで実際の描画を行う前の前処理 •ライト • 影を落とすかの判定し、描画パスの登録/解除 • 影のキャッシュの更新の可否 •メッシュ • 詳しくは後半に!
  19. 19. 描画パスの構築 • 現在のフレームで利用する描画パスの収集 • GBuffer, • DeferredLighting • ShadowCast • PostProcess • Etc…. • 描画パスの構築は、シングルで動作 • 優先順位の最上位の値(LayerId)を作成 • 後続の描画処理は、パスの優先順位を利用することで、正確な描画タ イミングを作り出せる • 描画パスが発行する描画命令は、マルチスレッド • 描画パス先頭で行う画面のクリアやコピーなど
  20. 20. 描画処理 •マルチスレッドで処理 • 個々の描画処理は相互依存しない 描画が依存するのは、描画リソースと描画パス(優先順位) • 各描画処理が収集した描画パスから中間描画命令を作成
  21. 21. 命令のキャプチャとプレイ • 一度作った描画命令を再利用 メモリの設定なども省けるため最速 • 使用例 シャドウキャストメッシュ、ポストプロセス • キャプチャとプレイの制約 描画パスに依存したリソースは、別の描画パスで使用不可能 • ローカルなコンスタントバッファをエンジンが持つグローバル化コン スタントバッファに変えるなど • 例 CameraConstantBufferはシーンに一つしかない など・・・
  22. 22. レンダリングパイプライン 中間描画命令 描画命令の ソート ネイティブ描 画命令
  23. 23. ソート •正しい命令順番に並び替える • 安定したソートを使用 • 同一優先順位、同一スレッドの描画命令は発行順番を維持 •並び替えはマルチスレッド スレッド0 スレッド1 不透明 半透明 不透明 半透明 不透明半透明 不透明 不透明 半透明不透明 半透明 半透明 中間描画命令 ソート後の命令
  24. 24. レンダリングパイプライン 中間描画命令 描画命令の ソート ネイティブ描 画命令
  25. 25. ネイティブ描画命令 •中間描画命令をグラフィックスAPIに渡す • DirectX11,DirectX12, Mantle, etc… •マルチスレッドで作成 ゲーム処理 ネイティブ描画コマンド0 メインスレッド レンダリングスレッド0 ネイティブ描画コマンドn レンダリングスレッドN セットアップ
  26. 26. リソースからネイティブ描画命令を支援 •再利用可能な処理は事前に最適化 • 中間描画命令を作成する段階で必要な情報を収集 プラットフォームによって実装が異なる • DX11ならリソースの単純な配列化 • DX12ならdescriptor tableの構築 • リソースを使いまわすことを前提に設計
  27. 27. リソースからネイティブ描画命令を支援 • 更新頻度でリソースの処理を分離 • 更新される可能性があるリソース • ConstantBuffer • 位置情報やカメラ情報など細かな単位の更新に使用されており、ハンド ルが可変なため • プラットフォームによりけり実装が異なる • Texture • ストリーミングテクスチャなどで、ハンドルが可変なため • 更新されないリソース • RWTexture,Buffer,RWBuffer,Sampler • ネイティブ描画命令の作成の際、CB,Textureのみ収集
  28. 28. ここまでのまとめ •マルチスレッドの描画命令の作成 •リソースの集約と再利用 •よりパフォーマンスアップするためには?
  29. 29. メッシュレンダラの目標 •従来よりも多くのジオメトリを高速に処理する • 描画コール数の削減 • 効果的なカリング • GPUによるCPU負荷の肩代わり • CPU SIMDの活用 • CPU,GPUキャッシュフレンドリ
  30. 30. 新しいエンジンとしての課題 •汎用設計でも高い性能 •拡張性を閉ざさない •マルチプラットフォーム • 最新のAPIに対応できるキャパシティ • Mantle, DirectX12, etc… • 下はDirectX11世代までを考慮 •ゼロドライバオーバーヘッド[1] への挑戦
  31. 31. メッシュレンダラの取り組み •描画API の Indirect 化 • すべてのメッシュが Indirect 命令による描画 •描画コールの削減 • Multi-Draw, Instancing • マージメッシュ •GPUカリング
  32. 32. 描画API の Indirect 化
  33. 33. Indirect 命令とは •描画 API 引数をGPUのバッファで指定 • GPUから引数制御が可能 • 引数データがCPU側の場合GPUへの転送が必要 • バッファのオフセットはCPUから指定 void DrawIndexedInstanced( uint IndexCountPerInstance, uint InstanceCount, uint StartIndexLocation, uint BaseVertexLocation, uint StartInstanceLocation); void DrawIndexedInstancedIndirect( ID3D11Buffer* pBufferForArgs, uint AlignedByteOffsetForArgs);
  34. 34. Indirect 命令のための引数 •ジオメトリ描画のためのデータ(20byte) •このデータの管理に注力 struct DrawIndexedInstancedArgs { uint IndexCountPerInstance; uint InstanceCount; uint StartIndexLocation; uint BaseVertexLocation; uint StartInstanceLocation; };
  35. 35. Indirect 引数の管理 •VRAMの一部領域を割り当て • 割り当てた領域をさらにアロケーターで管理 • 単一リソースとすることでCSアクセスを容易に •バッファ使用戦略 • メッシュ単位でLOD、影モデル含めた情報を転送 • LOD切替時はバッファオフセットを変更 • メッシュ状態(パーツ等)の切替時は再転送
  36. 36. Mesh 0 Mesh 3 Mesh 2 Mesh 4 Indirect 引数のメモリ使用図 LOD0 LOD1 LOD2 影LOD0 Mat A Mat A Mat B Mat B Mat C Mat A Mat B Mat B Mat D Mat E DrawIndexedInstancedArgs VRAM
  37. 37. Indirect 命令は使えるか •CPU負荷に大きな変化は無い? • PCの場合はドライバ実装による(遅くなることも?) • バッファ管理のオーバーヘッド •ポテンシャル • Multi-Draw の使用 • GPU駆動のメッシュ描画パイプライン[2]
  38. 38. 描画コールの削減
  39. 39. Multi-Draw API とは •複数の Indirect 描画を一度の描画コールで実行 •DirectX12, OpenGL4.3, 拡張DirectX11[2]は 同様の機能が使用可能 void DrawIndexedInstancedIndirect( ID3D11Buffer* pBufferForArgs, uint AlignedByteOffsetForArgs); void MultiDrawIndexedInstancedIndirect ( ID3D11Buffer* pBufferForArgs, uint AlignedByteOffsetForArgs, uint ArgsCount); ※こんなAPIは存在しません
  40. 40. メッシュ描画の素朴な実装 Mesh 1 Material A Material B Material B Material C Mesh 2 Material B Material B Material B Material C Material D Material D 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール
  41. 41. Multi-Draw を使用した実装 Mesh 1 Material A Material B Material B Material C Mesh 2 Material B Material B Material B Material C Material D Material D 描画コール 描画コール 描画コール 描画コール 描画コール 描画コール DrawIndexedInstancedArgs
  42. 42. Multi-Draw は使えるか •対応プラットフォームの問題 • DirectX11では複数のIndirect命令に置き換え •Indirect命令を使用するのであれば必ず考えるべき • 描画コールをシンプルに削減可能
  43. 43. Instancing に関して •同一描画可能インスタンスをハッシュマップ管理 • 自動 Instancing • CPUカリング後のインスタンス数をGPUへ • Indirect バッファの InstanceCount を CS で制御 •インスタンス情報のバッファ化 • CBからStructuredBufferへ変更 インスタンス情報 World Matrix Previous World Matrix Joint Offset Previous Joint Offset Shader Parameters
  44. 44. インスタンス情報の管理 •レンダラが全インスタンス情報を管理 • メッシュ固有オフセットと SV_InstanceID で引く 2 インスタンス情報 へのインデックス インスタンス情報 SV_InstanceID 8 1 0 5 3 12 7 13 15 11 … オフセット 0 1 2 3
  45. 45. マージメッシュの検証 •Multi-Draw によりジオメトリ描画が柔軟に • メッシュを跨いだ描画コールのマージも可能では? •20byteの Indirect 引数を連結していく • 必要なリソースの結合 • StartIndexLocation, BaseVertexLocation の再計算 • StartInstanceLocation で何番目のバッファかを指定
  46. 46. マージメッシュの実装? Mesh 1 Material A Material B Material B Material C Mesh 2 Material B Material B Material B Material C Material D Material D 描画コール 描画コール 描画コール 描画コール DrawIndexedInstancedArgs
  47. 47. Instancing, マージメッシュの課題 •描画コールは減るがオーバードロー負荷が目立つ • ピクセル負荷の高いものは致命的 • CPUとGPU負荷のトレードオフ • シーンによって効果的かどうかの選択が必要 •実装コストに結果が見合うのか? • 特にマージメッシュはリソースの結合が必要 • VB, IB, CB, Texture, etc… • Bindless Texture の使用
  48. 48. マージメッシュは使えるか •マテリアルがユーザーメイドのエンジンでは大変 •リソースの制約等の要件を満たすメッシュは… →シャドウマップ描画! •描画不具合時のデバッグが難しくなる?
  49. 49. GPU カリング
  50. 50. エンジン層アプリケーション層 新しいエンジン初期のカリングの流れ •カリングはすべてCPU処理 疎粒度な シーンカリング フラスタムカリング & 微小面積カリング 中間描画命令
  51. 51. カリング処理の再考 •フラスタムカリング • それなりのCPU負荷 • GPUの方が得意そうな処理? •オクルージョンカリング • 高速なCPU処理の実装難度が高い • GPUの方が得意そうな処理?
  52. 52. GPU駆動のカリングへ •理想 • CPUのコストをGPUへオフロード • メッシュはすべてGPUへ素通し、GPUでカリング •現実 • 中間描画命令の肥大化、大量の描画コール • データのGPUへのコピーコスト増
  53. 53. オクルージョンカリングの導入 •アルゴリズムはHiZを利用したものを使用[4] •GBufferへの描画対象メッシュのみ • ライトのPreZ処理は無い •Gbufferパスの前までにCSで実行 •同一フレームのGPUで処理するため遅延無し
  54. 54. GPUオクルージョンカリングの流れ •PreZでHiZを作成 • これはライトカリング等でも利用 •GBufferパスの頂点、ピクセル負荷を下げる PreZ Pass 1. 遮蔽物による Z の作成 2. Z から HiZ を作成 GBuffer Pass インスタンス数 0 であれば 描画されない Occlusion Culling Pass HiZ と対象オブジェクトAABBで 遮蔽テスト、Indirect 引数のイ ンスタンス数をデクリメント GPU処理フロー
  55. 55. GPUオクルージョンカリングは使えるか •カリング処理によるGPU負荷増 • 主にジオメトリの頂点負荷とのトレードオフ • GPUへのデータ転送負荷は最小限に •描画コールの数は減らない • CPUで遮蔽情報をリードする必要がある
  56. 56. GPUフラスタムカリングの検証 •CPUでカリングしないため中間描画命令が増加 • マージメッシュを使ったシャドウマップ描画への適用 Shadow Cast Pass インスタンス数 0 であれば 描画されない Frustum Culling Pass ライトフラスタムと対象オブ ジェクトAABBで遮蔽テスト Indirect 引数のインスタンス数 をインクリメント DrawIndexedInstancedArgs フラスタム0 フラスタム1 フラスタム2 フラスタム3 GPU処理フロー
  57. 57. GPUカリングは使えるか •CPU, GPUでのカリング処理のオーバーヘッドが 大きくなってしまうと意味がない •CSカリングによるGPU負荷の増加 • 非同期コンピュートで負荷を隠蔽できるか?
  58. 58. GPUカリングの展望 •フレーム遅延無しでのCPUオクルージョンクエリ • 非同期コンピュートラスタライザ • CPU, GPU負荷双方の削減可能性
  59. 59. メッシュレンダラのまとめ •エンジンで搭載されているもの • Multi-Draw, Instancing • GPU オクルージョンカリング •エンジン搭載を検証中のもの • マージメッシュ(シャドウマップ描画) • GPU フラスタムカリング(シャドウマップ描画)
  60. 60. ライトカリング
  61. 61. 2段階のアプローチ •GPU上でのオクルージョンカリング • PreZで作られた深度を利用 • フレーム遅延 •描画時のライトカリング • GBufferで作られた深度からHiZを作成 • CSで実行
  62. 62. よりよいスポットライトのカリング
  63. 63. ライトカリング
  64. 64. 実装 •従来の視線をFrustumからView空間のAABBへ •ConeをAABBからView空間のFrustumへ • 対象物を逆にすることで適切なカリングが可能
  65. 65. まとめと課題 •利点 • ライトの照明範囲を任意の凸包体で表現可能 •問題点 • 視推台をAABBにすることで誤った判定が発生
  66. 66. References 1. Approaching Zero Driver Overhead in OpenGL http://gdcvault.com/play/1020791/ 2. GPU-Driven Rendering Pipelines http://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_com bined_final_footer_220dpi.pdf 3. AMD GPU Services (AGS) Library http://gpuopen.com/gaming-product/amd-gpu-services-ags-library/ 4. Practical, Dynamic Visibility for Games http://blog.selfshadow.com/publications/practical-visibility/ 5. Practical Clustered Shading http://www.humus.name/Articles/PracticalClusteredShading.pdf

×