1
1
/*
2
- * Copyright 2019-2023 Diligent Graphics LLC
2
+ * Copyright 2019-2025 Diligent Graphics LLC
3
3
* Copyright 2015-2019 Egor Yusov
4
4
*
5
5
* Licensed under the Apache License, Version 2.0 (the "License");
31
31
#include " SwapChainBase.hpp"
32
32
#include " DXGITypeConversions.hpp"
33
33
#include " GraphicsAccessories.hpp"
34
+ #include " D3DErrors.hpp"
34
35
35
36
// / \file
36
37
// / Base implementation of a D3D swap chain
37
38
38
39
namespace Diligent
39
40
{
40
41
42
+ bool CheckDXGITearingSupport (IDXGIFactory2* pDXGIFactory2);
43
+
41
44
// / Base implementation of a D3D swap chain
42
45
template <class BaseInterface , typename DXGISwapChainType>
43
46
class SwapChainD3DBase : public SwapChainBase <BaseInterface>
@@ -101,7 +104,7 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
101
104
void CreateDXGISwapChain (IUnknown* pD3D11DeviceOrD3D12CmdQueue)
102
105
{
103
106
#if PLATFORM_WIN32
104
- auto hWnd = reinterpret_cast <HWND>(m_Window.hWnd );
107
+ HWND hWnd = reinterpret_cast <HWND>(m_Window.hWnd );
105
108
if (m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0 )
106
109
{
107
110
RECT rc;
@@ -124,7 +127,7 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
124
127
m_DesiredPreTransform = SURFACE_TRANSFORM_OPTIMAL;
125
128
m_SwapChainDesc.PreTransform = SURFACE_TRANSFORM_IDENTITY;
126
129
127
- auto DXGIColorBuffFmt = TexFormatToDXGI_Format (m_SwapChainDesc.ColorBufferFormat );
130
+ DXGI_FORMAT DXGIColorBuffFmt = TexFormatToDXGI_Format (m_SwapChainDesc.ColorBufferFormat );
128
131
129
132
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
130
133
@@ -199,18 +202,27 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
199
202
// DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT enables querying a waitable object that can be
200
203
// used to synchronize presentation with CPU timeline.
201
204
// 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 )
203
206
{
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))
212
223
{
213
- swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
224
+ m_TearingSupported = true ;
225
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
214
226
}
215
227
}
216
228
@@ -284,9 +296,9 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
284
296
// https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains#step-4-wait-before-rendering-each-frame
285
297
if (m_FrameLatencyWaitableObject != NULL )
286
298
{
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 );
290
302
if (Res != WAIT_OBJECT_0)
291
303
{
292
304
const char * ErrorMsg = Res == WAIT_TIMEOUT ?
@@ -360,8 +372,23 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
360
372
}
361
373
}
362
374
375
+ protected:
363
376
virtual void SetDXGIDeviceMaximumFrameLatency () {}
364
377
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:
365
392
using TBase::m_pRenderDevice;
366
393
using TBase::m_SwapChainDesc;
367
394
using TBase::m_DesiredPreTransform;
@@ -372,7 +399,8 @@ class SwapChainD3DBase : public SwapChainBase<BaseInterface>
372
399
373
400
HANDLE m_FrameLatencyWaitableObject = NULL ;
374
401
375
- Uint32 m_MaxFrameLatency = 0 ;
402
+ Uint32 m_MaxFrameLatency = 0 ;
403
+ bool m_TearingSupported = false ;
376
404
};
377
405
378
406
} // namespace Diligent
0 commit comments