Sharing context between processes

I’m attempting to share a single OpenGL 3.x context across multiple processes. I use the new wglCreateContextARB function and pass in the existing context. It then returns a handle which has the same value as the handle in the other process. No errors are given, yet it doesn’t work.

After some searching, I get the impression this isn’t supposed to work, but shouldn’t I get some kind of error then?

Google “parallel opengl FAQ”:

http://www.equalizergraphics.com/documentation/parallelOpenGLFAQ.html

You might describe what you’re trying to do in that other thread for better advice. If you need to be interacting with GL in both threads at the same time, you need multiple contexts. And what you want to do may or not be possible using ARB_sync or other mechanisms.

The usual advice is to try to keep all your GL interaction in one thread and offload CPU-heavy tasks to a background thread.

Thanks for your reply. I’m doing a little bit of research into creating a debugging aid for OpenGL. As such, the second thread/process is actually an entirely different program. The debugged program will have the original context, and for debugging I’d like to access all the resources this program created from inside my second program, hence the reason for sharing the contexts.

The problem might be the MakeCurrent calls, which likely don’t match up at the moment. I’ll give that a try later on and see if it helps.

I’m certain, that it is not allowed to share contexts across process boundaries.

First of all even if you could somehomw take control of open gl from another process that would be quite a major undertaking with little benefits if any.
I doubt that opengl conext is thread safe. To make it thread safe one would have to employ means of threds/processes synchronization which would slow things down dramatically. The only plausible scenario of using the same context in a separate process as I see it is offering the opengl context to another process for exlusive use so that the process that actually owns the contex does not have to access to it ( similarly how Google Chrome browser offers tab windows to the HTML engine running in another process.

Even though you probably cannot do it the way you described it in the original post is probably impossible it still can be done. Instead of using the context directly in another process you can write a proxy that woudl receive commands from another process and pass them to the current context.
Of course you would need some kind of interprocess communication such as dbus, shared memory, out of procees COM server etc. You got the idea.

Have you tested this yourself, or did you read it somewhere?

I need the interprocess communication in any case, and I’ve already tested that. Your suggestion was indeed my other option, but I’d like to have as little code as needed in the debugged process. But if I have to then that should certainly work.
As to your comment about speed, speed isn’t really relevant when I’m debugging a single frame, so I’m not worried about it. If I have to add loads of sync points, I’m ok with that. Thanks for thinking with me though, it’s appreciated.

There is no way to access to GL context from different process.
If you want to use GL context in separate process you need to write additional layer (proxy), wrap all calls and pass them to GL context. But you have to be sure that there is no any other app messing around with same context.

Also you can try to hijack application by injection your DLL in application memory space and hook on wglSwapBuffers. After that you can install proxy. Proxy spawn thread and start communication with another app (your debugger). Proxy needs to hook every OpenGL API command in order to track GL state changes.

Good resources for this is TAKSI project on sourceforge (how to inject dll) and glIntercept (how to hook on GL).

And just to be clear for those skimming this thread, we are only talking about MS Windows here.

In Linux, separate processes can share virtual address space, and in-fact this is how threads are implemented. And in fact, you can share GL contexts between processes/threads in Linux from what I read, but you still can only have one process/thread talking to GL through that context at a time.

That’s not the case on Linux. You can only share indirect contexts between processes using a special NV extension. The GLX docs (at least the last I read, maybe 1.4?) are quite explicit about that.

Bruce

GLX_EXT_import_context
http://oss.sgi.com/projects/ogl-sample/registry/EXT/import_context.txt

For those finding this thread later, let me follow up and re-state that my previous post was based on what I’ve read. I haven’t actually done this (shared a single context between multiple threads) myself, as I haven’t needed this … yet. Various sources (e.g. random googles here, here)) assert you can use the same context from different threads with locking, but I of course defer to those that have sifted the spec on this issue. Apparently, this behavior is not guaranteed to work, and so while we might be able to do this, if the assertions are true, we should avoid it.

However, you piqued my curiosity Bruce, so I went looking through the GLX spec. Didn’t find what you mentioned. Got a pointer? Though (related) I did find:

This in-and-of-itself doesn’t preclude multiple threads accessing GL through the same context, so long as they don’t ever both have it active simultaneously. It also seems curious wording if you should only make the thread current in the thread that created it… Why would this even be allowed?

Elsewhere in the spec we find:

void glXDestroyContext( Display *dpy, GLXContext ctx );

If ctx is still current to any thread, ctx is not destroyed until it is no longer used.

Again, this seems odd wording if GLX contexts cannot be shared between threads. I mean if that really is the case, then why wouldn’t glXCreateContext bookmark the thread ID in the client state and reject all attempts to make it current in or destroy it from any other thread?

Things that make you say “hmmmmm…” :slight_smile:

It simply means: you can pass a context around between threads of a process. All threads may access the context, but only one of them at any time.

To pass a context C, current to thread A, to thread B,
first call wglMakeCurrent(0,0) in thread A, then you may call wglMakeCurrent(hdc, C) in thread B.

It is not true, that only the thread, that created the context, may use it.

You can have multiple contexts, each made current to a separate thread. You can concurrently issue OpenGL commands in each of these threads (there are some peculiarities with shared objects to be obeyed, though)

skynet is right… Long time ago I played with composite UI design, trying to simulate multiple applications running on different framerate composed in 3d evnironment. UI must not suffer from low framerate of some application. So… to make that test I create multiple GL contexts and threads and pass one of contexts to one of threads (one thread is one application). All contexts share their objects. First context belong to composition thread. All other contexts & threads render their stuff in offscreen texures. Composition thread & context collect textures and compose on screen.

You can create multiple contexts in one thread, but do not make them current in that thread. Better pass context to some other thread and then make them current from host thread. Also… context sharing must be done in same thread. Both context must not be current.

Good stuff. Thanks, guys!

GLX contexts can definitely be shared between threads, assuming you don’t use them on more than one, although I wouldn’t recommend it - X is very fussy about the X Display Connection you used to create the context, and the connection you use to work with the context, and then also about using Display Connections across threads. I would/do share the contexts to see the same objects, but use each one very specifically in a single thread.

I was answering your ‘processes’ question - you were calling it threads/processes, and in this context, they’re very much different things.

I recall that I had to piece it together. From the GLX 1.3 Programmer’s guide:

Direct Rendering and Address Spaces
One of the basic assumptions of the X protocol is that if a client can name
an object then it can manipulate that object. GLX introduces the notion
of an Address Space. A GLX object cannot be used outside of the address
space in which it exists.
In a classic UNIX environment, each process is in its own address space.
In a multi-threaded environment, each of the threads will share a virtual
address space which references a common data region.

Meanwhile, ‘skynet’ found the extension I referred to: GLX_EXT_import_context
That lets you share between indirect contexts. I did mess with that, but for my use they were notably crappier. I believe, on NV cards at least, they’re more capable now.

Bruce