pouët.net

[OpenGL 3.3 Core] Program objects used in multiple contexts in multiple threads

category: code [glöplog]
 
I'm currently working on a pet project which runs multiple DirectShow streams at the same time, pushes the data sent in by the cameras to VRAM, does a few post-processing tricks on the feeds and then mixes all inputs to form an output. So far so good. Recently I moved from an approach where I relied on one rendering context (which, apart from the usual rendering trickery, was also used to transfer the cached data buffers to VRAM - boo!) to a new one, where now I use one context per camera (where each context is bound to a separate worker thread).

Being relatively aware of all the hell that could have opened if I treated the matter too reluctantly, I wrapped a few locations in critical sections to make user I don't get nasty desyncs between the main rendering pipeline and the other workers. Especially:

* Data buffers in RAM are never read from and written to at the same time.
* All functions responsible for working on textures off-screen are wrapped in CSes (to avoid situations where the uniform values for a shared program object happen to be happily overwritten by another thread).
* Textures shared by worker threads and the main rendering thread are also protected against multiple threads' access.

The problem I've spotted was that - on my Quad Core platform and GTX 570 - it appears that you must not use the same program object for all contexts sharing it, else you'll run into situations where the uniform values "leak" between executions of the same program! Flushing or finishing the pipeline in critical section does not seem to do any good - the leaks appear to be of random, spurious nature. A working example I have is that I have this "saturate" shader. If we dealt with 3 feeds running at the same time and bumped the saturation setting for only one of the feeds, you could see the setting kicking in to the other two feeds every couple of seconds. It was only one frame suffering from the effect, then everything was getting back normal again.

Have anyone of you bumped into a similar issue? My solution (fortunately I could afford it, given the scale of the project) was to simply create separate program object instances for each of the worker contexts. This is far from perfect and I'd love to do it the Proper Way, but I can't see any other solution on the horizon - apart from perhaps trying to reach Nvidia. Never tried that, so I'm not even sure if this is doable :)
added on the 2012-08-26 12:05:02 by kbi kbi
Creating separate programs IS The Proper Way, because uniforms are program-state.
added on the 2012-08-26 12:42:26 by kusma kusma
kusma: I know, which is why I tried to wrap all code working on each of the program objects within a critical section, so that the objects are not used for rasterization at the same time. In other words, what I have in mind is:

1) Thread 1 - enters CS, Thread 2 - (other quirky business)
2) Thread 1 - starts configuring Saturation program uniforms, Thread 2 - tries to enter CS, no go, locks
3) Thread 1 - executes Saturation program, Thread 2 - still locked
4) Thread 1 - leaves CS, Thread 2 - still locked
5) Thread 1 - (other quirky business), Thread 2 - enters CS

Why should the leakage occur at this point, assuming I flush the pipeline at the end of step 3? Doesn't that guarantee all queued operations have been executed on the server side and I should be fine and dandy to do whatever I like, including modifying the program states from within another thread or context?
added on the 2012-08-26 12:51:33 by kbi kbi

login