SFML community forums

Help => Window => Topic started by: SuperV1234 on November 20, 2011, 12:31:48 pm

Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 20, 2011, 12:31:48 pm
VSync is off, framerate is constant and I'm getting input using the Keyboard class.

At 60FPS, the input feels delayed (I don't have any better word for it).
At 150+FPS it feels just fine.

What could be causing this?
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 20, 2011, 03:45:59 pm
HAHA welcome to the club. Im really puzzled that nobody had problems with it before :D.

Check this: http://sfml-dev.org/forum/viewtopic.php?t=6237

With vertical sync you get a framerate pegged to 60/75/100 Hz. This is because each frame the window.display() pauses the whole application until the graphics card decides it is safe to fill the video buffer without the risk of tearing.

So, in 60 FPS 1 frame lasts 1 / 60 = 0,01667 seconds

Now, imagine you press a key just after the display method was called. It waits and waits, and your input stays unregistered. The worst case is getting 0,0166 delay because of Vertical Sync.

Laurent, maybe it would be possible for you to put the window.display in a thread, so it would not freeze the whole application? I really don't see why limiting DISPLAY framerate should limit the CALCULATION framerate.

A partial solution to your problem could be sth like this. It's in python but you may use the sf::Clock instaead of time:
Code: [Select]
     if time.clock() - last_display > 0.016:
         window.clear(sf.Color(200,   0,   0))
         window.display()
         last_display = time.clock()


It calls the window.display right before the Vertical Sync
Title: Input feels delayed at 60FPS
Post by: Laurent on November 20, 2011, 04:51:42 pm
SFML is very low-level, it provides building blocks but then it's up to you to decide how to use these blocks. If you want display and input to be separated, then separate them ;)

But to be honest, I've never had problems with input at 60Hz, I think it is responsive enough for most applications. What kind of app are you developping? What are inputs used for?
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 20, 2011, 05:04:18 pm
Quote from: "Laurent"
SFML is very low-level, it provides building blocks but then it's up to you to decide how to use these blocks. If you want display and input to be separated, then separate them ;)

But to be honest, I've never had problems with input at 60Hz, I think it is responsive enough for most applications. What kind of app are you developping? What are inputs used for?


I created an app that measures response time. Since typical human response ranges between 0.2 and 0.3 second, I would need better granularity than 0.0166 of a second. Without it my app is showing 0.233 all the time (exactly 14 frames out of 60).

Here is my app (windows, but runs on wine):
http://grebocin.com/upload/screenway11.zip

My final goal is to make an online racing game and I think it would be useful to shave off these extra 16 ms of lag that the display generates.

I agree about the blocks thing, but unfortunately I can't create some blocks myself. If SFML could at least retrieve refresh rate of current video mode, I would know when to call window.display to cause the least delay. Also, I think it's not possible to get a list of supported refresh rates at given resolution or to set a video mode with a desired refresh rate, right?
Title: Input feels delayed at 60FPS
Post by: Laurent on November 20, 2011, 06:26:45 pm
Quote
Also, I think it's not possible to get a list of supported refresh rates at given resolution or to set a video mode with a desired refresh rate, right?

It could be possible, but It's so rarely used that I don't want to complicate the API with this kind of detail.

Quote
My final goal is to make an online racing game and I think it would be useful to shave off these extra 16 ms of lag that the display generates.

Instead of measuring response time, why don't you simulate what you need (inputs for a racing game) and compare with/without the 16 ms lag to see if it actually makes a difference? I don't like to solve problems that don't exist ;)

Quote
If SFML could at least retrieve refresh rate of current video mode, I would know when to call window.display to cause the least delay

The simple solution is to use two threads. If your language doesn't allow this easily, it's not my fault :P
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 20, 2011, 07:46:33 pm
Sure thing, Laurent, I don't want to complicate SFML or convince you to do useless work. But would this addition be a big complication:

Code: [Select]
current_mode = sf::VideoMode::GetDesktopMode()
refresh_rate = current_mode.RefreshRate

or

RenderWindow::GetScreenRefreshRate()


 :?:
Title: Input feels delayed at 60FPS
Post by: Laurent on November 20, 2011, 08:32:38 pm
Quote
would this addition be a big complication

Yes :)
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 20, 2011, 09:10:39 pm
Quote from: "Laurent"
Quote
would this addition be a big complication

