Fix vsync-off support for direct3d11

This commit is contained in:
ceski
2025-08-18 20:05:08 -07:00
committed by Özkan Sezer
parent 0fcaf47658
commit 270737584e
5 changed files with 57 additions and 4 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"
@@ -157,6 +161,7 @@ typedef struct
ID3D11DeviceContext1 *d3dContext;
IDXGISwapChain1 *swapChain;
DXGI_SWAP_EFFECT swapEffect;
UINT swapChainFlags;
UINT syncInterval;
UINT presentFlags;
ID3D11RenderTargetView *mainRenderTargetView;
@@ -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 } };
@@ -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.
@@ -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)) {
@@ -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,
@@ -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)
{
@@ -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;
@@ -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) {
@@ -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;
}
@@ -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;