diff --git a/msvc/hexgame.vcxproj b/msvc/hexgame.vcxproj
index 48da8a3..fa04d07 100644
--- a/msvc/hexgame.vcxproj
+++ b/msvc/hexgame.vcxproj
@@ -22,7 +22,7 @@
15.0
{A20061AD-7985-4275-96C6-A25215941A26}
Win32Proj
- 10.0.16299.0
+ 10.0.17134.0
@@ -100,20 +100,22 @@
- D:\dev\lib\glm;D:\dev\lib\gl3w\include;D:\dev\projects\hexgame\ext\imgui;D:\dev\projects\hexgame\ext\aixlog\include;D:\dev\lib\SDL2-2.0.8\include;D:\dev\lib\SDL2_image-2.0.3\include;D:\dev\lib\Assimp\include;%(AdditionalIncludeDirectories)
+ C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\shared;C:\Program Files %28x86%29\Windows Kits\10\Include\10.0.17134.0\km;D:\dev\lib\glm;D:\dev\lib\gl3w\include;D:\dev\projects\hexgame\ext\imgui;D:\dev\projects\hexgame\ext\aixlog\include;D:\dev\lib\SDL2-2.0.8\include;D:\dev\lib\SDL2_image-2.0.3\include;D:\dev\lib\Assimp\include;%(AdditionalIncludeDirectories)
D:\dev\lib\Assimp\lib\x64;D:\dev\lib\SDL2_image-2.0.3\lib\x64;D:\dev\lib\SDL2-2.0.8\lib\x64;%(AdditionalLibraryDirectories)
SDL2.lib;SDL2_image.lib;Opengl32.lib;assimp-vc140-mt.lib;%(AdditionalDependencies)
+ NotSet
- D:\dev\lib\glm;D:\dev\lib\gl3w\include;D:\dev\projects\hexgame\ext\imgui;D:\dev\projects\hexgame\ext\aixlog\include;D:\dev\lib\SDL2-2.0.8\include;D:\dev\lib\SDL2_image-2.0.3\include;D:\dev\lib\Assimp\include;%(AdditionalIncludeDirectories)
+ C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\shared;C:\Program Files %28x86%29\Windows Kits\10\Include\10.0.17134.0\km;D:\dev\lib\glm;D:\dev\lib\gl3w\include;D:\dev\projects\hexgame\ext\imgui;D:\dev\projects\hexgame\ext\aixlog\include;D:\dev\lib\SDL2-2.0.8\include;D:\dev\lib\SDL2_image-2.0.3\include;D:\dev\lib\Assimp\include;%(AdditionalIncludeDirectories)
D:\dev\lib\Assimp\lib\x64;D:\dev\lib\SDL2_image-2.0.3\lib\x64;D:\dev\lib\SDL2-2.0.8\lib\x64;%(AdditionalLibraryDirectories)
SDL2.lib;SDL2_image.lib;Opengl32.lib;assimp-vc140-mt.lib;%(AdditionalDependencies)
+ NotSet
diff --git a/src/hexgame.cpp b/src/hexgame.cpp
index 2366c93..cd6b225 100644
--- a/src/hexgame.cpp
+++ b/src/hexgame.cpp
@@ -25,6 +25,7 @@
#define VIEWPORT_WIDTH 1920
#define VIEWPORT_HEIGHT 1080
#define CONE_ANGLE 30
+#define VSYNC_ENABLED true
#include
@@ -39,6 +40,11 @@
#include
+// TODO: replace aixlog with simpler logging
+#if defined(_WIN32)
+#pragma warning(push)
+#pragma warning(disable : 4003)
+#endif
#include "aixlog.hpp"
#include "util.h"
@@ -47,6 +53,7 @@
#include "renderer.h"
#include "gooey.h"
#include "mesh.h"
+#include "platform_wait_for_vblank.h"
using std::vector;
@@ -562,19 +569,26 @@ int main(int argc, char* argv[])
LOG(ERROR) << "Fooey, No Gooey!\n";
return 1;
}
-
+
+ if (!platform_init(handles.window)) {
+ LOG(ERROR) << "Couldn't get SDL platform info, exiting\n";
+ return 1;
+ }
+
// main loop
while (processSDLEvents()) {
- // TODO: remove hack to not peg CPU. replace with an actual frame timer
+#if defined(_WIN32)
+ // sort-of fixed in windows with platform_wait_for_vblank()
+#else
+ LOG(DEBUG) << "TODO: Implement better frame timer on linux\n"; // should notice this
SDL_Delay(16); // ~60hz
+#endif
game_state* g = g_game_state;
render_state* r = g_render_state;
moveCamera(g->is_moveup, g->is_moveleft, g->is_movedown, g->is_moveright,
g->is_moveforward, g->is_movebackward);
- rollCamera(g->is_rotateCW, g->is_rotateCCW);
-
renderFrame(g->hex_array, g_render_state->entities, g_render_state->entity_count);
if (r->is_debug_draw && g->draw_mode == CONE_FILL)
@@ -584,6 +598,8 @@ int main(int argc, char* argv[])
g->current_hex, g->is_selecting, getCameraPosition());
SDL_GL_SwapWindow(handles.window);
+
+ platform_wait_for_vblank(VSYNC_ENABLED);
}
cleanUp(handles);
diff --git a/src/platform_wait_for_vblank.h b/src/platform_wait_for_vblank.h
new file mode 100644
index 0000000..d11a353
--- /dev/null
+++ b/src/platform_wait_for_vblank.h
@@ -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
+
+#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
+}
+
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 6a0a892..49f74a5 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -224,18 +224,27 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
- SDL_GL_SetSwapInterval(1); // vsync
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode);
handles.window =
SDL_CreateWindow("hexgame", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
vpDims.x, vpDims.y, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
+
+ if (!handles.window) {
+ LOG(ERROR) << "Error creating window: " << SDL_GetError() << "\n";
+ return false;
+ }
- if (handles.window == NULL) {
- LOG(ERROR) << SDL_GetError() << "\n";
+ handles.glContext = SDL_GL_CreateContext(handles.window);
+
+ if (!handles.glContext) {
+ LOG(ERROR) << "Error creating glContext: " << SDL_GetError() << "\n";
return false;
}
- handles.glContext = SDL_GL_CreateContext(handles.window);
+ if (SDL_GL_SetSwapInterval(1) != 0) { // vsync
+ LOG(ERROR) << "SDL Errors: " << SDL_GetError() << "\n";
+ return false;
+ }
if (gl3wInit()) { // TODO: decide on extension library
LOG(ERROR) << "failed to initialize OpenGL\n";