Skip to content

Commit 1176936

Browse files
committed
Win32: Add d3dkmt + Scanline Sync
1 parent 4e75fde commit 1176936

23 files changed

Lines changed: 10138 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: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,10 @@ bool win32_window_init(WNDCLASSEX *wndclass,
19921992
if (class_name)
19931993
wndclass->style |= CS_CLASSDC;
19941994

1995+
#ifdef HAVE_D3DKMT
1996+
d3dkmt_init();
1997+
#endif
1998+
19951999
return RegisterClassEx(wndclass);
19962000
}
19972001

@@ -2099,3 +2103,65 @@ HACCEL win32_resources_get_accelerator(void)
20992103
return s_accel_table;
21002104
}
21012105
#endif /* !__WINRT__ */
2106+
2107+
#ifdef HAVE_D3DKMT
2108+
void d3dkmt_init(void)
2109+
{
2110+
if (!pD3DKMTOpenAdapterFromHdc)
2111+
{
2112+
unsigned d3dkmt_adapter_hAdapter = 0;
2113+
unsigned d3dkmt_adapter_VidPnSourceId = 0;
2114+
unsigned adapter_index = 0;
2115+
DISPLAY_DEVICE add;
2116+
2117+
add.cb = sizeof(add);
2118+
2119+
pD3DKMTOpenAdapterFromHdc = (D3DKMTOPENADAPTERFROMHDC)
2120+
GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTOpenAdapterFromHdc");
2121+
pD3DKMTGetScanLine = (D3DKMTGETSCANLINE)
2122+
GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTGetScanLine");
2123+
2124+
while (EnumDisplayDevices(NULL, adapter_index, &add, 0))
2125+
{
2126+
HDC hdc = CreateDC(NULL, add.DeviceName, NULL, NULL);
2127+
if (hdc != NULL)
2128+
{
2129+
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
2130+
OpenAdapterData.hDc = hdc;
2131+
if (pD3DKMTOpenAdapterFromHdc(&OpenAdapterData) == STATUS_SUCCESS)
2132+
{
2133+
d3dkmt_adapter_hAdapter = OpenAdapterData.hAdapter;
2134+
d3dkmt_adapter_VidPnSourceId = OpenAdapterData.VidPnSourceId;
2135+
}
2136+
DeleteDC(hdc);
2137+
2138+
if (d3dkmt_adapter_hAdapter)
2139+
break;
2140+
}
2141+
adapter_index++;
2142+
}
2143+
2144+
memset(&d3dkmt_adapter, 0, sizeof(d3dkmt_adapter_t));
2145+
2146+
if (pD3DKMTGetScanLine)
2147+
{
2148+
D3DKMT_GETSCANLINE sl = {0};
2149+
sl.hAdapter = d3dkmt_adapter_hAdapter;
2150+
sl.VidPnSourceId = d3dkmt_adapter_VidPnSourceId;
2151+
d3dkmt_adapter.sl = sl;
2152+
}
2153+
}
2154+
2155+
video_driver_scanline_init();
2156+
}
2157+
2158+
INLINE unsigned d3dkmt_scanline_get(void)
2159+
{
2160+
if (pD3DKMTGetScanLine)
2161+
{
2162+
if (pD3DKMTGetScanLine(&d3dkmt_adapter.sl) == STATUS_SUCCESS)
2163+
return d3dkmt_adapter.sl.ScanLine;
2164+
}
2165+
return 0;
2166+
}
2167+
#endif /* HAVE_D3DKMT */

gfx/common/win32_common.h

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

200+
#ifdef HAVE_D3DKMT
201+
typedef LONG NTSTATUS;
202+
#define STATUS_SUCCESS ((NTSTATUS)0)
203+
#include <d3dkmthk.h>
204+
typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
205+
static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
206+
typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
207+
static D3DKMTGETSCANLINE pD3DKMTGetScanLine;
208+
209+
typedef struct d3dkmt_adapter
210+
{
211+
D3DKMT_GETSCANLINE sl;
212+
} d3dkmt_adapter_t;
213+
214+
static d3dkmt_adapter_t d3dkmt_adapter;
215+
extern void d3dkmt_init(void);
216+
extern unsigned d3dkmt_scanline_get(void);
217+
#endif /* HAVE_D3DKMT */
218+
200219
RETRO_END_DECLS
201220

202221
#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)