Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit FPS in a loop with C++?

Tags:

c++

chrono

I'm trying to limit the frames per second in a loop that is performing intersection checking, using C++ with chrono and thread.

Here is my code:

std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::chrono::system_clock::time_point lastFrame = std::chrono::system_clock::now();  while (true) {     // Maintain designated frequency of 5 Hz (200 ms per frame)     now = std::chrono::system_clock::now();     std::chrono::duration<double, std::milli> delta = now - lastFrame;     lastFrame = now;      if (delta.count() < 200.0)     {         std::chrono::duration<double, std::milli> delta_ms(200.0 - delta.count());         auto delta_ms_duration = std::chrono::duration_cast<std::chrono::milliseconds>(delta_ms);         std::this_thread::sleep_for(std::chrono::milliseconds(delta_ms_duration.count()));     }      printf("Time: %f \n", delta.count());      // Perform intersection test  } 

The problem I'm having is that every other output of delta is showing miniscule amounts, rather than the ~200 ms / frame I'm aiming for:

Time: 199.253200 Time: 2.067700 Time: 199.420400 Time: 2.408100 Time: 199.494200 Time: 2.306200 Time: 199.586800 Time: 2.253400 Time: 199.864000 Time: 2.156500 Time: 199.293800 Time: 2.075500 Time: 201.787500 Time: 4.426600 Time: 197.304100 Time: 4.530500 Time: 198.457200 Time: 3.482000 Time: 198.365300 Time: 3.415400 Time: 198.467400 Time: 3.595000 Time: 199.730100 Time: 3.373400 

Any thoughts as to why this is happening?

like image 862
Irongrave Avatar asked Aug 02 '16 20:08

Irongrave


People also ask

How do I limit FPS on a program?

To limit FPS via RTSS, open the RTSS and click the Framerate limit option. Then configure the desired frame rate for the game. In addition, this program can be used to overclock GPU, create custom fan curves, monitor hardware temperatures.


1 Answers

If you think about how your code works, you'll find out that it works exactly how you wrote it. Delta oscillates because of a logical mistake in the code.

This is what happens:

  • We start with delta == 0.
  • Because the delta is smaller than 200, you code sleeps 200 - delta(0) == 200 ms.
  • Now, the delta itself becomes close to 200 (because you've measured that sleep time as well as an actual work) and you sleep 200 - delta(200) == 0 ms.
  • After that the cycle repeats.

To fix the problem you need to not measure the sleep time.

This is how it can be done:

#include <iostream> #include <cstdio> #include <chrono> #include <thread>  std::chrono::system_clock::time_point a = std::chrono::system_clock::now(); std::chrono::system_clock::time_point b = std::chrono::system_clock::now();  int main() {     while (true)     {         // Maintain designated frequency of 5 Hz (200 ms per frame)         a = std::chrono::system_clock::now();         std::chrono::duration<double, std::milli> work_time = a - b;          if (work_time.count() < 200.0)         {             std::chrono::duration<double, std::milli> delta_ms(200.0 - work_time.count());             auto delta_ms_duration = std::chrono::duration_cast<std::chrono::milliseconds>(delta_ms);             std::this_thread::sleep_for(std::chrono::milliseconds(delta_ms_duration.count()));         }          b = std::chrono::system_clock::now();         std::chrono::duration<double, std::milli> sleep_time = b - a;          // Your code here          printf("Time: %f \n", (work_time + sleep_time).count());     } } 

This code gives me a steady sequence of deltas:

Time: 199.057206  Time: 199.053581  Time: 199.064718  Time: 199.053515  Time: 199.053307  Time: 199.053415  Time: 199.053164  Time: 199.053511  Time: 199.053280  Time: 199.053283     
like image 56
HolyBlackCat Avatar answered Sep 27 '22 23:09

HolyBlackCat