mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Improvements to D3D11 detection and error handling.
This commit is contained in:
1 parent
85ce4ac219
commit
acde17e3ce
8 files changed
+98
-64
No files matched your search
+20
-38
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
Draw::DrawContext *GetDrawContext() override { return draw_; }
|
||||
|
||||
private:
|
||||
HRESULT CreateTheDevice();
|
||||
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
ID3D11Device *device_ = nullptr;
|
||||
ID3D11Device1 *device1_ = nullptr;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
Reference in new issue
Block a user