4 changed files with 140 additions and 11 deletions
@ -0,0 +1,102 @@
|
||||
|
||||
// attempt to fix vsync with opengl on windows
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=467617
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3dkmthk/nf-d3dkmthk-d3dkmtwaitforverticalblankevent
|
||||
// NOTE: requires installing windows driver kit addon for msvc
|
||||
// TODO: not working with hdc provided by SDL, try enumerating display devices as described here:
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3dkmthk/nf-d3dkmthk-d3dkmtopenadapterfromhdc
|
||||
// NOTE: the above seems to make some difference in lowering cpu usage, but cpu stays at max frequency even when relatively idle.
|
||||
|
||||
// TODO: if d3dkmt... doensn't work, try DWMFlush() https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmflush
|
||||
// glfw uses this https://github.com/glfw/glfw/blob/master/src/wgl_context.c
|
||||
//
|
||||
// if that doesn't work... https://docs.microsoft.com/en-us/windows/desktop/api/timeapi/nf-timeapi-timebeginperiod
|
||||
// to increase schedular granularity. can then use sleep(1) for 1ms resolution
|
||||
|
||||
#pragma once |
||||
|
||||
#include <cstdint> |
||||
|
||||
#include "SDL_syswm.h" |
||||
|
||||
#if defined(_WIN32) |
||||
#include "windows.h" |
||||
#include "d3dkmthk.h" |
||||
|
||||
typedef uint32_t D3DKMT_HANDLE; |
||||
typedef struct { |
||||
D3DKMT_HANDLE hAdapter = NULL; |
||||
UINT vidID = 0; |
||||
} platform_win_device_handles; |
||||
platform_win_device_handles g_platform_win_device_handles; |
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
inline bool |
||||
platform_init(SDL_Window* window) |
||||
{ |
||||
#if defined(_WIN32) |
||||
D3DKMT_HANDLE hAdapter = NULL; |
||||
UINT vidID = 0; |
||||
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData; |
||||
DISPLAY_DEVICE dd; |
||||
HDC hdc; |
||||
|
||||
memset(&dd, 0, sizeof(dd)); |
||||
dd.cb = sizeof dd; |
||||
|
||||
for (int i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); ++i) { |
||||
if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) |
||||
break; |
||||
} |
||||
|
||||
hdc = CreateDC(NULL, dd.DeviceName, NULL, NULL); |
||||
if (hdc == NULL) |
||||
return false; |
||||
|
||||
OpenAdapterData.hDc = hdc; |
||||
if ((D3DKMTOpenAdapterFromHdc(&OpenAdapterData)) >= 0) { |
||||
DeleteDC(hdc); |
||||
g_platform_win_device_handles.hAdapter = OpenAdapterData.hAdapter; |
||||
g_platform_win_device_handles.vidID = OpenAdapterData.VidPnSourceId; |
||||
return true; |
||||
} |
||||
|
||||
DeleteDC(hdc); |
||||
return false; |
||||
#endif // _WIN32
|
||||
|
||||
return true; |
||||
} |
||||
|
||||
inline void |
||||
platform_wait_for_vblank(bool wait=true) |
||||
{ |
||||
if (!wait) return; |
||||
|
||||
#if defined(_WIN32) |
||||
_D3DKMT_WAITFORVERTICALBLANKEVENT waitForVBlankData; |
||||
memset(&waitForVBlankData, 0, sizeof(waitForVBlankData)); |
||||
waitForVBlankData.hAdapter = g_platform_win_device_handles.hAdapter; |
||||
waitForVBlankData.VidPnSourceId = g_platform_win_device_handles.vidID; |
||||
NTSTATUS ret = D3DKMTWaitForVerticalBlankEvent(&waitForVBlankData); |
||||
|
||||
switch (ret) { |
||||
case 0x00000000: // STATUS_SUCCESS
|
||||
//OutputDebugString("Success\r\n");
|
||||
break; |
||||
//case STATUS_DEVICE_REMOVED:
|
||||
// OutputDebugString("STATUS_DEVICE_REMOVED\r\n");
|
||||
// break;
|
||||
case STATUS_INVALID_PARAMETER: |
||||
OutputDebugString("STATUS_INVALID_PARAMETER\r\n"); |
||||
break; |
||||
default: |
||||
OutputDebugString("????"); |
||||
} |
||||
#endif // _WIN32
|
||||
|
||||
// TODO: implement/test for linux
|
||||
} |
||||
|
||||
Loading…
Reference in new issue