Quote:Original post by bobmitch SOLVED!!! It's a quirk of nvidia's slightly experimental drivers I think. After puzzling over my code and how opengl works, I narrowed it down to either an SDL bug or a driver bug. The more I fiddled with various delays in my main loop, the more it seemed like a threading issue... but my code is running in a single thread right now. Solution: Disable threaded optimization in the advanced settings in the Nvidia control panel, it looks like it's set to Auto by default.[Edited by - dc443 on September 17, 2008 7:06:40 PM]
[SDL] Very strange event polling and vsync issue
I am using SDL and OpenGL along with Box2D in my project.
I would prefer to enable vsync, because it tends to reduce CPU load by at least 50%, while at the same time ensuring that there is never any graphical "tearing". What's not to like, right? Plus anyone can easily override the setting in their video drivers should they be bothered by the mouse lag that results (and thats an entirely different issue altogether).
Well, there's this particularly strange issue that I'm getting. Whenever you move the mouse in the window WITHOUT ANY BUTTONS HELD DOWN, the SDL_PollEvent(SDL_Event*) and SDL_PumpEvents() functions often take over 13 milliseconds to execute. This is about the same time as an entire frame, so the animation becomes stuttery and in my case even the physics simulation is forced to slow down as a result.
Okay, so I thought maybe this is just what it takes to figure out how far my mouse moved. This COULD be understandable since my mouse does refresh at 500Hz. But what's screwed up is, if I hold down a mouse button and THEN move it, there is now slowdown. Holding down of the four buttons (left click, middle click, right click, side button) works. I also know that SDL does in fact receieve all of the mouse motion data because if I am DRAGGING something along in my sim by holding down a button, it will run perfectly smoothly, then once I let go of the button, I have to stop moving the mouse or move it out of the screen to make the stuttering stop.
Note that when I say stuttering, it's more like instead of each frame being displayed for exactly 1/60 second, it becomes something like one frame for 1/32, and another for 1/480... sure, average fps is 60, but visually you get 30fps. Fraps will display 60fps because it averages the value over several frames.
You can try it for yourself and see if you can reproduce this issue:
http://sourceforge.net/projects/box2dsandbox/
Get the 0.15 download. The stuttering effect is easiest to notice when you pick up the concave random-looking shape, and toss it somewhere. while its moving and spinning, move your mouse. If you look closely, you will also notice the entire simulation slow down as well (less so if you do not run 60Hz refresh, in fact all of the effects are reduced at higher refresh rates, but I can very easily notice it at 75Hz on my screen).
This issue is not reproducible when vsync is off.
Anyone got any ideas?
EDIT:
This appears to only affect Nvidia hardware on certain driver versions and I originally thought it was purely an SDL bug. You may be unable to reproduce it with my link above.
SOLUTION:
while (SDL_PollEvent(&event)) { if( event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE )) quit = true; else if (event.type == SDL_MOUSEBUTTONDOWN) { ... } else if (event.type == SDL_MOUSEBUTTONUP) { ... } else if (event.type == SDL_MOUSEMOTION) { ... } else if (event.type == SDL_KEYDOWN) { ... } }
When I did timings I started the timer right before the while loop, and put the timer.stop() right in the beginning of the loop, like this:
timer.startTimer(); while (SDL_PollEvent(&event)) { printf("%f ms\n",timer.stopTimer()*1000.); ...
Also, if I comment out my entire event handling loop and use SDL_PumpEvents() instead, and use SDL_GetKeyState() and SDL_GetMouseState(), the exact same thing happens.
Okay, did some more testing and it definitely looks like this has something to do with VSync.
That's because when I have my refresh at 75Hz, polling events causes it to lag for 13.3 ms on average. 13.3333ms is exactly 1/75 second.
Similarly when I set my refresh to 60Hz, the lag increases to 16ms, and 1/60 s == 16.6667ms.
I still have no idea what might be causing this though. I mean, it works totally fine when a mouse button is pressed down. What is up with that!?!
That's because when I have my refresh at 75Hz, polling events causes it to lag for 13.3 ms on average. 13.3333ms is exactly 1/75 second.
Similarly when I set my refresh to 60Hz, the lag increases to 16ms, and 1/60 s == 16.6667ms.
I still have no idea what might be causing this though. I mean, it works totally fine when a mouse button is pressed down. What is up with that!?!
Where do you do your rendering? Also, which OS is this? And which rendering driver are you using?
I'm on windows. XP 32 bit.
Inside debugDrawBody() are standard gl draw functions. I'm pretty sure there are no problems in there.
I've moved the drawing and swapping of buffers to different spots in the loop (before or after the event polling) to no avail.
Also what do you mean by rendering driver?
while (!quit) { //clear glClear(GL_COLOR_BUFFER_BIT); //drawing b2Body* body = world->GetBodyList(); while(body) { debugDrawBody(body, d); body = body->GetNext(); } //end drawing //swap buffers SDL_GL_SwapBuffers(); //SDL Event Handling while (SDL_PollEvent(&event)) { ... } ... // advance physics }
Inside debugDrawBody() are standard gl draw functions. I'm pretty sure there are no problems in there.
I've moved the drawing and swapping of buffers to different spots in the loop (before or after the event polling) to no avail.
Also what do you mean by rendering driver?
I registered in this forums just for this question. I am having the same issue. I have a spinning pyramid and it will slow down when I move the mouse but when I move the mouse with some of the buttons pressed it will not happen. In my case I have a function that returns the time elapsed between frames and some times it gives me zero. I don't know how that's possible.
deltaTime some times is zero. I hope some one has a clue for this issue.
float getDeltaTime(void){ // return delta time return (this->deltaTime / 1000.0f);} // getDeltaTime
deltaTime some times is zero. I hope some one has a clue for this issue.
I think I solved the problem. At least in my case.
All I had to do was to get the time at the beginning of the frame then process all events then at the end of the loop get the time again and everything runs smooth again. I hope this helps you some how.
-r
All I had to do was to get the time at the beginning of the frame then process all events then at the end of the loop get the time again and everything runs smooth again. I hope this helps you some how.
// main loop for(;;) { // get time before frame this->beforeFrameTime = (float)SDL_GetTicks(); // handle events this->handleEvents(); // render stuff // ............. // get time after frame this->afterFrameTime = (float)SDL_GetTicks(); // time since last frame this->deltaTime = this->afterFrameTime - this->beforeFrameTime;}
-r
As I understand it, what will happen is, normally the game loop finishes and calls Swap Buffers, which waits 16 or so miliseconds until swapping the buffers and allowing the loop to continue. With the SDL bug, sometimes the events functions will hog up 16 seconds, which means that once it reaches swap_buffers it will instantly swap the buffers and return. The result? One frame displayed for 1/30 second and one frame displayed for almost no time at all. I guess your timer isnt precise enough to catch the super short frame, which is probably going past in under 1 milisecond.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement