Quote Originally Posted by Gus Lott View Post
And I'm pretty sure that most OpenGL calls block until completed. It wouldn't make sense for the pipeline otherwise to have some blocking and some non-blocking.
I would say exactly the opposite, it makes perfect sense for some calls to by asynchronous and some to be synchronous. Consider the following example pseudocode:
Qt Code:
  1. glBegin(...);
  2. glVertex(x1);
  3. glVertex(x2);
  4. glVertex(x3);
  5. glEnd();
To copy to clipboard, switch view to plain text mode 
It makes perfect sense to make glVertex calls asynchronous as it makes no sense to transfer data to the graphics card vertex by vertex as you'd be just wasting bandwidth and time. It makes perfect sense to synchronize the context not earlier than the glEnd() call.

The moment you called another blocking call after several non-blocking calls, the pipeline would have to block until the previous commands had been completed.
That's exactly the point Why block at every command if you can only block at the last one? What if there is a context switch somewhere inbetween? What to do with the data already pushed to the pipeline?

I think this is why the documentation says you need to intercept and prevent the draw/resize events in the main UI thread if you're going to draw from another thread.
That's not enough. You can only touch the gl context which is independent of the gl widget but you can't touch the widget itself (i.e. change its geometry) from another thread hence you can't simply push the gl widget to another thread. While it might work in some cases it is bound to fail eventually.

Again, my opinion is you don't need multiple threads to do multi-gpu rendering (of different contexts) and using multiple threads won't make your application do multi-gpu rendering automatically.