Проблема с vsync, используя перенасыщение в OpenGL

Я отчаянно пытаюсь заставить 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, поэтому расширение поддерживается.

1

Решение

Хорошо — между огромной помощью, которую я получил здесь, и моими собственными часами исследований и возни с ней, я обнаружил несколько вещей, включая решение, которое работает для меня (на случай, если другие столкнутся с этой проблемой).

Во-первых, я использовал 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):

  • wglSwapIntervalEXT (0) = Tearing = 58 FPS
  • wglSwapIntervalEXT (1) = разрывание = 58 кадров в секунду
  • wglSwapIntervalEXT (2) = без разрывов = 30 кадров в секунду
  • wglSwapIntervalEXT (1) + glFinish = без разрывов = 52 FPS

Я надеюсь, что это поможет кому-то в будущем. Спасибо за вашу помощь.

6

Другие решения

У меня также есть проблемы с 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

Я использую его, потому что мне нужно знать, когда обновляется мой монитор, чтобы после этого я мог синхронно выполнять задачи (что-то сделать с помощью камеры).

0

Как описано в этом вопросе Вот, «истинного» VSync не существует. Использование GLFinish является правильным подходом. Это заставит вашу Карту завершить обработку всего, что было отправлено, прежде чем продолжить и отобразить следующий кадр.

Вы должны следить за своим FPS и временем рендеринга кадра, вы можете обнаружить, что GLFinish просто обнаруживает еще одно узкое место в вашем коде.

-1
По вопросам рекламы [email protected]