Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] window.pollEvent() lagging when Joystick not plugged in  (Read 17777 times)

0 Members and 1 Guest are viewing this topic.

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
I'm going to mark this as solved since I already have a workaround. Although at the bottom of this post, I have a possible feature request. But first, here's the problem I encountered...

This is on Windows Vista with SFML-2.3.1.

There seems to be lag or "hiccups" in a smooth framerate when calling the window's pollEvent() without a Joystick/controller plugged in. I especially noticed this since I limit the framerate in my prototype game to 60fps - every second or so, there was a glitch or hiccup and by recording and printing out the frame periods I was able to verify this with most of the times being around 15 to 17 milliseconds but every so often a 30 or 40 ms period showing up.

Just through trial and error I noticed that this DOESN'T happen when I have an Xbox360 clone USB controller plugged in. Another way to "fix" the glitches was to remove the pollEvent() loop.

Anyway, after searching the forum a bit and consulting with a twitter pal, I found this thread:

http://en.sfml-dev.org/forums/index.php?topic=6079.0

That's obviously an old thread, but I guess some of it still applies.

TEST PROGRAM

//
// Simple example to demonstrate lag/hiccups in SFML when framerate is set to 60fps
// and window.pollEvent() is called.
//
// On my machine (Windows Vista 64bit) compiling with mingw  4.8.1 & SFML 2.3.1
// the lag or "hiccups" go away when I plug in a controller/joystick. Unplugging the
// controller again, the "hiccups" stay gone.
//
// Also commenting out the pollEvent() call "fixes" the problem. So maybe it's an
// interaction with a framerate limited to 60fps and polling for events when no
// controller is plugged in. Could just be my machine, too.
//   --> Core2 Duo T6500 CPU at 2.1 GHz
//       with Intel Graphics (but decent-ish "Entertainment" Notebook PC GPU)
//       surely I should be able to draw one quad at 60fps without lag.
//       Seems more like a bug somewhere with polling for controller Events???
//
// The hiccups can be seen in the flickering of the quad (that represents the frametime).
// This rectangle should be about 2*16 or 2*17 pixels long, where the 16 or 17 represent
// milliseconds between frames in the test program. However, the drawing is occasionally
// missed to to a lag introduced that takes the frametime up to around 30ms.
//
// Frame times can be verified by tapping the Return/Enter key to dump the last 100 frame
// times and whereas most are ~16ms, the occasional ~30ms time can be seen in the dump.
//

#include <SFML/Graphics.hpp>

#include <iostream>

int main()
{
  int Window_Width;
  int Window_Height;

  Window_Width = sf::VideoMode::getDesktopMode().width;
  Window_Height = sf::VideoMode::getDesktopMode().height;

  // Create a fullscreen window
  sf::RenderWindow renderWindow(sf::VideoMode(Window_Width, Window_Height),"FrameRate Test", sf::Style::None);

  renderWindow.setVerticalSyncEnabled(true);
  renderWindow.setFramerateLimit(60);

  // clock to measure time
  sf::Clock clock;
  sf::Int32 lastTime = 0;
  sf::Int32 thisTime = 0;
  sf::Int32 deltaTime;

  // check updates in ms
  int numChecks = 0;
  int i = 0;
  sf::Int32 check[100];

  // prime the timer/clock
  lastTime = clock.getElapsedTime().asMilliseconds();

  // draw a frame time quad
  sf::VertexArray ftquad(sf::Quads, 4);
  ftquad[0].position = sf::Vector2f(100,50);
  ftquad[1].position = sf::Vector2f(200,50);
  ftquad[2].position = sf::Vector2f(200,100);
  ftquad[3].position = sf::Vector2f(100,100);

  ftquad[0].color = sf::Color::Red;
  ftquad[1].color = sf::Color::Red;
  ftquad[2].color = sf::Color::Red;
  ftquad[3].color = sf::Color::Red;

  bool frametimes_dumped = false;

  // ********************************************************************************************************************
  // Start the game loop
  // ********************************************************************************************************************
  while (renderWindow.isOpen())
  {
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
          renderWindow.close();
    }

    // commenting out the pollEvent() call "fixes" the problem with lag/hiccups
    ///*
    sf::Event event;
    while (renderWindow.pollEvent(event)) {
        // DO NOTHING
    }
    //*/

    // -----------------------------------------------------------------
    // UPDATING
    // -----------------------------------------------------------------
    thisTime = clock.getElapsedTime().asMilliseconds();
    deltaTime = thisTime - lastTime;

    // record "frame time" from last frame to now
    check[numChecks] = deltaTime;
    numChecks++;
    if (numChecks >= 100) numChecks = 0;

    lastTime = thisTime;

    // draw a rectangle with length of twice the frame time
    ftquad[0].position = sf::Vector2f(100, 50);
    ftquad[1].position = sf::Vector2f(100 + deltaTime*2, 50);
    ftquad[2].position = sf::Vector2f(100 + deltaTime*2, 100);
    ftquad[3].position = sf::Vector2f(100, 100);

    // dump past 100 frame times when Return key is hit
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Return) && !frametimes_dumped) {
        frametimes_dumped = true;
        for (i=numChecks; i < 100; i++) // dump older recorded frame times
                std::cout << "check" << std::dec << i << " : " << check[i] << "ms\n" ;
        for (i=0; i < numChecks; i++) // dump most recent recorded frame times
                std::cout << "check" << std::dec << i << " : " << check[i] << "ms\n" ;
    }

    // -----------------------------------------------------------------
    // DRAWING
    // -----------------------------------------------------------------
    renderWindow.clear(sf::Color::Black);
    renderWindow.draw(ftquad);
    renderWindow.display();

  }

  return EXIT_SUCCESS;
}

 

On my PC at least (and perhaps others), if you run the program without a controller plugged in, you'll see a red bar that shows the frame period, but occasionally it'll miss a frame and will just draw black. Commenting out the pollEvent() call/loop or plugging in a Controller alleviates the problem and it draws every frame.

It's possible you won't see this on a higher powered CPU, but I'm guessing it'll show up even there if you limit your framerate to 60fps and add the sort of complexity & number of entities you're drawing in an actual game.

WORKAROUND

I hacked together a somewhat similar workaround as the one mentioned in the older forum thread, but in this case, by adding a bool member to Win32/JoystickImpl.hpp

 
  // hacky new methods
  bool isfixConnected();
  void setfixConnected(bool flag);

  // hacky new private member
  bool m_fix_connected;

 

and Win32/JoystickImpl.cpp

  bool JoystickImpl::isfixConnected() {return m_fix_connected;}
  void JoystickImpl::setfixConnected(bool flag) {m_fix_connected = flag;}
 

and then changing Window/JoystickManager.cpp JoystickManager::update() to this

////////////////////////////////////////////////////////////
void JoystickManager::update()
{
    for (int i = 0; i < Joystick::Count; ++i)
    {
        Item& item = m_joysticks[i];

        if (item.state.connected)
        {
            // Get the current state of the joystick
            item.state = item.joystick.update();

            // Check if it's still connected
            if (!item.state.connected)
            {
                item.joystick.close();
                item.capabilities   = JoystickCaps();
                item.state          = JoystickState();
                item.identification = Joystick::Identification();
            }
        }
        else
        {
            // Check if the joystick was connected since last update
            // Hack - fix glitch when joystick is not connected
          if (!item.joystick.isfixConnected()) {
            // HACK - have it only check once...
            item.joystick.setfixConnected(true);

            if (JoystickImpl::isConnected(i))
            {
                if (item.joystick.open(i))
                {
                    item.capabilities   = item.joystick.getCapabilities();
                    item.state          = item.joystick.update();
                    item.identification = item.joystick.getIdentification();
                }
            }
          }
        }
    }
}

 

So it will only check once (when the game launches) whether a controller is plugged in. This fixes the "hiccups" in the frame rate.

FEATURE REQUEST?

I guess it might be a useful addition to add a flag to the Window & Joystick implementations to workaround this, so that the default is to check every time JoystickManager::update() is called, but allow the game dev to set a flag after creating the window so that it only checks once when the game starts.

That is until a definite solution is found.

