godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.08k stars 69 forks source link

Separate input polling from render thread #1288

Open iBoonie opened 3 years ago

iBoonie commented 3 years ago

I thought this deserved a mention https://github.com/godotengine/godot/issues/26828 coming from a FPS background, it drives me insane when there is any input delay.

Describe the project you are working on: FPS project.

Describe the problem or limitation you are having in your project: No problem, but having fluid input 100% of the time would be very nice.

Describe the feature / enhancement and how it helps to overcome the problem or limitation: If input is polled in the render thread and the game lags at all, it introduces input lag. Unity, Unreal, Source and all major engines have this problem (although it's being fixed in Unity https://github.com/Unity-Technologies/InputSystem).

If a user can't reach high enough frame-rates, they will have input lag. Polling in a separate thread would eliminate this problem. Instead of getting input lag, you would just get visual frame skip when moving your mouse (which is still present when you poll at lower rates anyway). The advantage of this is it will make input feel snappy all the time (for both mouse and keyboard input).

Example: If the input was polled in a separate thread and a person flicked their mouse the same distance at 15fps and 300 fps, it would land in the same spot at the exact same time (although the 15 fps player would skip/chunk a lot of frames).

More info: https://www.epicgames.com/unrealtournament/forums/unreal-tournament-discussion/ut-development-bug-reports-qa/3209-mouse-input-issues-concerns-and-what-will-be-done-about-it https://www.epicgames.com/unrealtournament/forums/unreal-tournament-discussion/ut-development-bug-reports-qa/16532-mouse-input-investigation https://www.reddit.com/r/GlobalOffensive/comments/6y47m8/ https://www.reddit.com/r/reflex/comments/499s68/ https://www.reddit.com/r/Competitiveoverwatch/comments/6xet7k/

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: It's possible to implement this using GDNative or using a Module, but having it directly in the engine would be best.

If this enhancement will not be used often, can it be worked around with a few lines of script?: If implemented, everyone would be using it.

Is there a reason why this should be core and not an add-on in the asset library?: Everyone deserves fluid input, it would make the user experience better for everyone (especially people on lower spec machines). Having it in engine while most others don't would be a nice step above.

Xrayez commented 3 years ago

It's possible to implement this using GDNative or using a Module, but having it directly in the engine would be best.

Can you give some ideas? I'm not sure whether it's possible currently. It's not even possible to override stuff like the Input implementation (InputDefault is removed in 4.0 as well, see related discussion at #104).

iBoonie commented 3 years ago

I should have said that it might be possible rather than it is. I haven't looking too deep into it yet, but a super hacky way might be to just toss aside the entire Godot input system and poll everything manually, but that would be last case scenario (and even then, it's probably not worth it). I would really hate to do that, but not being able to override is kind of a big thing.

RandomShaper commented 3 years ago

As @Calinou has pointed out, my PR #42220 may be what this proposal is about, only that it's still limited to Android.

But if it's approved, I'll do it for all the other platforms and 4.0.

MagnesiaReal commented 3 years ago

this would work for future rhythm games that need precision on input

Calinou commented 3 years ago

@MagnesiaReal Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

guilhermefelipecgs commented 1 year ago

I saw this post below from overwatch that explains this scenario very well and I came to share it here. https://us.forums.blizzard.com/en/overwatch/t/new-feature-high-precision-mouse-input-gameplay-option/422094

guilhermefelipecgs commented 1 year ago

I decided to do a test here and it seems that godot already supports this feature. I just had to put this in the code Input.use_accumulated_input = false

In the video below, I tested it first with my mx ergo mouse that reaches 125hz and then I switched to the g pro x superlight that reaches 1000hz. So technically I believe it is already possible for an fps game to implement a hitscan on a subframe for example.

https://user-images.githubusercontent.com/1387165/197031243-fb29831b-406f-4313-abe9-3e3abaa8dd8f.mp4

RandomShaper commented 1 year ago

The missing piece would be to implement agile input flushing on every platform. It's still only supported on Android, if I haven't missed anything.

WantToSignUp commented 1 year ago

@guilhermefelipecgs I tried the same thing but its not right behavior, dosent exactly works as you would expect. Log the input events with timing, you will find out that it will give you batch of 100 events with a 1000Hz mouse at 10 fps, but it will always have 100 ms delays after each batch of events processed.

@RandomShaper With agile input flushing, is it possible to flush it at a higher rate than the main/physics thread? Main and physics thread still tied to the rendering overall, the only difference is that it can run more time per rendered frame, but thats not guarantee that those more frames will be evenly spaced out. For example, graphically intensive, but CPU lightweight FPS game, 30 fps rendering, physics calculation time only takes 1 ms, running at fix 90 physics fps: Rendering thread --------------------------------------------------------------33 ms Gameloop thread - 1 ms - 1 ms - 1 ms ---------------------------------------30 ms wait for renderer to catch up

Inputs made in that 3 ms time period would be processed within 1 ms, but after that every input would be just grouped into the next sim which happens 30 ms later. It would be nice if the func _input(event) function could happen in that different thread altogether at high rates or if we could add triggers, like mouse button event that will flush the inputs, and force the main thread to do a full simulation. I might misunderstood how agile input works, but to me it seems like that solution is not enough, unless the way the engine deals with fixed simulation steps changed to different behavior like for example the way unity does it, which spaces them out evenly instead of doing it as fast as possible then wait for render thread to catch up.

RandomShaper commented 1 year ago

You're right, Agile flushing improves things in the sense that you can receive and process input multiple times per rendered frame, but it doesn't go as far as spacing game logic evenly thanks to it being timed independently from rendering.

Lielay9 commented 10 months ago

The agile-input-flushing has served our projects well on Android and due to the nature of PC generally being more performant, delayed input hasn't been great source of problems. However, the recent popularity of handheld PC:s/Consoles (Steam Deck, Switch and the like) has again surfaced some of the problems that we've swept under the rug before. In our initial tests, the input lag on those devices is rather noticeable. The issue isn't a show-stopper, but there is a renewed interest in tackling input lag in some form to better accommodate the new platforms.

Amealky commented 2 months ago

Hello is there any news on this ? I intend to make a game with fight mechanics ( so with input buffer ) and I think it will be nice to separate the input polling from the render loop but dunno how to do

Maybe a solution could be to write my own c++ polling event script in a thread and start it at the beginning then make an access to it directly in gdscript ? what did you think of the easy feasability of this ( I now that will require some c++ code but I don't think writing a simple polling event script will be that hard )