Search code examples
javamultithreadingopenglkeyboardlwjgl

Multithreaded LWJGL Keyboard Delay


In a LWJGL game I'm making I have 3 threads - one for graphics, one for processing/physics and one to provide world access and deal with multiplayer connections. The issue I'm having is that when I call Keyboard.isKeyDown() in the physics thread I have to hold it down for sometimes half a second or so before anything happens. This isn't because the thread is running slowly - it's the only thing in the loop at the moment, and a println call shows that it's updating. I'm wondering if this has something to do with the fact that the OpenGL context exists in the graphics thread and I'm calling keyboard calls from the physics thread? If I do the check in the graphics thread it works fine, but taking inputs there and sending them to the other thread would somewhat defy the point of having separate threads.

My keyboard check currently looks like this:

boolean escPressed = false;
private void process(){
    if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
        if(!escPressed){
            escPressed = true;
            GameStateManager.pauseUnpause();
        }
    }
    else{
        escPressed = false;
    }
}

My thread setup is simply this

public class Client {

    public static GraphicsThread graphics;
    public static PhysicsThread physics;
    public static ConnectionThread server;

    public static void main(String[] args) {
        GameStateManager.setState(GameStateManager.EnumState.MENU);
        graphics = new GraphicsThread();
        physics = new PhysicsThread();
        server = new ConnectionThread();


        physics.start();
        graphics.start();
        server.start();
    }

}

So can anyone tell me why there is a delay when calling the method from a different thread?

Update I did a quick test, and it any calls to Keyboard just seem to take a very long time to complete.

while(true){
    start = System.currentTimeMillis();
    Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
    end = System.currentTimeMillis();
    System.out.println(end-start);
}

Running that test showed results as high as 1100ms, which is ridiculously high. When running in the graphics thread it completes in less than a millisecond and prints 0. Not sure what's happening here.


Solution

  • LWJGL 2 or 3? Shouldnt really matter..

    though, as far as I know there shouldnt be a problem with calling this method on other Threads, although Calling it on the Thread where the OpenGL context is bound to is a good idea anyways.

    For my setup I have one Thread dedicated to all OpenGL context related stuff. (E.g. openGL calls only). So in your case, Il would check for the keyPressed state in the graphics Thread, which passes a hint to the Physics Thread which does all the heavylifting (if there is any). Though details are up to you of course.

    I hope this helps you

    Edit:
    I came across this post when dealing with this problem as well, basically its not possible because of choice of design by LWJGL. You can manually separate it by hinting (as described above), or keep track of the state of every input device (updated in the graphics thread) which you check on from other Threads instead of using the Keyboards class.