Я отчаянно пытаюсь заставить Vsync работать в моем приложении OpenGL. Вот жизненная статистика:
Я использую Windows, кодирую в C ++ OpenGL и использую FreeGLUT для своего контекста OpenGL (двойная буферизация). Я знаю, что для того, чтобы буфер подкачки ожидал вертикальной синхронизации в Windows, вы должны вызвать wglSwapIntervalEXT ().
Мой код вызывает это (как вы увидите ниже), но я все еще получаю вертикальный разрыв. Единственный способ остановить это — вызвать glFinish (), что, конечно, связано со значительным снижением производительности.
Соответствующие части моей функции main () выглядят так:
//Initiating glut window
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize (initial_window_width, initial_window_height);
glutInitWindowPosition (100, 100);
int glut_window_hWnd = glutCreateWindow(window_title.c_str());
//Setting up swap intervals
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = NULL;
if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
// Extension is supported, init pointers.
wglSwapIntervalEXT = PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
// this is another function from WGL_EXT_swap_control extension
wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
}
wglSwapIntervalEXT (1)
init ();
glutMainLoop(); ///Starting the glut loop
return(0);
Следует отметить, что возвращение из функции wglInitSwapControlARB имеет значение true, поэтому расширение поддерживается.
Хорошо — между огромной помощью, которую я получил здесь, и моими собственными часами исследований и возни с ней, я обнаружил несколько вещей, включая решение, которое работает для меня (на случай, если другие столкнутся с этой проблемой).
Во-первых, я использовал freeGLUT, я преобразовал свой код в GLFW, и результат был таким же, так что это НЕ проблема API, не тратьте свое время, как я!
По крайней мере, в моей программе использование wglSwapIntervalEXT (1) НЕ останавливает вертикальное разрывание, и это привело к тому, что решить такую головную боль было невозможно.
С моим драйвером NVIDIA, установленным в VSYNC = ON, я все еще получаю разрыв (потому что это эквивалентно SwapInterval (1), который не помогает) — но он был установлен правильно, драйвер делал то, что должно было быть, я просто не сделал » не знаю, потому что я все еще плакал.
Поэтому я установил для своего драйвера NVIDIA значение VSYNC = «Предпочтения приложения» и использовал wglSwapIntervalEXT (60) вместо 1, который я всегда использовал, и обнаружил, что это на самом деле работает, поскольку дает частоту обновления около 1 Гц.
Я не знаю, почему wglSwapIntervalEXT (1) не Vsync мой экран, но wglSwapIntervalEXT (2) имеет желаемый эффект, хотя, очевидно, я теперь рендеринг каждого другого кадра, который неэффективен.
Я обнаружил, что с отключенным VSYNC glFinish не помогает с разрывом, но с включенным он делает (если кто-нибудь может объяснить, почему это было бы здорово).
Итак, в итоге, с установленным wglSwapIntervalEXT (1) и включенным glFinish () у меня больше нет слез, но я до сих пор не понимаю, почему.
Вот некоторые показатели производительности в моем приложении (намеренно загружены, чтобы FPS был ниже 60):
Я надеюсь, что это поможет кому-то в будущем. Спасибо за вашу помощь.
У меня также есть проблемы с vsync и freeglut.
Ранее я использовал glut, и я был в состоянии селективно включить vsync для нескольких GLUT-окон.
Теперь с freeglut кажется, что wglSwapIntervalEXT () не имеет никакого эффекта.
Что влияет, так это глобальная опция vsync на панели управления NVIDIA. Если я включаю vsync там, у меня есть vsync в обоих моих окнах freeglut, и если я отключаю, у меня нет. Неважно, что я установил специально для моего приложения (в панели управления nvidia).
Также это подтверждает то, что я наблюдаю:
if(wglSwapIntervalEXT(0))
printf("VSYNC set\n");
int swap=wglGetSwapIntervalEXT();
printf("Control window vsync: %i\n",swap);
значение свопа — это всегда значение, установленное на панели управления NVIDIA.
Неважно, что вы хотите установить с помощью wglSwapIntervalEXT ().
В противном случае вы можете прочитать, для чего подходит GLFinish ():
http://www.opengl.org/wiki/Swap_Interval
Я использую его, потому что мне нужно знать, когда обновляется мой монитор, чтобы после этого я мог синхронно выполнять задачи (что-то сделать с помощью камеры).
Как описано в этом вопросе Вот, «истинного» VSync не существует. Использование GLFinish является правильным подходом. Это заставит вашу Карту завершить обработку всего, что было отправлено, прежде чем продолжить и отобразить следующий кадр.
Вы должны следить за своим FPS и временем рендеринга кадра, вы можете обнаружить, что GLFinish просто обнаруживает еще одно узкое место в вашем коде.