Stuttering time fixed using VSync on

In the OpenGL 2D engine that I implemented, I have a fixed timestep, as described in the famous fix for your temporary publication along with the overlay.

I have a test object that moves vertically (y axis). In motion, stuttering occurs (a pre-programmed movement, not from user input). This means that the subject is not smoothly moving around the screen.

See the uncompressed video that I am linking: LINK

The game frame rate is 60 frames per second (Vsync is enabled from the Nvidia driver)

The game logic is updated with a fixed 20 updates / ticks per second set by me. This is normal. The object moves 50 pixels to update.

However, the movement on the screen stutters greatly.

EDIT: I noticed, step by step in the recorded video frame by frame, that the stuttering is caused by the fact that the frame is displayed twice.

EDIT2: setting application priority for Realtime in the task manager completely eliminates stuttering! However, this is obviously not a solution.

Below is the delta of deviation of the object y at different times when VSync is off The first column is the elapsed time since the last frame, in microseconds (ex 4403 ) The second column is the movement along the y axis of the object since the last frame. In fact, the object moves 1000 pixels per second, and the log below confirms it.

 time since last frame: 4403 ypos delta since last frame: 4.403015 time since last frame: 3807 ypos delta since last frame: 3.806976 time since last frame: 3716 ypos delta since last frame: 3.716003 time since last frame: 3859 ypos delta since last frame: 3.859009 time since last frame: 4398 ypos delta since last frame: 4.398010 time since last frame: 8961 ypos delta since last frame: 8.960999 time since last frame: 7871 ypos delta since last frame: 7.871002 time since last frame: 3985 ypos delta since last frame: 3.984985 time since last frame: 3684 ypos delta since last frame: 3.684021 

Now that VSync is On

 time since last frame: 17629 ypos delta since last frame: 17.628906 time since last frame: 15688 ypos delta since last frame: 15.687988 time since last frame: 16641 ypos delta since last frame: 16.641113 time since last frame: 16657 ypos delta since last frame: 16.656738 time since last frame: 16715 ypos delta since last frame: 16.715332 time since last frame: 16663 ypos delta since last frame: 16.663086 time since last frame: 16666 ypos delta since last frame: 16.665771 time since last frame: 16704 ypos delta since last frame: 16.704102 time since last frame: 16626 ypos delta since last frame: 16.625732 

I would say that they look normal.

It made me bonkers for several days, what am I missing?

The following is my Frame function, which is called in a loop:

 void Frame() { static sf::Time t; static const double ticksPerSecond = 20; static uint64_t stepSizeMicro = 1000000 / ticksPerSecond; // microseconds static sf::Time accumulator = sf::seconds(0); gElapsedTotal = gClock.getElapsedTime(); sf::Time elapsedSinceLastFrame = gElapsedTotal - gLastFrameTime; gLastFrameTime = gElapsedTotal; if (elapsedSinceLastFrame.asMicroseconds() > 250000 ) elapsedSinceLastFrame = sf::microseconds(250000); accumulator += elapsedSinceLastFrame; while (accumulator.asMicroseconds() >= stepSizeMicro) { Update(stepSizeMicro / 1000000.f); gGameTime += sf::microseconds(stepSizeMicro); accumulator -= sf::microseconds(stepSizeMicro); } uint64_t blendMicro = accumulator.asMicroseconds() / stepSizeMicro; float blend = accumulator.asMicroseconds() / (float) stepSizeMicro; if (rand() % 200 == 0) Trace("blend: %f", blend); CWorld::GetInstance()->Draw(blend); } 

Additional information on request:

  • Stuttering occurs both in full-screen mode 1920x1080, and in window mode 1600x900

  • customization is a simple SFML project. I don't know if it uses VBO / VAO internally when rendering textured rectangles

  • do nothing on my computer. Keep in mind that this problem occurs on other computers, it’s not only my installation

  • performed on the main display. The display really doesn't matter. The problem arises in both full-screen and windowed modes.

+5
source share
3 answers

I have profiled my own code. The problem was that there was an area of ​​my code that occasionally had performance spikes due to misses in the cache. This caused my loop to take more than 16.6666 milliseconds, the maximum time it takes to smoothly display at 60 Hz. From time to time it was only one frame. This frame caused a stutter. The logic of the code itself was correct, it turned out to be a performance problem.

In the future, in the hope that this will help other people, as I debugged it, I put

 if ( timeSinceLastFrame > 16000 ) // microseconds { Trace("Slow frame detected"); DisplayProfilingInformation(); } 

in my frame code. When an if triggered, it displays the profiling statistics for the functions in the last frame to see which function took the longest in the previous frame. Thus, I was able to pinpoint a performance error for a structure that is not suitable for its use. A large, nasty card of cards that generated a lot of misses in the cache and freezes from time to time in performance.

Hope this helps future unhappy souls.

+1
source

It seems that you are not synchronizing your 60 Hz frame loop with the 60 Hz VSync GPU. Yes, you enabled Vsync in Nvidia, but that only forces Nvidia to use the reverse buffer, which is replaced by Vsync.

You need to set the swap interval to 1 and execute glFinish() to wait for Vsync.

0
source

Difficult, but from the above it seems to me that this is not a problem with the "frame rate", but rather somewhere in your "live" code. Another observation is the line "Update (stepSizeMicro / 1000000.f);". dividing by 1000000.f may mean that you are losing resolution due to limitations in the resolution of the bit of floating-point numbers, so rounding might be your killer?

-1
source

Source: https://habr.com/ru/post/1204111/


All Articles