Multithreaded resource loading

Started by
2 comments, last by Tocs1001 12 years, 10 months ago
Hi,

I am writing an OpenGL game engine running on multiple platforms. Now I want to implement a nice real-time rendered loading screen but don't really know how to do this in a good way. I did two attempts though.

In my first attempt I did like this:

1. Begin rendering of loading screen.
2. Create a new thread.
3. Begin loading and generate textures in the newly created thread.
(The loading screen is being rendered parallel)
4. But, crash.

Of course this crashed since I made OpenGL function calls like glTexImage2D in the new thread. Not in the main OpenGL thread - not OK.

In my second attempt I made some kind of resource loading queue in my resource manager. Each time the resource manager got an update it loaded one resource, and then the loading screen was rendered. Next update (frame) it loaded another resource, until the queue was empty and all resources loaded. This was pretty ugly and didn't work that well. Also, the loading screen didn't get that smooth using this approach since it only got redrawn after a new resource had been loaded.

So, how do you guys do?
http://epiccode.org/
Advertisement
Both approaches can be used, although I prefer the second.
In order to update textures and buffers through another thread, you have to make another rendering context (in the same share-group with the main RC) and make current for the updating thread. Also, you should use GL synchronization objects to prevent simultaneous access. If you can afford that, using double buffering (at least two copies of objects) nice suits this approach.

Since GL drivers serialize access to a GPU, I prefer second method - updating in the rendering thread. In order to make this solution efficient you should:

1. Offload as much as possible rendering thread (calculations/tessellation/loading/building should be done in other threads)

2. Send updates via messages or similar mechanism and place them into a queue (or multiple queues). I'm using multiple queues.

3. Make updates as small as possible and during rendering a single frame pass just one or few of them (you can use "quota" to define how much of them should be process in a single frame; it depends on their type, size, etc.)

It suits my needs. I hope it will serve your purposes also. :)
Thanks for your input! :)
http://epiccode.org/
If I recall correctly... You can create a second context on your loading thread, using wglShareList () to make both context's share resources, and wglMakeCurrent () to select the appropriate context. Your original thread failed because it didn't have a current context. Having 2 contexts with shared lists will prevent your loading thread from conflicting with your rendering thread. (Given you don't try to use a resource that isn't loaded and the like)

I haven't actually done this myself, but its the way I heard you can do it.

This topic is closed to new replies.

Advertisement