Create texture with different GLContext(on another thread)

Hello,

I made a threaded loader for the IO part of reading the texture from a harddisk, but ended up having trouble with JOGL, because one context cannot be used in different threads simultaneously…

So my problem is:

How do I create a new context in which I can create a texture object with JOGL, load texture data into the object(store the texture on the graphicscard) and then later share it with the rendering-context?

To sum up I need:

  • Separate Rendering GLContext (for rendering Thread)
  • Separate texture loading GLContext(for loading Thread)
  • Ability to access both glcontexts at the same time, and finally to pass on the generated texture from loading-context -> rendering context

Bump guys :frowning: I’m really stuck…

Two options:

  1. Load the texture on a separate thread into memory (but don’t send it to JOGL yet), then notify rendering thread. On next render quick dump the texture in memory to the graphics card.

  2. Have a 1x1 GLPbuffer. When creating your rendering glcontext, tell it to share with the glpbuffer’s context. Use the GLPbuffer’s context for texture loading, just make sure the rendering context doesn’t use the texture until the pbuffer has completely created it.

Yes I get the basic idea, sounds good with the GLPbuffer, but I really need some code examples on creating multiple contexts, because I can’t seem to make it work. Also how to create a GLPbuffer and such?

Also, is GLPbuffer supported by all graphics cards?

edit
Btw, method 1. I tried already, it only yields around 2 times faster a result, and about half of the work needs to be done on the rendering thread = stalling the rendering loop…this is not acceptable :slight_smile: (too oldschool :P)

To create a GLPbuffer, do:


GLPbuffer pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(1, 1, new GLCapabilities(), new DefaultGLCapabilitiesChooser(), null);

To create a shared context do:


GLCanvas canvas = new GLCanvas(new GLCapabilities(), pbuffer.getContext());

This is off of the top of my head, so arguments might be off in ordering, etc.

You might also need to disable single threading, but I won’t get into that until we know if GLPbuffer is smart enough to not run on the AWT thread automatically.

Cant see why u need two contexts for loading textures?

When creating a texture on another thread you get a “GLException: no glContext current on this thread…” Also, if you dont use seperate threads, you cannot draw loading animations or do anything in the rendering thread until the texture has fully loaded.

So, to increase responsiveness I need multiple glContexts…

Also, I havent gone back to coding it, i still need to try out the stuff from earlier posts :slight_smile:

Keep the heavy lifting (io/decoding) in a background thread, and incrementally upload the data to OpenGL every frame in your render loop. You can either upload a single texture/object each frame, or even split texture uploads over multiple frames to keep your loading animation smooth.

Multiple contexts are a pain and a big source of compatibility bugs, and to be avoided at all costs imho.

As far as I know, it doesnt seem possible to copy a texture from main memory onto the graphics card in an interative manner. Of course I could upload scans of the image until an entire scan can be put together, but this seems overkill.

And using an entire frame to upload a texture is unacceptable. I already did this, and it takes as much time to transfer to the graphicscard as it does to load from the harddisk(IO).

If your textures are too big/heavy to be uploaded at once, then glTexSubImage2D will let you upload in chunks - I’d choose a maximum bytes per frame to upload and choose the maximum amount of scanlines that can fit within that. I think you’ll find it’s just as fast and a lot more reliable than trying to get multiple contexts working across multiple OSes and graphics cards.

i agree with orange tang i tried multiple contexts for a similiar issue and it is unsafe to use.

If you need your textures to be loaded while you are interacting (not on app init. ) i guess you can put them into a buffer and on demand retrieve them from main memory ( need a fancy shader for that)

Ok, I think this will be the way to go then, but this requires a bit more knowledge about JOGL than I have :slight_smile: I was hoping for an easy way to do it, this kinda makes the TextureIO class obselete… Has anyone made classes for uploading scanlines and then assembling them with texsubimage2d?

if(true)
return attachedFileWithSource;
if(false)
return null;

:slight_smile:

I dont have such code, but if you want a quick one try using an on-demand method. (dont know if it works for ur case) If you need to display a texture pixel load the region of this texture where (s,t) are part of it.

In the end you might not even load the whole thing if you dont need it (not seen)

Usually you want to display an entire sprite in a 2d image for example, so in modern computer games you still want the game to progress while loading models/sprites, so displaying a placeholder until sprites and models are loaded is the best procedure. Of course displaying a loading animation while loading is a way to avoid using placeholders, but that still hangs the loading screen if using a single thread.

ok in case of games the above wont do, im into CAD not a game engineer :persecutioncomplex: sorry

Im guessing CAD is for other purposes, like rendering 3dimages for picture/movies ? If so, then I guess amortized cost is more important than worstcase… In games I need to insure a constant low cost per frame, single stutters are unwelcome :smiley: