jmonkeyengine
jmonkeyengine copied to clipboard
GLFW Main Thread Issues
So, we have a few issues open around that but they mostly address symptoms of lwjgl3's problems, where they are at it's core design decisions of GLFW that we have to address hereby.
So, the problems are: https://github.com/LWJGL/lwjgl3/issues/311 and "the OS only delivers key input events to the Main Thread anyway".
This concept is orthogonal to lwjgl2s/Applications start() method, which is expected to return either directly or after the context is created, but certainly it should NOT "join" the Render Thread.
This can all be worked around by making GLFW init on the main thread and then spawn a render thread, which can use glfwMakeCurrent (or comparable) to bind the openGL Context to the Render Thread and not the GLFW Main Thread.
That approach has two possible problems:
- When we return from start(), the Main Thread will end at some point. Would Key Events still arrive? Would the window close?
- Is there GLFW API (Resize Window, Recreate Window) which is then impossible to do?
If we can't fix these problems, the only thing we can do is annotate start() with the information, that this will never return until the application has been terminated.
Note that the following files use the glfw api and thus potentially require the MainThread. This can be seen in the docs, see https://www.glfw.org/docs/latest/group__input.html#ga1caf18159767e761185e49a3be019f8d
./src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java
./src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
./src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
./src/main/java/com/jme3/input/lwjgl/GlfwKeyMap.java
./src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
./src/main/java/com/jme3/system/lwjgl/LwjglContext.java
It has to be checked whether all of this code can be run before kicking off rendering, then we'd cover 90% already. Then we can only fall to the above two problems.
As far as I know LWJGL3s approach was to decouple GL from Window Management, though, so in case we cannot fix this, we will have to use another window manager, which should be doable as well.
Is someone curious enough to look into these files?
Edit: How about splitting LwjglWindow's run() method so that we do "initInThread" really in thread and only the runLoop in the Thread then? I am not sure if that is sufficient, but it looks like all init is properly done in initInThread.
I have looked into this: While it would be theoretically possible to run the render loop in a different thread, there would be a few drawbacks:
- Context Recreation doesn't work. Currently, we just have a flag on the context, which would re-create the context during looping. That's not the Main Thread
- Context Destruction doesn't work.
After the call to start(), we cannot regain control of the Main Thread anymore, so we are kind of at loss here.
Furthermore, I tried to add context moving, that is: creating everything on the Main Thread and then pass the openGL context to the Render Thread, but I get:
FATAL ERROR in native method: Thread[jME3 Main,5,main]: No context is current or a function that is not available in the current context was called. The JVM will abort execution.
even though glfwGetCurrentContext certainly is != 0.
What doesn't solve the issue, but could be done to help embedding lwjgl3 applications is seperating context creation from the main loop and allow the main loop to be throttled from the outside. That way say someone could embed the application in whatever canvas they imagine and use that refresh rate.
So just some things to consider here. I think it is fine if the start() is blocking until the application exits, that can be worked around easily if other tasks are required outside of JME.
I think the issue starts where some applications need the main thread for other things. One example is where an application is only using JME for a short time, perhaps to view 3d models, and would like the ability to open multiple windows independent of one another. But does not want the main thread to terminate when the window is closed. Although this can be worked around, it is not as simple as start() releasing the main thread back. My currently solution for this is to have my main thread just run other programs in their own main thread and create communication sockets between them.
Also, I have not seen any issues with glfw not being on the main thread in Windows 10 (see comment in #1048). I have not tested other platforms though, and from what it sounds like we can confirm that OS X has this issue.
Note, this has been fixed for a while now. Only on Linux and Windows. https://github.com/jMonkeyEngine/jmonkeyengine/pull/1690/files