Texture Update with multithreading

Hi!
I am trying to separate texture creation and rendering into separate threads but it doesn’t seem to work. I’ve opened another thread, created new RC, but see nothing - any suggestions?
Thanks

Is it essential that they are in different threads? If you are rendering the textures to re-use them, why not just draw them change the view point and redraw the scene.


Fleejay

I am not sure what your problem is but I can offer this information. Please pardon me if you already know this.

Each separate thread gets it’s own private stack. All objects or primitives that are not dynamically allocated (new or alloc) are created on that stack. OpenGL keeps track of it’s state using a lot of non-dynamic items which are, of course, created on the stack of the thread that initiates the RC. Lets call this thread the ‘rendering thread’.

So how does this effect us? It forces us to make every single OpenGL call or other function call that results in an OpenGL call FROM WITHIN THE RENDERING THREAD. If an OpenGL call is executed from another thread then the results are undefined because that thread does not have access to an OpenGL context. This means that you might over-write other important memory causing a fault. Even if a fault does not occur, the end result is a display that shows either nothing at all or garbage.

Is it possible that you are making an OpenGL call from within the non-rendering thread? If so that would explain the problem. Otherwise, I am out of ideas.

Good Luck!
Paul

Thanks, but let me try to be a bit more specific. Let’s say I have a huge amount of textures that I want to update. Let’s say I want to update 20 textures per frame. I’m trying to isolate render functions into separate thread but so it could share the textures with the update thread. In other words, one thread “writes” the textures and another “reads” (binds them) for render. The question is - is it possible and if yes how?
Thanks again.
Lev

ok, off the top of my head, I think you have a good idea going with the background processing and all, but in reality I don’t think it will work.

If I understand correctly, you want seperate threads to do your texture updates/animations and then have your primary thread pull those textures and do its magic. What happens if the primary thread wants to read the texs before the workers have finished updating them? Hope you’re ready to enter the fun-filled world of mutex, semaphores and thread concurrency

There are a number of ways to implement your idea in windows ( if you’re not talking about win32 then I’m just wasting your time here ). Check out TLS( thread local storage ) as well as some shared memory teqs that can be found all over the MSDN . In my useless opinion, I think you’d be better off keeping it all in a single thread…or at least keep all your rendering needs there. The overhead as well as headaches caused by marshalling thread data just dosen’t seem to be worth it.

Dave

Thanks, I’ll try But you’re probably right.

Isn’t there some WGL call, like wglShareLists or something that you would need to do for the two contexts to be able to share textures? Clearly you need two contexts because each context should only be “current” in one thread at a time.

The real problem is that all the texture updates, as well as the rasterization is being communicated over the same bus to the graphics card. Multithreading would just interleave the CPU/GPU traffic between the requests each thread is making but likely wouldn’t help you to get higher bandwidth to the card. It is probably better, and easier, to stick with one context and just interleave rendering and loading operations using some system of your own devising.

There may even be a performance penalty for working with two contexts simulataneously that would make any speed improvements due to parallelism moot.

Originally posted by timfoleysama:
Isn’t there some WGL call, like wglShareLists or something that you would need to do for the two contexts to be able to share textures?

Yes, wglShareLists() applies to both display lists and texture objects.

  • Tom

This is just an idea and I’m not sure if it would fit your needs, but it’s an idea I thought I’d throw out. If you really feel you need to do the two threads you could possibly just have the one thread update the texture data without actually sending the new data to the card. In other words, do all your texture updates without doing any OpenGL calls in that thread. You then somehow notify the main thread that the textures are ready to be updated and then have that thread do the actual gl calls to update the textures. I know, it’s not pretty, creating multiple contexts just so you can update the texture data in a separate thread isn’t really pretty either.

Personally, I’d tend to agree with lpVoid that just doing it in a single thread would probably be a lot cleaner way to do it.

But it could show itself worthwhile having two threads.
As the OpenGL thread updates the texture it does IO calls and Win32 is supposedly good at doing something else in the meantime… even if you are not running on a SMP machine.

There was this guy from the OpenGL maillist that had done this, he did procedural textures in realtime and used threads for it, he got massive speed improvements.

IsaackRasmussen,

I agree that if you do file I/O, deferring that to another thread is a convenient way to avoid using asynchronous (“overlapped” in Windows parlance) I/O. If you just do the I/O in another thread, but put the call to TexSubImage2D() into the rendering thread, you will probably get lots of parallelism.

However, the case you’re talking about, procedural textures, sounds like it wouldn’t have this benefit, as procedurally generating the textures takes a lot of CPU, just like rendering. So, for that to speed up using multiple threads, either he must have a dual-CPU machine, or his GL rendering thread must be blocked on I/O elsewhere (which would be a bad idea). So I don’t understand that example.

Could “waiting for vblank” count as I/O? I guess it could, if the driver was written with cooperation in mind and used higher-level primitives like Events for signalling swap-done. However, given that scheduling time slices on Windows can be larger than the time to draw an entire frame, and given the cut-throat benchmark competition, I would guess they do what all Windows drivers do: disable interrupts and poll until complete. So no parallelism there, either.

Jwatte:

If you had this one thread that renders and uploads textures, it could go check those procedural textures that ready to be uploaded.
The other thread that only does CPU work, would get interrupted from time to time by nature of multiprocessing…

wouldn’t this at least show an speed up… you think not?

You gotten me in doubt now. I’m sorry, I can’t remember the excact details from the example I was talking about.