glfwPollEvents and multithreading

Started by zzuegg, June 15, 2015, 22:11:11

Previous topic - Next topic

zzuegg

Hi, i am currently trying to move to lwjgl and i have some issues with glfw.
Basically i have to call glfwPollEvents in the thread that created the window, and not the thread that holds the GLContext. Also, i have not found a way to rebind the window to a new thread.
Did i miss some nice function to do that?


spasi

Please read the relevant info on thread safety in the GLFW documentation. The javadoc provided by LWJGL also explains from which thread(s) each function may be called.

These limits exist because a) on Mac OS X you may only handle events from the main thread and b) on Windows, you may only handle events from the thread that created the window. It's not a problem on Linux, but GLFW must expose a safe cross-platform API. The design is similar to the EDT in AWT/Swing or the Application thread in JavaFX.

The best practice would be to do (almost) everything GLFW-related on the main thread, and communicate with other threads via one or more message queues.

zzuegg

Thank you, i already read the doc and have seen the "Main Thread" hint. However, it is a bit strange regarding to what the main thread is.
I setup looks like:

Thread A: spawns primary Context A
Thread B: binds Context A and spawns Secondary Context B
Thread C: binds Context B

Comunication between those threads is stricktly done trough Message queues.
However, to poll events, i have to call glfwPollEvents on Thread A to poll events for Context B and Thread B to poll events for Context C.

Probably it is only  strange because i am comming from Jogl and the setup worked flawless there.

And it seems i cannot create the Context B on Thread C
As long i want to share Context B, i have to call glfwCreateWindow on Thread B.. Synch nightmare..

spasi

The main thread is the thread that runs your application's main method. On Mac OS X in particular, you also need to run the JVM with -XstartOnFirstThread, because the main thread also has to be the first thread in the process (thread 0).

Quote from: zzuegg on June 16, 2015, 06:48:13
Thread A: spawns primary Context A
Thread B: binds Context A and spawns Secondary Context B
Thread C: binds Context B

This looks unnecessarily complicated. You can create all windows on the main thread, then use glfwMakeContextCurrent on other threads to make the window contexts current in those threads. You do all event polling on the main thread. See this sample for an example.

Quote from: zzuegg on June 16, 2015, 06:48:13Probably it is only  strange because i am comming from Jogl and the setup worked flawless there.

I don't know what JOGL does exactly, but I'm sure it cannot do what it does without sacrificing performance or features.

Kai


zzuegg

Thank you. Going to test a bit around and hopefully get access to some mac for testing too.

At least on Windows it i can use any thread for creating contexts, with the limitation that it has to be the same thread that calls glfwInit(). No issue here.

If it turns out that it is really required to the the "Main Thread" on OSX/Linux i would have to "refactor" quite a bit  :(

spasi

Quote from: zzuegg on June 17, 2015, 10:42:52At least on Windows it i can use any thread for creating contexts, with the limitation that it has to be the same thread that calls glfwInit(). No issue here.

If it turns out that it is really required to the the "Main Thread" on OSX/Linux i would have to "refactor" quite a bit  :(

Actually, there's no dependency to glfwInit(). You only need to call glfwInit() once, regardless of how many contexts you create.

There are 3 concepts you need to be aware of: (A) window/context creation (B) running the event loop that dispatches events for the window and (C) making the context current in a thread.

- On Windows, (A) and (B) must happen on the same thread. It doesn't have to be the main thread. (C) can happen on any thread.
- On Linux, you can have (A), (B) and (C) on any thread.
- On Mac OS X, (A) and (B) must happen on the same thread, that must also be the main thread (thread 0). Again, (C) can happen on any thread.

A cross-platform application must be written such that it respects the strictest of the above scenarios (which is Mac OS X). Anything else means your application will break when it runs on different OSes.

zzuegg

Thank you for clarification. Probably saved me quite a big trouble.

I had to create an additional primary context always bound to the main thread and not dooing anything else then sitting there and waiting to be shared.
As an extension to your list from the previous post:
-On Windows, if (C) is done on a different thread, you can't share the context anymore on the main thread.