Improvements to D3D11 detection and error handling.

This commit is contained in:
Henrik Rydgard committed 2017-02-23 10:40:55 +01:00
1 parent 85ce4ac219
commit acde17e3ce
8 files changed
+98 -64

No files matched your search

+20 -38
View File
@@ -5,7 +5,7 @@
#include "OSVersion.h"
#include "Common/CommonWindows.h"
bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor) {
bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool greater) {
uint64_t conditionMask = 0;
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
@@ -15,7 +15,7 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u
osvi.dwMinorVersion = minor;
osvi.wServicePackMajor = spMajor;
osvi.wServicePackMinor = spMinor;
uint32_t op = VER_EQUAL;
uint32_t op = greater ? VER_GREATER_EQUAL : VER_EQUAL;
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, op);
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, op);
@@ -28,43 +28,25 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u
}
std::string GetWindowsVersion() {
const bool IsWindowsXPSP2 = DoesVersionMatchWindows(5, 1, 2, 0);
const bool IsWindowsXPSP3 = DoesVersionMatchWindows(5, 1, 3, 0);
const bool IsWindowsVista = DoesVersionMatchWindows(6, 0);
const bool IsWindowsVistaSP1 = DoesVersionMatchWindows(6, 0, 1, 0);
const bool IsWindowsVistaSP2 = DoesVersionMatchWindows(6, 0, 2, 0);
const bool IsWindows7 = DoesVersionMatchWindows(6, 1);
const bool IsWindows7SP1 = DoesVersionMatchWindows(6, 1, 1, 0);
const bool IsWindows8 = DoesVersionMatchWindows(6, 2);
const bool IsWindows8_1 = DoesVersionMatchWindows(6, 3);
if (IsWindowsXPSP2)
return "Microsoft Windows XP, Service Pack 2";
if (IsWindowsXPSP3)
return "Microsoft Windows XP, Service Pack 3";
if (IsWindowsVista)
return "Microsoft Windows Vista";
if (IsWindowsVistaSP1)
return "Microsoft Windows Vista, Service Pack 1";
if (IsWindowsVistaSP2)
return "Microsoft Windows Vista, Service Pack 2";
if (IsWindows7)
return "Microsoft Windows 7";
if (IsWindows7SP1)
return "Microsoft Windows 7, Service Pack 1";
if (IsWindows8)
return "Microsoft Windows 8 or greater"; // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)."
if (IsWindows8_1)
return "Microsoft Windows 8.1";
const bool IsWindowsXPSP2 = DoesVersionMatchWindows(5, 1, 2, 0, false);
const bool IsWindowsXPSP3 = DoesVersionMatchWindows(5, 1, 3, 0, false);
const bool IsWindowsVista = DoesVersionMatchWindows(6, 0, 0, 0, false);
const bool IsWindowsVistaSP1 = DoesVersionMatchWindows(6, 0, 1, 0, false);
const bool IsWindowsVistaSP2 = DoesVersionMatchWindows(6, 0, 2, 0, false);
const bool IsWindows7 = DoesVersionMatchWindows(6, 1, 0, 0, false);
const bool IsWindows7SP1 = DoesVersionMatchWindows(6, 1, 1, 0, false);
const bool IsWindows8 = DoesVersionMatchWindows(6, 2, 0, 0, false);
const bool IsWindows8_1 = DoesVersionMatchWindows(6, 3, 0, 0, false);
if (IsWindowsXPSP2) return "Microsoft Windows XP, Service Pack 2";
if (IsWindowsXPSP3) return "Microsoft Windows XP, Service Pack 3";
if (IsWindowsVista) return "Microsoft Windows Vista";
if (IsWindowsVistaSP1) return "Microsoft Windows Vista, Service Pack 1";
if (IsWindowsVistaSP2) return "Microsoft Windows Vista, Service Pack 2";
if (IsWindows7) return "Microsoft Windows 7";
if (IsWindows7SP1) return "Microsoft Windows 7, Service Pack 1";
if (IsWindows8) return "Microsoft Windows 8 or greater"; // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)."
if (IsWindows8_1) return "Microsoft Windows 8.1";
return "Unsupported version of Microsoft Windows.";
}
+1 -1
View File
@@ -4,7 +4,7 @@
#ifdef _MSC_VER
bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor = 0, uint32_t spMinor = 0);
bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool acceptGreater);
std::string GetWindowsVersion();
std::string GetWindowsSystemArchitecture();
+1 -1
View File
@@ -161,7 +161,7 @@ void GameSettingsScreen::CreateViews() {
renderingBackendChoice->HideChoice(1); // D3D9
renderingBackendChoice->HideChoice(2); // D3D11
#else
if (!DoesVersionMatchWindows(6, 0)) {
if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) {
// Hide the D3D11 choice if Windows version is older than Windows Vista.
renderingBackendChoice->HideChoice(2); // D3D11
}
+28 -10
View File
@@ -13,11 +13,9 @@
#include "thin3d/d3d11_loader.h"
D3D11Context::D3D11Context() : draw_(nullptr), adapterId(-1), hDC(nullptr), hWnd_(nullptr), hD3D11(nullptr) {
LoadD3D11();
}
D3D11Context::~D3D11Context() {
UnloadD3D11();
}
void D3D11Context::SwapBuffers() {
@@ -31,13 +29,12 @@ void D3D11Context::SwapInterval(int interval) {
// Dummy
}
bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
HRESULT D3D11Context::CreateTheDevice() {
bool windowed = true;
hWnd_ = wnd;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
#else
UINT createDeviceFlags = 0;
#endif
static const D3D_DRIVER_TYPE driverTypes[] = {
@@ -45,7 +42,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);
const UINT numDriverTypes = ARRAYSIZE(driverTypes);
static const D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_1,
@@ -53,7 +50,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
const UINT numFeatureLevels = ARRAYSIZE(featureLevels);
HRESULT hr = S_OK;
// Temporarily commenting out until we can dynamically load D3D11CreateDevice.
@@ -71,11 +68,31 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
break;
}
return hr;
}
bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
hWnd_ = wnd;
LoadD3D11Error result = LoadD3D11();
HRESULT hr = E_FAIL;
if (result == LoadD3D11Error::SUCCESS) {
hr = CreateTheDevice();
}
if (FAILED(hr)) {
const char *defaultError = "Your GPU does not appear to support Direct3D 11.\n\nWould you like to try again using Direct3D 9 instead?";
I18NCategory *err = GetI18NCategory("Error");
std::wstring error = ConvertUTF8ToWString(err->T("D3D11NotSupported", defaultError));
std::wstring error;
if (result == LoadD3D11Error::FAIL_NO_COMPILER) {
error = ConvertUTF8ToWString(err->T("D3D11CompilerMissing", "D3DCompiler_47.dll not found. Please install. Or press Yes to try again using Direct3D9 instead."));
} else if (result == LoadD3D11Error::FAIL_NO_D3D11) {
error = ConvertUTF8ToWString(err->T("D3D11Missing", "Your operating system version does not include D3D11. Please run Windows Update.\n\nPress Yes to try again using Direct3D9 instead."));
}
error = ConvertUTF8ToWString(err->T("D3D11NotSupported", defaultError));
std::wstring title = ConvertUTF8ToWString(err->T("D3D11InitializationError", "Direct3D 11 initialization error"));
bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);
if (yes) {
@@ -143,4 +160,5 @@ void D3D11Context::Shutdown() {
device_->Release();
device_ = nullptr;
hWnd_ = nullptr;
UnloadD3D11();
}
+2
View File
@@ -40,6 +40,8 @@ public:
Draw::DrawContext *GetDrawContext() override { return draw_; }
private:
HRESULT CreateTheDevice();
Draw::DrawContext *draw_ = nullptr;
ID3D11Device *device_ = nullptr;
ID3D11Device1 *device1_ = nullptr;
+6
View File
@@ -23,6 +23,8 @@
#include "Common/CommonWindows.h"
#include "Common/KeyMap.h"
#include "Common/OSVersion.h"
#include <Windowsx.h>
#include <map>
@@ -640,6 +642,10 @@ namespace MainWindow
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE:
if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) {
// Remove the D3D11 choice on versions below XP
RemoveMenu(GetMenu(hWnd), ID_OPTIONS_DIRECT3D11, MF_BYCOMMAND);
}
break;
case WM_GETMINMAXINFO:
+30 -9
View File
@@ -9,28 +9,48 @@ LPD3D11CREATEDEVICE ptr_D3D11CreateDevice;
LPD3D11CREATEDEVICEANDSWAPCHAIN ptr_D3D11CreateDeviceAndSwapChain;
pD3DCompile ptr_D3DCompile;
bool LoadD3D11() {
LoadD3D11Error LoadD3D11() {
if (g_D3D11Module) {
return true;
// Already done
return LoadD3D11Error::SUCCESS;
}
g_D3D11Module = LoadLibrary(L"d3d11.dll");
if (g_D3D11Module) {
ptr_D3D11CreateDevice = (LPD3D11CREATEDEVICE)GetProcAddress(g_D3D11Module, "D3D11CreateDevice");
ptr_D3D11CreateDeviceAndSwapChain = (LPD3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(g_D3D11Module, "D3D11CreateDeviceAndSwapChain");
} else {
return LoadD3D11Error::FAIL_NO_D3D11;
}
if (!ptr_CreateDXGIFactory) {
g_DXGIModule = LoadLibrary(L"dxgi.dll");
if (g_DXGIModule) {
ptr_CreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(g_DXGIModule, "CreateDXGIFactory1");
}
g_DXGIModule = LoadLibrary(L"dxgi.dll");
if (g_DXGIModule) {
ptr_CreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(g_DXGIModule, "CreateDXGIFactory1");
} else {
FreeLibrary(g_D3D11Module);
g_D3D11Module = nullptr;
return LoadD3D11Error::FAIL_NO_D3D11;
}
g_D3DCompileModule = LoadLibrary(D3DCOMPILER_DLL);
if (!g_D3DCompileModule)
g_D3DCompileModule = LoadLibrary(L"D3dcompiler_42.dll");
if (!g_D3DCompileModule) {
FreeLibrary(g_D3D11Module);
g_D3D11Module = nullptr;
FreeLibrary(g_DXGIModule);
g_DXGIModule = nullptr;
return LoadD3D11Error::FAIL_NO_COMPILER;
}
g_D3DCompileModule = LoadLibrary(L"D3dcompiler_47.dll");
ptr_D3DCompile = (pD3DCompile)GetProcAddress(g_D3DCompileModule, "D3DCompile");
return g_DXGIModule != nullptr && g_D3D11Module != nullptr && g_D3DCompileModule != nullptr;
return LoadD3D11Error::SUCCESS;
}
bool UnloadD3D11() {
if (!g_D3D11Module)
return false;
if (g_DXGIModule) {
FreeLibrary(g_DXGIModule);
g_DXGIModule = nullptr;
@@ -43,5 +63,6 @@ bool UnloadD3D11() {
FreeLibrary(g_D3DCompileModule);
g_D3DCompileModule = nullptr;
}
return true;
}
+10 -5
View File
@@ -7,15 +7,20 @@
#include <d3d11.h>
#include <D3Dcompiler.h>
typedef HRESULT(WINAPI *LPCREATEDXGIFACTORY)(REFIID, void **);
typedef HRESULT(WINAPI *LPD3D11CREATEDEVICEANDSWAPCHAIN)(__in_opt IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, __in_opt CONST DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, __out_opt IDXGISwapChain **ppSwapChain, __out_opt ID3D11Device **ppDevice, __out_opt D3D_FEATURE_LEVEL *pFeatureLevel, __out_opt ID3D11DeviceContext **ppImmediateContext);
typedef HRESULT(WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL *, UINT, UINT32, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
// typedef HRESULT(WINAPI *LPD3DCOMPILE)(LPCVOID pSrcData, SIZE_T SrcDataSize, LPCSTR pSourceName, const D3D_SHADER_MACRO pDefines, ID3DInclude *pInclude, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob *ppCode, ID3DBlob *ppErrorMsgs);
typedef HRESULT (WINAPI *LPCREATEDXGIFACTORY)(REFIID, void **);
typedef HRESULT (WINAPI *LPD3D11CREATEDEVICEANDSWAPCHAIN)(__in_opt IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, __in_opt CONST DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, __out_opt IDXGISwapChain **ppSwapChain, __out_opt ID3D11Device **ppDevice, __out_opt D3D_FEATURE_LEVEL *pFeatureLevel, __out_opt ID3D11DeviceContext **ppImmediateContext);
typedef HRESULT (WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL *, UINT, UINT32, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
extern LPCREATEDXGIFACTORY ptr_CreateDXGIFactory;
extern LPD3D11CREATEDEVICE ptr_D3D11CreateDevice;
extern LPD3D11CREATEDEVICEANDSWAPCHAIN ptr_D3D11CreateDeviceAndSwapChain;
extern pD3DCompile ptr_D3DCompile;
bool LoadD3D11();
enum class LoadD3D11Error {
SUCCESS,
FAIL_NO_D3D11,
FAIL_NO_COMPILER,
};
LoadD3D11Error LoadD3D11();
bool UnloadD3D11();