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/SwapChainD3D12Impl.h | 10 +- .../src/DeviceContextD3D12Impl.cpp | 6 +- Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp | 4 +- .../src/RenderDeviceFactoryD3D12.cpp | 6 +- .../GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp | 184 ++++++--------------- 5 files changed, 67 insertions(+), 143 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h index 3b75be44..01d814b8 100644 --- a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h @@ -28,7 +28,7 @@ #include #include "SwapChainD3D12.h" -#include "SwapChainBase.h" +#include "SwapChainD3DBase.h" namespace Diligent { @@ -36,10 +36,10 @@ namespace Diligent class ITextureViewD3D12; class IMemoryAllocator; /// Implementation of the Diligent::ISwapChainD3D12 interface -class SwapChainD3D12Impl : public SwapChainBase +class SwapChainD3D12Impl : public SwapChainD3DBase { public: - typedef SwapChainBase TSwapChainBase; + using TSwapChainBase = SwapChainD3DBase; SwapChainD3D12Impl(IReferenceCounters *pRefCounters, const SwapChainDesc& SwapChainDesc, const FullScreenModeDesc& FSDesc, @@ -58,11 +58,9 @@ public: virtual ITextureViewD3D12* GetDepthBufferDSV()override final{return m_pDepthBufferDSV;} private: + virtual void UpdateSwapChain(bool CreateNew)override final; void InitBuffersAndViews(); - /// DXGI swap chain - CComPtr m_pSwapChain; - std::vector< RefCntAutoPtr, STDAllocatorRawMem> > m_pBackBufferRTV; RefCntAutoPtr m_pDepthBufferDSV; }; diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 3753a0a9..513f2907 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -61,17 +61,17 @@ namespace Diligent CmdSignatureDesc.ByteStride = sizeof(UINT)*4; IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW; auto hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDrawIndirectSignature), reinterpret_cast(static_cast(&m_pDrawIndirectSignature)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create indirect draw command signature") + CHECK_D3D_RESULT_THROW(hr, "Failed to create indirect draw command signature"); CmdSignatureDesc.ByteStride = sizeof(UINT)*5; IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDrawIndexedIndirectSignature), reinterpret_cast(static_cast(&m_pDrawIndexedIndirectSignature)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create draw indexed indirect command signature") + CHECK_D3D_RESULT_THROW(hr, "Failed to create draw indexed indirect command signature"); CmdSignatureDesc.ByteStride = sizeof(UINT)*3; IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH; hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDispatchIndirectSignature), reinterpret_cast(static_cast(&m_pDispatchIndirectSignature)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create dispatch indirect command signature") + CHECK_D3D_RESULT_THROW(hr, "Failed to create dispatch indirect command signature"); } DeviceContextD3D12Impl::~DeviceContextD3D12Impl() diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp index 70aaff66..12b64835 100644 --- a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp +++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp @@ -79,7 +79,7 @@ namespace Diligent CComPtr error; HRESULT hr = D3D12SerializeRootSignature(&RootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pGenerateMipsRS), reinterpret_cast( static_cast(&m_pGenerateMipsRS))); - CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature for mipmap generation") + CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature for mipmap generation"); D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc = {}; PSODesc.pRootSignature = m_pGenerateMipsRS; @@ -90,7 +90,7 @@ namespace Diligent PSODesc.CS.pShaderBytecode = ShaderByteCode;\ PSODesc.CS.BytecodeLength = sizeof(ShaderByteCode);\ hr = pd3d12Device->CreateComputePipelineState(&PSODesc, __uuidof(PSO), reinterpret_cast( static_cast(&PSO))); \ - CHECK_D3D_RESULT_THROW(hr, "Failed to create Pipeline state for mipmap generation") \ + CHECK_D3D_RESULT_THROW(hr, "Failed to create Pipeline state for mipmap generation"); \ PSO->SetName(L"Generate mips PSO"); CreatePSO(m_pGenerateMipsLinearPSO[0], g_pGenerateMipsLinearCS); diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp index 2fdbe59b..8f05e917 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp @@ -159,7 +159,7 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12( const EngineD3D12Attr CComPtr factory; HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory") + CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory"); CComPtr hardwareAdapter; if(CreationAttribs.AdapterId == EngineD3D12Attribs::DefaultAdapterId) @@ -192,10 +192,10 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12( const EngineD3D12Attr CComPtr warpAdapter; hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast(static_cast(&warpAdapter)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter") + CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter"); hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast(static_cast(&d3d12Device)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device") + CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device"); } #if _DEBUG diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp index 6add53b8..6078f6a2 100644 --- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp @@ -38,108 +38,16 @@ SwapChainD3D12Impl::SwapChainD3D12Impl(IReferenceCounters *pRefCounters, RenderDeviceD3D12Impl* pRenderDeviceD3D12, DeviceContextD3D12Impl* pDeviceContextD3D12, void* pNativeWndHandle) : - TSwapChainBase(pRefCounters, pRenderDeviceD3D12, pDeviceContextD3D12, SCDesc), + TSwapChainBase(pRefCounters, pRenderDeviceD3D12, pDeviceContextD3D12, SCDesc, FSDesc, pNativeWndHandle), m_pBackBufferRTV(STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr, GetRawAllocator(), "Allocator for vector>")) { - -#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 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; - CComPtr factory; - HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory") - auto *pd3d12CmdQueue = pRenderDeviceD3D12->GetCmdQueue()->GetD3D12CommandQueue(); - -#if PLATFORM_WIN32 - - 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); - hr = factory->CreateSwapChainForHwnd(pd3d12CmdQueue, hWnd, &swapChainDesc, &FullScreenDesc, nullptr, &pSwapChain1); - CHECK_D3D_RESULT_THROW( hr, "Failed to create Swap Chain" ); - - // This sample does not support fullscreen transitions. - hr = factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER); - -#elif PLATFORM_UNIVERSAL_WINDOWS - - if (FSDesc.Fullscreen) - LOG_WARNING_MESSAGE("UWP applications do not support fullscreen mode"); - - hr = factory->CreateSwapChainForCoreWindow( - pd3d12CmdQueue, - 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) )); - + CreateDXGISwapChain(pd3d12CmdQueue); InitBuffersAndViews(); } SwapChainD3D12Impl::~SwapChainD3D12Impl() { - if (m_pSwapChain) - { - BOOL IsFullScreen = FALSE; - m_pSwapChain->GetFullscreenState(&IsFullScreen, nullptr); - if (IsFullScreen) - m_pSwapChain->SetFullscreenState(FALSE, nullptr); - } } void SwapChainD3D12Impl::InitBuffersAndViews() @@ -233,53 +141,71 @@ void SwapChainD3D12Impl::Present() #endif } -void SwapChainD3D12Impl::Resize( Uint32 NewWidth, Uint32 NewHeight ) +void SwapChainD3D12Impl::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 ) - { - RenderDeviceD3D12Impl *pDeviceD3D12 = ValidatedCast(m_pRenderDevice.RawPtr()); - pDeviceContext->Flush(); + RenderDeviceD3D12Impl *pDeviceD3D12 = ValidatedCast(m_pRenderDevice.RawPtr()); + pDeviceContext->Flush(); - try - { - auto *pImmediateCtxD3D12 = ValidatedCast(pDeviceContext.RawPtr()); - bool bIsDefaultFBBound = pImmediateCtxD3D12->IsDefaultFBBound(); + try + { + auto *pImmediateCtxD3D12 = ValidatedCast(pDeviceContext.RawPtr()); + bool bIsDefaultFBBound = pImmediateCtxD3D12->IsDefaultFBBound(); - // All references to the swap chain must be released before it can be resized - m_pBackBufferRTV.clear(); - m_pDepthBufferDSV.Release(); + // All references to the swap chain must be released before it can be resized + m_pBackBufferRTV.clear(); + m_pDepthBufferDSV.Release(); - // This will release references to D3D12 swap chain buffers hold by - // m_pBackBufferRTV[] - pDeviceD3D12->IdleGPU(true); + // This will release references to D3D12 swap chain buffers hold by + // m_pBackBufferRTV[] + pDeviceD3D12->IdleGPU(true); + if(CreateNew) + { + m_pSwapChain.Release(); + auto *pd3d12CmdQueue = ValidatedCast(m_pRenderDevice.RawPtr())->GetCmdQueue()->GetD3D12CommandQueue(); + CreateDXGISwapChain(pd3d12CmdQueue); + } + 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"); + } + InitBuffersAndViews(); - InitBuffersAndViews(); - - if( bIsDefaultFBBound ) - { - // Set default render target and viewport - pDeviceContext->SetRenderTargets( 0, nullptr, nullptr ); - pDeviceContext->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 + pDeviceContext->SetRenderTargets(0, nullptr, nullptr); + pDeviceContext->SetViewports(1, nullptr, 0, 0); } } + catch (const std::runtime_error &) + { + LOG_ERROR("Failed to resize the swap chain"); + } + } +} + +void SwapChainD3D12Impl::Resize( Uint32 NewWidth, Uint32 NewHeight ) +{ + if( TSwapChainBase::Resize(NewWidth, NewHeight) ) + { + UpdateSwapChain(false); } } -- cgit v1.2.3