Skip to main content
GameDev.net gamedev.net
🔒 Locked

How to render while data loads...??

Started by OpenGL_Guru May 24, 2006 at 9:32 AM 21 replies 9.1k views
Original Post
OpenGL_Guru
OpenGL_Guru
i am having trouble being able to execute any openGL code while i load data through a GUI. i have a menu that i can sort through that i wrote and the final option will load the data accordingly. i would like to render a rotating logo of some sort to indicate that the data is loading but it seems that i can do nothing until the data is loaded. i have even tried to render before the function to load the data is called but no such luck. i hope that everyone understands my problem.. thanks for your help!
heh
taby
taby
If you break up the loading process into steps, you can render in-between.
DrEvil
DrEvil
You either break up the load process as mentioned or implment asynchronous loading in a seperate thread, and your main thread can spin in a render loop while the loading thread does it's thing.
OpenGL_Guru
OpenGL_Guru
Quote:
Original post by DrEvil
You either break up the load process as mentioned or implment asynchronous loading in a seperate thread, and your main thread can spin in a render loop while the loading thread does it's thing.


how would you go about breaking up the load process? i figured i would need something of the sort, just have never needed to do it before..thanks!

oh yeah i could use pthread in linux after researching but as a fly in the ointment i need something cross platform that would work in windows and linux.
heh
DrEvil
DrEvil
Well, a simple method may be to update your load screen in between loading each asset. It won't be perfectly smooth but it would be better than freezing for the whole time. Assuming you have a collection of meshes, textures, etc, add the capability to poll your load screen in between the loading of each individual asset.

Maybe a generic callback could be invoked
LoadState::OnResourceStartLoading(const std::string &_resourcename);
LoadState::OnResourceDoneLoading(const std::string &_resourcename);

Within these callbacks you can simply animate a load graphic, or optionally display text for each asset that is loading. This is useful for debugging or visualizing what assets are taking the most time.

This won't give you a silky smooth load process, only threading can do that well, unless you go down to a very low level into your loading code, and for example your file IO class reads files in blocks and has the capability to poll a callback as well between each block read.

Threading it is less intrusive and easier in many ways, but be careful, because often there are issues with creating graphics objects from a seperate thread(at least with d3d there was, never tried with opengl).
OpenGL_Guru
OpenGL_Guru
Quote:
Original post by DrEvil
Well, a simple method may be to update your load screen in between loading each asset. It won't be perfectly smooth but it would be better than freezing for the whole time. Assuming you have a collection of meshes, textures, etc, add the capability to poll your load screen in between the loading of each individual asset.

Maybe a generic callback could be invoked
LoadState::OnResourceStartLoading(const std::string &_resourcename);
LoadState::OnResourceDoneLoading(const std::string &_resourcename);

Within these callbacks you can simply animate a load graphic, or optionally display text for each asset that is loading. This is useful for debugging or visualizing what assets are taking the most time.

This won't give you a silky smooth load process, only threading can do that well, unless you go down to a very low level into your loading code, and for example your file IO class reads files in blocks and has the capability to poll a callback as well between each block read.

Threading it is less intrusive and easier in many ways, but be careful, because often there are issues with creating graphics objects from a seperate thread(at least with d3d there was, never tried with opengl).


well right now i am not able to do ANYTHING while the data loads. i have even tried to disable the GUI(in ortho mode) by a key press while loading and nothing happens until after the data is finished loading.

MSDN doesnt seem to be much help either on creating and deleting threads in windows. it wants you to use namespace System which when i compile says that this namespace doesnt exist.

heh
gumpy
gumpy
Quote:
Original post by OpenGL_Guru
MSDN doesnt seem to be much help either on creating and deleting threads in windows. it wants you to use namespace System which when i compile says that this namespace doesnt exist.

you're looking at the threading api for .net. what language(s) and api(s) are you using besides opengl?
This space for rent.
OpenGL_Guru
OpenGL_Guru
Quote:
Original post by gumpy macdrunken
Quote:
Original post by OpenGL_Guru
MSDN doesnt seem to be much help either on creating and deleting threads in windows. it wants you to use namespace System which when i compile says that this namespace doesnt exist.

you're looking at the threading api for .net. what language(s) and api(s) are you using besides opengl?


C++ using .NET 2003 Standard & of course openGL (and glut)
heh
CrazyCdn
CrazyCdn
I haven't read this MSJ article in a few years so I forget how good it is, but may be a start for you.
"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin
Falken42
Falken42
If you don't want to work with threads, you can always try Overlapped I/O. For example, ReadFileEx calls a callback function when the transfer has completed.
zppz
zppz
Quote:
Original post by DrEvilThreading it is less intrusive and easier in many ways, but be careful, because often there are issues with creating graphics objects from a seperate thread(at least with d3d there was, never tried with opengl).


Yes, there are issues with opengl too. Although it can be tricky getting two rendering contexts to work together, once you get it working it's a much more professional way of doing loading.

Presuming you are working on windows, look up on msdn:
wglMakeCurrent
wglShareLists

The first of these will set the current thread as the one which will control rendering. Once you call this, all opengl calls by other threads will be ignored, unless the other thread calls makeCurrent itself first. This is sufficient if you just want to draw primitives, but maybe you can see that it will already require critical sections or something to make sure a thread doesnt get interrupted.
But since you want to do more than just draw primitives, you need wglShareLists as well. The name is a little confusing since it will share pretty much all opengl data across contexts - display lists, textures etc. Looking at the MSDN docs now, it doesnt mention that you also need to call this sharing function before you load any data into either context - so do it right after you create each context.
This still deserves more explanation but I am at work now...
rick_appleton
rick_appleton
Quote:
Original post by zppz
Quote:
Original post by DrEvilThreading it is less intrusive and easier in many ways, but be careful, because often there are issues with creating graphics objects from a seperate thread(at least with d3d there was, never tried with opengl).


