11/*
2- * Copyright 2019-2023 Diligent Graphics LLC
2+ * Copyright 2019-2025 Diligent Graphics LLC
33 * Copyright 2015-2019 Egor Yusov
44 *
55 * Licensed under the Apache License, Version 2.0 (the "License");
3131#include " SwapChainBase.hpp"
3232#include " DXGITypeConversions.hpp"
3333#include " GraphicsAccessories.hpp"
34+ #include " D3DErrors.hpp"
3435
3536// / \file
3637// / Base implementation of a D3D swap chain
3738
3839namespace Diligent
3940{
4041
42+ bool CheckDXGITearingSupport (IDXGIFactory2* pDXGIFactory2);
43+
4144// / Base implementation of a D3D swap chain
4245template <class BaseInterface , typename DXGISwapChainType>
4346class SwapChainD3DBase : public SwapChainBase <BaseInterface>
@@ -101,7 +104,7 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
101104 void CreateDXGISwapChain (IUnknown* pD3D11DeviceOrD3D12CmdQueue)
102105 {
103106#if PLATFORM_WIN32
104- auto hWnd = reinterpret_cast <HWND>(m_Window.hWnd );
107+ HWND hWnd = reinterpret_cast <HWND>(m_Window.hWnd );
105108 if (m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0 )
106109 {
107110 RECT rc;
@@ -124,7 +127,7 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
124127 m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL;
125128 m_SwapChainDesc.PreTransform = SURFACE_TRANSFORM_IDENTITY;
126129
127- auto DXGIColorBuffFmt = TexFormatToDXGI_Format (m_SwapChainDesc.ColorBufferFormat );
130+ DXGI_FORMAT DXGIColorBuffFmt = TexFormatToDXGI_Format (m_SwapChainDesc.ColorBufferFormat );
128131
129132 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
130133
@@ -199,18 +202,27 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
199202 // DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT enables querying a waitable object that can be
200203 // used to synchronize presentation with CPU timeline.
201204 // The flag is not supported in D3D11 fullscreen mode.
202- if (!( m_FSDesc.Fullscreen && m_pRenderDevice-> GetDeviceInfo (). Type == RENDER_DEVICE_TYPE_D3D11) )
205+ if (!m_FSDesc.Fullscreen )
203206 {
204- // We do not need pDXGIFactory3 itself, however DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT flag
205- // is only supported starting with Windows 8.1, and so is IDXGIFactory3 interface. We query this
206- // interface to check Windows 8.1.
207- // Note that we can't use IsWindows8Point1OrGreater because unlike IsWindows8OrGreater, it returns
208- // false if an application is not manifested for Windows 8.1 or Windows 10, even if the current
209- // operating system version is Windows 8.1 or Windows 10.
210- CComPtr<IDXGIFactory3> pDXGIFactory3;
211- if (SUCCEEDED (pDXGIFactory.QueryInterface (&pDXGIFactory3)))
207+ if (m_pRenderDevice->GetDeviceInfo ().Type == RENDER_DEVICE_TYPE_D3D11)
208+ {
209+ // We do not need pDXGIFactory3 itself, however DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT flag
210+ // is only supported starting with Windows 8.1, and so is IDXGIFactory3 interface. We query this
211+ // interface to check Windows 8.1.
212+ // Note that we can't use IsWindows8Point1OrGreater because unlike IsWindows8OrGreater, it returns
213+ // false if an application is not manifested for Windows 8.1 or Windows 10, even if the current
214+ // operating system version is Windows 8.1 or Windows 10.
215+ CComPtr<IDXGIFactory3> pDXGIFactory3;
216+ if (SUCCEEDED (pDXGIFactory.QueryInterface (&pDXGIFactory3)))
217+ {
218+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
219+ }
220+ }
221+
222+ if (CheckDXGITearingSupport (pDXGIFactory))
212223 {
213- swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
224+ m_TearingSupported = true ;
225+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
214226 }
215227 }
216228
@@ -284,9 +296,9 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
284296 // https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains#step-4-wait-before-rendering-each-frame
285297 if (m_FrameLatencyWaitableObject != NULL )
286298 {
287- auto Res = WaitForSingleObjectEx (m_FrameLatencyWaitableObject,
288- 500 , // 0.5 second timeout (shouldn't ever occur)
289- true );
299+ DWORD Res = WaitForSingleObjectEx (m_FrameLatencyWaitableObject,
300+ 500 , // 0.5 second timeout (shouldn't ever occur)
301+ true );
290302 if (Res != WAIT_OBJECT_0)
291303 {
292304 const char * ErrorMsg = Res == WAIT_TIMEOUT ?
@@ -360,8 +372,23 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
360372 }
361373 }
362374
375+ protected:
363376 virtual void SetDXGIDeviceMaximumFrameLatency () {}
364377
378+ HRESULT PresentInternal (Uint32 SyncInterval)
379+ {
380+ if (!m_pSwapChain)
381+ return E_FAIL;
382+
383+ UINT Flags = 0 ;
384+ // DXGI_PRESENT_ALLOW_TEARING can only be used with sync interval 0
385+ if (SyncInterval == 0 && m_TearingSupported)
386+ Flags |= DXGI_PRESENT_ALLOW_TEARING;
387+
388+ return m_pSwapChain->Present (SyncInterval, Flags);
389+ }
390+
391+ protected:
365392 using TBase::m_pRenderDevice;
366393 using TBase::m_SwapChainDesc;
367394 using TBase::m_DesiredPreTransform;
@@ -372,7 +399,8 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
372399
373400 HANDLE m_FrameLatencyWaitableObject = NULL ;
374401
375- Uint32 m_MaxFrameLatency = 0 ;
402+ Uint32 m_MaxFrameLatency = 0 ;
403+ bool m_TearingSupported = false ;
376404};
377405
378406} // namespace Diligent
0 commit comments