Yes :)


Really? If you say so...

I just found how to get it in python and on windows:

Code: [Select]
import win32api

device = win32api.EnumDisplayDevices()
settings = win32api.EnumDisplaySettings(device.DeviceName, 0)
print 'DeviceName:', device.DeviceName
print 'DeviceString:', device.DeviceString
print 'BitsPerPel:', settings.BitsPerPel
print 'DisplayFrequency:', settings.DisplayFrequency
print 'PelsWidth:', settings.PelsWidth
print 'PelsHeight:', settings.PelsHeight


Returns:
Code: [Select]
DeviceName: \\.\DISPLAY1
DeviceString: NVIDIA GeForce GTX 260
BitsPerPel: 32
DisplayFrequency: 60
PelsWidth: 640
PelsHeight: 480


It looks pretty simple to me, but it's only for windows...
Title: Input feels delayed at 60FPS
Post by: Laurent on November 20, 2011, 10:04:02 pm
The implementation is very easy on all systems. I just said that I didn't want to complicate the public API of SFML.

You're the first user to request it in 5 years, and only to implement a workaround for the lack of real threads in Python, so you can understand that I don't want to modify the API for that ;)
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 21, 2011, 10:51:09 pm
But my vSync is off. I still don't understand how to solve this :(
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 10:56:22 am
I tried checking for inputs in a separate thread, but the delay is still there with 60 max FPS (and disabled VSync). Can anyone explain how this can be fixed? I'm making a bullet hell game and precision is absolutely required. There are also a lot of entities on screen so FPS will drop below 100.
Title: Input feels delayed at 60FPS
Post by: Laurent on November 23, 2011, 11:07:25 am
Quote
Can anyone explain how this can be fixed?

It depends how you manage it. For example, if you get input and move your sprite at 150 Hz, but still refresh your screen at 60 Hz, the user won't notice the difference. It's completely useless in this case.

You should try to explain your problem better. Maybe provide a simplified code that shows the problem, if possible. 60 Hz is a lot, if things feel delayed at such a frequency there's probably something wrong in your game logic.
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 12:04:47 pm
Quote from: "Laurent"
Quote
Can anyone explain how this can be fixed?

It depends how you manage it. For example, if you get input and move your sprite at 150 Hz, but still refresh your screen at 60 Hz, the user won't notice the difference. It's completely useless in this case.

You should try to explain your problem better. Maybe provide a simplified code that shows the problem, if possible. 60 Hz is a lot, if things feel delayed at such a frequency there's probably something wrong in your game logic.


Code: [Select]
public void Run()
        {
            while (Running)
            {
                RenderWindow.Clear(Color.White);

                float frameTime = RenderWindow.GetFrameTime()/16f;
                if (SSSettings.FrametimeStatic) frameTime = SSSettings.FrametimeStaticValue;

                RunInputs();
                Game.Update(frameTime);
                Game.Draw();

                RenderWindow.Display();
            }
        }


This is my main loop. I clear the window, calculate the delta time, get inputs from Keyboard object and update the game logic.

If I set my FPS limit to 60, input is slightly delayed. If I set my FPS limit to 200-250 input feels perfect.
Title: Input feels delayed at 60FPS
Post by: Laurent on November 23, 2011, 12:11:13 pm
Where is the thread that manages input?

Quote
Code: [Select]
RenderWindow.GetFrameTime()/16f

Any reason for this "16"?
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 12:31:39 pm
Quote from: "Laurent"
Where is the thread that manages input?

