From f88358621a3a2ffa1a9b7a87baa84695075337bd Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sat, 31 Mar 2018 11:55:55 -0700 Subject: Implemented switching to a fullscreen mode in d3d on Win32 --- .../include/SwapChainD3D11Impl.h | 10 +- .../src/RenderDeviceFactoryD3D11.cpp | 2 +- .../GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp | 191 ++++++--------------- 3 files changed, 59 insertions(+), 144 deletions(-) (limited to 'Graphics/GraphicsEngineD3D11') diff --git a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h index 2289f20d..5f5fe4fe 100644 --- a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h +++ b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h @@ -27,17 +27,17 @@ /// Declaration of Diligent::SwapChainD3D11Impl class #include "SwapChainD3D11.h" -#include "SwapChainBase.h" +#include "SwapChainD3DBase.h" namespace Diligent { class IMemoryAllocator; /// Implementation of the Diligent::ISwapChainD3D11 interface -class SwapChainD3D11Impl : public SwapChainBase +class SwapChainD3D11Impl : public SwapChainD3DBase { public: - typedef SwapChainBase TSwapChainBase; + using TSwapChainBase = SwapChainD3DBase; SwapChainD3D11Impl(IReferenceCounters *pRefCounters, const SwapChainDesc& SCDesc, const FullScreenModeDesc& FSDesc, @@ -57,9 +57,9 @@ public: virtual ID3D11DepthStencilView* GetDSV()override final{ return m_pDepthStencilView; } private: + virtual void UpdateSwapChain(bool CreateNew)override final; void CreateRTVandDSV(); - /// D3D11 swap chain - CComPtr m_pSwapChain; + /// Back buffer render target view CComPtr m_pRenderTargetView; /// Back buffer depth-stencil view diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceFactoryD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceFactoryD3D11.cpp index 3084b881..bd8916b9 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceFactoryD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceFactoryD3D11.cpp @@ -254,7 +254,7 @@ void EngineFactoryD3D11Impl::AttachToD3D11Device(void *pd3d11NativeDevice, { CComPtr pd3d11DeferredCtx; HRESULT hr = pd3d11Device->CreateDeferredContext(0, &pd3d11DeferredCtx); - CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 deferred context") + CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 deferred context"); RefCntAutoPtr pDeferredCtxD3D11( NEW_RC_OBJ(RawAlloctor, "DeviceContextD3D11Impl instance", DeviceContextD3D11Impl) (RawAlloctor, pRenderDeviceD3D11, pd3d11DeferredCtx, EngineAttribs, true)); diff --git a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp index 34bb54d0..7b0f99b5 100644 --- a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp @@ -38,117 +38,15 @@ SwapChainD3D11Impl::SwapChainD3D11Impl(IReferenceCounters *pRefCounters, RenderDeviceD3D11Impl* pRenderDeviceD3D11, DeviceContextD3D11Impl* pDeviceContextD3D11, void* pNativeWndHandle) : - TSwapChainBase(pRefCounters, pRenderDeviceD3D11, pDeviceContextD3D11, SCDesc) + TSwapChainBase(pRefCounters, pRenderDeviceD3D11, pDeviceContextD3D11, SCDesc, FSDesc, pNativeWndHandle) { - -#if PLATFORM_WIN32 - auto hWnd = reinterpret_cast(pNativeWndHandle); - - if( m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0 ) - { - RECT rc; - if(FSDesc.Fullscreen) - { - const HWND hDesktop = GetDesktopWindow(); - GetWindowRect(hDesktop, &rc); - } - else - { - GetClientRect(hWnd, &rc); - } - m_SwapChainDesc.Width = rc.right - rc.left; - m_SwapChainDesc.Height = rc.bottom - rc.top; - } -#endif - - auto *pDevice = pRenderDeviceD3D11->GetD3D11Device(); - - auto DXGIColorBuffFmt = TexFormatToDXGI_Format(m_SwapChainDesc.ColorBufferFormat); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; - swapChainDesc.Width = m_SwapChainDesc.Width; - swapChainDesc.Height = m_SwapChainDesc.Height; - // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats: - // - DXGI_FORMAT_R16G16B16A16_FLOAT - // - DXGI_FORMAT_B8G8R8A8_UNORM - // - DXGI_FORMAT_R8G8B8A8_UNORM - // - DXGI_FORMAT_R10G10B10A2_UNORM - // If RGBA8_UNORM_SRGB swap chain is required, we will create RGBA8_UNORM swap chain, but - // create RGBA8_UNORM_SRGB render target view - swapChainDesc.Format = DXGIColorBuffFmt == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGIColorBuffFmt; - swapChainDesc.Stereo = FALSE; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.BufferCount = m_SwapChainDesc.BufferCount; - swapChainDesc.Scaling = DXGI_SCALING_NONE; - // Windows Store apps must use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL or DXGI_SWAP_EFFECT_FLIP_DISCARD. - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - - CComPtr pSwapChain1; - -#if PLATFORM_WIN32 - - // This sequence obtains the DXGI factory that was used to create the Direct3D device above. - CComPtr pDXGIDevice; - pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast( static_cast(&pDXGIDevice) ) ); - CComPtr pDXGIAdapter; - pDXGIDevice->GetAdapter(&pDXGIAdapter); - CComPtr pDXGIFactory; - pDXGIAdapter->GetParent(__uuidof(pDXGIFactory), reinterpret_cast( static_cast(&pDXGIFactory) )); - - DXGI_SWAP_CHAIN_FULLSCREEN_DESC FullScreenDesc = {}; - FullScreenDesc.Windowed = FSDesc.Fullscreen ? FALSE : TRUE; - FullScreenDesc.RefreshRate.Numerator = FSDesc.RefreshRateNumerator; - FullScreenDesc.RefreshRate.Denominator = FSDesc.RefreshRateDenominator; - FullScreenDesc.Scaling = static_cast(FSDesc.Scaling); - FullScreenDesc.ScanlineOrdering = static_cast(FSDesc.ScanlineOrder); - CHECK_D3D_RESULT_THROW( pDXGIFactory->CreateSwapChainForHwnd(pDevice, hWnd, &swapChainDesc, &FullScreenDesc, nullptr, &pSwapChain1), - "Failed to create DXGI swap chain" ); - -#elif PLATFORM_UNIVERSAL_WINDOWS - - if (FSDesc.Fullscreen) - LOG_WARNING_MESSAGE("UWP applications do not support fullscreen mode"); - - CComPtr pDXGIDevice; - pDevice->QueryInterface(__uuidof(IDXGIDevice3), reinterpret_cast(static_cast(&pDXGIDevice))); - CComPtr pDXGIAdapter; - pDXGIDevice->GetAdapter(&pDXGIAdapter); - CComPtr pDXGIFactory; - pDXGIAdapter->GetParent(__uuidof(pDXGIFactory), reinterpret_cast(static_cast(&pDXGIFactory))); - - HRESULT hr = pDXGIFactory->CreateSwapChainForCoreWindow( - pDevice, - reinterpret_cast(pNativeWndHandle), - &swapChainDesc, - nullptr, - &pSwapChain1); - CHECK_D3D_RESULT_THROW( hr, "Failed to create DXGI swap chain" ); - - // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and - // ensures that the application will only render after each VSync, minimizing power consumption. - pDXGIDevice->SetMaximumFrameLatency( 1 ); - -#endif - - pSwapChain1->QueryInterface( __uuidof(m_pSwapChain), reinterpret_cast(static_cast(&m_pSwapChain)) ); - + auto *pd3d11Device = pRenderDeviceD3D11->GetD3D11Device(); + CreateDXGISwapChain(pd3d11Device); CreateRTVandDSV(); } SwapChainD3D11Impl::~SwapChainD3D11Impl() { - // Swap chain must be in windowed mode when terminating the app - if(m_pSwapChain) - { - BOOL IsFullScreen = FALSE; - m_pSwapChain->GetFullscreenState(&IsFullScreen, nullptr); - if(IsFullScreen) - m_pSwapChain->SetFullscreenState(FALSE, nullptr); - } } void SwapChainD3D11Impl::CreateRTVandDSV() @@ -231,53 +129,70 @@ void SwapChainD3D11Impl::Present() pImmediateCtxD3D11->CommitRenderTargets(); } -void SwapChainD3D11Impl::Resize( Uint32 NewWidth, Uint32 NewHeight ) +void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) { - if( TSwapChainBase::Resize(NewWidth, NewHeight) ) + // When switching to full screen mode, WM_SIZE is send to the window + // and Resize() is called before the new swap chain is created + if(!m_pSwapChain) + return; + + auto pDeviceContext = m_wpDeviceContext.Lock(); + VERIFY(pDeviceContext, "Immediate context has been released"); + if (pDeviceContext) { - auto pDeviceContext = m_wpDeviceContext.Lock(); - VERIFY( pDeviceContext, "Immediate context has been released" ); - if( pDeviceContext ) + auto *pImmediateCtxD3D11 = ValidatedCast(pDeviceContext.RawPtr()); + bool bIsDefaultFBBound = pImmediateCtxD3D11->IsDefaultFBBound(); + if (bIsDefaultFBBound) { - auto *pImmediateCtxD3D11 = ValidatedCast(pDeviceContext.RawPtr()); - bool bIsDefaultFBBound = pImmediateCtxD3D11->IsDefaultFBBound(); - if( bIsDefaultFBBound ) - { - ITextureView *pNullTexView[] = { nullptr }; - pImmediateCtxD3D11->SetRenderTargets( _countof( pNullTexView ), pNullTexView, nullptr ); - } + ITextureView *pNullTexView[] = { nullptr }; + pImmediateCtxD3D11->SetRenderTargets(_countof(pNullTexView), pNullTexView, nullptr); + } - // Swap chain cannot be resized until all references are released - m_pRenderTargetView.Release(); - m_pDepthStencilView.Release(); + // Swap chain cannot be resized until all references are released + m_pRenderTargetView.Release(); + m_pDepthStencilView.Release(); - try + try + { + if(CreateNew) + { + m_pSwapChain.Release(); + auto *pd3d11Device = ValidatedCast(m_pRenderDevice.RawPtr())->GetD3D11Device(); + CreateDXGISwapChain(pd3d11Device); + } + else { DXGI_SWAP_CHAIN_DESC SCDes; - memset( &SCDes, 0, sizeof( SCDes ) ); - m_pSwapChain->GetDesc( &SCDes ); - CHECK_D3D_RESULT_THROW( m_pSwapChain->ResizeBuffers(SCDes.BufferCount, m_SwapChainDesc.Width, - m_SwapChainDesc.Height, SCDes.BufferDesc.Format, - SCDes.Flags), - "Failed to resize the DXGI swap chain" ); + memset(&SCDes, 0, sizeof(SCDes)); + m_pSwapChain->GetDesc(&SCDes); + CHECK_D3D_RESULT_THROW(m_pSwapChain->ResizeBuffers(SCDes.BufferCount, m_SwapChainDesc.Width, + m_SwapChainDesc.Height, SCDes.BufferDesc.Format, + SCDes.Flags), + "Failed to resize the DXGI swap chain"); + } + CreateRTVandDSV(); - CreateRTVandDSV(); - - if( bIsDefaultFBBound ) - { - // Set default render target and viewport - pImmediateCtxD3D11->SetRenderTargets( 0, nullptr, nullptr ); - pImmediateCtxD3D11->SetViewports( 1, nullptr, 0, 0 ); - } - } - catch( const std::runtime_error & ) + if (bIsDefaultFBBound) { - LOG_ERROR( "Failed to resize the swap chain" ); + // Set default render target and viewport + pImmediateCtxD3D11->SetRenderTargets(0, nullptr, nullptr); + pImmediateCtxD3D11->SetViewports(1, nullptr, 0, 0); } } + catch (const std::runtime_error &) + { + LOG_ERROR("Failed to resize the swap chain"); + } } } +void SwapChainD3D11Impl::Resize( Uint32 NewWidth, Uint32 NewHeight ) +{ + if( TSwapChainBase::Resize(NewWidth, NewHeight) ) + { + UpdateSwapChain(false); + } +} } -- cgit v1.2.3