Browse Source

first attempt to fix vsync on windows

master
cinnaboot 8 years ago
parent
commit
b46bf81ee9
  1. 8
      msvc/hexgame.vcxproj
  2. 24
      src/hexgame.cpp
  3. 102
      src/platform_wait_for_vblank.h
  4. 17
      src/renderer.cpp

8
msvc/hexgame.vcxproj

@ -22,7 +22,7 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{A20061AD-7985-4275-96C6-A25215941A26}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -100,20 +100,22 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>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)</AdditionalIncludeDirectories>
<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)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>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)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2_image.lib;Opengl32.lib;assimp-vc140-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>NotSet</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>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)</AdditionalIncludeDirectories>
<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)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>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)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2_image.lib;Opengl32.lib;assimp-vc140-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>NotSet</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

24
src/hexgame.cpp

@ -25,6 +25,7 @@
#define VIEWPORT_WIDTH 1920
#define VIEWPORT_HEIGHT 1080
#define CONE_ANGLE 30
#define VSYNC_ENABLED true
#include <vector>
@ -39,6 +40,11 @@
#include <SDL_image.h>
// 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);

102
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 <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
}

17
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";

Loading…
Cancel
Save