Load Image fail in multithread?

Started by
5 comments, last by htz92127 13 years, 4 months ago
I load image with the DevIL(OpenIL). It could be seccessful when the fuction been called in the same thread as render therad. However, it failed in multithread.
I want to know is the DevIL support multithread? Otherwise, I need open same OpenGL state? I remember there is a D3DCREATE_MULTITHREADED Flags in DX.
Advertisement
The rendering context can only be active in a single thread at any time. So to load your texture in another thread, you need to activate it in that thread. However, be aware that doing so will deactivate it in the previous thread, which will stop any OpenGL command to work in that thread instead.

I have not checked the very latest in OpenGL, so there may be some way around this to load resources asynchronously in different threads nowadays (I have a vague memory of this being in the pipe sometime). But you'll have to check the specification or the extensions available.
Three solutions:
1. Map/unmap buffer objects in the main thread and do the loading and copy to buffer in another thread.
2. Create a shared context and use that one for uploading data.
3. Do the loading off disk in another thread and screw multithreading for the actual data copy. Just do it in the main thread.

The last solution has the disadvantage of taking away time from your render loop and not using more than one core when it would matter. It has the advantage of being simple, though, and it works.

The first solution has the problem that it is a terrible mess. One thread writes to a data buffer that it does not own which another thread maps and unmaps and which may "randomly" be lost and may need to be filled again (thank you, Khronos guys, for such a feature!), in which case the latter thread has to signal the former one again and blah.

The second solution has the advantage that it is only moderately complicated and that it works, and there is no mess. However, sharing contexts may not work equally well with all drivers (especially older ones) and may (presumably?) cause data swapping on some systems, which is why many people deem it bad Karma to go anywhere near sharing contexts.
Thanks for your replies.
But I am a beginner of the OpenGL, I didn't know how to create shared context?
Could you tell me how to do that?
In Windows you can do it like this:
HGLRC hGLRC = wglCreateContext(hDC);HGLRC hGLRCThread = wglCreateContext(hDC);// Enable sharingwglShareLists(hGLRC, hGLRCThread);


Then you use wglMakeCurrent(...) to set a different context in each thread, and you can use the same textures in both.
Is the function wglCreateContext() Windows-only? And that I am using ilutGLBindTexImage() to help me bind image, how can I share the context? Should I bind it by myself?
Yes, that is Windows only. There are wglXXXXXXX functions for Windows and glxXXXXXXX for Unix derivates (mostly identical or similar).

Note that wglCreateContext + wglShareLists is not atomic, which is usually not a problem. It's the same as with making a singleton threadsafe -- it's silly.
Simply spawn threads after these function calls, and you have no issue that you need to take care of.

If thread safety is a problem, you can instead use wglCreateContextAttribsARB.
This has a somewhat different usage (and, you must load it with wglGetProcAddress first!), but it is nice and easy once you grasp it. More options, kind of more comprehensive, and thread-safe.
You should read the documentation at MSDN
http://msdn.microsoft.com/en-us/library/dd374387%28VS.85%29.aspx

wglShareLists is documented here
http://msdn.microsoft.com/en-us/library/dd374390%28v=VS.85%29.aspx

Platform specific info for Windows
http://www.opengl.org/wiki/Platform_specifics:_Windows
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
I write the app with opengl instead DX as I don't want to use windows-only function. I think I know how to solve the problem:
Load all images in the main thread.

This topic is closed to new replies.

Advertisement