From e79491175515bc6672772935e0f25edba6beda82 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Thu, 17 Mar 2022 21:05:42 +0200 Subject: [PATCH 1/3] Enable flip presentation mode and tearing in D3D11 --- .../DirectX/DX11/GPUDeviceDX11.cpp | 13 +++++++++++++ .../DirectX/DX11/GPUDeviceDX11.h | 4 ++++ .../DirectX/DX11/GPUSwapChainDX11.cpp | 18 +++++++++++++++++- .../DirectX/DX11/GPUSwapChainDX11.h | 1 + .../DirectX/IncludeDirectXHeaders.h | 1 + 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index ead6ca9c3..c5cb7c472 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -265,6 +265,19 @@ bool GPUDeviceDX11::Init() return true; } UpdateOutputs(adapter); + { + ComPtr factory5; + _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); + if (factory5) + { + BOOL allowTearing; + if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) && allowTearing) + { + AllowTearing = true; + } + } + } + // Get flags and device type base on current configuration uint32 flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h index de0132ea3..ec2ba0177 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h @@ -50,6 +50,10 @@ public: GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter); ~GPUDeviceDX11(); +public: + + bool AllowTearing = false; + public: // Gets DX11 device diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp index 56fcfcc77..79e76a2a5 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp @@ -17,6 +17,8 @@ GPUSwapChainDX11::GPUSwapChainDX11(GPUDeviceDX11* device, Window* window) #endif , _swapChain(nullptr) , _backBuffer(nullptr) + , _allowTearing(false) + , _isFullscreen(false) { ASSERT(_windowHandle); _window = window; @@ -108,6 +110,8 @@ void GPUSwapChainDX11::SetFullscreen(bool isFullscreen) { LOG(Warning, "Cannot change fullscreen mode for '{0}' to {1}.", ToString(), isFullscreen); } + + _isFullscreen = isFullscreen; } #else LOG(Info, "Cannot change fullscreen mode on this platform"); @@ -123,7 +127,12 @@ void GPUSwapChainDX11::Present(bool vsync) { // Present frame ASSERT(_swapChain); - const HRESULT result = _swapChain->Present(vsync ? 1 : 0, 0); + UINT presentFlags = 0; + if (!vsync && !_isFullscreen && _allowTearing) + { + presentFlags |= DXGI_PRESENT_ALLOW_TEARING; + } + const HRESULT result = _swapChain->Present(vsync ? 1 : 0, presentFlags); LOG_DIRECTX_RESULT(result); // Base @@ -140,6 +149,7 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height) _device->WaitForGPU(); GPUDeviceLock lock(_device); + _allowTearing = _device->AllowTearing; _format = GPU_BACK_BUFFER_PIXEL_FORMAT; #if PLATFORM_WINDOWS @@ -177,6 +187,12 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height) swapChainDesc.Windowed = TRUE; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + if (_allowTearing) + { + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } #else swapChainDesc.Width = width; swapChainDesc.Height = height; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h index f0a785930..35688affc 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h @@ -23,6 +23,7 @@ private: #if PLATFORM_WINDOWS HWND _windowHandle; IDXGISwapChain* _swapChain; + bool _allowTearing, _isFullscreen; #else IUnknown* _windowHandle; IDXGISwapChain1* _swapChain; diff --git a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h index ca4dae608..7cf4be599 100644 --- a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h +++ b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h @@ -39,6 +39,7 @@ typedef IGraphicsUnknown IDXGISwapChain3; #include #include #include +#include #endif #if GRAPHICS_API_DIRECTX12 #include From 33fe5e75187079945fac3a24670d429bb4d41ee4 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Thu, 17 Mar 2022 21:06:33 +0200 Subject: [PATCH 2/3] Fix uninitialized values and release COM resources after use --- Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp | 1 + Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp | 1 + Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index c5cb7c472..35d2253a2 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -275,6 +275,7 @@ bool GPUDeviceDX11::Init() { AllowTearing = true; } + factory5->Release(); } } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 5aae0febf..303aa6e3d 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -274,6 +274,7 @@ bool GPUDeviceDX12::Init() { AllowTearing = true; } + factory5->Release(); } } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp index f4784f479..18b1af930 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp @@ -51,6 +51,8 @@ GPUSwapChainDX12::GPUSwapChainDX12(GPUDeviceDX12* device, Window* window) , _windowHandle(static_cast(window->GetNativePtr())) , _swapChain(nullptr) , _currentFrameIndex(0) + , _allowTearing(false) + , _isFullscreen(false) { ASSERT(_windowHandle); _window = window; From 6e6f2859ab8874825452ee852f1b1c6923aead09 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 26 Mar 2022 16:48:02 +0200 Subject: [PATCH 3/3] Fix switching to fullscreen mode in D3D11/D3D12 flip presentation modes --- .../DirectX/DX11/GPUDeviceDX11.cpp | 19 ++++++++----------- .../DirectX/DX11/GPUSwapChainDX11.cpp | 12 +++++++++++- .../DirectX/DX12/GPUSwapChainDX12.cpp | 12 +++++++++++- .../Engine/Platform/Windows/WindowsWindow.cpp | 10 ++++++++++ 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 35d2253a2..aadac4abf 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -265,18 +265,15 @@ bool GPUDeviceDX11::Init() return true; } UpdateOutputs(adapter); + + ComPtr factory5; + _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); + if (factory5) { - ComPtr factory5; - _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); - if (factory5) - { - BOOL allowTearing; - if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) && allowTearing) - { - AllowTearing = true; - } - factory5->Release(); - } + BOOL allowTearing; + if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) && allowTearing) + AllowTearing = true; + factory5->Release(); } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp index 79e76a2a5..c7b884c59 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp @@ -112,6 +112,16 @@ void GPUSwapChainDX11::SetFullscreen(bool isFullscreen) } _isFullscreen = isFullscreen; + + // Buffers must be resized in flip presentation model + if (swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL || + swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD) + { + const int32 width = _width; + const int32 height = _height; + _width = _height = 0; + Resize(width, height); + } } #else LOG(Info, "Cannot change fullscreen mode on this platform"); @@ -218,7 +228,7 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height) ASSERT(_swapChain); // Disable DXGI changes to the window - VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, 0)); + VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER)); #else auto dxgiFactory = (IDXGIFactory2*)_device->GetDXGIFactory(); VALIDATE_DIRECTX_RESULT(dxgiFactory->CreateSwapChainForCoreWindow(_device->GetDevice(), static_cast(_windowHandle), &swapChainDesc, nullptr, &_swapChain)); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp index 18b1af930..e7e976987 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp @@ -137,6 +137,16 @@ void GPUSwapChainDX12::SetFullscreen(bool isFullscreen) } _isFullscreen = isFullscreen; + + // Buffers must be resized in flip presentation model + if (swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL || + swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD) + { + const int32 width = _width; + const int32 height = _height; + _width = _height = 0; + Resize(width, height); + } } #else LOG(Info, "Cannot change fullscreen mode on this platform"); @@ -219,7 +229,7 @@ bool GPUSwapChainDX12::Resize(int32 width, int32 height) _backBuffers.Resize(swapChainDesc.BufferCount); // Disable DXGI changes to the window - dxgiFactory->MakeWindowAssociation(_windowHandle, 0); + VALIDATE_DIRECTX_RESULT(dxgiFactory->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER)); } else { diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp index 50f092407..cb1617219 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp @@ -1031,6 +1031,10 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) // In this case, we don't resize yet -- we wait until the user stops dragging, and a WM_EXITSIZEMOVE message comes. UpdateRegion(); } + else if (_isSwitchingFullScreen) + { + // Ignored + } else { // This WM_SIZE come from resizing the window via an API like SetWindowPos() so resize @@ -1090,6 +1094,12 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) Close(ClosingReason::User); return 0; } + if (wParam == VK_RETURN) + { + LOG(Info, "Alt+Enter pressed"); + SetIsFullscreen(!IsFullscreen()); + return 0; + } break; case WM_POWERBROADCAST: switch (wParam)