Merge pull request #8096 from stenzek/d3d-old-drivers

D3DCommon: Fallback to base CreateSwapChain on failure
This commit is contained in:
Connor McLaughlin
2019-06-08 20:41:04 +10:00
committed by GitHub
12 changed files with 80 additions and 59 deletions

View File

@ -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 {};

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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 {};
} }

View File

@ -5,8 +5,6 @@
#pragma once #pragma once
#include <array> #include <array>
#include <functional>
#include <map>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoBackends/D3D12/Common.h" #include "VideoBackends/D3D12/Common.h"
@ -14,7 +12,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 +52,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 +157,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;

View File

@ -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)
{ {

View File

@ -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();

View File

@ -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 &&

View File

@ -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;

View File

@ -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,40 +65,63 @@ bool SwapChain::CreateSwapChain(bool stereo)
m_height = client_rc.bottom - client_rc.top; m_height = client_rc.bottom - client_rc.top;
} }
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; // Try using the Win8 version if available.
swap_chain_desc.Width = m_width; Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory2;
swap_chain_desc.Height = m_height; HRESULT hr = m_dxgi_factory.As(&dxgi_factory2);
swap_chain_desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT; if (SUCCEEDED(hr))
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<HWND>(m_wsi.render_surface), &swap_chain_desc, nullptr,
nullptr, &m_swap_chain);
if (FAILED(hr))
{ {
// Flip-model discard swapchains aren't supported on Windows 8, so here we fall back to m_allow_tearing_supported = IsTearingSupported(dxgi_factory2.Get());
// a sequential swapchain
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_d3d_device.Get(), swap_chain_desc.Width = m_width;
static_cast<HWND>(m_wsi.render_surface), swap_chain_desc.Height = m_height;
&swap_chain_desc, nullptr, nullptr, &m_swap_chain); 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<IDXGISwapChain1> swap_chain1;
hr = dxgi_factory2->CreateSwapChainForHwnd(m_d3d_device.Get(),
static_cast<HWND>(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<HWND>(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)) 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();

View File

@ -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;