From 46033898ba3e0b27138f79703fda3fad6e239e3e Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 18 Jan 2020 18:12:09 +1000 Subject: [PATCH] Frontends: Use DXGI_PRESENT_FLAG_ALLOW_TEARING for presentatation --- src/duckstation-qt/d3d11displaywindow.cpp | 41 ++++++++++--- src/duckstation-qt/d3d11displaywindow.h | 1 + src/duckstation/CMakeLists.txt | 2 +- src/duckstation/d3d11_host_display.cpp | 73 +++++++++++++++++------ src/duckstation/d3d11_host_display.h | 1 + src/duckstation/duckstation.vcxproj | 16 ++--- 6 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/duckstation-qt/d3d11displaywindow.cpp b/src/duckstation-qt/d3d11displaywindow.cpp index 7f2cd2972..f311d3bc1 100644 --- a/src/duckstation-qt/d3d11displaywindow.cpp +++ b/src/duckstation-qt/d3d11displaywindow.cpp @@ -3,6 +3,7 @@ #include "common/d3d11/shader_compiler.h" #include "common/log.h" #include +#include #include #include Log_SetChannel(D3D11DisplayWindow); @@ -193,7 +194,7 @@ void D3D11DisplayWindow::onWindowResized(int width, int height) bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) { - const bool debug = true; + const bool debug = false; ComPtr dxgi_factory; HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); @@ -203,6 +204,18 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) return false; } + m_allow_tearing_supported = false; + ComPtr dxgi_factory5; + hr = dxgi_factory.As(&dxgi_factory5); + if (SUCCEEDED(hr)) + { + BOOL allow_tearing_supported = false; + hr = dxgi_factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported, + sizeof(allow_tearing_supported)); + if (SUCCEEDED(hr)) + m_allow_tearing_supported = (allow_tearing_supported == TRUE); + } + UINT create_flags = 0; if (debug) create_flags |= D3D11_CREATE_DEVICE_DEBUG; @@ -227,11 +240,17 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) swap_chain_desc.Windowed = TRUE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + if (m_allow_tearing_supported) + swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf()); if (FAILED(hr)) { Log_WarningPrintf("Failed to create a flip-discard swap chain, trying discard."); swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swap_chain_desc.Flags = 0; + m_allow_tearing_supported = false; + hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf()); if (FAILED(hr)) { @@ -240,15 +259,16 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) } } -#if 1 - ComPtr info; - hr = m_device.As(&info); - if (SUCCEEDED(hr)) + if (debug) { - info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE); - info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE); + ComPtr info; + hr = m_device.As(&info); + if (SUCCEEDED(hr)) + { + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE); + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE); + } } -#endif if (!QtDisplayWindow::createDeviceContext(worker_thread)) { @@ -422,7 +442,10 @@ void D3D11DisplayWindow::Render() ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - m_swap_chain->Present(BoolToUInt32(m_vsync), 0); + if (!m_vsync && m_allow_tearing_supported) + m_swap_chain->Present(0, DXGI_PRESENT_ALLOW_TEARING); + else + m_swap_chain->Present(BoolToUInt32(m_vsync), 0); ImGui::NewFrame(); ImGui_ImplDX11_NewFrame(); diff --git a/src/duckstation-qt/d3d11displaywindow.h b/src/duckstation-qt/d3d11displaywindow.h index 56e6bf865..88e948a3b 100644 --- a/src/duckstation-qt/d3d11displaywindow.h +++ b/src/duckstation-qt/d3d11displaywindow.h @@ -91,5 +91,6 @@ private: bool m_display_texture_changed = false; bool m_display_linear_filtering = false; + bool m_allow_tearing_supported = false; bool m_vsync = false; }; diff --git a/src/duckstation/CMakeLists.txt b/src/duckstation/CMakeLists.txt index 1385244a1..35fdf1003 100644 --- a/src/duckstation/CMakeLists.txt +++ b/src/duckstation/CMakeLists.txt @@ -19,7 +19,7 @@ if(WIN32) d3d11_host_display.cpp d3d11_host_display.h ) - target_link_libraries(duckstation PRIVATE d3d11.lib winmm.lib) + target_link_libraries(duckstation PRIVATE d3d11.lib dxgi.lib winmm.lib) endif() target_link_libraries(duckstation PRIVATE core common imgui nativefiledialog glad simpleini SDL2::Main) diff --git a/src/duckstation/d3d11_host_display.cpp b/src/duckstation/d3d11_host_display.cpp index 52e9da6ed..d1c3b580f 100644 --- a/src/duckstation/d3d11_host_display.cpp +++ b/src/duckstation/d3d11_host_display.cpp @@ -4,6 +4,7 @@ #include "common/log.h" #include #include +#include #include #include #include @@ -191,7 +192,7 @@ void D3D11HostDisplay::WindowResized() bool D3D11HostDisplay::CreateD3DDevice() { - const bool debug = false; + const bool debug = true; SDL_SysWMinfo syswm = {}; if (!SDL_GetWindowWMInfo(m_window, &syswm)) @@ -200,10 +201,39 @@ bool D3D11HostDisplay::CreateD3DDevice() return false; } + ComPtr dxgi_factory; + HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); + if (FAILED(hr)) + { + Log_ErrorPrintf("Failed to create DXGI factory: 0x%08X", hr); + return false; + } + + m_allow_tearing_supported = false; + ComPtr dxgi_factory5; + hr = dxgi_factory.As(&dxgi_factory5); + if (SUCCEEDED(hr)) + { + BOOL allow_tearing_supported = false; + hr = dxgi_factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported, + sizeof(allow_tearing_supported)); + if (SUCCEEDED(hr)) + m_allow_tearing_supported = (allow_tearing_supported == TRUE); + } + UINT create_flags = 0; if (debug) create_flags |= D3D11_CREATE_DEVICE_DEBUG; + hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, D3D11_SDK_VERSION, + m_device.GetAddressOf(), nullptr, m_context.GetAddressOf()); + + if (FAILED(hr)) + { + Log_ErrorPrintf("Failed to create D3D device: 0x%08X", hr); + return false; + } + DXGI_SWAP_CHAIN_DESC swap_chain_desc = {}; swap_chain_desc.BufferDesc.Width = m_window_width; swap_chain_desc.BufferDesc.Height = m_window_height; @@ -215,32 +245,36 @@ bool D3D11HostDisplay::CreateD3DDevice() swap_chain_desc.Windowed = TRUE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, - D3D11_SDK_VERSION, &swap_chain_desc, m_swap_chain.GetAddressOf(), - m_device.GetAddressOf(), nullptr, m_context.GetAddressOf()); + if (m_allow_tearing_supported) + swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf()); if (FAILED(hr)) { Log_WarningPrintf("Failed to create a flip-discard swap chain, trying discard."); swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swap_chain_desc.Flags = 0; + m_allow_tearing_supported = false; + + hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf()); + if (FAILED(hr)) + { + Log_ErrorPrintf("CreateSwapChain failed: 0x%08X", hr); + return false; + } } - if (FAILED(hr)) + if (debug) { - Log_ErrorPrintf("D3D11CreateDeviceAndSwapChain failed: 0x%08X", hr); - return false; + ComPtr info; + hr = m_device.As(&info); + if (SUCCEEDED(hr)) + { + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE); + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE); + } } -#if 0 - ComPtr info; - hr = m_device.As(&info); - if (SUCCEEDED(hr)) - { - info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE); - info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE); - } -#endif - return true; } @@ -374,7 +408,10 @@ void D3D11HostDisplay::Render() ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - m_swap_chain->Present(BoolToUInt32(m_vsync), 0); + if (!m_vsync && m_allow_tearing_supported) + m_swap_chain->Present(0, DXGI_PRESENT_ALLOW_TEARING); + else + m_swap_chain->Present(BoolToUInt32(m_vsync), 0); ImGui_ImplSDL2_NewFrame(m_window); ImGui_ImplDX11_NewFrame(); diff --git a/src/duckstation/d3d11_host_display.h b/src/duckstation/d3d11_host_display.h index 21f6f9088..c127397ad 100644 --- a/src/duckstation/d3d11_host_display.h +++ b/src/duckstation/d3d11_host_display.h @@ -85,5 +85,6 @@ private: bool m_display_texture_changed = false; bool m_display_linear_filtering = false; + bool m_allow_tearing_supported = false; bool m_vsync = false; }; diff --git a/src/duckstation/duckstation.vcxproj b/src/duckstation/duckstation.vcxproj index a12f01415..fd1e3a4f6 100644 --- a/src/duckstation/duckstation.vcxproj +++ b/src/duckstation/duckstation.vcxproj @@ -218,7 +218,7 @@ Console true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib32-debug;%(AdditionalLibraryDirectories) @@ -240,7 +240,7 @@ Console true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib64-debug;%(AdditionalLibraryDirectories) @@ -265,7 +265,7 @@ Console true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib32-debug;%(AdditionalLibraryDirectories) @@ -290,7 +290,7 @@ Console true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib64-debug;%(AdditionalLibraryDirectories) @@ -313,7 +313,7 @@ true true true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib32;%(AdditionalLibraryDirectories) Default @@ -338,7 +338,7 @@ true true true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib32;%(AdditionalLibraryDirectories) UseLinkTimeCodeGeneration @@ -362,7 +362,7 @@ true true true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib64;%(AdditionalLibraryDirectories) Default @@ -387,7 +387,7 @@ true true true - SDL2.lib;d3d11.lib;winmm.lib;%(AdditionalDependencies) + SDL2.lib;d3d11.lib;dxgi.lib;winmm.lib;%(AdditionalDependencies) $(SolutionDir)dep\msvc\lib64;%(AdditionalLibraryDirectories) UseLinkTimeCodeGeneration