Quote
Code: [Select]
RenderWindow.GetFrameTime()/16f

Any reason for this "16"?


This is the unthreaded version, as the threaded version had the same outcome. For the threaded version I just created a new thread that constantly called "RunInputs();" and sent recieved inputs to the Game.

The 16 is just for convenience, I use it for calculations in game logic. At 60 FPS, the framerate divided by 16 is 1. So if I'm running at 30 FPS, the framerate divided by 16 is 2. That means I have to move my objects twice as far.
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 23, 2011, 02:52:24 pm
Quote
Code: [Select]
if (SSSettings.FrametimeStatic) frameTime = SSSettings.FrametimeStaticValue;
Game.Update(frameTime);


What is SSSettings? What does Game.Update do with the frameTime?

Where exactly do you set the framerate limit for the window in case of static framerate?
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 04:28:14 pm
Quote from: "kolofsson"
Quote
Code: [Select]
if (SSSettings.FrametimeStatic) frameTime = SSSettings.FrametimeStaticValue;
Game.Update(frameTime);


What is SSSettings? What does Game.Update do with the frameTime?

Where exactly do you set the framerate limit for the window in case of static framerate?


SSSettings is a static class holding some, well, settings for my library.
FrametimeStatic equals false in the example.

Frametime is a float variable that equals:
1 when having 60 FPS
2 when having 30 FPS
0.5 when having 120 FPS
... and so on

When I move my entities, I move them like this:
entity.Position += new Vector2i(100 * frametime, 100 * frametime)

So I ensure that the result is the same with any framerate.
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 04:34:34 pm
Quote from: "kolofsson"
Where exactly do you set the framerate limit for the window in case of static framerate?


I'm just doing this currently:
Code: [Select]
RenderWindow.EnableVerticalSync(false);
RenderWindow.SetFramerateLimit((uint) SSSettings.FramerateLimit);


with SSSettings.FramerateLimit being 60.
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 23, 2011, 06:07:18 pm
Quote from: "SuperV1234"
Quote from: "kolofsson"
Where exactly do you set the framerate limit for the window in case of static framerate?


I'm just doing this currently:
Code: [Select]
RenderWindow.EnableVerticalSync(false);
RenderWindow.SetFramerateLimit((uint) SSSettings.FramerateLimit);


with SSSettings.FramerateLimit being 60.


Somebody prove me wrong, but I think you should use either EnableVerticalSync or SetFramerateLimit. If you enable Vsync, there is no need to limit the framerate as it is limited.
Title: Input feels delayed at 60FPS
Post by: SuperV1234 on November 23, 2011, 06:51:18 pm
Quote from: "kolofsson"
Quote from: "SuperV1234"
Quote from: "kolofsson"
Where exactly do you set the framerate limit for the window in case of static framerate?


I'm just doing this currently:
Code: [Select]
RenderWindow.EnableVerticalSync(false);
RenderWindow.SetFramerateLimit((uint) SSSettings.FramerateLimit);


with SSSettings.FramerateLimit being 60.


Somebody prove me wrong, but I think you should use either EnableVerticalSync or SetFramerateLimit. If you enable Vsync, there is no need to limit the framerate as it is limited.


Input delay occurs in both the cases.

But I've played games (like Touhou) that are limited at 60FPS with VSync forced off, and they don't have any input delay.
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 25, 2011, 11:30:01 pm
Quote from: "Laurent"
You're the first user to request it in 5 years, and only to implement a workaround for the lack of real threads in Python...


Just to make it clear, I managed to create a thread in Python, but I was having trouble to understand how to use sf::Window::SetActive (bool). I read the docs which state:

Quote
A window is active only on the current thread, if you want to make it active on another thread you have to deactivate it on the previous thread first if it was active. Only one window can be active on a thread at a time, thus the window previously active (if any) automatically gets deactivated.


