Can I create a separate thread for initializations?

Started by manji, September 29, 2009, 11:47:45

Previous topic - Next topic

manji

I am a complete noob when it comes to multithreading, but after struggling with it for a bit, I came upon this problem. In my game, I need to load some images, sounds and models, and then render the game. I would like to be able to show a loading screen while these initializations take place. As I found out, in LWJGL(and openGL), the various GL commands must occur always in the same thread, the same thread you created the display.
So my question is: How can I create a separate thread for the initialization part, considering that this part uses GL commands? I tried to put almost my whole program in a thread(except from the display stuff), but I had a NullPointerException exception at the first OpenGL command.
toyWars game blog: http://toywars.wordpress.com/

Kai

QuoteSo my question is: How can I create a separate thread for the initialization part, considering that this part uses GL commands? I tried to put almost my whole program in a thread(except from the display stuff), but I had a NullPointerException exception at the first OpenGL command.

Hi,

the NPE is due to the fact that the calling thread did not own the GL context (the context was not 'current' for that thread).
Initially, the context is made current by Display.create() for the calling thread.

If you want to do some resource loading which involves GL commands and simultaneously display a progress bar, you would have to split up the whole resource loading work into separate "tasks". Otherwise you wouldn't be able to tell the progress anyways.
Then, whenever one tasks ended, you would update the progress (as a "float" or something like that) and trigger a refresh of the rendered status bar.

A technique that is famous when having multiple threads all doing GL stuff, is to have a Queue that takes instances of "Tasks" (java "Runnables" for instance) that invoke the GL commands. You would then have the one-and-only "GL-Thread" that processes the tasks in that Queue. This way, it is assured that every GL method is invoked from the same thread.
This is kinda identical to the way, Swing's SwingUtilities "invokeLater" and "invokeAndWait" works.

I hope that will get things going for you.

manji

Thank you for your response elaborative Kai.

QuoteIf you want to do some resource loading which involves GL commands and simultaneously display a progress bar, you would have to split up the whole resource loading work into separate "tasks". Otherwise you wouldn't be able to tell the progress anyways.
Then, whenever one tasks ended, you would update the progress (as a "float" or something like that) and trigger a refresh of the rendered status bar.
Well, I guess I could do that, but it's a little complicated and I'd rather not tamper with the way the loading part works now. Of course it is a possible workaround. One notice here, I do not plan to use a progress bar, just a simple loading screen with some dots going left and right. So I was hoping for two tasks taking place in parallel, one for loading, and one for just showing the loading screen.

QuoteA technique that is famous when having multiple threads all doing GL stuff, is to have a Queue that takes instances of "Tasks" (java "Runnables" for instance) that invoke the GL commands. You would then have the one-and-only "GL-Thread" that processes the tasks in that Queue. This way, it is assured that every GL method is invoked from the same thread.
I will try to implement something like this, although I did not get it completely. When you say "...one-and-only "GL-Thread" that processes the tasks in that Queue", what exactly do you mean by "procecces". I guess that trying to call start() to a reference to any element of the queue, won't work. Or do you mean that I still need to handle the loading part in a way that it pauses once in a while and then resumes?

Again, thank you.
toyWars game blog: http://toywars.wordpress.com/

Kai

QuoteSo I was hoping for two tasks taking place in parallel, one for loading, and one for just showing the loading screen.
Well, since you only have *one* GL-thread you would have to switch between rendering your progress bar and loading the resources, since both requires you to do GL calls.

QuoteWhen you say "...one-and-only "GL-Thread" that processes the tasks in that Queue", what exactly do you mean by "procecces". I guess that trying to call start() to a reference to any element of the queue, won't work. Or do you mean that I still need to handle the loading part in a way that it pauses once in a while and then resumes?
In the Queue you would have instances of the java "Runnable" interface, which would probably be just some small anonymous classes that implement small tasks in the "run()" method of the Runnable.
If you put that Runnable then into the Queue it will eventually be taken out of the Queue by the GL-thread and that GL-thread would then call "run()" on that task. After the task is finished, the GL-thread would take the next Runnable, and so forth.

It is some kind of the consumer/producer pattern. The GL-thread is the consumer that takes all actions to be performed as Runnable instances, and the producer being the one that initiates the tasks.

If you let the "GL-thread" only work on that Queue and you use nowhere else GL-commands than in instances of Runnable filled into that Queue, you are totally safe with having multiple threads "producing" the tasks, as long as there are no side-effects between the tasks (the effect of one tasks depends on another task).

ndhb

Can you tell us what it is you hope to achieve by spawning multiple threads? Performance will likely decrease because of the context switch and if you wish to show a progress bar, you can just as well interleave the rendering of this widget with the resource loading. Maybe your time is better used elsewhere, unless you only do it to learn something new.


Evil-Devil

Don't know if it works and haven't tried myself yet, but wouldn't it be possible to use a volative directbuffer with two threads? one that writes and the other ask for the actual position/size to determine the estimated lasting time.

Just an idea.

manji

@Kai: I can see what you suggest now, but I don't understand what is the gain in this. These "tasks" still will not be run simultaneously, but sequentially. I can't see the need of threads here, other than making the code cleaner.

@ndhb: I thought that it could be much easier, I didn't know that OpenGL was not thread-safe. Moreover, I was hoping that this could be a good opportunity to introduce myself to multithreading.

@Evil-Devil: I don't know  ;)

I'll try to demonstrate my problem in greater detail, if I haven't make it clear yet. Let's say I have some functions that load all my models, textures, sounds etc of my game. For instance, in the loadModels() there could be a list of models, and a loop though this list would load them one by one. As my game works now, when it reaches the loadModels(), the whole program waits for it to finish. I would like to be able to show a (dynamic)loading screen, while this happens. I initially thought there could be two ways for this to be implemented:

1) Just run the loadModels() in a new thread, in parallel with the main thread, and check every now and then if it has finished. If yes, stop the thread and continue to the rest of the program. In this way, the thread that has the loadModels(), and the rendering thread are independent. I don't need to know the progress of the loading anyway, just show a screen. But unfortunately, the loadModels() happens to use GL commands so this solution is not possible.

2) Handle the loadModels(), so as to pause once in a while(after a model has been loaded), return to the rendering part(maybe update the loading screen), and then return to the loadModels() and resume from where you were left.

The 1st seemed easy, it makes sense, but it is not possible (as it turns out).
The 2nd is not so easy, I do not like it(the loading of a single model could take let's say 5 secs, there is still an idle rendering time), but it is possible.
toyWars game blog: http://toywars.wordpress.com/

broumbroum

as of what Kai said :
Quote from: KaiIt is some kind of the consumer/producer pattern. The GL-thread is the consumer that takes all actions to be performed as Runnable instances, and the producer being the one that initiates the tasks.
this thread might help you : http://lwjgl.org/forum/index.php/topic,3064.msg16922.html#msg16922

Rene

I don't have a lot of experience with this yet, but maybe this will work:

If I'm correct the HDD is the limiting factor in this case so multiple loading threads wouldn't speed up the loading process that much. But if you want to show a loading screen while loading your resources you might want to consider separating the reading from hard disk, and your GL calls (These calls are to send the data to the VRAM I guess?).

In that case, the resource loading thread loads your models from disk to system ram, and the 'load screen thread' (the GL thread) should send the data from system ram to VRAM as soon as all data is available.
When I am king, they shall not have bread and shelter only, but also teachings out of books, for a full belly is little worth where the mind is starved - Mark Twain

broumbroum