トップ回答者
DirectX 11のデバイスの作成ができない

質問
-
ソースコードはこちらです。
https://github.com/Shirley-Chan/GetGPU/blob/master/GetGPU/ExeVersion/Main.cpp
D3D11CreateDevice関数の第2引数にD3D_DRIVER_TYPE_HARDWAREを与えると、hrにE_INVALIDARGの値が入ってしまい、これをD3D_DRIVER_TYPE_UNKNOWNに切り替えたらS_OKになってしまいます。
この原因は何なんでしょうか?
ちなみにデバッグを行っているPCのグラフィックスアダプターは
Intel HD Graphics 630
NVIDIA GeForce GTX 1060
の2つです。
回答
-
D3D11CreateDeviceドキュメントのRemarksセクションにある通りではないでしょうか?
In Direct3D 11, if you are trying to create a hardware or a software device, set pAdapter != NULL which constrains the other inputs to be:
- DriverType must be D3D_DRIVER_TYPE_UNKNOWN
第1引数pAdapter != NULL の場合は第2引数DriverTypeはD3D_DRIVER_TYPE_UNKNOWNでなければならないと記されています。
なお、前スレッドで解決後に指摘していますがComPtrの使い方が間違っているため永久に解放されることがない箇所があります。あと気が向いたの書いたコードがあるので貼り付けておきます。
#include <filesystem> // std::experimental::filesystem::path, std::experimental::filesystem::current_path #include <optional> // std::optional #include <string> // std::char_traits #include <wrl/client.h> #include <dxgi.h> #pragma comment(lib, "dxgi.lib") #if __has_include(<d3d12.h>) #include <d3d12.h> #endif #include <d3d11.h> #pragma comment(lib, "d3d11.lib") #include <xmllite.h> #pragma comment(lib, "xmllite.lib") #include <Shlwapi.h> #pragma comment(lib, "Shlwapi.lib") namespace fs = std::experimental::filesystem; template<class T> using ComPtr = Microsoft::WRL::ComPtr<T>; static inline void check(HRESULT hr) { if (FAILED(hr)) throw std::runtime_error{ "error" }; } static std::optional<D3D_FEATURE_LEVEL> TryCreate(ComPtr<IDXGIAdapter1>& adapter) { static const D3D_FEATURE_LEVEL levels[]{ #ifdef __d3d12_h__ D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, #endif D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; #ifdef __d3d12_h__ static const auto d3d12CreateDevice = [] { auto d3d12 = LoadLibraryW(L"d3d12.dll"); return d3d12 ? reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(GetProcAddress(d3d12, "D3D12CreateDevice")) : nullptr; }(); if (d3d12CreateDevice) { for (auto level : levels) if (SUCCEEDED(d3d12CreateDevice(adapter.Get(), level, __uuidof(ID3D12Device), nullptr))) return level; } else #endif if (D3D_FEATURE_LEVEL level; SUCCEEDED(D3D11CreateDevice(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, levels, UINT(std::size(levels)), D3D11_SDK_VERSION, nullptr, &level, nullptr))) return level; return std::nullopt; } static constexpr double ToDouble(const D3D_FEATURE_LEVEL level) { return level / 0x1000 + level % 0x1000 / 0x0100 / 10.0; } static_assert(ToDouble(D3D_FEATURE_LEVEL_11_1) == 11.1); int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { try { auto const path = 0 < std::char_traits<TCHAR>::length(lpCmdLine) ? fs::path{ lpCmdLine } : fs::current_path(); ComPtr<IStream> stream; check(SHCreateStreamOnFileEx((path / L"gpu.xml").c_str(), STGM_CREATE | STGM_WRITE, 0, 0, nullptr, &stream)); ComPtr<IXmlWriter> writer; check(CreateXmlWriter(IID_PPV_ARGS(&writer), nullptr)); check(writer->SetOutput(stream.Get())); check(writer->SetProperty(XmlWriterProperty_Indent, true)); check(writer->WriteStartDocument(XmlStandalone_Omit)); check(writer->WriteStartElement(nullptr, L"gpulist", nullptr)); ComPtr<IDXGIFactory1> factory; check(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); auto found = false; for (unsigned int index = 0;; index++) { ComPtr<IDXGIAdapter1> adapter; auto result = factory->EnumAdapters1(index, &adapter); if (result == DXGI_ERROR_NOT_FOUND) break; check(result); DXGI_ADAPTER_DESC1 desc; check(adapter->GetDesc1(&desc)); if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) continue; if (auto level = TryCreate(adapter)) { found = true; check(writer->WriteStartElement(nullptr, L"gpuinfo", nullptr)); check(writer->WriteElementString(nullptr, L"name", nullptr, desc.Description)); check(writer->WriteElementString(nullptr, L"dedicatedvideomemory", nullptr, std::to_wstring(desc.DedicatedVideoMemory).c_str())); check(writer->WriteElementString(nullptr, L"dedicatedsystemmemory", nullptr, std::to_wstring(desc.DedicatedSystemMemory).c_str())); check(writer->WriteElementString(nullptr, L"sharedsystemmemory", nullptr, std::to_wstring(desc.SharedSystemMemory).c_str())); check(writer->WriteElementString(nullptr, L"hardwareid", nullptr, std::to_wstring(index).c_str())); check(writer->WriteElementString(nullptr, L"maxfeaturelevel", nullptr, std::to_wstring(ToDouble(*level)).c_str())); check(writer->WriteEndElement()); } } if (!found) throw std::runtime_error{ "This computer is installed no hardware device compatibled DirectX use hardware adapter.Warning : This tool can not judge compatibled warp device mode." }; check(writer->WriteEndElement()); check(writer->WriteEndDocument()); check(writer->Flush()); } catch (const std::exception& e) { return MessageBoxA(NULL, e.what(), "エラー", MB_ICONERROR | MB_OK); } return 0; }
- 回答としてマーク 立花楓Microsoft employee, Moderator 2018年6月15日 1:24
すべての返信
-
D3D11CreateDeviceドキュメントのRemarksセクションにある通りではないでしょうか?
In Direct3D 11, if you are trying to create a hardware or a software device, set pAdapter != NULL which constrains the other inputs to be:
- DriverType must be D3D_DRIVER_TYPE_UNKNOWN
第1引数pAdapter != NULL の場合は第2引数DriverTypeはD3D_DRIVER_TYPE_UNKNOWNでなければならないと記されています。
なお、前スレッドで解決後に指摘していますがComPtrの使い方が間違っているため永久に解放されることがない箇所があります。あと気が向いたの書いたコードがあるので貼り付けておきます。
#include <filesystem> // std::experimental::filesystem::path, std::experimental::filesystem::current_path #include <optional> // std::optional #include <string> // std::char_traits #include <wrl/client.h> #include <dxgi.h> #pragma comment(lib, "dxgi.lib") #if __has_include(<d3d12.h>) #include <d3d12.h> #endif #include <d3d11.h> #pragma comment(lib, "d3d11.lib") #include <xmllite.h> #pragma comment(lib, "xmllite.lib") #include <Shlwapi.h> #pragma comment(lib, "Shlwapi.lib") namespace fs = std::experimental::filesystem; template<class T> using ComPtr = Microsoft::WRL::ComPtr<T>; static inline void check(HRESULT hr) { if (FAILED(hr)) throw std::runtime_error{ "error" }; } static std::optional<D3D_FEATURE_LEVEL> TryCreate(ComPtr<IDXGIAdapter1>& adapter) { static const D3D_FEATURE_LEVEL levels[]{ #ifdef __d3d12_h__ D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, #endif D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; #ifdef __d3d12_h__ static const auto d3d12CreateDevice = [] { auto d3d12 = LoadLibraryW(L"d3d12.dll"); return d3d12 ? reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(GetProcAddress(d3d12, "D3D12CreateDevice")) : nullptr; }(); if (d3d12CreateDevice) { for (auto level : levels) if (SUCCEEDED(d3d12CreateDevice(adapter.Get(), level, __uuidof(ID3D12Device), nullptr))) return level; } else #endif if (D3D_FEATURE_LEVEL level; SUCCEEDED(D3D11CreateDevice(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, levels, UINT(std::size(levels)), D3D11_SDK_VERSION, nullptr, &level, nullptr))) return level; return std::nullopt; } static constexpr double ToDouble(const D3D_FEATURE_LEVEL level) { return level / 0x1000 + level % 0x1000 / 0x0100 / 10.0; } static_assert(ToDouble(D3D_FEATURE_LEVEL_11_1) == 11.1); int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { try { auto const path = 0 < std::char_traits<TCHAR>::length(lpCmdLine) ? fs::path{ lpCmdLine } : fs::current_path(); ComPtr<IStream> stream; check(SHCreateStreamOnFileEx((path / L"gpu.xml").c_str(), STGM_CREATE | STGM_WRITE, 0, 0, nullptr, &stream)); ComPtr<IXmlWriter> writer; check(CreateXmlWriter(IID_PPV_ARGS(&writer), nullptr)); check(writer->SetOutput(stream.Get())); check(writer->SetProperty(XmlWriterProperty_Indent, true)); check(writer->WriteStartDocument(XmlStandalone_Omit)); check(writer->WriteStartElement(nullptr, L"gpulist", nullptr)); ComPtr<IDXGIFactory1> factory; check(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); auto found = false; for (unsigned int index = 0;; index++) { ComPtr<IDXGIAdapter1> adapter; auto result = factory->EnumAdapters1(index, &adapter); if (result == DXGI_ERROR_NOT_FOUND) break; check(result); DXGI_ADAPTER_DESC1 desc; check(adapter->GetDesc1(&desc)); if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) continue; if (auto level = TryCreate(adapter)) { found = true; check(writer->WriteStartElement(nullptr, L"gpuinfo", nullptr)); check(writer->WriteElementString(nullptr, L"name", nullptr, desc.Description)); check(writer->WriteElementString(nullptr, L"dedicatedvideomemory", nullptr, std::to_wstring(desc.DedicatedVideoMemory).c_str())); check(writer->WriteElementString(nullptr, L"dedicatedsystemmemory", nullptr, std::to_wstring(desc.DedicatedSystemMemory).c_str())); check(writer->WriteElementString(nullptr, L"sharedsystemmemory", nullptr, std::to_wstring(desc.SharedSystemMemory).c_str())); check(writer->WriteElementString(nullptr, L"hardwareid", nullptr, std::to_wstring(index).c_str())); check(writer->WriteElementString(nullptr, L"maxfeaturelevel", nullptr, std::to_wstring(ToDouble(*level)).c_str())); check(writer->WriteEndElement()); } } if (!found) throw std::runtime_error{ "This computer is installed no hardware device compatibled DirectX use hardware adapter.Warning : This tool can not judge compatibled warp device mode." }; check(writer->WriteEndElement()); check(writer->WriteEndDocument()); check(writer->Flush()); } catch (const std::exception& e) { return MessageBoxA(NULL, e.what(), "エラー", MB_ICONERROR | MB_OK); } return 0; }
- 回答としてマーク 立花楓Microsoft employee, Moderator 2018年6月15日 1:24
-
shirley-chan さん、こんにちは。フォーラム オペレーターの立花です。
MSDN フォーラムへのご投稿ありがとうございます。
フォーラム オペレーターからのお願いです。
同じ問題であとから参照された方が情報をすぐに得られるように
参考となった投稿には [回答としてマーク] をご設定ください。
回答いただいた方のモチベーションの向上にもつながります。
ご協力のほど、どうぞよろしくお願いいたします。
あと、回答いただいたらお礼も記載してくださいね。
~ 参考になった投稿には回答としてマークの設定にご協力ください ~
MSDN/TechNet Community Support 立花楓
- 編集済み 立花楓Microsoft employee, Moderator 2018年4月13日 0:49 内容修正