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.
This commit is contained in:
parent
0177c6c2c7
commit
9316e25652
|
@ -23,7 +23,7 @@ namespace DX11
|
||||||
static Common::DynamicLibrary s_d3d11_library;
|
static Common::DynamicLibrary s_d3d11_library;
|
||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
ComPtr<IDXGIFactory2> dxgi_factory;
|
ComPtr<IDXGIFactory> dxgi_factory;
|
||||||
ComPtr<ID3D11Device> device;
|
ComPtr<ID3D11Device> device;
|
||||||
ComPtr<ID3D11Device1> device1;
|
ComPtr<ID3D11Device1> device1;
|
||||||
ComPtr<ID3D11DeviceContext> context;
|
ComPtr<ID3D11DeviceContext> context;
|
||||||
|
@ -173,7 +173,7 @@ std::vector<u32> GetAAModes(u32 adapter_index)
|
||||||
ComPtr<ID3D11Device> temp_device = device;
|
ComPtr<ID3D11Device> temp_device = device;
|
||||||
if (!temp_device)
|
if (!temp_device)
|
||||||
{
|
{
|
||||||
ComPtr<IDXGIFactory2> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
|
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
|
||||||
if (!temp_dxgi_factory)
|
if (!temp_dxgi_factory)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SwapChain;
|
||||||
|
|
||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
extern ComPtr<IDXGIFactory2> dxgi_factory;
|
extern ComPtr<IDXGIFactory> dxgi_factory;
|
||||||
extern ComPtr<ID3D11Device> device;
|
extern ComPtr<ID3D11Device> device;
|
||||||
extern ComPtr<ID3D11Device1> device1;
|
extern ComPtr<ID3D11Device1> device1;
|
||||||
extern ComPtr<ID3D11DeviceContext> context;
|
extern ComPtr<ID3D11DeviceContext> context;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace DX11
|
namespace DX11
|
||||||
{
|
{
|
||||||
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory,
|
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory,
|
||||||
ID3D11Device* d3d_device)
|
ID3D11Device* d3d_device)
|
||||||
: D3DCommon::SwapChain(wsi, dxgi_factory, d3d_device)
|
: D3DCommon::SwapChain(wsi, dxgi_factory, d3d_device)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ class DXFramebuffer;
|
||||||
class SwapChain : public D3DCommon::SwapChain
|
class SwapChain : public D3DCommon::SwapChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, ID3D11Device* d3d_device);
|
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, ID3D11Device* d3d_device);
|
||||||
~SwapChain();
|
~SwapChain();
|
||||||
|
|
||||||
static std::unique_ptr<SwapChain> Create(const WindowSystemInfo& wsi);
|
static std::unique_ptr<SwapChain> Create(const WindowSystemInfo& wsi);
|
||||||
|
|
|
@ -43,7 +43,7 @@ std::vector<u32> DXContext::GetAAModes(u32 adapter_index)
|
||||||
ComPtr<ID3D12Device> temp_device = g_dx_context ? g_dx_context->m_device : nullptr;
|
ComPtr<ID3D12Device> temp_device = g_dx_context ? g_dx_context->m_device : nullptr;
|
||||||
if (!temp_device)
|
if (!temp_device)
|
||||||
{
|
{
|
||||||
ComPtr<IDXGIFactory2> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
|
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
|
||||||
if (!temp_dxgi_factory)
|
if (!temp_dxgi_factory)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -57,7 +57,8 @@ std::vector<u32> DXContext::GetAAModes(u32 adapter_index)
|
||||||
return {};
|
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))
|
if (!SUCCEEDED(hr))
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
|
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
|
||||||
#include "VideoBackends/D3D12/StreamBuffer.h"
|
#include "VideoBackends/D3D12/StreamBuffer.h"
|
||||||
|
|
||||||
struct IDXGIFactory2;
|
struct IDXGIFactory;
|
||||||
|
|
||||||
namespace DX12
|
namespace DX12
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ public:
|
||||||
// Destroys active context.
|
// Destroys active context.
|
||||||
static void Destroy();
|
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(); }
|
ID3D12Device* GetDevice() const { return m_device.Get(); }
|
||||||
ID3D12CommandQueue* GetCommandQueue() const { return m_command_queue.Get(); }
|
ID3D12CommandQueue* GetCommandQueue() const { return m_command_queue.Get(); }
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ private:
|
||||||
void MoveToNextCommandList();
|
void MoveToNextCommandList();
|
||||||
void DestroyPendingResources(CommandListResources& cmdlist);
|
void DestroyPendingResources(CommandListResources& cmdlist);
|
||||||
|
|
||||||
ComPtr<IDXGIFactory2> m_dxgi_factory;
|
ComPtr<IDXGIFactory> m_dxgi_factory;
|
||||||
ComPtr<ID3D12Debug> m_debug_interface;
|
ComPtr<ID3D12Debug> m_debug_interface;
|
||||||
ComPtr<ID3D12Device> m_device;
|
ComPtr<ID3D12Device> m_device;
|
||||||
ComPtr<ID3D12CommandQueue> m_command_queue;
|
ComPtr<ID3D12CommandQueue> m_command_queue;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace DX12
|
namespace DX12
|
||||||
{
|
{
|
||||||
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory,
|
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory,
|
||||||
ID3D12CommandQueue* d3d_command_queue)
|
ID3D12CommandQueue* d3d_command_queue)
|
||||||
: D3DCommon::SwapChain(wsi, dxgi_factory, d3d_command_queue)
|
: D3DCommon::SwapChain(wsi, dxgi_factory, d3d_command_queue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ class DXFramebuffer;
|
||||||
class SwapChain : public D3DCommon::SwapChain
|
class SwapChain : public D3DCommon::SwapChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory,
|
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory,
|
||||||
ID3D12CommandQueue* d3d_command_queue);
|
ID3D12CommandQueue* d3d_command_queue);
|
||||||
~SwapChain();
|
~SwapChain();
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,9 @@ void UnloadLibraries()
|
||||||
s_libraries_loaded = false;
|
s_libraries_loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDXGIFactory2* CreateDXGIFactory(bool debug_device)
|
IDXGIFactory* CreateDXGIFactory(bool debug_device)
|
||||||
{
|
{
|
||||||
IDXGIFactory2* factory;
|
IDXGIFactory* factory;
|
||||||
|
|
||||||
// Use Win8.1 version if available.
|
// Use Win8.1 version if available.
|
||||||
if (create_dxgi_factory2 &&
|
if (create_dxgi_factory2 &&
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
|
||||||
struct IDXGIFactory2;
|
struct IDXGIFactory;
|
||||||
|
|
||||||
enum class AbstractTextureFormat : u32;
|
enum class AbstractTextureFormat : u32;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ void UnloadLibraries();
|
||||||
std::vector<std::string> GetAdapterNames();
|
std::vector<std::string> GetAdapterNames();
|
||||||
|
|
||||||
// Helper function which creates a DXGI factory.
|
// Helper function which creates a DXGI factory.
|
||||||
IDXGIFactory2* CreateDXGIFactory(bool debug_device);
|
IDXGIFactory* CreateDXGIFactory(bool debug_device);
|
||||||
|
|
||||||
// Globally-accessible D3DCompiler function.
|
// Globally-accessible D3DCompiler function.
|
||||||
extern pD3DCompile d3d_compile;
|
extern pD3DCompile d3d_compile;
|
||||||
|
|
|
@ -25,7 +25,7 @@ static bool IsTearingSupported(IDXGIFactory2* dxgi_factory)
|
||||||
allow_tearing != 0;
|
allow_tearing != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GetFullscreenState(IDXGISwapChain1* swap_chain)
|
static bool GetFullscreenState(IDXGISwapChain* swap_chain)
|
||||||
{
|
{
|
||||||
BOOL fs = FALSE;
|
BOOL fs = FALSE;
|
||||||
return SUCCEEDED(swap_chain->GetFullscreenState(&fs, nullptr)) && fs;
|
return SUCCEEDED(swap_chain->GetFullscreenState(&fs, nullptr)) && fs;
|
||||||
|
@ -33,9 +33,8 @@ static bool GetFullscreenState(IDXGISwapChain1* swap_chain)
|
||||||
|
|
||||||
namespace D3DCommon
|
namespace D3DCommon
|
||||||
{
|
{
|
||||||
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device)
|
SwapChain::SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, IUnknown* d3d_device)
|
||||||
: m_wsi(wsi), m_dxgi_factory(dxgi_factory), m_d3d_device(d3d_device),
|
: m_wsi(wsi), m_dxgi_factory(dxgi_factory), m_d3d_device(d3d_device)
|
||||||
m_allow_tearing_supported(IsTearingSupported(dxgi_factory))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +65,13 @@ bool SwapChain::CreateSwapChain(bool stereo)
|
||||||
m_height = client_rc.bottom - client_rc.top;
|
m_height = client_rc.bottom - client_rc.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try using the Win8 version if available.
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory2;
|
||||||
|
HRESULT hr = m_dxgi_factory.As(&dxgi_factory2);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
m_allow_tearing_supported = IsTearingSupported(dxgi_factory2.Get());
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||||
swap_chain_desc.Width = m_width;
|
swap_chain_desc.Width = m_width;
|
||||||
swap_chain_desc.Height = m_height;
|
swap_chain_desc.Height = m_height;
|
||||||
|
@ -79,27 +85,43 @@ bool SwapChain::CreateSwapChain(bool stereo)
|
||||||
swap_chain_desc.Stereo = stereo;
|
swap_chain_desc.Stereo = stereo;
|
||||||
swap_chain_desc.Flags = GetSwapChainFlags();
|
swap_chain_desc.Flags = GetSwapChainFlags();
|
||||||
|
|
||||||
HRESULT hr = m_dxgi_factory->CreateSwapChainForHwnd(
|
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain1;
|
||||||
m_d3d_device.Get(), static_cast<HWND>(m_wsi.render_surface), &swap_chain_desc, nullptr,
|
hr = dxgi_factory2->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
||||||
nullptr, &m_swap_chain);
|
static_cast<HWND>(m_wsi.render_surface),
|
||||||
|
&swap_chain_desc, nullptr, nullptr, &swap_chain1);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to
|
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to
|
||||||
// a sequential swapchain
|
// a sequential swapchain
|
||||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||||
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
hr = dxgi_factory2->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
||||||
static_cast<HWND>(m_wsi.render_surface),
|
static_cast<HWND>(m_wsi.render_surface),
|
||||||
&swap_chain_desc, nullptr, nullptr, &m_swap_chain);
|
&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))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
// Flip-model swapchains aren't supported on Windows 7, so here we fall back to a legacy
|
DXGI_SWAP_CHAIN_DESC desc = {};
|
||||||
// BitBlt-model swapchain
|
desc.BufferDesc.Width = m_width;
|
||||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
desc.BufferDesc.Height = m_height;
|
||||||
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(),
|
desc.BufferDesc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false);
|
||||||
static_cast<HWND>(m_wsi.render_surface),
|
desc.SampleDesc.Count = 1;
|
||||||
&swap_chain_desc, nullptr, nullptr, &m_swap_chain);
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT;
|
||||||
|
desc.OutputWindow = static_cast<HWND>(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))
|
if (FAILED(hr))
|
||||||
|
@ -147,11 +169,11 @@ bool SwapChain::ResizeSwapChain()
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
WARN_LOG(VIDEO, "ResizeBuffers() failed with HRESULT %08X", hr);
|
WARN_LOG(VIDEO, "ResizeBuffers() failed with HRESULT %08X", hr);
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 desc;
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
if (SUCCEEDED(m_swap_chain->GetDesc1(&desc)))
|
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
|
||||||
{
|
{
|
||||||
m_width = desc.Width;
|
m_width = desc.BufferDesc.Width;
|
||||||
m_height = desc.Height;
|
m_height = desc.BufferDesc.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateSwapChainBuffers();
|
return CreateSwapChainBuffers();
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace D3DCommon
|
||||||
class SwapChain
|
class SwapChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory2* dxgi_factory, IUnknown* d3d_device);
|
SwapChain(const WindowSystemInfo& wsi, IDXGIFactory* dxgi_factory, IUnknown* d3d_device);
|
||||||
virtual ~SwapChain();
|
virtual ~SwapChain();
|
||||||
|
|
||||||
// Sufficient buffers for triple buffering.
|
// Sufficient buffers for triple buffering.
|
||||||
|
@ -26,7 +26,7 @@ public:
|
||||||
// Returns true if the stereo mode is quad-buffering.
|
// Returns true if the stereo mode is quad-buffering.
|
||||||
static bool WantsStereo();
|
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; }
|
AbstractTextureFormat GetFormat() const { return m_texture_format; }
|
||||||
u32 GetWidth() const { return m_width; }
|
u32 GetWidth() const { return m_width; }
|
||||||
u32 GetHeight() const { return m_height; }
|
u32 GetHeight() const { return m_height; }
|
||||||
|
@ -57,8 +57,8 @@ protected:
|
||||||
virtual void DestroySwapChainBuffers() = 0;
|
virtual void DestroySwapChainBuffers() = 0;
|
||||||
|
|
||||||
WindowSystemInfo m_wsi;
|
WindowSystemInfo m_wsi;
|
||||||
Microsoft::WRL::ComPtr<IDXGIFactory2> m_dxgi_factory;
|
Microsoft::WRL::ComPtr<IDXGIFactory> m_dxgi_factory;
|
||||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swap_chain;
|
Microsoft::WRL::ComPtr<IDXGISwapChain> m_swap_chain;
|
||||||
Microsoft::WRL::ComPtr<IUnknown> m_d3d_device;
|
Microsoft::WRL::ComPtr<IUnknown> m_d3d_device;
|
||||||
AbstractTextureFormat m_texture_format = AbstractTextureFormat::RGBA8;
|
AbstractTextureFormat m_texture_format = AbstractTextureFormat::RGBA8;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue