direct3d 12 summary
DESCRIPTION
Direct3D 12の概要をまとめたスライドです。TRANSCRIPT
Direct3D 12 Summary
@shobomaru, 2014/09/07 v0.1
はじめに
• Direct3D 12の情報を現時点で可能な限り集めてみた
• 最終的な仕様は変更される可能性がある
• すべての情報は最終スライドに記載したリンクから集めた
• Microsoftの講演動画と、それを元に説明しているIntelのブログが主
• ただし英訳が怪しいので誤った情報を書いているかもしれない
2
Direct3D 11
• 層の厚いAPI
• GPUやドライバからの乖離
• 1つのスレッドに負荷が集中
3
Direct3D 12
• ゲーム機に近いローレベルAPI
• 少ないCPUオーバーヘッド
• ハードウェアとの直接対応
• マルチスレッド効率の改善
4
新しい概念
• Pipeline State Object (PSO)
• Barrier & Fence
• Command Lists & Bundles
• Descriptor Tables & Heaps
• Dynamic Heaps
5
Pipeline State Object (PSO)
• GPUの状態に対応する各種パラメータをひとつに纏めたもの。
• Input Assemblerから各種シェーダ、Output Managerまでをひとつのオブジェクトにする。
• 固定機能ステート(ビューポートやシザー矩形等)はPSOに入らない。
6
PSO
7
Pipeline State Object
Input Assembler
Vertex Shader
Hull Shader
Tessellator
Rasterizer
Domain Shader
Geometry Shader
Pixel Shader
Output Merger
GPU Memory
Non-PSO State
PSOの利点
• 最近のGPUは、複数の状態をひとつに統合することがある。• 例:Pixel ShaderとOutput Manager
• Direct3D 11のAPIは分離されているので、ドライバは状態の確定を待ってから解決しなければならない。
• PSOは一度生成したら変更できないので、直ちに統合してGPUネイティブ命令に変換することができ、オーバーヘッドを削減できる。• 描画時には、PSOからHW Stateへコピーするだけ。
• PSOは使いまわしが可能なので、2回目以降の同じ描画では生成コストがゼロ。
8
PSOに属するものと属さないもの
PSOに属する
• シェーダ
• VS/HS/TS/DS/GS/PS
• ブレンドステート
• ラスタライズステート
• 深度ステンシルステート
• 入力レイアウト
• 入力アセンブリのトポロジーの種類
• 三角形、線、点、パッチ
• レンダーターゲットと深度ステンシルのプロパティ
• フォーマット
• サンプル数
PSOに属さない
• リソースバインディング
• ビューポート
• シザー矩形
• ブレンドファクター
• 深度テスト
• ステンシルリファレンス
• 入力アセンブリのトポロジーの並び
• リスト、ストリップ、隣接リスト、隣接ストリップ
9
リソースのハザード問題
• レンダリング結果をテクスチャとして使う状況を考える。
• 例:環境マップ、シャドウマップ
• このとき、GPUはレンダリングが完了するまで次の描画を止め、キャッシュをフラッシュを待つ必要がある。でなければ、描画途中のものをテクスチャにしてしまう。
• このような同期待ちのために、SRVやRTV等を一つ一つ追跡すると、ドライバとランタイム両方のCPU負荷が大きくなる。
10
Barrier
• アプリケーションが、どのリソース(サブリソース)が何の用途から何の用途へ遷移するかを指定することで、同期を取る。
• 複数のリソースを一度に同期するこも可能。
11
D3D12_RESOURCE_BARRIER_DESC Desc;
Desc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
Desc.Transition.pResource = pRTTexture;
Desc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
Desc.Transition.StateBefore = D3D12_RESOURCE_USAGE_RENDER_TARGET;
Desc.Transition.StateAfter = D3D12_RESOURCE_USAGE_PIXEL_SHADER_RESOURCE;
pContext->ResourceBarrier( 1, &Desc );
Barrierの種類
• 遷移 (Transition)
• RTVやDSVからSRVへの遷移など
• 別名 (Aliasing)
• タイルリソース(Direct3D 11.2+)で使用
• UAV
12
リソースの生存時間問題とFence
• Direct3D 11以前は、APIコールされた直後に処理を開始するのではなく、コマンドキューに溜める。• コマンドキューが消費されるまでリソースを保持しなければならず、参照カウントと状態追跡にCPU時間を消費する。
• Direct3D 12では、そのキューの中身を隠さない。• アプリケーションは、非同期ファイルIOに似た処理となる。
• CPUがGPUの進捗を知ることができる、細粒度Fence APIを追加。• GPUがCommand Queueのセーフポイントに達したら、アプリケーションがリソース破棄・生成することができる。
• リソース破棄は即座に行われるので、アプリケーションが管理しなければならない。
13
リソースの常駐管理・状態反映の削減
• 調査中…
14
冗長なリソースバインドの削減
• Direct3D 11では、Viewを各シェーダのスロットにバインドする。
• この仕様は最近のGPUに合っておらず、アプリケーションが別のリソースを使って描画しようとすると再バインドが必要になり、CPUを消費する。
• Direct3D 12では、GPUネイティブのリソース記述を直接メモリに書き出す、ある種のバインドレスレンダリングを使う。
15
Descriptor
• Direct3D 11「ビュー」のハードウェア相当
• リソースパラメータを定義したメモリ上の小さなチャンク
• 一切の余計なメモリ確保がなく、OSの生存時間管理外
• Direct3D 11では、再バインドの度にGPUへコピーし直していた
16
Descriptor{TypeFormat Mip CountpData
}
Descriptor Heaps
• Descriptorを順にまとめた配列
• レイアウトはアプリケーションが定義
• フレームを跨いだ使いまわしが可能
• Heapの容量はGPUアーキテクチャに依存
• 古いGPUや低消費電力GPUで65K
• Heapの切り替えは高コスト
17
GPU Memory
Desc
rip
tor
Heap
Descriptor Tables
• Descriptor HeapにあるDescriptorと、各シェーダステージが要求するスロット番号とインデックスに紐づける
• シェーダに複数のTableを設定できるが、古いGPUは非サポート
• Descriptor Tableの差し替えは非常に低コスト
• Heapにハードウェア固有記述データが入っているため
18
Start IndexSize
Descriptor Heaps & Tables
• Direct3D 12の全体像は次のようになる
19
Pipeline State Object
Input Assembler
Vertex Shader
Hull Shader
Tessellator
Rasterizer
Domain Shader
Geometry Shader
Pixel Shader
Output Merger
GPU Memory
Non-PSO State
Descriptor Tableの使用例
• ある頂点シェーダにTableを設定するとき…
• 1回目の描画では、TableにHeapのオフセット20から32まで指し示す。
• 2回目の描画では、TableにHeapのオフセット32から40まで指し示す。
• G-Bufferを解決するピクセルシェーダにTableを設定するとき…
• シェーダではマテリアルIDで動的にTableのインデックスを指定
• Tableに種類別マテリアルをまとめて設定
20
Descriptor TablesによるHLSLの対応付け
21
// Two fixed 8-element array at SRV table 2, offset 3,
and SRV table 4, offset 2
Texture2D texA[8] : register(t3, 2);
Texture2D texB[8] : register(t2, 4);
// Fixed 2-element array at Sampler table 1 offset 0
SamplerState sam[2] : register(s0, 1);
// Fixed 4-element array at CB table 2 offset 0
struct MyCBufferType
{
float foo;
float bar;
};
cbuffer MyCBufferType buf[4] : register(c0, 2);
float4 main(
uint i1 : INDEX1,
uint i2 : INDEX2,
float2 coord : TEXCOORD) : SV_TARGET
{
MyCBufferType b = buf[i1];
// CBuffer table 2 element #(i1)
SamplerState s = sam[i1];
// Sampler table 1 element #(i1)
Texture2D tA = texA[i1];
// SRV table 2 element #(i1+3)
Texture2D tB = texB[i2];
// SRV table 4 element #(i2+2)
float4 colorA = tA.Sample(s, coord);
float4 colorB = tB.Sample(s, coord);
return colorA * b.foo + colorB * b.bar;
}
描画コマンドの高速化
• Direct3D 11では、すべてのコマンドがImmediate Contextを通して実行される。
• マルチスレッドに適応したDeffered Contextもあるが、ハードウェアに完全に対応しておらず、あまり並列に実行できない。
• Direct3D 12では、Command ListとBundleを使う。
• Immediate Contextは廃止
22
Command List
• 描画に必要なコマンドを記録したもの
• PSOのように、実行に必要なGPUの情報をそのまま持っている
• 一度のみの使用に最適化されている
• 複数回使う描画には後述のBundleを使う
• Command ListをCommand Queueにサブミットすることで実行される
• WDDM 2.0ではキュー送信のコストが削減される
23
Bundle
• 小さなコマンドリスト
• 一度だけコマンドを記録でき、Command Listから何度でも使用可能
• Descriptor Tableが異なれば、同じBundleでも描画結果は変わる
• マルチスレッドで生成可能
24
Command List & Bundle
25
Command Queue
Execute Command List 1
Execute Command List 2
Signal Fence
Command List 1
Clear
SetTable
Execute Bundle A
SetTable
Draw
SetPSO
Draw
Command List 2
Clear
Dispatch
SetTable
Execute Bundle A
SetTable
Execute Bundle B
Bundleを使った例:2つのモデルの描画
26
// Create bundle
pDevice->CreateCommandList(D3D12_COMMAND_LIST_TYPE_BUNDLE, pBundleAllocator, pPSO, pDescriptorHeap, &pBundle);
// Record commands
pBundle->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
pBundle->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
pBundle->DrawInstanced(6, 1, 0, 0);
pBundle->SetShaderResourceViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
pBundle->DrawInstanced(6, 1, 6, 0);
pBundle->Close();
// Setup
pContext->SetPipelineState(pPSO);
pContext->SetRenderTargetViewTable(0, 1, FALSE, 0);
pContext->SetVertexBufferTable(0, 1);
// Draw 1 and 2
pContext->SetConstantBufferViewTable(D3D12_SHADER_STAGE_PIXEL, 0, 1);
pContext->ExecuteBundle(pBundle);
pContext->SetConstantBufferViewTable(D3D12_SHADER_STAGE_PIXEL, 1, 1);
pContext->ExecuteBundle(pBundle);
Dynamic Heaps
• D3D 11のバッファは型付き
• Vertex Buffer, Constant Buffer, Index Buffer, etc.
• D3D 12には型の概念がない
• 必要な容量を指定してアロケータからチャンクを取得する
• 必要なら一括確保したメモリを切り出して使うことができる
• アライメントが標準化されていて、CPUやGPUに依存しない
• メモリアドレスがCPUから常に見えている
27
Dynamic Heapsとリソースリネーミング
• D3D 11のようなリソースリネーミングの仕組みがない
• Dynamicバッファを生成し、2つのスレッドからMapDiscardするとリソースハザードが発生し、ドライバが正しいバッファの情報を片方のスレッドにパッチしなければならなかった
• D3D 12は、Dynamicバッファがない
• リネームの責任がアプリ側にある
28
Direct3D 12の新しい機能
• プログラマブルブレンド
• ピクセルシェーダでの順序依存のUAV読み書き
• OIT(描画順に依存しないピクセル単位の半透明描画)を実現可能
• コンサバティブラスタライズ• ピクセルの中心ポイントで判定するのではなく、ピクセル矩形の一部に入り込んだものをラスタライズする
• GPUベースのカリングや当たり判定の精度、SVO-GIの効率改善
• LDRのASTC圧縮とJPEG圧縮リソース
• スウィズルリソースへのアクセス
29
Q&A
• Q:Direct3D 11との互換性は?
• A:ない。
• Q:対応GPUは?
• A:NVIDIA Fermi世代以降、AMD Southern Islands世代以降、Intel Haswell世代以降(Iris Proシリーズのみ)、Snapdragon(世代不明)はメーカーが対応を公言。
• Q:対応OSは?
• A:Windows 7以降、Windows Phone、Xbox One。
• Q:登場時期は?
• A:2015年末、2014年後半にベータ版を公開。
30
参考文献
• Direct3D 12 API Preview (Microsoft)
• DirectX 12 (Microsoft)
• Direct3D 12 Overview (Intel)
• DirectX 12,ついに発表。その特徴に迫る (4Gamer)
31