Sign in to follow this  
hplus0603

glGetError() causes 5-second stalls?

Recommended Posts

I'm working on a toy project using GLFW and GLAD. The project renders a UI composited by simple 2D sprites, using GLFW for the main window and GLAD for GL extension/version loading/handling. This is on Windows 8.1, x64, using NVIDIA GTX 870M graphics and an Intel HD4600 framebuffer. The CPU is a Core i7-4702HQ.
The program also spawns two threads for background audio, but all communication with those is done through a non-blocking FIFO.

The project runs in windowed mode, and uses the regular Windows cursor for mouse input; the GLFW callbacks in my program then turns input events into data I can poll in the actual main loop. The main loop runs at 60 Hz just fine when I use glfwPollEvents(), and I've also tried glfwWaitEvents() (because this is a GUI-style app, no real-time simulation going on.)

The problem is that, occasionally (every 10-20 seconds perhaps) my proejct stalls the main thread. Clicking on things on the screen doesn't register until I wait for the stall to complete. These stalls are sometimes less -- from a few hundred milliseconds, often 1-2 seconds, and sometimes as big as 5 seconds.

I've traced the stall down to specific calls to glGetError(). When I remove all glGetError() calls, the stalls move to a call to glReadPixels() that I do right before glfwSwapBuffers() to prevent the GPU from running ahead of the program. I *want* this synchronization. As I said, it runs at 60 Hz just fine, most of the time.

So, the first level of advice I expect I'll get is "never read anything back." I understand that advice, and I don't think it's applicable here. If the only problem was that reading something back flushes/stalls the GPU, then I'd expect the maximum stall to be at most 16 milliseconds -- the game runs at 60 Hz just fine, and the fill rate used just isn't that much (and this is a very fast machine. It runs Unreal Engine 4 demos just fine :-)

Secondly, glGetError() doesn't necessarily have to stall or flush the pipeline. Indeed, the whole point of GL is that the application pushes commands into a command stream, and glGetError() reports the fact that "I couldn't put this command into the stream because you called it wrong." Anything that happens on the other end of that stream is not readable through glGetError() -- at least, in the platonic model of the API. I understand that IHVs may do other crazy stuff in their drivers. But not stalling for 5 seconds.

Stalls that behave like this kind-of feel like a thread priority inversion problem. I can't quite see how that would happen, though. At most, the CPU load on my system is 50% (and usually lower,) and my application only spawns a total of three threads, out of 8 hardware threads available on the 4 CPU cores.

Note that when I remove both the glGetError() calls and the glReadPixels() calls, the stalls happen less often, but they do still happen, at the glfwSwapBuffers() call in that case. Occasionally.

So -- has anyone seen stalls like this? Any idea what it could be, and what I could do to fix it? Edited by hplus0603

Share this post


Link to post
Share on other sites
For what it's worth, when I run this same program on Intel HD 2000 graphics on Linux (yay portability,) the stalls are totally not there.
I'm starting to think this is a diver bug/mis-feature in the NVIDIA driver.
But I'm still surprised nobody else has seen it?

Share this post


Link to post
Share on other sites

You have the same thing as me, except I don't have any Intel drivers on Linux. Just Nvidia. There are small stalls on windows, and on Linux everything just runs like clockwork. And then some.

 

I don't know why or how or who or what.

Share this post


Link to post
Share on other sites

I've traced the stall down to specific calls to glGetError(). When I remove all glGetError() calls, the stalls move to a call to glReadPixels() that I do right before glfwSwapBuffers() to prevent the GPU from running ahead of the program. I *want* this synchronization. As I said, it runs at 60 Hz just fine, most of the time.

Wait, glFinish() doesn't work? (I admit I don't know if drivers respect its semantics in practice, but in theory it's supposed to wait until the GPU is done with its stuff)

 

That said, no idea what else causes the stalls, so =/

 

(EDIT: mentioned the wrong function >_>)

Edited by Sik_the_hedgehog

Share this post


Link to post
Share on other sites
Btw: When I remove both glReadPixels() and glGetError(), the stalls move to glfwSwapBuffers().
The same code, run on Intel Graphics on Linux, doesn't randomly stall for 5 seconds.
I plan to try the same program on different Windows machines next.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this