Could you explain how to use the SetActive method? Is there a sample code somewhere that I could refer to (even in C++)? If I check the window input in the main loop and display the window in a thread, when should I call the setactive(false) and when the setactive(true). I mean, since the thread and the main loop run alternately, how to tell which thread should be the active one?

Also, I had to set the Window as global to be able to use it in the thread. Can the window object be passed somehow to the thread so that it's shared between the main loop and the thread? Again, can I find a code snippet in C++ somewhere that would demonstrate how sf:window and sf:thread can work together?

Thanks in advance for your help!
Title: Input feels delayed at 60FPS
Post by: Laurent on November 26, 2011, 10:01:25 am
Quote
Just to make it clear, I managed to create a thread in Python

That will probably be worse, because there's no true threading in Python. But anyway, you'll see the result by yourself, and it will be an excellent use case for Bastien, if I remember correctly he was waiting for feedback before possibly improving multithreaded performances of the Python binding :)
But keep this in mind, the result might be worse.

Quote
Could you explain how to use the SetActive method?

SetActive is only about drawing. A window needs to be active when you want to draw stuff. So:
- you must call SetActive(false) before launching the rendering thread
- that's all, SetActive(true) is called automatically by Clear/Draw/Display
Title: Input feels delayed at 60FPS
Post by: kolofsson on November 26, 2011, 12:33:06 pm
Quote from: "Laurent"
Quote
Just to make it clear, I managed to create a thread in Python

That will probably be worse, because there's no true threading in Python. But anyway, you'll see the result by yourself, and it will be an excellent use case for Bastien, if I remember correctly he was waiting for feedback before possibly improving multithreaded performances of the Python binding :)
But keep this in mind, the result might be worse.


Well, before I set the setactive to false, the other thread would never get executed. As a result I had my display window white and frozen. Then I set the setactive to false, it draws the first frame and then stops drawing.

In C++, how can you make a thread which uses RenderWindow that is not declared as a global?
Title: Input feels delayed at 60FPS
Post by: Laurent on November 26, 2011, 12:54:06 pm
Sorry, I don't understand the meaning of your last message. Do you mean that using SetActive correctly still doesn't make things work? If so, you should rather show your code.
Title: Input feels delayed at 60FPS
Post by: Razzeeyy on January 05, 2012, 08:29:33 am
Sadly, I have the same problem.
It's noticeable when I'm trying to make 'game' simulate the shots.
And if I make a shot delay 0, at 1000+ fps I see the natural solid 'line' instead of single shots.
But when I limit my fps to 75 or enable VSync then I get the unnatural half-sized 'bullet image' line.
(i can send sources and binaries to you if you want :P)

That means the input is pausing while waiting for vsync =( sadly...
And, yes it is not noticeable when you doing a simple quest or something like that, but it becomes noticeable when you trying to make a FPS or simulate things that moving fast and controlled by input.

P.S. I'm using SFML 1.6
Title: Input feels delayed at 60FPS
Post by: Laurent on January 05, 2012, 08:34:21 am
Things have changed in SFML 2, inputs are directly queried at the OS level rather than being a layer on top of events.
Title: Input feels delayed at 60FPS
Post by: Razzeeyy on January 05, 2012, 12:15:15 pm
Quote from: "Laurent"
Things have changed in SFML 2, inputs are directly queried at the OS level rather than being a layer on top of events.


so we will never have that delay again? :)

little offtop:
also why (as I see)  sfml 2 switched from "float second = 1" definition of time, to "int second = 1000". That was made for any performance needs?
Title: Input feels delayed at 60FPS
Post by: Laurent on January 05, 2012, 12:33:00 pm
Quote
so we will never have that delay again?

I'd say it differently: if you have a delay with SFML 2, it won't be SFML's fault.

Quote
also why (as I see) sfml 2 switched from "float second = 1" definition of time, to "int second = 1000". That was made for any performance needs?

http://www.sfml-dev.org/forum/viewtopic.php?t=4864

But it will change again soon.