Just putting this out there in case someone else runs into the same problem.

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #1 on: October 07, 2015, 10:52:33 am »
I think it's probably because SFML cause a bunch of registry access operations periodically. All these operations is related to the joystick. So it may cause high lags...
There is need for option to disable joystick update. For example I don't use joysticks at all, but it affects my app, I see for about hundreds of registry operations per second with sysinternals Process Monitor

Also I have suggestion to replace setframelimit(60) with SetFrameLimit(0). On my system it allows to decrease CPU load for about 4000% ( from 50% load to 1% load on 4 core processor). Also it makes more smooth and stable frame rate
« Last Edit: October 07, 2015, 11:00:59 am by mkalex777 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #2 on: October 07, 2015, 01:56:18 pm »
Also I have suggestion to replace setframelimit(60) with SetFrameLimit(0). On my system it allows to decrease CPU load for about 4000% ( from 50% load to 1% load on 4 core processor).
setFramerateLimit(0) disables the frame rate limit, meaning that the game loop is cycled as frequently as possible.

Are you sure it reduces the processor load? Unless you have VSync or some other kind of waiting/sleeping enabled, that doesn't make sense.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #3 on: October 07, 2015, 05:42:09 pm »
Also I have suggestion to replace setframelimit(60) with SetFrameLimit(0). On my system it allows to decrease CPU load for about 4000% ( from 50% load to 1% load on 4 core processor).
setFramerateLimit(0) disables the frame rate limit, meaning that the game loop is cycled as frequently as possible.

Are you sure it reduces the processor load? Unless you have VSync or some other kind of waiting/sleeping enabled, that doesn't make sense.

Yes, of cause I'm using VBlank sync to limit frame smoothly. It's the single way which allows to limit render rate with smooth timeline (with no lags). So, when I want to measure renderer performance I disable vblanksync in game settings. When I need maximum smooth and to eliminate screen tearing effect I enable vblanksync.
It's easy, high quality way with minimum cpu load and it used in all commercial games.

I have no idea what is doing SetFrameLimit, probably it was designed to skip some frames to make frame rate slower. But if you skipping frames, it means that you will trap in problems with smoothness. You will get jerky movements, you can reduce that effect if you are using time based movements and video resampling filter (which interpolates colors with complicated and heavy filtering detects object motions on the image, etc) which is too heavy task for todays videocard shader processing, because it requires a lot of calculations and to using complicated algorithms. But anyway you cannot eliminate such effect. And your video will be always much worse than with no frame limiting.

If you don't need for smoothness movements in your app (if you are using static image with no movements) you can use frame limiting, but I have no idea for what :)
Because you will get better results with vblank sync even for static image.

And yes, I have extremely high CPU load with using SetFrameLimit. It even affects entire system, I get high lags in other applications. For example, my renderer for the game with no player entities consumes for about 0,5% of CPU time. If I set SetFrameLimit(60), cpu load jumps to 50-60% (two core of 4 was totaly burned to execute some useless idle loop).

I can say more you cannot eliminate jerky movement effect which appears when you skipping frames even if you will use pixel color interpolation between near frames and other filtering algorithms. It's physically impossible. For better filtering result, your display should have refresh rate at least 100 times faster than your target value. It means that if you want to get good quality (NOT high) with SetFrameLimit(60), your display should works with frequency 6000 frames per second. And your videocard should be able to apply complicated filtering for each frame. It just impossible with today's technology.

The best approach to visualize such effects is to use slow text movement (one pixel per frame), also it affects fast color changing (each frame has new color of pixel). With skipping frame your image will looks very different. You will find that the text is not moving smoothly, its speed will always jump. And you will be surprised that the colors also will be so different from vblank sync synchronization ;)
« Last Edit: October 07, 2015, 06:03:09 pm by mkalex777 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #4 on: October 07, 2015, 07:17:09 pm »
Yes, of cause I'm using VBlank sync to limit frame smoothly.
Okay, you should have mentioned that. VSync and a framerate limit are not intended to work together, so don't be surprised about high CPU loads. It's either or.

I have no idea what is doing SetFrameLimit, probably it was designed to skip some frames to make frame rate slower.
Instead of guessing wildly, you could read the documentation for example.

It doesn't skip frames. With that premise being wrong, your conclusion is invalid, too ;)

setFramerateLimit() isn't meant to be the perfect choice for every application, its inaccuracy is mentioned in the documentation as well. But it's simple to set up and useful in cases where vertical synchronization can't be used.
« Last Edit: October 07, 2015, 07:18:55 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #5 on: October 07, 2015, 07:23:52 pm »
Remember that even with vsync (when it's even available, it isn't always) you are not guaranteed a completely stable framerate. You always have to take into account that time-per-frame can vary and decouple your game logic updates from your rendering. And once you do that, setting a framerate limit is usually just as fine as using vsync (unless you have tearing problems specifically).
Just don't mix the two.

This classic article also seems to be relevant, so I'll link it: http://gafferongames.com/game-physics/fix-your-timestep/

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #6 on: October 07, 2015, 07:31:09 pm »
I think it's probably because SFML cause a bunch of registry access operations periodically. All these operations is related to the joystick. So it may cause high lags...
Don't just think/guess that it is so. Measure. Use a profiler.
Personally I doubt these registry accesses take any significant time at all, but do test that hypotheses.

There is need for option to disable joystick update.
I don't think you've provided sufficient evidence to back up that claim. How much time does your profiler tell you is spent doing those updates? Is is a significant amount of the programs total CPU time?

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #7 on: October 07, 2015, 10:03:43 pm »
Remember that even with vsync (when it's even available, it isn't always) you are not guaranteed a completely stable framerate. You always have to take into account that time-per-frame can vary and decouple your game logic updates from your rendering. And once you do that, setting a framerate limit is usually just as fine as using vsync (unless you have tearing problems specifically).
Just don't mix the two.

This classic article also seems to be relevant, so I'll link it: http://gafferongames.com/game-physics/fix-your-timestep/

I don't need to implement it because all physics and movements in my game is time based and not depends on frame rate. It works with the same speed for 1250 fps and for 75 fps  ;)
But vsync looks definitely better because it absolutely smooth.

I tested and it seems that you are right, with disabled vblank sync SetFrameLimit works at least not so bad, with no high cpu load. It's not so stable like vblank sync, but it works not so bad.

Here is my results for LCD display with physical refresh rate 75 Hz:
Full graph width = last 200 frames
Avg = moving average
Time measurement error = ±0,00000037 [sec]  (timer frequency 2742939 [Hz])

SetFrameLimit(75);
SetVerticalSyncEnabled(false);



SetFrameLimit(0);
SetVerticalSyncEnabled(true);
« Last Edit: October 07, 2015, 10:18:30 pm by mkalex777 »

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #8 on: October 07, 2015, 10:26:51 pm »
There is need for option to disable joystick update.
I don't think you've provided sufficient evidence to back up that claim. How much time does your profiler tell you is spent doing those updates? Is is a significant amount of the programs total CPU time?

You can just open process monitor and look what really happens, here is evidence (just 10-20 sec of running SFML app):
« Last Edit: October 07, 2015, 10:44:55 pm by mkalex777 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #9 on: October 07, 2015, 10:42:02 pm »
I don't need to implement it because all physics and movements in my game is time based and not depends on frame rate.  It works with the same speed for 1250 fps and for 75 fps  ;)
Does that mean you run the physic updates with different delta-times?

If so, this will easily add non-deterministic behavior to your physics. For example, if the computer lags for a blink of an eye, objects may tunnel through others instead of colliding.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #10 on: October 07, 2015, 10:52:35 pm »
I don't need to implement it because all physics and movements in my game is time based and not depends on frame rate.  It works with the same speed for 1250 fps and for 75 fps  ;)
Does that mean you run the physic updates with different delta-times?

If so, this will easily add non-deterministic behavior to your physics. For example, if the computer lags for a blink of an eye, objects may tunnel through others instead of colliding.

No, renderer uses just interpolated values from the target value which is calculated with fixed time step, so if there will be lag in update, all entities just will smoothly stop with a little of inertia added by filter (0,5-1 sec) :)

The lag value on the graph is related to network lag. I taken screenshot when it was disconnected, so it shows all zeros :)
« Last Edit: October 07, 2015, 11:08:58 pm by mkalex777 »

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #11 on: October 07, 2015, 11:02:33 pm »
Remember that even with vsync (when it's even available, it isn't always) you are not guaranteed a completely stable framerate. You always have to take into account that time-per-frame can vary and decouple your game logic updates from your rendering. And once you do that, setting a framerate limit is usually just as fine as using vsync (unless you have tearing problems specifically).
Just don't mix the two.


Hmm, this is interesting because I'm mixing the two. But you're right - the tutorial says not to mix them. It's just that for my PC, mixing them doesn't make things worse. It makes them better.  :P

The problem is that on my notebook PC, using setVerticalSyncEnabled(true) doesn't limit the framerate to the refresh rate (60Hz).

Not sure if it's the correct place to check and set this, but in the "Intel Graphics and Media Control Panel" there IS an option under 3D relating to Vertical Sync. It's currently set to "Application Settings" which I assume means SFML would enable/disable it according to my setting with setVerticalSyncEnabled().

The other option is "On", but changing to that and clicking Apply still doesn't limit the framerate in my game.

That's why I'm currently using both setVerticalSyncEnabled(true) to prevent tearing AND setFramerateLimit(60) to keep from hogging the CPU.

Of course my PC may be quite different from what most of you guys are using, but a medium powered notebook PC is pretty useful in game dev since many of your players/customers will only have a medium powered PC.

Anyway, is this a known issue/situation where some notebook PCs don't allow vsync (at least with SFML)?

EDIT: seems some notebook OpenGL drivers on Windows might be ignoring the vsync flag...

http://en.sfml-dev.org/forums/index.php?topic=10429.msg71870#msg71870

EDIT2: a couple of other links about forcing vsync to be enabled on Windows

https://www.opengl.org/discussion_boards/showthread.php/146791-How-to-enable-force-VSYNC

http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl

I'll have to see if I can figure that all out.
« Last Edit: October 07, 2015, 11:29:03 pm by espectra »

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #12 on: October 11, 2015, 02:25:18 am »
The problem is that on my notebook PC, using setVerticalSyncEnabled(true) doesn't limit the framerate to the refresh rate (60Hz).

It seems that it's because there is an issue with SFML. I have the same issue on Windows 10 machine.
With SFML setting VerticalBlankSync(true) just doesn't works on this machine.
But I can run my DirectX application on the same machine and it can use vblank sync with no problem (and I see that it really works on the timing realtime graph)...
But when I trying to enable it from SFML application, vblank sync just has no effect (it runs with 1000 fps).

May be it's related to specific driver or OpenGL...
« Last Edit: October 11, 2015, 02:28:32 am by mkalex777 »

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #13 on: October 11, 2015, 03:13:26 am »
The problem is that on my notebook PC, using setVerticalSyncEnabled(true) doesn't limit the framerate to the refresh rate (60Hz).

It seems that it's because there is an issue with SFML. I have the same issue on Windows 10 machine.
With SFML setting VerticalBlankSync(true) just doesn't works on this machine.
But I can run my DirectX application on the same machine and it can use vblank sync with no problem (and I see that it really works on the timing realtime graph)...
But when I trying to enable it from SFML application, vblank sync just has no effect (it runs with 1000 fps).

May be it's related to specific driver or OpenGL...

I did an experiment yesterday with Slick2D/LWJGL which uses OpenGL and it had the same problem, so it may be an OpenGL driver problem, either just with my driver or possibly also the OpenGL drivers for other GPUs.

FWIW my notebook has a built-in Intel graphics accelerator, "Mobile Intel 4 Series Express" and the driver is the latest version but since it's an old PC (2009), the latest driver update is from 2013 and it only supports up to OpenGL 2.1.

For now in my prototype game I'm just using setFramerateLimit(). There's no tearing on the notebook, but I plan to check it on a friend's PC with an Nvidia GPU to see if I need to do something to prevent tearing.

mkalex777

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: [SOLVED] window.pollEvent() lagging when Joystick not plugged in
« Reply #14 on: October 11, 2015, 04:11:31 pm »
May be it's related with OpenGL version, here is my observations:

OpenGL 4.5: vblank sync works OK
OpenGL 2.1: vblank sync didn't works