Search code examples
c++sfmlframe-rategame-loop

SFML rendering performance issue


I've been making my game's core for the past week and I hit a wall because rendering was simply not good enough. Movement was jerky, I was getting tearing and there was a lot of lag in general. I thought that it may not be my game engine's fault so I tested rendering with a very simple gameloop:

        sf::RenderWindow window(sf::VideoMode(1024, 768), "Testing");
                window.setVerticalSyncEnabled(true);
        sf::Clock clock;
        sf::Event event;
        float elapsed;
        while(window.isOpen())
        {
                elapsed += clock.restart().asSeconds();
                std::cout << 1.f/elapsed << std::endl;
                while(elapsed > 1.f/60.f)
                {
                        while(window.pollEvent(event))
                        {
                                if (event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                        }
                        elapsed -= 1.f/60.f;
                }
                window.clear();
                window.display();
        }

The fps starts at 40 , goes up to 60 and then falls back to 30, it increments again and repeats. If I set VSynct to false, I get anywhere between 30-500 fps. Either I am not testing the frame rate correctly or there is something wrong with my nvidia drivers (I did reinstall them 2 times with no changes). Any help is appreciated!


Solution

  • You pointed me to a material which has similar code to yours, but you wrote it differently.

    From: gameprogrammingpatterns.com/game-loop.html

    double previous = getCurrentTime();
    double lag = 0.0;
    while (true)
    {
      double current = getCurrentTime();
      double elapsed = current - previous;
      previous = current;
      lag += elapsed;
    
      processInput();
    
      while (lag >= MS_PER_UPDATE)
      {
        update();
        lag -= MS_PER_UPDATE;
      }
    
      render();
    }
    

    You seem to be using one variable elapsed for both, elapsed and lag. That is what was baffling me. Your mangling with elapsed makes it unusable for the purpose measuring time. I think your code should look more like:

        sf::RenderWindow window(sf::VideoMode(1024, 768), "Testing");
                window.setVerticalSyncEnabled(true);
        sf::Clock clock;
        sf::Event event;
        float lag;
        float elapsed;
    
        while(window.isOpen())
        {
                lag = elapsed = clock.restart().asSeconds();
                std::cout << 1.f/elapsed << std::endl;
                while(lag > 1.f/60.f)
                {
                        while(window.pollEvent(event))
                        {
                                if (event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                        }
                        lag -= 1.f/60.f;
                }
                window.clear();
                window.display();
        }
    

    I am still not sure if this will be correct. I don't know what clock.restart().asSeconds() does exactly. Personally, I would implement it line by line like the example. Why redesign working code?

    Edit: OP confirmed that, using elapsed for "throttling" was breaking its purpose as time a measurement variable.