简体   繁体   English

在OpenGL中使用glut的vsync出现问题

[英]Trouble with vsync using glut in OpenGL

I'm struggling desperately to get Vsync to work in my OpenGL application. 我拼命地努力让Vsync在我的OpenGL应用程序中工作。 Here's the vital stats: 重要数据如下:

I'm using Windows, coding in C++ OpenGL and I'm using FreeGLUT for my OpenGL context (double buffering). 我正在使用Windows,使用C ++ OpenGL进行编码,并且正在将FreeGLUT用于我的OpenGL上下文(双缓冲)。 I'm aware that for the swap buffer to wait for vertical sync in Windows you are required to call wglSwapIntervalEXT(). 我知道要让交换缓冲区等待Windows中的垂直同步,您需要调用wglSwapIntervalEXT()。

My code does call this (as you'll see below), yet I am still getting vertical tearing. 我的代码确实调用了此代码(如您在下面看到的),但是我仍在垂直撕裂。 The only way I've managed to stop it is by calling glFinish() which of course has a significant performance penalty associated with it. 我设法阻止它的唯一方法是调用glFinish(),这当然会给它带来很大的性能损失。

The relevant parts of my main() function look like this: 我的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);

I should point out that the return from the wglInitSwapControlARB function is true, so the extension is supported. 我应该指出,从wglInitSwapControlARB函数返回的结果为true,因此支持该扩展。

Ok - between the great help I've received here, and my own hours of research and messing around with it I've discovered a few things, including a solution that works for me (in case others come across this problem). 好的-在我从这里获得的巨大帮助以及我自己的研究时间和处理时间之间,我发现了一些东西,包括一个对我有用的解决方案(以防其他人遇到此问题)。

Firstly, I was using freeGLUT, I converted my code to GLFW and the result was the same, so this was NOT an API issue, don't waste your time like I did! 首先,我使用的是freeGLUT,我将代码转换为GLFW,结果是相同的,所以这不是API问题,不要像我那样浪费时间!

In my program at least, using wglSwapIntervalEXT(1) DOES NOT stop vertical tearing, and this was what led to it being such a headache to solve. 至少在我的程序中,使用wglSwapIntervalEXT(1)不会停止垂直撕裂,这就是导致它难以解决的原因。

With my NVIDIA driver set to VSYNC = ON I was still getting tearing (because this is equivalent to SwapInterval(1) which doesn't help) - but it was set correctly, the driver was doing what it should have been I just didn't know it because I was still getting tearing. 将我的NVIDIA驱动程序设置为VSYNC = ON时,我仍在流泪(因为这等效于SwapInterval(1),但无济于事)-但它设置正确,驱动程序正在做我应该做的事,不知道是因为我还在流泪。

So I set my NVIDIA driver to VSYNC = 'Application preference' and used wglSwapIntervalEXT(60) instead of 1 which I had always been using, and found that this was actually working because it was giving me a refresh rate of about 1Hz. 因此,我将NVIDIA驱动程序设置为VSYNC ='Application preference',并使用了wglSwapIntervalEXT(60)而不是我一直使用的1,并发现它确实有效,因为它给了我约1Hz的刷新率。

I don't know why wglSwapIntervalEXT(1) doesn't Vsync my screen, but wglSwapIntervalEXT(2) has the desired effect, though obviously I'm now rendering every other frame which is inefficient. 我不知道为什么wglSwapIntervalEXT(1)不能使我的屏幕垂直同步,但是wglSwapIntervalEXT(2)可以达到预期的效果,尽管显然我现在正在渲染其他效率低下的帧。

I found that with VSYNC disabled glFinish DOES NOT help with tearing, but with it enabled it does (If anyone can explain why that would be great). 我发现在禁用VSYNC的情况下,glFinish不会帮助您撕裂,但启用它后,它确实可以(如果有人可以解释为什么这样做会很棒)。

So in summary, with wglSwapIntervalEXT(1) set and glFinish() enabled I no longer have tearing, but I don't understand still why. 因此,总而言之,在设置了wglSwapIntervalEXT(1)并启用glFinish()的情况下,我再也不会撕裂了,但我仍然不明白为什么。

Here's some performance stats in my app (deliberately loaded to have FPS's below 60): 这是我的应用程序中的一些性能统计信息(故意加载以使FPS低于60):

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

I hope this helps someone in the future. 我希望这对以后的人有所帮助。 Thanks for all your help. 感谢你的帮助。

As described in this question here , no "true" VSync exists. 由于在这个问题上所描述这里 ,没有“真”的VSync存在。 Using GLFinish is the correct approach. 使用GLFinish是正确的方法。 This will cause your Card to finish processing everything it has been sent before continuing and rendering the next frame. 这将导致您的卡在继续并渲染下一帧之前完成对已发送的所有内容的处理。

You should keep track of your FPS and the time to render a frame, you might find GLFinish is simply exposing another bottleneck in your code. 您应该跟踪FPS和渲染框架的时间,您可能会发现GLFinish只是暴露了代码中的另一个瓶颈。

i am also having problem with vsync and freeglut. 我也有与vsync和freeglut的问题。 previously i used glut, and i was able to selectivly enable vsync for multiple GLUT-windows. 以前我使用过剩,并且能够为多个GLUT窗口选择性地启用vsync。

Now with freeglut, it seems like that the wglSwapIntervalEXT() has no effect. 现在有了freeglut,似乎wglSwapIntervalEXT()无效了。 What has effect is the global vsync option in the NVIDIA control panel. 有效的是NVIDIA控制面板中的global vsync选项。 If I enable the vsync there, i have vsync in both of my freeglut windows, and if i disable i dont have. 如果我在那里启用了vsync,则我的两个freeglut窗口中都具有vsync,如果禁用,则没有。 It does not matter what i set specificly for my application (in the nvidia control panel). 我为我的应用程序具体设置了什么(在nvidia控制面板中)都没有关系。 Also this confirms what i observe: 这也证实了我的观察:

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

the value of swap is always the value that is set in the NVIDIA control panel. swap的值始终是NVIDIA控制面板中设置的值。 Does not matter what is want to set with wglSwapIntervalEXT(). 不管用wglSwapIntervalEXT()设置什么。

Otherwise here you can read what the GLFinish() is good for: http://www.opengl.org/wiki/Swap_Interval 否则,您可以在这里阅读GLFinish()的优点: http : //www.opengl.org/wiki/Swap_Interval

I use it because i need to know when my monitor is updated, so i can synchronously execute tasks after that (capture with a camera something). 我使用它是因为我需要知道显示器的更新时间,以便在此之后可以同步执行任务(用照相机捕捉东西)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM