From 9316e25652c8e2bd3b844b225e549452bcfc86ec Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 12 May 2019 14:42:16 +1000 Subject: [PATCH] D3DCommon: Fallback to base CreateSwapChain on failure It appears that some older drivers do not support CreateSwapChainForHwnd, resulting in DXGI_ERROR_INVALID_CALL. For these cases, fall back to the base CreateSwapChain() from DXGI 1.0. In theory this should also let us run on Win7 without the platform update, but in reality we require the newer shader compiler so this probably won't work regardless. Also any hardware of this vintage is unlikely to run Dolphin well. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 4 +- Source/Core/VideoBackends/D3D/D3DBase.h | 2 +- Source/Core/VideoBackends/D3D/SwapChain.cpp | 2 +- Source/Core/VideoBackends/D3D/SwapChain.h | 2 +- Source/Core/VideoBackends/D3D12/DXContext.cpp | 5 +- Source/Core/VideoBackends/D3D12/DXContext.h | 6 +- Source/Core/VideoBackends/D3D12/SwapChain.cpp | 2 +- Source/Core/VideoBackends/D3D12/SwapChain.h | 2 +- .../Core/VideoBackends/D3DCommon/Common.cpp | 4 +- Source/Core/VideoBackends/D3DCommon/Common.h | 4 +- .../VideoBackends/D3DCommon/SwapChain.cpp | 96 ++++++++++++------- .../Core/VideoBackends/D3DCommon/SwapChain.h | 8 +- 12 files changed, 80 insertions(+), 57 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index c44e46e15e..ab3ea9321c 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -23,7 +23,7 @@ namespace DX11 static Common::DynamicLibrary s_d3d11_library; namespace D3D { -ComPtr dxgi_factory; +ComPtr dxgi_factory; ComPtr device; ComPtr device1; ComPtr context; @@ -173,7 +173,7 @@ std::vector GetAAModes(u32 adapter_index) ComPtr temp_device = device; if (!temp_device) { - ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); + ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); if (!temp_dxgi_factory) return {}; diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 2afaf120e0..090a0b4f4d 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -28,7 +28,7 @@ class SwapChain; namespace D3D { -extern ComPtr dxgi_factory; +extern ComPtr dxgi_factory; extern ComPtr device; extern ComPtr device1; extern ComPtr context; diff --git a/Source/Core/VideoBackends/D3D/SwapChain.cpp b/Source/Core/VideoBackends/D3D/SwapChain.cpp index d5ce3372c0..7c60554859 100644 --- a/Source/Core/VideoBackends/D3D/SwapChain.cpp +++ b/Source/Core/VideoBackends/D3D/SwapChain.cpp @@ -7,7 +7,7 @@ namespace DX11 { -SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, +SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, ID3D11Device* d3d_device) : D3DCommon::SwapChain(wsi, dxgi_factory, d3d_device) { diff --git a/Source/Core/VideoBackends/D3D/SwapChain.h b/Source/Core/VideoBackends/D3D/SwapChain.h index 1579459eb6..abb5477e8c 100644 --- a/Source/Core/VideoBackends/D3D/SwapChain.h +++ b/Source/Core/VideoBackends/D3D/SwapChain.h @@ -23,7 +23,7 @@ class DXFramebuffer; class SwapChain : public D3DCommon::SwapChain { public: - SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, ID3D11Device* d3d_device); + SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, ID3D11Device* d3d_device); ~SwapChain(); static std::unique_ptr Create(const WindowSystemInfo& wsi); diff --git a/Source/Core/VideoBackends/D3D12/DXContext.cpp b/Source/Core/VideoBackends/D3D12/DXContext.cpp index a2f089220f..63eb4dca51 100644 --- a/Source/Core/VideoBackends/D3D12/DXContext.cpp +++ b/Source/Core/VideoBackends/D3D12/DXContext.cpp @@ -43,7 +43,7 @@ std::vector DXContext::GetAAModes(u32 adapter_index) ComPtr temp_device = g_dx_context ? g_dx_context->m_device : nullptr; if (!temp_device) { - ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); + ComPtr temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false); if (!temp_dxgi_factory) return {}; @@ -57,7 +57,8 @@ std::vector DXContext::GetAAModes(u32 adapter_index) return {}; } - HRESULT hr = d3d12_create_device(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&temp_device)); + HRESULT hr = + d3d12_create_device(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&temp_device)); if (!SUCCEEDED(hr)) return {}; } diff --git a/Source/Core/VideoBackends/D3D12/DXContext.h b/Source/Core/VideoBackends/D3D12/DXContext.h index 2e46dab597..8972049d4a 100644 --- a/Source/Core/VideoBackends/D3D12/DXContext.h +++ b/Source/Core/VideoBackends/D3D12/DXContext.h @@ -14,7 +14,7 @@ #include "VideoBackends/D3D12/DescriptorHeapManager.h" #include "VideoBackends/D3D12/StreamBuffer.h" -struct IDXGIFactory2; +struct IDXGIFactory; namespace DX12 { @@ -54,7 +54,7 @@ public: // Destroys active context. static void Destroy(); - IDXGIFactory2* GetDXGIFactory() const { return m_dxgi_factory.Get(); } + IDXGIFactory* GetDXGIFactory() const { return m_dxgi_factory.Get(); } ID3D12Device* GetDevice() const { return m_device.Get(); } ID3D12CommandQueue* GetCommandQueue() const { return m_command_queue.Get(); } @@ -159,7 +159,7 @@ private: void MoveToNextCommandList(); void DestroyPendingResources(CommandListResources& cmdlist); - ComPtr m_dxgi_factory; + ComPtr m_dxgi_factory; ComPtr m_debug_interface; ComPtr m_device; ComPtr m_command_queue; diff --git a/Source/Core/VideoBackends/D3D12/SwapChain.cpp b/Source/Core/VideoBackends/D3D12/SwapChain.cpp index 6601004e16..8435cc981d 100644 --- a/Source/Core/VideoBackends/D3D12/SwapChain.cpp +++ b/Source/Core/VideoBackends/D3D12/SwapChain.cpp @@ -8,7 +8,7 @@ namespace DX12 { -SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, +SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, ID3D12CommandQueue* d3d_command_queue) : D3DCommon::SwapChain(wsi, dxgi_factory, d3d_command_queue) { diff --git a/Source/Core/VideoBackends/D3D12/SwapChain.h b/Source/Core/VideoBackends/D3D12/SwapChain.h index 8291c32c7b..6f8ee3b8f0 100644 --- a/Source/Core/VideoBackends/D3D12/SwapChain.h +++ b/Source/Core/VideoBackends/D3D12/SwapChain.h @@ -23,7 +23,7 @@ class DXFramebuffer; class SwapChain : public D3DCommon::SwapChain { public: - SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, + SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, ID3D12CommandQueue* d3d_command_queue); ~SwapChain(); diff --git a/Source/Core/VideoBackends/D3DCommon/Common.cpp b/Source/Core/VideoBackends/D3DCommon/Common.cpp index f82c2d3f8c..5c0f16b144 100644 --- a/Source/Core/VideoBackends/D3DCommon/Common.cpp +++ b/Source/Core/VideoBackends/D3DCommon/Common.cpp @@ -72,9 +72,9 @@ void UnloadLibraries() s_libraries_loaded = false; } -IDXGIFactory2* CreateDXGIFactory(bool debug_device) +IDXGIFactory* CreateDXGIFactory(bool debug_device) { - IDXGIFactory2* factory; + IDXGIFactory* factory; // Use Win8.1 version if available. if (create_dxgi_factory2 && diff --git a/Source/Core/VideoBackends/D3DCommon/Common.h b/Source/Core/VideoBackends/D3DCommon/Common.h index 3fd5710b05..aece64256a 100644 --- a/Source/Core/VideoBackends/D3DCommon/Common.h +++ b/Source/Core/VideoBackends/D3DCommon/Common.h @@ -12,7 +12,7 @@ #include "Common/CommonTypes.h" #include "VideoCommon/VideoCommon.h" -struct IDXGIFactory2; +struct IDXGIFactory; enum class AbstractTextureFormat : u32; @@ -26,7 +26,7 @@ void UnloadLibraries(); std::vector GetAdapterNames(); // Helper function which creates a DXGI factory. -IDXGIFactory2* CreateDXGIFactory(bool debug_device); +IDXGIFactory* CreateDXGIFactory(bool debug_device); // Globally-accessible D3DCompiler function. extern pD3DCompile d3d_compile; diff --git a/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp b/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp index 376f891a96..e0bca9158b 100644 --- a/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp +++ b/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp @@ -25,7 +25,7 @@ static bool IsTearingSupported(IDXGIFactory2* dxgi_factory) allow_tearing != 0; } -static bool GetFullscreenState(IDXGISwapChain1* swap_chain) +static bool GetFullscreenState(IDXGISwapChain* swap_chain) { BOOL fs = FALSE; return SUCCEEDED(swap_chain->GetFullscreenState(&fs, nullptr)) && fs; @@ -33,9 +33,8 @@ static bool GetFullscreenState(IDXGISwapChain1* swap_chain) namespace D3DCommon { -SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device) - : m_wsi(wsi), m_dxgi_factory(dxgi_factory), m_d3d_device(d3d_device), - m_allow_tearing_supported(IsTearingSupported(dxgi_factory)) +SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, IUnknown* d3d_device) + : m_wsi(wsi), m_dxgi_factory(dxgi_factory), m_d3d_device(d3d_device) { } @@ -66,40 +65,63 @@ bool SwapChain::CreateSwapChain(bool stereo) m_height = client_rc.bottom - client_rc.top; } - DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; - swap_chain_desc.Width = m_width; - swap_chain_desc.Height = m_height; - swap_chain_desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.SampleDesc.Count = 1; - swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false); - swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swap_chain_desc.Stereo = stereo; - swap_chain_desc.Flags = GetSwapChainFlags(); - - HRESULT hr = m_dxgi_factory->CreateSwapChainForHwnd( - m_d3d_device.Get(), static_cast(m_wsi.render_surface), &swap_chain_desc, nullptr, - nullptr, &m_swap_chain); - if (FAILED(hr)) + // Try using the Win8 version if available. + Microsoft::WRL::ComPtr dxgi_factory2; + HRESULT hr = m_dxgi_factory.As(&dxgi_factory2); + if (SUCCEEDED(hr)) { - // Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to - // a sequential swapchain - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(), - static_cast(m_wsi.render_surface), - &swap_chain_desc, nullptr, nullptr, &m_swap_chain); + m_allow_tearing_supported = IsTearingSupported(dxgi_factory2.Get()); + + DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; + swap_chain_desc.Width = m_width; + swap_chain_desc.Height = m_height; + swap_chain_desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.SampleDesc.Quality = 0; + swap_chain_desc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false); + swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swap_chain_desc.Stereo = stereo; + swap_chain_desc.Flags = GetSwapChainFlags(); + + Microsoft::WRL::ComPtr swap_chain1; + hr = dxgi_factory2->CreateSwapChainForHwnd(m_d3d_device.Get(), + static_cast(m_wsi.render_surface), + &swap_chain_desc, nullptr, nullptr, &swap_chain1); + if (FAILED(hr)) + { + // Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to + // a sequential swapchain + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + hr = dxgi_factory2->CreateSwapChainForHwnd(m_d3d_device.Get(), + static_cast(m_wsi.render_surface), + &swap_chain_desc, nullptr, nullptr, &swap_chain1); + } + + m_swap_chain = swap_chain1; } + // Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy + // BitBlt-model swapchain. Note that this won't work for DX12, but systems which don't + // support the newer DXGI interface aren't going to support DX12 anyway. if (FAILED(hr)) { - // Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy - // BitBlt-model swapchain - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(), - static_cast(m_wsi.render_surface), - &swap_chain_desc, nullptr, nullptr, &m_swap_chain); + DXGI_SWAP_CHAIN_DESC desc = {}; + desc.BufferDesc.Width = m_width; + desc.BufferDesc.Height = m_height; + desc.BufferDesc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false); + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT; + desc.OutputWindow = static_cast(m_wsi.render_surface); + desc.Windowed = TRUE; + desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + desc.Flags = 0; + + m_allow_tearing_supported = false; + hr = m_dxgi_factory->CreateSwapChain(m_d3d_device.Get(), &desc, &m_swap_chain); } if (FAILED(hr)) @@ -147,11 +169,11 @@ bool SwapChain::ResizeSwapChain() if (FAILED(hr)) WARN_LOG(VIDEO, "ResizeBuffers() failed with HRESULT %08X", hr); - DXGI_SWAP_CHAIN_DESC1 desc; - if (SUCCEEDED(m_swap_chain->GetDesc1(&desc))) + DXGI_SWAP_CHAIN_DESC desc; + if (SUCCEEDED(m_swap_chain->GetDesc(&desc))) { - m_width = desc.Width; - m_height = desc.Height; + m_width = desc.BufferDesc.Width; + m_height = desc.BufferDesc.Height; } return CreateSwapChainBuffers(); diff --git a/Source/Core/VideoBackends/D3DCommon/SwapChain.h b/Source/Core/VideoBackends/D3DCommon/SwapChain.h index b84c1a95c3..038bbe75e6 100644 --- a/Source/Core/VideoBackends/D3DCommon/SwapChain.h +++ b/Source/Core/VideoBackends/D3DCommon/SwapChain.h @@ -17,7 +17,7 @@ namespace D3DCommon class SwapChain { public: - SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device); + SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, IUnknown* d3d_device); virtual ~SwapChain(); // Sufficient buffers for triple buffering. @@ -26,7 +26,7 @@ public: // Returns true if the stereo mode is quad-buffering. static bool WantsStereo(); - IDXGISwapChain1* GetDXGISwapChain() const { return m_swap_chain.Get(); } + IDXGISwapChain* GetDXGISwapChain() const { return m_swap_chain.Get(); } AbstractTextureFormat GetFormat() const { return m_texture_format; } u32 GetWidth() const { return m_width; } u32 GetHeight() const { return m_height; } @@ -57,8 +57,8 @@ protected: virtual void DestroySwapChainBuffers() = 0; WindowSystemInfo m_wsi; - Microsoft::WRL::ComPtr m_dxgi_factory; - Microsoft::WRL::ComPtr m_swap_chain; + Microsoft::WRL::ComPtr m_dxgi_factory; + Microsoft::WRL::ComPtr m_swap_chain; Microsoft::WRL::ComPtr m_d3d_device; AbstractTextureFormat m_texture_format = AbstractTextureFormat::RGBA8;