Skip to content

Fix vsync-off support for direct3d11 #13767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,7 @@ elseif(WINDOWS)
#include <gameinput.h>
int main(int argc, char **argv) { return 0; }" HAVE_GAMEINPUT_H
)
check_include_file(dxgi1_5.h HAVE_DXGI1_5_H)
check_include_file(dxgi1_6.h HAVE_DXGI1_6_H)
check_include_file(tpcshrd.h HAVE_TPCSHRD_H)
check_include_file(roapi.h HAVE_ROAPI_H)
Expand Down
1 change: 1 addition & 0 deletions include/build_config/SDL_build_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
#cmakedefine HAVE_WINDOWS_GAMING_INPUT_H 1
#cmakedefine HAVE_GAMEINPUT_H 1
#cmakedefine HAVE_DXGI_H 1
#cmakedefine HAVE_DXGI1_5_H 1
#cmakedefine HAVE_DXGI1_6_H 1

#cmakedefine HAVE_MMDEVICEAPI_H 1
Expand Down
1 change: 1 addition & 0 deletions include/build_config/SDL_build_config_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ typedef unsigned int uintptr_t;
#define HAVE_DXGI_H 1
#define HAVE_XINPUT_H 1
#if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0A00 /* Windows 10 SDK */
#define HAVE_DXGI1_5_H 1
#define HAVE_DXGI1_6_H 1
#define HAVE_WINDOWS_GAMING_INPUT_H 1
#endif
Expand Down
1 change: 1 addition & 0 deletions include/build_config/SDL_build_config_wingdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define HAVE_DSOUND_H 1
/* No SDK version checks needed for these because the SDK has to be new. */
#define HAVE_DXGI_H 1
#define HAVE_DXGI1_5_H 1
#define HAVE_DXGI1_6_H 1
#define HAVE_XINPUT_H 1
#define HAVE_WINDOWS_GAMING_INPUT_H 1
Expand Down
57 changes: 53 additions & 4 deletions src/render/direct3d11/SDL_render_d3d11.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
#include "../../video/SDL_pixels_c.h"

#include <d3d11_1.h>
#ifdef HAVE_DXGI1_5_H
#include <dxgi1_5.h>
#else
#include <dxgi1_4.h>
#endif
#include <dxgidebug.h>

#include "SDL_shaders_d3d11.h"
Expand Down Expand Up @@ -157,6 +161,7 @@ typedef struct
ID3D11DeviceContext1 *d3dContext;
IDXGISwapChain1 *swapChain;
DXGI_SWAP_EFFECT swapEffect;
UINT swapChainFlags;
UINT syncInterval;
UINT presentFlags;
ID3D11RenderTargetView *mainRenderTargetView;
Expand Down Expand Up @@ -206,6 +211,9 @@ typedef struct
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#endif

#ifdef HAVE_DXGI1_5_H
static const GUID SDL_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
#endif
static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
Expand Down Expand Up @@ -511,6 +519,9 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
HRESULT result = S_OK;
UINT creationFlags = 0;
bool createDebug;
#ifdef HAVE_DXGI1_5_H
IDXGIFactory5 *dxgiFactory5 = NULL;
#endif

/* This array defines the set of DirectX hardware feature levels this app will support.
* Note the ordering should be preserved.
Expand Down Expand Up @@ -601,6 +612,20 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
goto done;
}

#ifdef HAVE_DXGI1_5_H
// Check for tearing support, which requires the IDXGIFactory5 interface.
data->swapChainFlags = 0;
result = IDXGIFactory2_QueryInterface(data->dxgiFactory, &SDL_IID_IDXGIFactory5, (void **)&dxgiFactory5);
if (SUCCEEDED(result)) {
BOOL allowTearing = FALSE;
result = IDXGIFactory5_CheckFeatureSupport(dxgiFactory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
if (SUCCEEDED(result) && allowTearing) {
data->swapChainFlags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
}
IDXGIFactory5_Release(dxgiFactory5);
}
#endif // HAVE_DXGI1_5_H

// FIXME: Should we use the default adapter?
result = IDXGIFactory2_EnumAdapters(data->dxgiFactory, 0, &data->dxgiAdapter);
if (FAILED(result)) {
Expand Down Expand Up @@ -870,7 +895,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
} else {
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
}
swapChainDesc.Flags = 0;
swapChainDesc.Flags = data->swapChainFlags;

if (coreWindow) {
result = IDXGIFactory2_CreateSwapChainForCoreWindow(data->dxgiFactory,
Expand Down Expand Up @@ -956,6 +981,28 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer)
SAFE_RELEASE(data->mainRenderTargetView);
}

static void D3D11_UpdatePresentFlags(SDL_Renderer *renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal;

if (data->syncInterval > 0) {
data->presentFlags = 0;
} else {
data->presentFlags = DXGI_PRESENT_DO_NOT_WAIT;
#ifdef HAVE_DXGI1_5_H
// Present tearing requires sync interval 0, a swap chain flag, and not in exclusive fullscreen mode.
if ((data->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)) {
HRESULT result = S_OK;
BOOL fullscreenState = FALSE;
result = IDXGISwapChain_GetFullscreenState(data->swapChain, &fullscreenState, NULL);
if (SUCCEEDED(result) && !fullscreenState) {
data->presentFlags = DXGI_PRESENT_ALLOW_TEARING;
}
}
#endif // HAVE_DXGI1_5_H
}
}

// Initialize all resources that change when the window's size changes.
static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
{
Expand Down Expand Up @@ -985,7 +1032,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
0,
w, h,
DXGI_FORMAT_UNKNOWN,
0);
data->swapChainFlags);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done;
Expand All @@ -997,6 +1044,8 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
}
}

D3D11_UpdatePresentFlags(renderer);

// Set the proper rotation for the swap chain.
if (WIN_IsWindows8OrGreater()) {
if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
Expand Down Expand Up @@ -2663,11 +2712,10 @@ static bool D3D11_SetVSync(SDL_Renderer *renderer, const int vsync)

if (vsync > 0) {
data->syncInterval = vsync;
data->presentFlags = 0;
} else {
data->syncInterval = 0;
data->presentFlags = DXGI_PRESENT_DO_NOT_WAIT;
}
D3D11_UpdatePresentFlags(renderer);
return true;
}

Expand Down Expand Up @@ -2733,6 +2781,7 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);

data->swapChainFlags = 0;
data->syncInterval = 0;
data->presentFlags = DXGI_PRESENT_DO_NOT_WAIT;

Expand Down
Loading