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

OpenGL - Sharing textures between contexts

Started by dpadam450 Oct 6, 2025 at 2:01 PM 6 replies 3.7k views
Original Post
dpadam450
dpadam450

I see wglShareLists() but it doesn't seem any of my objects like textures are able to share between contexts.

I have two monitors each running a fullscreen openGL context. I don't mind setting up openGL completely context independent but was curious if there is another way.

I tried wglShareLists() but at initialization and after the objects were created. The secondary context always hits a debug error message for invalid operation, must call glGen* before binding an object.

NBA2K, Madden, Maneater, Killing Floor, Sims 
Aressera
Aressera

If all you need to do is to render to multiple windows, you can do that with a single OpenGL context. It's a bit convoluted, but this works for me. I mainly use this capability in my editor. Essentially you can retarget the same context to render to multiple windows.

  1. When first window is created, create a dummy OpenGL context for it using GetDC(), ChoosePixelFormat(), SetPixelFormat(), wglCreateContext() in that order. Then initialize GLEW or whatever you are using, then destroy the dummy context. This must be done on the main thread or crashes can happen.
  2. For each window you want to render into, choose the final pixel format using GetDC(), wglChoosePixelFormatARB(), SetPixelFormat(). This must be done on the main thread or crashes can happen. This doesn't necessarily need to happen all upfront, you can also add new windows after the OpenGL context is created in step 3, but you need at least one to start with.
  3. Create the real context using wglCreateContextAttribsARB() for the first of the HDC returned by GetDC() in step 2. This can be done from any thread (i.e. you can render from any thread after doing the HDC initialization on the main thread).
  4. After context initialization, and before rendering each window on every frame, use wglMakeCurrent() to change what window the context is rendered into, by supplying the associated HDC. This should be done from the same thread you used in step 3 (the render thread). If you using vsync, it needs to be set (wglSwapIntervalEXT()) after all calling wglMakeCurrent() for all HDC, before rendering the first frame, or any time the number of HDC you render into changes (e.g. after ReleaseDC()).
  5. Call SwapBuffers() just once per frame after rendering into all windows, from the render thread.

Keep in mind you now have to render more than one window in the same time, because they are rendering from the same thread, so performance is more of a concern since all windows need to render within the refresh rate.

cgrant
cgrant

My recommendation is to do away completely with legacy/compatibility OpenGL context. Use attributed context and pass the context that needs to be shared into the context creation function. With that said, first with what @aressera said, if you are not using OpenGL features on multiple threads then having multiple OpenGL context is a moot point as you'd be just switching context on the same thread. However, if you indeed are using multiple threads. One thing you need to we aware of is that if you are sharing resource created in OpenGL context A, with OpenGL context B, and the resources in context A were created before context A was shared with context B, they will not be visible to context B. One would assume that sharing would cause a synchronization on all resource, but I don't think this is case is practice and from my observation. This means that all context that will be shared needs to be created prior to creating the shareable resources. There may be some exception to the rule such as the default windowing system back drawable used by the context for the framebuffer.

dpadam450
dpadam450

Ha, damn. Didn't realize that wglCreateContextAttribsARB took a “hShareContext” parameter. Sadly I took about an hour to just have my code work by loading the textures that would need to be shared again while each context was loaded. Surprsingly this went very easy. Only a few textures get shared between monitors, so reloading them wasn't a memory waste. Good to know. I may rip this out and try what you suggested.

NBA2K, Madden, Maneater, Killing Floor, Sims 
RmbRT
RmbRT

@Aressera I'm a bit confused about the rendering thread. You said you can render from any threads after creating the context from the main thread, but then mention that one thread has to render both screens in the frame interval.

Walk with God.
dpadam450
dpadam450

I think he just means that if you are running v-sync, that you could now go over the allotted time, causing you to have to wait for the next v-sync. Where as if you created 3 separate windows with 3 separate contexts then they would be updating the monitors all independently which would run faster code. Not sure how all 3 monitors work in regards to v-sync. Do they all post v-sync at the same time, or if they are all 3 refreshing at different times, then you might stall waiting for 3 separate v-syncs when rendering one frame.

NBA2K, Madden, Maneater, Killing Floor, Sims 
dpadam450
dpadam450

Also, the stated suggestion did work so thanks. I removed all my other code and now the sharing works.

NBA2K, Madden, Maneater, Killing Floor, Sims 

Topic Locked

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

Sign in to reply to this topic.