Skip to content
Permalink
Browse files

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

D3DCommon: Fallback to base CreateSwapChain on failure
  • Loading branch information...
stenzek committed Jun 8, 2019
2 parents 0177c6c + 1028e2c commit 6567409177655422445a971dfb6c130f933ff970
@@ -23,7 +23,7 @@ namespace DX11
static Common::DynamicLibrary s_d3d11_library;
namespace D3D
{
ComPtr<IDXGIFactory2> dxgi_factory;
ComPtr<IDXGIFactory> dxgi_factory;
ComPtr<ID3D11Device> device;
ComPtr<ID3D11Device1> device1;
ComPtr<ID3D11DeviceContext> context;
@@ -173,7 +173,7 @@ std::vector<u32> GetAAModes(u32 adapter_index)
ComPtr<ID3D11Device> temp_device = device;
if (!temp_device)
{
ComPtr<IDXGIFactory2> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
if (!temp_dxgi_factory)
return {};

@@ -28,7 +28,7 @@ class SwapChain;

namespace D3D
{
extern ComPtr<IDXGIFactory2> dxgi_factory;
extern ComPtr<IDXGIFactory> dxgi_factory;
extern ComPtr<ID3D11Device> device;
extern ComPtr<ID3D11Device1> device1;
extern ComPtr<ID3D11DeviceContext> context;
@@ -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)
{
@@ -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<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;
if (!temp_device)
{
ComPtr<IDXGIFactory2> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
ComPtr<IDXGIFactory> temp_dxgi_factory = D3DCommon::CreateDXGIFactory(false);
if (!temp_dxgi_factory)
return {};

@@ -57,7 +57,8 @@ std::vector<u32> 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 {};
}
@@ -5,16 +5,14 @@
#pragma once

#include <array>
#include <functional>
#include <map>

#include "Common/CommonTypes.h"
#include "VideoBackends/D3D12/Common.h"
#include "VideoBackends/D3D12/DescriptorAllocator.h"
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
#include "VideoBackends/D3D12/StreamBuffer.h"

struct IDXGIFactory2;
struct IDXGIFactory;

namespace DX12
{
@@ -54,7 +52,7 @@ class DXContext
// 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 +157,7 @@ class DXContext
void MoveToNextCommandList();
void DestroyPendingResources(CommandListResources& cmdlist);

ComPtr<IDXGIFactory2> m_dxgi_factory;
ComPtr<IDXGIFactory> m_dxgi_factory;
ComPtr<ID3D12Debug> m_debug_interface;
ComPtr<ID3D12Device> m_device;
ComPtr<ID3D12CommandQueue> m_command_queue;
@@ -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)
{
@@ -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();

@@ -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 &&
@@ -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<std::string> 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;
@@ -25,17 +25,16 @@ 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;
}

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<HWND>(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<IDXGIFactory2> 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<HWND>(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<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))
{
// 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<HWND>(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<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))
@@ -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();
@@ -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 @@ class SwapChain
// 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 @@ class SwapChain
virtual void DestroySwapChainBuffers() = 0;

WindowSystemInfo m_wsi;
Microsoft::WRL::ComPtr<IDXGIFactory2> m_dxgi_factory;
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swap_chain;
Microsoft::WRL::ComPtr<IDXGIFactory> m_dxgi_factory;
Microsoft::WRL::ComPtr<IDXGISwapChain> m_swap_chain;
Microsoft::WRL::ComPtr<IUnknown> m_d3d_device;
AbstractTextureFormat m_texture_format = AbstractTextureFormat::RGBA8;

0 comments on commit 6567409

Please sign in to comment.
You can’t perform that action at this time.