【DirectX12】Direct3Dデバイスの作成【初期化】
こんにちは、ここあです。
昨日記事を上げる事が出来なかったので、今日二つ上げようと思っていたのですが、思った以上に帰ってくるのが遅くなってしまったため、明日二つ上げることにしました。
今日はDirect3Dデバイスの作成について解説していきます。
Library & Includes
#include <d3dx12.h> #pragma comment(lib, "d3d12.lib") #include <dxgi1_4.h> #pragma comment(lib, "dxgi.lib") #include <D3Dcompiler.h> #pragma comment(lib, "d3dcompiler.lib") #include <DirectXMath.h> using Microsoft::WRL::ComPtr; using namespace DirectX;
Direct3Dデバイスの作成
初期化の一番初めにやらなければいけない事が、Direct3Dデバイスの作成です(以下D3Dデバイス)。
Windowsには通常、複数のD3Dデバイスが存在し、GPUを複数PCに積んでいる場合には、それぞれがD3Dデバイスとなります。なので、最初にその中からどのデバイスが目的に合ったものなのかの選択を最初に行います。
DXGIファクトリの生成
IDXGIFactory4を使用します。IDXGIFactory4は生成されたファクトリを操作するためのインタフェースクラスです。
CreateDXGIFactory1関数でDXGIファクトリを生成します。
IID_PPV_ARGSマクロを使うことで、引数から自動的に2つのパラメータを作成してもらう事で、もしプログラムで使いたいインタフェースが変わった場合の、変更箇所を1ヶ所にすることで間違いを起こしにくくします。
CreateDXGIFactory1
ComPtr<IDXGIFactory4> dxgiFactory; // DXGIファクトリの生成 if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) { return false; }
デバイスを列挙する為に、IDXGIFactory1::EnumAdapters1関数を使います。この関数はインターフェイスが取得できなかった場合にDXGI_ERROR_NOT_FOUNDを返すので、それが返されるまでループを回して目的のデバイスを探していきます。
IDXGIFactory1::EnumAdapters1
IDXGIAdapter1::GetDesc1関数でデバイスの情報を取得できます。ここでは、この情報を、ハードウェアではないデバイスを除外するために使用しています。
IDXGIAdapter1::GetDesc1 method | Microsoft Docs
デバイスを作成できるか確認
ハードウェアデバイスである確認が取れたものは、D3D12CreateDevice関数で実際に作成できるかどうかを調べます。この関数はインタフェースポインタを格納する変数のアドレスとして、nullptrを渡した場合、作成できるかどうかを調べることが出来ます。今回はnullptrを渡さなければならないのでIID_PPV_ARGSマクロは使えません。
D3D12CreateDevice機能|マイクロソフトドキュメント
- D3D12CreateDevice関数
機能レベルとは、GPUがどの世代のDirectXに対応しているかを示すためのものです。IDXGIAdapter1の情報がこの条件を満たさない場合、作成に失敗します。
ComPtr<IDXGIFactory1> dxgiAdapter; //デバイス取得用 int adapterIndex = 0; //列挙するデバイスのインデックス bool adapterFound = false; //目的のデバイスを見つけたか // 目的のデバイスを探索 while(dxgiFactory->EnumAdapters1( adapterIndex, &dxgiAdapter) != DXGI_ERROR_NOT_FOUND) { DXGI_ADAPTER_DESC1 desc; dxgiAdapter->GetDesc1(&desc); // デバイスの情報を取得 // ハードウェアのみ選ぶ if (!(desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) { if (SUCCEEDED(D3D12CreateDevice(dxgiAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr))) { adapterFound = true; break; } } ++adapterIndex; }
WARPデバイスの作成
ループが終わっても、作成可能デバイスが見つからなかった場合、WARPデバイスの作成を試みます。
IDXGIFactory4::EnumWarpAdapter関数を使い、使用可能なWARPデバイスがあるかを調べます。
見つからない場合、Direct3Dは使えないので、falseを返します。
最後にD3D12CreateDevice関数の呼び出しで、実際にデバイスを作成します。
ComPtr<ID3D12Device> g_device; //global変数
// デバイス情報を取得できているか if (!adapterFound) { if (FAILED(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&dxgiAdapter)))) return false; warp = true; } // if (FAILED(D3D12CreateDevice(dxgiAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&g_device)))) { return false; }
終わりに
これでデバイスを作ることが出来ました。
明日はDirectX12になって追加されたコマンドキューの作成とスワップチェーンの作成について解説したいと思います。
今回のデバイス作成を実装したコードはGitHubに上げています。
それでは、今回はこれで。
もし解説が間違っていたり、より良い方法などがあった場合は教えて頂けるとありがたいです。
github.com