Skip to content

Commit 1119982

Browse files
authored
Win32: Add d3dkmt + Scanline Sync (#18974)
* Win32: Add d3dkmt + Scanline Sync * NTDDI versioning attempt * Header adjustments
1 parent a872a8d commit 1119982

23 files changed

Lines changed: 10145 additions & 71 deletions

Makefile.common

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,7 @@ ifeq ($(HAVE_D3D12), 1)
18351835
HAVE_D3D_COMMON = 1
18361836
OBJ += gfx/drivers/d3d12.o
18371837
DEFINES += -DHAVE_D3D12
1838+
DEFINES += -DHAVE_D3DKMT
18381839
endif
18391840

18401841
ifneq ($(findstring 1, $(HAVE_D3D10) $(HAVE_D3D11) $(HAVE_D3D12)),)

config.def.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@
377377

378378
/* Video VSYNC (recommended) */
379379
#define DEFAULT_VSYNC true
380+
#define DEFAULT_SCANLINE_SYNC false
380381

381382
/* Vulkan specific */
382383
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3

configuration.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,7 @@ static struct config_bool_setting *populate_settings_bool(
19701970
SETTING_BOOL("video_hdr_scanlines", &settings->bools.video_hdr_scanlines, true, DEFAULT_VIDEO_HDR_SCANLINES, false);
19711971
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, DEFAULT_VSYNC, false);
19721972
SETTING_BOOL("video_adaptive_vsync", &settings->bools.video_adaptive_vsync, true, DEFAULT_ADAPTIVE_VSYNC, false);
1973+
SETTING_BOOL("video_scanline_sync", &settings->bools.video_scanline_sync, true, DEFAULT_SCANLINE_SYNC, false);
19731974
SETTING_BOOL("video_hard_sync", &settings->bools.video_hard_sync, true, DEFAULT_HARD_SYNC, false);
19741975
SETTING_BOOL("video_waitable_swapchains", &settings->bools.video_waitable_swapchains, true, DEFAULT_WAITABLE_SWAPCHAINS, false);
19751976
SETTING_BOOL("video_disable_composition", &settings->bools.video_disable_composition, true, DEFAULT_DISABLE_COMPOSITION, false);

configuration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ typedef struct settings
669669
bool video_windowed_fullscreen;
670670
bool video_vsync;
671671
bool video_adaptive_vsync;
672+
bool video_scanline_sync;
672673
bool video_hard_sync;
673674
bool video_waitable_swapchains;
674675
bool video_vfilter;

gfx/common/vulkan_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1831,7 +1831,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
18311831
VkPresentModeKHR swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR;
18321832
VkCompositeAlphaFlagBitsKHR composite = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
18331833
settings_t *settings = config_get_ptr();
1834-
bool vsync = settings->bools.video_vsync;
1834+
bool vsync = settings->bools.video_vsync && !settings->bools.video_scanline_sync;
18351835
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
18361836
#ifdef VK_USE_PLATFORM_WIN32_KHR
18371837
bool video_windowed_fullscreen = settings->bools.video_windowed_fullscreen;

gfx/common/win32_common.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,69 @@ typedef REASON_CONTEXT POWER_REQUEST_CONTEXT, *PPOWER_REQUEST_CONTEXT, *LPPOWER_
169169
#define MIN_WIDTH 320
170170
#define MIN_HEIGHT 240
171171

172+
#ifdef HAVE_D3DKMT
173+
static d3dkmt_adapter_t d3dkmt_adapter;
174+
175+
static void d3dkmt_init(void)
176+
{
177+
if (!pD3DKMTOpenAdapterFromHdc)
178+
{
179+
unsigned d3dkmt_adapter_hAdapter = 0;
180+
unsigned d3dkmt_adapter_VidPnSourceId = 0;
181+
unsigned adapter_index = 0;
182+
DISPLAY_DEVICE add;
183+
184+
add.cb = sizeof(add);
185+
186+
pD3DKMTOpenAdapterFromHdc = (D3DKMTOPENADAPTERFROMHDC)
187+
GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTOpenAdapterFromHdc");
188+
pD3DKMTGetScanLine = (D3DKMTGETSCANLINE)
189+
GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTGetScanLine");
190+
191+
while (EnumDisplayDevices(NULL, adapter_index, &add, 0))
192+
{
193+
HDC hdc = CreateDC(NULL, add.DeviceName, NULL, NULL);
194+
if (hdc != NULL)
195+
{
196+
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
197+
OpenAdapterData.hDc = hdc;
198+
if (pD3DKMTOpenAdapterFromHdc(&OpenAdapterData) == STATUS_SUCCESS)
199+
{
200+
d3dkmt_adapter_hAdapter = OpenAdapterData.hAdapter;
201+
d3dkmt_adapter_VidPnSourceId = OpenAdapterData.VidPnSourceId;
202+
}
203+
DeleteDC(hdc);
204+
205+
if (d3dkmt_adapter_hAdapter)
206+
break;
207+
}
208+
adapter_index++;
209+
}
210+
211+
memset(&d3dkmt_adapter, 0, sizeof(d3dkmt_adapter_t));
212+
213+
if (pD3DKMTGetScanLine)
214+
{
215+
D3DKMT_GETSCANLINE sl = {0};
216+
sl.hAdapter = d3dkmt_adapter_hAdapter;
217+
sl.VidPnSourceId = d3dkmt_adapter_VidPnSourceId;
218+
d3dkmt_adapter.sl = sl;
219+
}
220+
}
221+
222+
video_driver_scanline_init();
223+
}
224+
225+
unsigned d3dkmt_scanline_get(void)
226+
{
227+
if (pD3DKMTGetScanLine)
228+
{
229+
if (pD3DKMTGetScanLine(&d3dkmt_adapter.sl) == STATUS_SUCCESS)
230+
return d3dkmt_adapter.sl.ScanLine;
231+
}
232+
return 0;
233+
}
234+
#endif /* HAVE_D3DKMT */
172235

173236
typedef struct win32_common_state
174237
{
@@ -1992,6 +2055,10 @@ bool win32_window_init(WNDCLASSEX *wndclass,
19922055
if (class_name)
19932056
wndclass->style |= CS_CLASSDC;
19942057

2058+
#ifdef HAVE_D3DKMT
2059+
d3dkmt_init();
2060+
#endif
2061+
19952062
return RegisterClassEx(wndclass);
19962063
}
19972064

@@ -2099,3 +2166,4 @@ HACCEL win32_resources_get_accelerator(void)
20992166
return s_accel_table;
21002167
}
21012168
#endif /* !__WINRT__ */
2169+

gfx/common/win32_common.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,32 @@ void win32_resources_free(void);
197197
HACCEL win32_resources_get_accelerator(void);
198198
#endif /* !__WINRT__ */
199199

200+
#ifdef HAVE_D3DKMT
201+
#include <sdkddkver.h>
202+
#if !defined(NTDDI_VERSION) || NTDDI_VERSION < 0x06000000
203+
# undef NTDDI_VERSION
204+
# define NTDDI_VERSION 0x06000000 /* NTDDI_LONGHORN / Vista */
205+
#endif
206+
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
207+
# undef _WIN32_WINNT
208+
# define _WIN32_WINNT 0x0600
209+
#endif
210+
typedef LONG NTSTATUS;
211+
#define STATUS_SUCCESS ((NTSTATUS)0)
212+
#include <d3dkmthk.h>
213+
typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
214+
static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
215+
typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
216+
static D3DKMTGETSCANLINE pD3DKMTGetScanLine;
217+
218+
typedef struct d3dkmt_adapter
219+
{
220+
D3DKMT_GETSCANLINE sl;
221+
} d3dkmt_adapter_t;
222+
223+
extern unsigned d3dkmt_scanline_get(void);
224+
#endif /* HAVE_D3DKMT */
225+
200226
RETRO_END_DECLS
201227

202228
#endif

gfx/drivers/d3d11.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
30983098
#endif /* __WINRT__ */
30993099

31003100
if ( (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS)
3101+
&& (d3d11->flags & D3D11_ST_FLAG_VSYNC)
31013102
&& (d3d11->frameLatencyWaitableObject = DXGIGetFrameLatencyWaitableObject(d3d11->swapChain)))
31023103
{
31033104
settings_t* settings = config_get_ptr();
@@ -4966,7 +4967,7 @@ static void d3d11_gfx_set_nonblock_state(void* data,
49664967
if (!d3d11)
49674968
return;
49684969

4969-
if (toggle)
4970+
if (toggle || !swap_interval)
49704971
d3d11->flags &= ~D3D11_ST_FLAG_VSYNC;
49714972
else
49724973
d3d11->flags |= D3D11_ST_FLAG_VSYNC;

gfx/drivers/d3d12.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3722,6 +3722,7 @@ static bool d3d12_init_swapchain(d3d12_video_t* d3d12,
37223722
}
37233723

37243724
if ( (d3d12->flags & D3D12_ST_FLAG_WAITABLE_SWAPCHAINS)
3725+
&& (d3d12->flags & D3D12_ST_FLAG_VSYNC)
37253726
&& (d3d12->chain.frameLatencyWaitableObject = DXGIGetFrameLatencyWaitableObject(d3d12->chain.handle)))
37263727
{
37273728
settings_t* settings = config_get_ptr();
@@ -6020,7 +6021,7 @@ static void d3d12_gfx_set_nonblock_state(void* data,
60206021
if (!d3d12)
60216022
return;
60226023

6023-
if (toggle)
6024+
if (toggle || !swap_interval)
60246025
d3d12->flags &= ~D3D12_ST_FLAG_VSYNC;
60256026
else
60266027
d3d12->flags |= D3D12_ST_FLAG_VSYNC;

gfx/drivers/vulkan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5247,7 +5247,7 @@ static void vulkan_set_nonblock_state(void *data, bool state,
52475247
if (vk->ctx_driver->swap_interval)
52485248
{
52495249
int interval = 0;
5250-
if (!state)
5250+
if (!state && swap_interval)
52515251
interval = swap_interval;
52525252
if (adaptive_vsync_enabled && interval == 1)
52535253
interval = -1;

0 commit comments

Comments
 (0)