Skip to content

Commit

Permalink
D3D11: Add support for DXGI_PRESENT_ALLOW_TEARING
Browse files Browse the repository at this point in the history
  • Loading branch information
flibitijibibo committed Oct 14, 2023
1 parent 3fe3c8c commit 7654843
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 4 deletions.
50 changes: 48 additions & 2 deletions src/FNA3D_Driver_D3D11.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
#include <dxgi.h>
#endif

#ifndef DXGI_PRESENT_ALLOW_TEARING
#define DXGI_PRESENT_ALLOW_TEARING 0x00000200UL
#endif /* DXGI_PRESENT_ALLOW_TEARING */

#define ERROR_CHECK(msg) \
if (FAILED(res)) \
{ \
Expand Down Expand Up @@ -212,6 +216,7 @@ typedef struct D3D11Renderer /* Cast FNA3D_Renderer* to this! */
void* factory; /* IDXGIFactory1 or IDXGIFactory2 */
IDXGIAdapter1 *adapter;
ID3DUserDefinedAnnotation *annotation;
BOOL supportsTearing;
SDL_mutex *ctxLock;
SDL_iconv_t iconv;

Expand Down Expand Up @@ -1489,6 +1494,7 @@ static void D3D11_SwapBuffers(
int32_t drawableWidth, drawableHeight;
FNA3D_Rect srcRect, dstRect;
D3D11SwapchainData *swapchainData;
uint32_t presentFlags;

/* Only the faux-backbuffer supports presenting
* specific regions given to Present().
Expand Down Expand Up @@ -1601,7 +1607,19 @@ static void D3D11_SwapBuffers(
}

/* Present! */
IDXGISwapChain_Present(swapchainData->swapchain, renderer->syncInterval, 0);
if (renderer->syncInterval == 0 && renderer->supportsTearing)
{
presentFlags = DXGI_PRESENT_ALLOW_TEARING;
}
else
{
presentFlags = 0;
}
IDXGISwapChain_Present(
swapchainData->swapchain,
renderer->syncInterval,
presentFlags
);

/* Bind the faux-backbuffer now, in case DXGI unsets target state */
D3D11_SetRenderTargets(
Expand Down Expand Up @@ -5111,6 +5129,7 @@ static FNA3D_Device* D3D11_CreateDevice(
D3D_FEATURE_LEVEL_10_0
};
uint32_t flags, supportsDxt3, supportsDxt5, supportsSrgb;
void* factory5;
int32_t i;
HRESULT res;

Expand All @@ -5128,6 +5147,25 @@ static FNA3D_Device* D3D11_CreateDevice(
&renderer->factory
);
ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL)

/* Check for explicit tearing support */
if (SUCCEEDED(IDXGIFactory1_QueryInterface(
(IDXGIFactory1*) renderer->factory,
&D3D_IID_IDXGIFactory5,
(void**) &factory5
))) {
if (FAILED(IDXGIFactory5_CheckFeatureSupport(
(IDXGIFactory5*) factory5,
DXGI_FEATURE_PRESENT_ALLOW_TEARING,
&renderer->supportsTearing,
sizeof(renderer->supportsTearing)
))) {
renderer->supportsTearing = FALSE;
}
IDXGIFactory5_Release((IDXGIFactory5*) factory5);
}

/* Select the appropriate device for rendering */
D3D11_PLATFORM_GetDefaultAdapter(
renderer->factory,
&renderer->adapter
Expand Down Expand Up @@ -5591,7 +5629,15 @@ static void D3D11_PLATFORM_CreateSwapChain(
swapchainDesc.BufferCount = 3;
swapchainDesc.OutputWindow = dxgiHandle;
swapchainDesc.Windowed = 1;
swapchainDesc.Flags = 0;
if (renderer->supportsTearing)
{
/* This enum may not be complete, so use the magic number */
swapchainDesc.Flags = 2048; /* DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; */
}
else
{
swapchainDesc.Flags = 0;
}

/* For Windows 10+, use a better form of discard swap behavior */
if (SUCCEEDED(IDXGIFactory1_QueryInterface(
Expand Down
171 changes: 169 additions & 2 deletions src/FNA3D_Driver_D3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static const IID D3D_IID_IDXGIFactory1 = {0x770aae78,0xf26f,0x4dba,{0xa8,0x29,0x
static const IID D3D_IID_IDXGIFactory2 = {0x50c83a1c,0xe072,0x4c48,{0x87,0xb0,0x36,0x30,0xfa,0x36,0xa6,0xd0}};
static const IID D3D_IID_IDXGIFactory4 = {0x7632e1f5,0xee65,0x4dca,{0x87,0xfd,0x84,0xcd,0x75,0xf8,0x83,0x8d}};
static const IID D3D_IID_IDXGIFactory6 = {0xc1b6694f,0xff09,0x44a9,{0xb0,0x3c,0x77,0x90,0x0a,0x0a,0x1d,0x17}};
static const IID D3D_IID_IDXGIFactory5 = {0x7632e1f5,0xee65,0x4dca,{0x87,0xfd,0x84,0xcd,0x75,0xf8,0x83,0x8d}};
static const IID D3D_IID_IDXGIAdapter1 = {0x29038f61,0x3839,0x4626,{0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05}};
static const IID D3D_IID_ID3D11Texture2D = {0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c}};
static const IID D3D_IID_ID3DUserDefinedAnnotation = {0xb2daad8b,0x03d4,0x4dbf,{0x95,0xeb,0x32,0xab,0x4b,0x63,0xd0,0xab}};
Expand Down Expand Up @@ -283,14 +284,180 @@ struct IDXGIFactory4
#define IDXGIFactory4_Release(This) \
( (This)->lpVtbl -> Release(This) )

/* IDXGIFactory6 */
/* From dxgi1_6.h, cleaned up a bit... */
/* IDXGIFactory5 */
/* From dxgi1_5.h, cleaned up a bit... */

typedef enum
{
DXGI_FEATURE_PRESENT_ALLOW_TEARING = 0
} DXGI_FEATURE;

typedef struct IDXGIFactory5 IDXGIFactory5;
typedef struct IDXGIFactory5Vtbl
{
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IDXGIFactory5 * This,
REFIID riid,
void **ppvObject);

ULONG ( STDMETHODCALLTYPE *AddRef )(
IDXGIFactory5 * This);

ULONG ( STDMETHODCALLTYPE *Release )(
IDXGIFactory5 * This);

HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
IDXGIFactory5 * This,
REFGUID Name,
UINT DataSize,
const void *pData);

HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
IDXGIFactory5 * This,
REFGUID Name,
const IUnknown *pUnknown);

HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
IDXGIFactory5 * This,
REFGUID Name,
UINT *pDataSize,
void *pData);

HRESULT ( STDMETHODCALLTYPE *GetParent )(
IDXGIFactory5 * This,
REFIID riid,
void **ppParent);

HRESULT ( STDMETHODCALLTYPE *EnumAdapters )(
IDXGIFactory5 * This,
UINT Adapter,
IDXGIAdapter **ppAdapter);

HRESULT ( STDMETHODCALLTYPE *MakeWindowAssociation )(
IDXGIFactory5 * This,
HWND WindowHandle,
UINT Flags);

HRESULT ( STDMETHODCALLTYPE *GetWindowAssociation )(
IDXGIFactory5 * This,
HWND *pWindowHandle);

HRESULT ( STDMETHODCALLTYPE *CreateSwapChain )(
IDXGIFactory5 * This,
IUnknown *pDevice,
DXGI_SWAP_CHAIN_DESC *pDesc,
IDXGISwapChain **ppSwapChain);

HRESULT ( STDMETHODCALLTYPE *CreateSoftwareAdapter )(
IDXGIFactory5 * This,
HMODULE Module,
IDXGIAdapter **ppAdapter);

HRESULT ( STDMETHODCALLTYPE *EnumAdapters1 )(
IDXGIFactory5 * This,
UINT Adapter,
IDXGIAdapter1 **ppAdapter);

BOOL ( STDMETHODCALLTYPE *IsCurrent )(
IDXGIFactory5 * This);

BOOL ( STDMETHODCALLTYPE *IsWindowedStereoEnabled )(
IDXGIFactory5 * This);

HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForHwnd )(
IDXGIFactory5 * This,
IUnknown *pDevice,
HWND hWnd,
void *pDesc,
void *pFullscreenDesc,
void *pRestrictToOutput,
void **ppSwapChain);

HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForCoreWindow )(
IDXGIFactory5 * This,
IUnknown *pDevice,
IUnknown *pWindow,
void *pDesc,
void *pRestrictToOutput,
void **ppSwapChain);

HRESULT ( STDMETHODCALLTYPE *GetSharedResourceAdapterLuid )(
IDXGIFactory5 * This,
HANDLE hResource,
LUID *pLuid);

HRESULT ( STDMETHODCALLTYPE *RegisterStereoStatusWindow )(
IDXGIFactory5 * This,
HWND WindowHandle,
UINT wMsg,
DWORD *pdwCookie);

HRESULT ( STDMETHODCALLTYPE *RegisterStereoStatusEvent )(
IDXGIFactory5 * This,
HANDLE hEvent,
DWORD *pdwCookie);

void ( STDMETHODCALLTYPE *UnregisterStereoStatus )(
IDXGIFactory5 * This,
DWORD dwCookie);

HRESULT ( STDMETHODCALLTYPE *RegisterOcclusionStatusWindow )(
IDXGIFactory5 * This,
HWND WindowHandle,
UINT wMsg,
DWORD *pdwCookie);

HRESULT ( STDMETHODCALLTYPE *RegisterOcclusionStatusEvent )(
IDXGIFactory5 * This,
HANDLE hEvent,
DWORD *pdwCookie);

void ( STDMETHODCALLTYPE *UnregisterOcclusionStatus )(
IDXGIFactory5 * This,
DWORD dwCookie);

HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForComposition )(
IDXGIFactory5 * This,
IUnknown *pDevice,
void *pDesc,
void *pRestrictToOutput,
void **ppSwapChain);

UINT ( STDMETHODCALLTYPE *GetCreationFlags )(
IDXGIFactory5 * This);

HRESULT ( STDMETHODCALLTYPE *EnumAdapterByLuid )(
IDXGIFactory5 * This,
LUID AdapterLuid,
REFIID riid,
void **ppvAdapter);

HRESULT ( STDMETHODCALLTYPE *EnumWarpAdapter )(
IDXGIFactory5 * This,
REFIID riid,
void **ppvAdapter);

HRESULT ( STDMETHODCALLTYPE *CheckFeatureSupport )(
IDXGIFactory5 * This,
DXGI_FEATURE Feature,
void *pFeatureSupportData,
UINT FeatureSupportDataSize);
} IDXGIFactory5Vtbl;

struct IDXGIFactory5
{
struct IDXGIFactory5Vtbl *lpVtbl;
};

#define IDXGIFactory5_Release(This) \
( (This)->lpVtbl -> Release(This) )

#define IDXGIFactory5_CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) \
( (This)->lpVtbl -> CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) )

/* IDXGIFactory6 */
/* From dxgi1_6.h, cleaned up a bit... */

typedef enum
{
DXGI_GPU_PREFERENCE_UNSPECIFIED = 0,
Expand Down

0 comments on commit 7654843

Please sign in to comment.