Browse Source

Use sleep-based frame limiting instead of vsync since it's unreliable on buggy graphics drivers.

tags/v2.2.0
Andrew Belt 2 years ago
parent
commit
36c9c1232e
1 changed files with 16 additions and 25 deletions
  1. +16
    -25
      src/window/Window.cpp

+ 16
- 25
src/window/Window.cpp View File

@@ -91,8 +91,8 @@ struct Window::Internal {
bool ignoreNextMouseDelta = false;
double monitorRefreshRate = 0.0;
int frameSwapInterval = -1;
double frameTime = 0.0;
double lastFrameDuration = 0.0;
double frameTime = NAN;
double lastFrameDuration = NAN;

math::Vec lastMousePos;

@@ -298,6 +298,7 @@ Window::Window() {
glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1);

glfwMakeContextCurrent(win);
glfwSwapInterval(0);
const GLFWvidmode* monitorMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
if (monitorMode->refreshRate > 0) {
internal->monitorRefreshRate = monitorMode->refreshRate;
@@ -412,11 +413,11 @@ void Window::run() {

void Window::step() {
double frameTime = system::getTime();
double lastFrameTime = internal->frameTime;
if (std::isfinite(internal->frameTime)) {
internal->lastFrameDuration = frameTime - internal->frameTime;
}
internal->frameTime = frameTime;
internal->lastFrameDuration = frameTime - lastFrameTime;
internal->fbCount = 0;
// DEBUG("%.2lf Hz", 1.0 / internal->lastFrameDuration);
// double t1 = 0.0, t2 = 0.0, t3 = 0.0, t4 = 0.0, t5 = 0.0;

// Make event handlers and step() have a clean NanoVG context
@@ -433,17 +434,6 @@ void Window::step() {
// In case glfwPollEvents() sets another OpenGL context
glfwMakeContextCurrent(win);

// Set swap interval
int frameSwapInterval = 0;
if (settings::frameRateLimit > 0.f) {
frameSwapInterval = std::ceil(internal->monitorRefreshRate / settings::frameRateLimit);
}

if (frameSwapInterval != internal->frameSwapInterval) {
glfwSwapInterval(frameSwapInterval);
internal->frameSwapInterval = frameSwapInterval;
}

// Call cursorPosCallback every frame, not just when the mouse moves
{
double xpos, ypos;
@@ -514,25 +504,26 @@ void Window::step() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgEndFrame(vg);
// t4 = system::getTime();
}
// t4 = system::getTime();
}

glfwSwapBuffers(win);

// On some platforms, glfwSwapBuffers() doesn't wait on monitor refresh, so we have to sleep as a fallback.
double frameDurationRemaining = getFrameDurationRemaining();
if (frameDurationRemaining > 0.0) {
std::this_thread::sleep_for(std::chrono::duration<double>(frameDurationRemaining));
// Limit frame rate
if (settings::frameRateLimit > 0) {
double remaining = getFrameDurationRemaining();
if (remaining > 0.0) {
system::sleep(remaining);
}
}

// t5 = system::getTime();

// DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f",
// (t1 - frameTime) * 1e3f,
// (t2 - t1) * 1e3f,
// (t3 - t2) * 1e3f,
// (t4 - t2) * 1e3f,
// (t4 - t3) * 1e3f,
// (t5 - t4) * 1e3f,
// (t5 - frameTime) * 1e3f
// );
@@ -717,8 +708,8 @@ double Window::getLastFrameDuration() {


double Window::getFrameDurationRemaining() {
double frameDurationDesired = 1.f / settings::frameRateLimit;
return frameDurationDesired - (system::getTime() - internal->frameTime);
double frameDuration = 1.f / settings::frameRateLimit;
return frameDuration - (system::getTime() - internal->frameTime);
}




Loading…
Cancel
Save