Skip to content
Go back

DirectX12仕様メモ

· Updated:

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)

処理の流れ

初期化

  1. CreateDXGIFactoryIDXGIFactoryを生成
  2. 要件を満たすディスプレイを探す
    1. IDXGIFactory::EnumAdaptersなどでIDXGIAdapterを列挙
    2. IDXGIAdapter::EnumOutputsIDXGIOutputを列挙
  3. D3D12CreateDeviceID3D12Deviceを生成
  4. デバイスが要件を満たすか確認
    1. ID3D12Device::CheckFeatureSupportで機能の情報を取得
  5. ID3D12Device::CreateCommandQueueでDIRECTキューを生成
  6. IDXGIFactory2::CreateSwapChainForCoreWindowなどでIDXGISwapChainを生成
    1. IDXGISwapChain::GetBufferでバックバッファのID3D12Resourceを取得

前準備

  1. ID3D12CommandAllocatorを生成
  2. ID3D12CommandListを生成

描画

  1. SwapChainに関係のないコマンドを記録
  2. SwapChainに関係のあるコマンドを記録
    1. IDXGISwapChain3::GetCurrentBackBufferIndexで対象のバックバッファ番号を取得
  3. コマンドリストを実行
  4. IDXGISwapChain::Presentでバックバッファを画面に表示

ID3D12Device

Feature Level

ID3D12CommandQueue

Type

  • DIRECT :

ID3D12CommandAllocator

  • ID3DCommandListと異なり、Resetを呼び出すときにそれで記録されたコマンドリストが実行中であってはいけない (Microsoft Learn)
  • 記録中のCommandListから利用されるのは同時に1つだけ (Microsoft Learn)

ID3D12CommandList

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

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で取得できる
      • キューに空きができるのを待つ合間に別の処理を行うことができる
  • ⇒ 効率的な処理ができるようになる

Tearing Support

SUSPENDED

Present()

  • メインスレッド以外でも問題なく呼び出せる (Microsoft Learn)
    • 並列には呼び出せないので、単一のスレッドで行う
    • 内部でメッセージを送ることがあるため、UIスレッドとデッドロックしないように注意する必要がある

GetBuffer()

  • バックバッファのID3D12Resourceを取得する
  • スワップチェインをリサイズするまで有効 (Microsoft Learn)

GetCurrentBackBufferIndex()

  • Presentすると+1され、BufferCountで1周する?

バリア

ステート

  • やりたいことに合わせてステートを遷移させる (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ステートはアクセス時に関連するステートに昇格promoteする (Microsoft Learn)
    • 読み込み系フラグのみであればいくつでも追加できる
      • この状態では、書き込み系への遷移は明示的に行う必要がある
    • 書き込み系フラグは最初に1回だけ
      • この状態では、次回の遷移は明示的に行う必要がある
    • バッファやSIMULTANEOUS_ACCESSなテクスチャはすべてのステートに遷移可能
    • SIMULTANEOUS_ACCESSでないテクスチャはSRV系やCOPY系ステートにのみ遷移可能
  • 特定の条件を満たすとExecuteCommandListsの呼び出し後にステートがCOMMONに降格decayする (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) で追加

ID3D12GraphicsCommandList

バージョン対応表

WindowsWDDMSMDXGID3DDXGIAdapterDXGIDeviceDXGIFactoryDXGIOutputDXGISwapChainD3DDeviceD3D12GraphicsCommandList主な追加機能
15072.05.11.412344300
1511
1607 (Anniversary Update)2.16.01.512.145541Root Signature 1.1 / HDR10 / Variable Refresh Rates
1703 (Creators Update)2.21.64621
1709 (Fall Creators Update)2.36.132
18032.46.2643?
18092.56.3754?Raytracing / Render Pass
19032.66.465?Variable Rate Shading
1909
20042.76.512.2?7?Mesh Shader / Sampler Feedback / Raytracing 1.1
20H28?
21H1
2.8
2.96.6
3.0