描画制御用のコマンドバッファ作成
これまでのDirectXでは殆ど内部に隠蔽されていましたが、
DirectxX12からは自分で直接コマンドを作成して制御する形になっています。
DirectX11の流れ
- DeviceContextでリソースのバインドや描画のコマンドを作成
- DirectXが特定のタイミングに自動でGPUへコマンドの実行依頼(途中であれば1に戻る)
- SwapChainのPresent(Vシンク待ち)やQueryコマンドで描画待ち
※2は自分で手動で行う方法もあります。
DirectX12の流れ
- コマンドリストの内容リセット
- コマンドリストに対してリソースのバインドや描画コマンドの作成
- 自分でGPUに対してコマンドの実行依頼(複数のコマンドリストがある場合は1に戻る)
- SwapChainで画面のフリップ
- Fenceを使ってGPU待ちを行う
こんな感じに変わっています。
DirectX12では流れが増えてしまった感じもあります。
ただ実はコマンドリストは並列化(マルチスレッド)やキャッシュ(事前に作成)が行えます。
その辺りを駆使して最適化を行っていけば、CPUについてはDirectX11を上回る性能を出せるはずです!
※GPUの最適化には色々と工夫が必要のようです
では早速、コマンド制御用のオブジェクトを作成していきましょう。
ID3D12CommandQueue
ComPtr<ID3D12CommandQueue> pCommandQueue;
if (FAILED(pDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&pCommandQueue))))
{
return false;
}
ID3D12CommandAllocator
ComPtr<ID3D12CommandAllocator> pCommandAllocator;
if (FAILED(pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pCommandAllocator))))
{
return false;
}
ID3D12GraphicsCommandList
ComPtr<ID3D12GraphicsCommandList> pCommandList;
if (FAILED(pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pCommandAllocator.Get(), nullptr, IID_PPV_ARGS(&pCommandList))))
{
return false;
}
// 初期がコマンドの受付状態なので閉じておく
if (FAILED(pCommandList->Close()))
{
return false;
}
ID3D12Fence
ComPtr<ID3D12Fence> pFence;
if (FAILED(pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence))))
return false;
}
HANDLE FenceEvent;
// 同期待ちするためのイベント作成
FenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (FenceEvent == nullptr && FAILED(GetLastError()))
{
return false;
}
これでコマンドバッファを扱うためのオブジェクトが一通り揃います。
ID3D12CommandQueue | GPUに対してコマンドバッファの実行依頼が行えます。 |
---|---|
ID3D12CommandAllocator | コマンドリストのメモリ確保を管理します。 ※設定によってはキャッシュに利用できます。 |
ID3D12GraphicsCommandList | コマンドリストの生成と管理を行います。 ※設定によってはキャッシュすることが可能です。 |
ID3D12Fence | GPUと同期して実行完了待ちを行うことができます。 今回は待つ際にWindowsのEventを利用しています。 |