SFML community forums

Help => General => Topic started by: smguyk on December 19, 2013, 12:46:08 pm

Title: Problem with setFramerateLimit()
Post by: smguyk on December 19, 2013, 12:46:08 pm
Hi!

When I set the window's framerate limit to 60 I get ~35 FPS. When I set the limit to 120 I get ~65 FPS. When I don't define a limit I get over 8000 FPS.

Now, I want my game to run at 60 FPS. I can't really set the framerate limit to 60 though because then for some reason it stays at ~35 FPS.

Can someone please help me? What am I doing wrong?!

Edit: I made a quick example code (untested)

int main() {
  sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test", sf::Style::Close);
  window.setFramerateLimit(60);

  sf::Font font;
  if (!font.loadFromMemory(fontChar, fontSize)) {
    return -1;
  }

  sf::Clock c;
  sf::Text t = sf::Text("", font, 30);
  t.setColor(sf::Color(0, 0, 0));

  while (window.isOpen()) {
    sf::Event evt;
    while (window.pollEvent(evt)) {
      switch (evt.type) {
      case sf::Event::Closed:
        window.close();
        break;
      default:
        break;
      }
    }

    window.clear(sf::Color(255, 255, 255));

    float fps = 1.f / c.restart().asSeconds();
    std::stringstream ss;
    ss << "FPS: " << (int)fps;
    t.setString(ss.str());

    window.draw(t);
    window.display();
  }

  return 0;
}
Title: Re: Problem with setFramerateLimit()
Post by: Rhimlock on December 19, 2013, 01:02:45 pm
I suppose this is quite inaccurate
float fps = 1.f / c.restart().asSeconds();

You should rather try:
int fps = 1000000 / c.restart().asMicroseconds();


(untested) ;-)
Title: Re: Problem with setFramerateLimit()
Post by: smguyk on December 19, 2013, 01:08:11 pm
I suppose this is quite inaccurate
float fps = 1.f / c.restart().asSeconds();

You should rather try:
int fps = 1000000 / c.restart().asMicroseconds();


(untested) ;-)


It yields the same results for me.

Am I calculating the FPS correctly? Maybe that's the issue here but I don't see what's wrong with my code.
Title: Re: Problem with setFramerateLimit()
Post by: eXpl0it3r on December 19, 2013, 01:10:55 pm
What version of SFML are you using? Not too long ago we've had an improvement to the inaccuracy of sf::sleep, which is the cause of the issue here. I think it's already included in SFML 2.1, but I'm not certain - might want to look at the commit history.

Overall the framelimit with sf::sleep will always be a bit inaccurate, so if possible one should use VSync, but since that can be deactivated in the driver, one will still want to use framelimit.
Nexus implemented for Zloxx II an interesting idea, where you measure the frametime in the beginning and if it's not at the desired point, you can move the framelimit up. That way you could start with a fixed 60 limit and if the measured time is too far away from 1/60, you could move the limit up (or down) a bit to get closer to 60fps.

I suppose this is quite inaccurate
float fps = 1.f / c.restart().asSeconds();

You should rather try:
int fps = 1000000 / c.restart().asMicroseconds();
It's not really that inaccurate given that we're dealing with frametimes of 0.008 - 0.01s and don't care too much about the microseconds. And if you want to be accurate than your integer division isn't the best way to go about it either... ;)
Title: Re: Problem with setFramerateLimit()
Post by: smguyk on December 19, 2013, 01:19:36 pm
What version of SFML are you using? Not too long ago we've had an improvement to the inaccuracy of sf::sleep, which is the cause of the issue here. I think it's already included in SFML 2.1, but I'm not certain - might want to look at the commit history.

I'm using SFML 2.1.

Overall the framelimit with sf::sleep will always be a bit inaccurate, so if possible one should use VSync, but since that can be deactivated in the driver, one will still want to use framelimit.

I read about sf::sleep being inaccurate but the range was only a few FPS like 55 instead of 60 FPS and not 35 instead of 60. I'd be perfectly fine with +-5 FPS but -25 is too much... it's driving me crazy!
Title: Re: Problem with setFramerateLimit()
Post by: wintertime on December 19, 2013, 01:22:56 pm
I would just remove setFrameLimit and use setVerticalSyncEnabled, because random sleeps, which are naturally not synchronized to the gpu/monitor, are not a good way of handling this in a game.
If someone chooses to disable vsync in the driver (presumably for benchmarking) then its their choice and not the application programmers. Therefore it should just run as fast as possible, but the application should have logic updates decoupled from the framerate to prevent malfunction.
Title: Re: Problem with setFramerateLimit()
Post by: eXpl0it3r on December 19, 2013, 01:30:27 pm
I read about sf::sleep being inaccurate but the range was only a few FPS like 55 instead of 60 FPS and not 35 instead of 60. I'd be perfectly fine with +-5 FPS but -25 is too much... it's driving me crazy!
I know, it's most likely your hardware/driver not playing nice then... :-[

I would just remove setFrameLimit and use setVerticalSyncEnabled, because random sleeps, which are naturally not synchronized to the gpu/monitor, are not a good way of handling this in a game.
If someone chooses to disable vsync in the driver (presumably for benchmarking) then its their choice and not the application programmers. Therefore it should just run as fast as possible, but the application should have logic updates decoupled from the framerate to prevent malfunction.
While I agree, I don't see a reason for not providing a fallback. :)
Title: Re: Problem with setFramerateLimit()
Post by: binary1248 on December 19, 2013, 01:30:56 pm
Cliking on the FAQ link in eXpl0it3r's signature:
https://github.com/SFML/SFML/wiki/FAQ#wiki-window-set-framerate-limit

tl;dr version: Learn to live with it, making your game depend on having a fixed FPS isn't a good idea anyway.
Title: Re: Problem with setFramerateLimit()
Post by: smguyk on December 19, 2013, 01:36:20 pm
Thanks for your replies.

I think I'm going to be using setVerticalSyncEnabled(true) in the future then.

I still kind of want to have a fallback position though, so I was thinking to maybe call setVerticalSyncEnabled, then check if VSync is enabled and if not, set a framerate limit. There's no function for checking if VSync is enabled though, or is there?
Title: Re: Problem with setFramerateLimit()
Post by: eXpl0it3r on December 19, 2013, 01:39:29 pm
There's no function for checking if VSync is enabled though, or is there?
Not with SFML. You could however check the frametime a few times and if it's way too high, then it's not set (bad). ;)