Yes, there are issues with opengl too. Although it can be tricky getting two rendering contexts to work together, once you get it working it's a much more professional way of doing loading.

Presuming you are working on windows, look up on msdn:
wglMakeCurrent
wglShareLists

The first of these will set the current thread as the one which will control rendering. Once you call this, all opengl calls by other threads will be ignored, unless the other thread calls makeCurrent itself first. This is sufficient if you just want to draw primitives, but maybe you can see that it will already require critical sections or something to make sure a thread doesnt get interrupted.
But since you want to do more than just draw primitives, you need wglShareLists as well. The name is a little confusing since it will share pretty much all opengl data across contexts - display lists, textures etc. Looking at the MSDN docs now, it doesnt mention that you also need to call this sharing function before you load any data into either context - so do it right after you create each context.
This still deserves more explanation but I am at work now...


I'm working on a threaded resourceloader at the moment, and was wondering it your just theorizing here, or if you've actually done this. I fully agree that it _should_ be possible this way, but I wasn't really prepared to do it like this.

zppz
zppz
Yes, I have actually done it. I wasn't really prepared to do it either but in my case the 'data loading' involved connecting to a server, and needed to be cancellable. Like many things in development, it was a PITA to figure out but now seems quite simple in retrospect. A rough outline:
At app startup you create two contexts, one is the main context which you will already have, the other is solely for loading and never renders anything. Set them to share data. Keep both these contexts around all the time.
When you start loading, create a thread to do the actual loading work. Call wglMakeCurrent in this thread with the context designated for loading. Load your stuff, end the thread. When finished, the textures/display lists/vertex arrays you loaded will be available in the main context. During the loading the main thread/context can continue rendering as normal.
I can't remember where I needed the critical sections... maybe that was for something else. When I get home I will check it out.
OpenGL_Guru
OpenGL_Guru
Quote:
Original post by zppz
Quote:
Original post by DrEvilThreading it is less intrusive and easier in many ways, but be careful, because often there are issues with creating graphics objects from a seperate thread(at least with d3d there was, never tried with opengl).


Yes, there are issues with opengl too. Although it can be tricky getting two rendering contexts to work together, once you get it working it's a much more professional way of doing loading.

Presuming you are working on windows, look up on msdn:
wglMakeCurrent
wglShareLists

The first of these will set the current thread as the one which will control rendering. Once you call this, all opengl calls by other threads will be ignored, unless the other thread calls makeCurrent itself first. This is sufficient if you just want to draw primitives, but maybe you can see that it will already require critical sections or something to make sure a thread doesnt get interrupted.
But since you want to do more than just draw primitives, you need wglShareLists as well. The name is a little confusing since it will share pretty much all opengl data across contexts - display lists, textures etc. Looking at the MSDN docs now, it doesnt mention that you also need to call this sharing function before you load any data into either context - so do it right after you create each context.
This still deserves more explanation but I am at work now...


thanks zppz,..that is a start .. one problem.. this application needs to be cross platform -- no 'windows only' stuff so i am guessing that wgl functions are out of the question. i dont HAVE to have this in the application but before the first version i thought i would like to try to have something different happen when the data is loading other than changing the cursor to an hourglass symbol. thanks again..
heh
rick_appleton
rick_appleton
Quote:
Original post by OpenGL_Guru

thanks zppz,..that is a start .. one problem.. this application needs to be cross platform -- no 'windows only' stuff so i am guessing that wgl functions are out of the question. i dont HAVE to have this in the application but before the first version i thought i would like to try to have something different happen when the data is loading other than changing the cursor to an hourglass symbol. thanks again..


X11 has a similar function.
rick_appleton
rick_appleton
zppz: I would love to see some source code for this. I've been trying to do this also, but wglShareLists keeps on failing. Checking glGetError returns GL_INVALID_OPERATION. I have checked that the pixel format I request is identical to the one in the main thread. Beyond that I have no idea what to check.

I've downloaded the threaded MS sample GLThreads and tried to add a wglShareLists there, but that didn't work either (same problem).

I then downloaded a sample using wglShareLists in a single thread, and that did work.
WillPash
WillPash
If you are looking for a multi-platform solution OpenMP could do the trick.It is standard now on many games, especially on the new Microsoft XNA/Xbox360 framework. I read somewhere in some other site, that it is recommended that you should use openMP rather than the Win32 specific thread calls. Is this true and would it be good and convient way to develop a loading system, which on the same time loads data and renders a screen. I also render using OpenGL and want to make my program as portable as possible so i am still looking at openMP as a viable multithreading alternative. Best thing about OpenMP, it is standard in many recent multiplatform C++ compilers and it takes advantage of multi-core processors.

I have research it and it is easy to implement in a small or a well-structured program as the syntax is easy. The only thing developers always advise with multithreading,is to plan how and where you are going to use multithreaded commands...

There is a good introduction on OpenMP in Wikipedia Here
Dave 'Kit' Wilson - Reliant Code
zppz
zppz
I started making a 'tutorial' for this, maybe to add to the NeHe collection, but it turned out to be only a few lines addition to Lesson 6, so I'm not sure if it is worth 'tutorial' status. I will at least reply to this thread with some source, but once again I am at work...
Iftah
Iftah
Im shocked he asks for cross platform threads and no one mentions SDL.

SDL has cross platform threads, and window creation and input, and can work along with openGL.

Iftah.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.