DirectX 12の仕様について個人的にまとめたものです。内容には間違いが含まれている場合があります。
概要
- DX12を使うならDXGIは1.4以上を必要とする?
DXGIのバージョン
- 1.4 : WDDM 2.0 / Windows 10
IDXGIAdapter3,IDXGIFactory4,IDXGIOutput4,IDXGISwapChain3を新たに定義- Direct3D 12に従って実装を軽量化
- 利用できるビデオメモリ量が確認可能に
- バックバッファのインデックスが不変に
- multi-adapterに対応
DXGI_SWAP_EFFECT_FLIP_DISCARD,DXGI_SWAP_EFFECT_FLIP_SEQUENTIALをサポートSetFullscreenStateでフルスクリーンにしてもOS要素が上に来ることを可能に
- 1.5 : WDDM 2.1 / Windows 10 (version 1607)
IDXGIDevice4,IDXGIFactory5,IDXGIOutput5,IDXGISwapChain4を新たに定義- HDR10に対応
- 可変リフレッシュレートに対応
- 1.6 : WDDM 2.2+ / Windows 10 (version 1703~)
- HDRディスプレイの識別が可能に (version 1703)
DXGI_ADAPTER_FLAG3に同期に関するフラグを追加 (version 1709)- 指定の特性を持つadapterを優先的に列挙する関数を追加 (version 1803)
- adapter enumeration stateの変化を検知できるように (version 1809)
処理の流れ
初期化
CreateDXGIFactoryでIDXGIFactoryを生成- 要件を満たすディスプレイを探す
IDXGIFactory::EnumAdaptersなどでIDXGIAdapterを列挙IDXGIAdapter::EnumOutputsでIDXGIOutputを列挙
D3D12CreateDeviceでID3D12Deviceを生成- デバイスが要件を満たすか確認
ID3D12Device::CheckFeatureSupportで機能の情報を取得
ID3D12Device::CreateCommandQueueでDIRECTキューを生成IDXGIFactory2::CreateSwapChainForCoreWindowなどでIDXGISwapChainを生成IDXGISwapChain::GetBufferでバックバッファのID3D12Resourceを取得
前準備
ID3D12CommandAllocatorを生成ID3D12CommandListを生成
描画
- SwapChainに関係のないコマンドを記録
- SwapChainに関係のあるコマンドを記録
IDXGISwapChain3::GetCurrentBackBufferIndexで対象のバックバッファ番号を取得
- コマンドリストを実行
IDXGISwapChain::Presentでバックバッファを画面に表示
ID3D12Device
- すべてのメソッドがfree-threaded [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
Feature Level
ID3D12CommandQueue
- すべてのメソッドがfree-threaded [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
- ExecuteCommandListsで送り出されるコマンドリストが実行中ではないことを保証する必要がある [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
Type
- DIRECT :
ID3D12CommandAllocator
- ID3DCommandListと異なり、Resetを呼び出すときにそれで記録されたコマンドリストが実行中であってはいけない (Microsoft Learn)
- 記録中のCommandListから利用されるのは同時に1つだけ (Microsoft Learn)
ID3D12CommandList
- メソッドはfree-threadedではない [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
- ID3D12CommandAllocatorと異なり、それが実行中でもResetできる (Microsoft Learn)
- 記録中のCommandListに使われているCommandAllocatorでResetすることはできない (Microsoft Learn)
- 各コマンドの妥当性はCloseの呼び出し時に検証される (Microsoft Learn)
IDXGISwapChain
- 各機能の対応非対応は
ID3D12Device::CheckFeatureSupportで確認する (Microsoft Learn)
Format
- Feature level ≥ 9.1:
- R8G8B8A8_UNORM
- R8G8B8A8_UNORM_SRGB
- B8G8R8A8_UNORM
- B8G8R8A8_UNORM_SRGB
- Feature level ≥ 10.0:
- R16G16B16A16_FLOAT
- R10G10B10A2_UNORM
- Feature level ≥ 11.0:
- R10G10B10_XR_BIAS_A2_UNORM
Multi-sampling
- D3D12はバックバッファのマルチサンプリングに対応しない (Microsoft Learn)
Buffer Count
- いずれか1つは常に画面表示で使われているので、バックバッファとして使えるのは(BufferCount-1)になると考える [Intel Developer Zone 20162016. Sample Application for Direct3D 12 Flip Model Swap Chains. Intel Developer Zone. https://www.intel.com/content/www/us/en/developer/articles/code-sample/sample-application-for-direct3d-12-flip-model-swap-chains.html.]
Swap Effect
- D3D12はDISCARDとSEQUENTIALに対応しない (Microsoft Learn)
- FLIP_DISCARDは内容を保持しないので、全体を毎フレーム書き換えるときに用いる (Microsoft Learn)
- FLIP_SEQUENTIALは内容を保持するので、同じ内容の部分を再利用したいときに用いる (Microsoft Learn)
Frame Latency
- FLAG_FRAME_LATENCY_WAITABLE_OBJECTを立てると、レイテンシを制御できるようになる (Microsoft Learn)
- Presentを管理するキューの大きさが
IDXGISwapChain2::SetMaximumFrameLatencyで指定できる- キューに空きがあれば、次のVBlankを待たずに返ってくる
- キューに空きがあるかどうかを確認するためのオブジェクトが
IDXGISwapChain2::GetFrameLatencyWaitableObjectで取得できる- キューに空きができるのを待つ合間に別の処理を行うことができる
- Presentを管理するキューの大きさが
- ⇒ 効率的な処理ができるようになる
- オフスクリーンレンダリングを行い、のちにバックバッファへコピーする方法 [NVIDIA Developer 20162016. DX12 Do's and Don'ts. NVIDIA Developer. https://developer.nvidia.com/dx12-dos-and-donts.]
- バックバッファが利用不可であれば、VBlankを待たずに結果を破棄することもできる
- そのままバックバッファにレンダリングする方法 [NVIDIA Developer 20162016. DX12 Do's and Don'ts. NVIDIA Developer. https://developer.nvidia.com/dx12-dos-and-donts.]
- BufferCount ≥ (Maximum Frame Latency + 1)であれば、常にバックバッファが利用可能になる
- レイテンシーを小さくする方法 [Intel Developer Zone 20162016. Sample Application for Direct3D 12 Flip Model Swap Chains. Intel Developer Zone. https://www.intel.com/content/www/us/en/developer/articles/code-sample/sample-application-for-direct3d-12-flip-model-swap-chains.html.]
- WaitableObjectがシグナルしてから入力を受け取る
- Presentでブロックされなくなるので、その分のレイテンシを減らせる
- オフスクリーンレンダリングを行い、のちにバックバッファへコピーする方法 [NVIDIA Developer 20162016. DX12 Do's and Don'ts. NVIDIA Developer. https://developer.nvidia.com/dx12-dos-and-donts.]
Tearing Support
Present()
- メインスレッド以外でも問題なく呼び出せる (Microsoft Learn)
- 並列には呼び出せないので、単一のスレッドで行う
- 内部でメッセージを送ることがあるため、UIスレッドとデッドロックしないように注意する必要がある
GetBuffer()
- バックバッファの
ID3D12Resourceを取得する - スワップチェインをリサイズするまで有効 (Microsoft Learn)
GetCurrentBackBufferIndex()
- Presentすると+1され、BufferCountで1周する?
バリア
- サブリソースごとよりもリソース全体でステートを追跡したほうが効率が良い [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCESを使う
ステート
- やりたいことに合わせてステートを遷移させる (Microsoft Learn)
- 読み込み系
- VERTEX_AND_CONSTANT_BUFFER:頂点バッファ、CBV
- INDEX_BUFFER:インデックスバッファ
- NON_PIXEL_SHADER_RESOURCE:ピクセルシェーダ以外でのSRV
- PIXEL_SHADER_RESOURCE:ピクセルシェーダでのSRV
- INDIRECT_ARGUMENT:Draw*Indirectの引数、SetPredicationの引数
- DEPTH_READ:DSVの読み込み
- COPY_SOURCE:Copy元
- RESOLVE_SOURCE:Resolve元
- 書き込み系
- RENDER_TARGET:RTV、ClearRenderTargetViewの対象
- UNOREDRED_ACCESS:UAV、ClearUnorderedAccessViewの対象
- DEPTH_WRITE:DSVの書き込み、ClearDepthStencilViewの対象
- STREAM_OUT:Stream Outputの対象
- COPY_DEST:Copy先
- RESOLVE_DEST:Resolve先
- 書き込み系フラグは最大で1つ
- 読み込み系フラグはいくつでもOK
- 書き込み系フラグを立てたら、読み込み系フラグを立ててはいけない
- 読み込み系
- 初期化時のステートはDEFAULTでは任意に設定できる (Microsoft Learn)
- UPLOADはGENERIC_READにセットする
- READBACKはCOPY_DESTにセットする
- PresentされるバックバッファはCOMMONにする必要がある (Microsoft Learn)
- PRESENTフラグはCOMMONと同値
- 間に別処理が挟まるときなどにバリアの分割を行う [DirectX-Specs 20202020. D3D12 CPU Efficiency. DirectX-Specs. https://microsoft.github.io/DirectX-Specs/d3d/CPUEfficiency.html.]
- 例えば、シャドウマップの書き込み終わりにDSV→SRVをBEGIN_ONLYでバリアを置いて、シェーディング開始前にDSV→SRVをEND_ONLYでバリアを置く
- ドライバに書き込み終了タイミングを知らせることで、後のバリアの効率を向上する
暗黙的なステート遷移
- COMMONステートはアクセス時に関連するステートに昇格する (Microsoft Learn)
- 読み込み系フラグのみであればいくつでも追加できる
- この状態では、書き込み系への遷移は明示的に行う必要がある
- 書き込み系フラグは最初に1回だけ
- この状態では、次回の遷移は明示的に行う必要がある
- バッファやSIMULTANEOUS_ACCESSなテクスチャはすべてのステートに遷移可能
- SIMULTANEOUS_ACCESSでないテクスチャはSRV系やCOPY系ステートにのみ遷移可能
- 読み込み系フラグのみであればいくつでも追加できる
- 特定の条件を満たすとExecuteCommandListsの呼び出し後にステートがCOMMONに降格する (Microsoft Learn)
- コピーキューでアクセスしたリソース
- 任意のキューでアクセスしたバッファやSIMULTANEOUS_ACCESSなテクスチャ
- 読み込み系ステートにpromoteされたリソース
バージョンによる差異
ID3D12Device
- ID3D12Device:
- ID3D12Device1: Windows 10 Anniversary Update (1607) で追加
- PipelineLibrary(PSOのキャッシュデータベース)
- 複数のフェンスのシグナルを、1つのイベントで受け取れる
- Pageableのresidencyに優先順位を付与できる
- ID3D12Device2: Windows 10 Creators Update (1703) で追加
- Descの必要な部分だけを集めたバイトストリームでPipelineStateを作れる
- ID3D12Device3: Windows 10 Fall Creators Update (1709) で追加
- GPUが落ちても生存する診断用Heapを作れる
- 非同期版MakeResident
- ID3D12Device4: (1803) で追加
- closed状態のCommandListを生成できる(生成時にCommandAllocatorが不要)
- メモリ保護(アクセス可能なリソース群を設定できる)
- リソースのメモリ割当に関する情報としてオフセット値を追加で取得できる
- ID3D12Device5: (1809) で追加
- MetaCommand
- State Object
- SUSPENDED
ID3D12GraphicsCommandList
- ID3D12GraphicsCommandList:
- ID3D12GraphicsCommandList1: Windows 10 Creators Update (1703) で追加
- アトミックなバッファ間コピー
- Depth Bounds
- 範囲Resovle
- サンプリング位置の変更
- View Instance Mask
- ID3D12GraphicsCommandList2: Windows 10 Fall Creators Update (1709) で追加
- バッファへの即値の書き込み
- ID3D12GraphicsCommandList3: (1803) で追加
- メモリ保護
- ID3D12GraphicsCommandList4: (1809) で追加
- RenderPass
- Raytracing
- MetaCommand
- SUSPENDED
バージョン対応表
| Windows | WDDM | SM | DXGI | D3D | DXGIAdapter | DXGIDevice | DXGIFactory | DXGIOutput | DXGISwapChain | D3DDevice | D3D12GraphicsCommandList | 主な追加機能 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1507 | 2.0 | 5.1 | 1.4 | 12 | 3 | 4 | 4 | 3 | 0 | 0 | ||
| 1511 | ||||||||||||
| 1607 (Anniversary Update) | 2.1 | 6.0 | 1.5 | 12.1 | 4 | 5 | 5 | 4 | 1 | Root Signature 1.1 / HDR10 / Variable Refresh Rates | ||
| 1703 (Creators Update) | 2.2 | 1.6 | 4 | 6 | 2 | 1 | ||||||
| 1709 (Fall Creators Update) | 2.3 | 6.1 | 3 | 2 | ||||||||
| 1803 | 2.4 | 6.2 | 6 | 4 | 3? | |||||||
| 1809 | 2.5 | 6.3 | 7 | 5 | 4? | Raytracing / Render Pass | ||||||
| 1903 | 2.6 | 6.4 | 6 | 5? | Variable Rate Shading | |||||||
| 1909 | ||||||||||||
| 2004 | 2.7 | 6.5 | 12.2? | 7? | Mesh Shader / Sampler Feedback / Raytracing 1.1 | |||||||
| 20H2 | 8? | |||||||||||
| 21H1 | ||||||||||||
| 2.8 | ||||||||||||
| 2.9 | 6.6 | |||||||||||
| 3.0 | ||||||||||||