diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index ead6ca9c3..aadac4abf 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -266,6 +266,17 @@ bool GPUDeviceDX11::Init() } 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; + factory5->Release(); + } + + // Get flags and device type base on current configuration uint32 flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if GPU_ENABLE_DIAGNOSTICS 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..c7b884c59 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,18 @@ void GPUSwapChainDX11::SetFullscreen(bool isFullscreen) { LOG(Warning, "Cannot change fullscreen mode for '{0}' to {1}.", ToString(), 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"); @@ -123,7 +137,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 +159,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 +197,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; @@ -202,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/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/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..e7e976987 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; @@ -135,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"); @@ -217,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/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 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)