使用OpenGL中的过量使用vsync的麻烦

时间:2014-01-21 15:53:35

标签: c++ windows opengl freeglut vsync

我正拼命地让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,因此支持扩展。

3 个答案:

答案 0 :(得分:6)

好的 - 在我收到的这些帮助和我自己的研究时间之间以及搞乱它之间我发现了一些东西,包括一个对我有用的解决方案(以防其他人遇到这个问题)

首先,我使用的是freeGLUT,我将代码转换为GLFW,结果是一样的,所以这不是API问题,不要像我一样浪费你的时间!

至少在我的程序中,使用wglSwapIntervalEXT(1)不会停止垂直撕裂,这就是导致它如此难以解决的原因。

我的NVIDIA驱动程序设置为VSYNC = ON我仍然在撕裂(因为这相当于SwapInterval(1)没有帮助) - 但它设置正确,驱动程序正在做我应该做的事情我只是不知道,因为我还在撕裂。

所以我将我的NVIDIA驱动程序设置为VSYNC ='应用程序首选项'并使用wglSwapIntervalEXT(60)而不是我一直使用的1,并发现这实际上是有效的,因为它给了我大约1Hz的刷新率

我不知道为什么wglSwapIntervalEXT(1)没有对我的屏幕进行Vsync,但是wglSwapIntervalEXT(2)具有所需的效果,但显然我现在正在渲染其他效率低下的帧。

我发现在VSYNC禁用的情况下,glFinish无法帮助撕裂,但启用它确实(如果有人能解释为什么那会很棒)。

总而言之,在wglSwapIntervalEXT(1)设置和glFinish()启用后,我不再有撕裂,但我仍然不明白为什么。

以下是我的应用中的一些性能统计数据(故意加载以使FPS低于60):

  • wglSwapIntervalEXT(0)=撕裂= 58 FPS
  • wglSwapIntervalEXT(1)=撕裂= 58 FPS
  • wglSwapIntervalEXT(2)=无撕裂= 30 FPS
  • wglSwapIntervalEXT(1)+ glFinish = No Tearing = 52 FPS

我希望这有助于将来的某些人。谢谢你的帮助。

答案 1 :(得分:0)

我也遇到了vsync和freeglut的问题。 以前我使用过剩,我能够选择性地为多个GLUT窗口启用vsync。

现在使用freeglut,似乎wglSwapIntervalEXT()没有效果。 有效的是NVIDIA控制面板中的全局vsync选项。如果我在那里启用vsync,我在我的两个freeglut窗口都有vsync,如果我禁用我没有。我为我的应用程序设置了什么并不重要(在nvidia控制面板中)。 这也证实了我所观察到的:

if(wglSwapIntervalEXT(0)) 
printf("VSYNC set\n");
int swap=wglGetSwapIntervalEXT();
printf("Control window vsync: %i\n",swap);

swap的值始终是NVIDIA控制面板中设置的值。 无关紧要用wglSwapIntervalEXT()设置的内容。

否则在这里您可以阅读GLFinish()的优点: http://www.opengl.org/wiki/Swap_Interval

我使用它是因为我需要知道我的显示器何时更新,所以我可以在此之后同步执行任务(使用相机捕捉)。

答案 2 :(得分:-1)

如本问题here中所述,不存在“真正的”VSync。使用GLFinish是正确的方法。这将导致您的卡完成处理已发送的所有内容,然后继续并呈现下一帧。

你应该跟踪你的FPS和渲染帧的时间,你可能会发现GLFinish只是暴露了你代码中的另一个瓶颈。