I work on an application that is using one GL context per window that are each on their own thread. There are 4 windows and a fifth shared context.
The application uses glFenceSync object’s to try and ensure everything stay’s nicely synchroized.
However I was just reading OpenGL Insights chapter 34 Timer Queries and it is makes it look like there’s not much of a point in separating context’s into different threads being that in figure 34.1 it has the different context’s running in parallel. The work was submitted from 1 thread.
If I were able to find a picture of the figure I’m referring too I would have posted it, sorry.
My question is: What is the best way to handle drawing to multiple windows?
Are there any papers / books on this topic? How was this kind of thing handled in the past, before sync objects?
Some more background, is that even though there are 4 windows being drawn too, only 1 (sometimes 2) have any “real” work load. The other windows have pretty minimal things being drawn to them.
Would a better (faster) solution be to have a render target for each window and draw everything to those from one context then let each window draw only their render target?
If there is anything that is not clear, please point it out.
I do not want to hijack the “thread”. But I am curious about the modern state of OpenGL in terms of calling the APIs from any given thread with respect to a particular context that might reside on its own thread.
With Direct3D (9) it doesn’t matter which thread called the API. I think this is easier for integration. Though I still do not know if a Present will take control of the device interface’s critical section or not. That would be a game changer. I assume a Present is handled independently since it must wait for the vertical blank. I will have to do my own tests at some point since the Microsoft forums are a no man’s land.
I would like to adopt the same approach with OpenGL (3.2 I think) without having to implement a queue that mirrors the relevant OpenGL APIs if possible.
Ontopic: If a context is bound to a thread, and presenting to the window is a blocking operation on that thread, then I would think going with one render target per window would not work out if you need to do more than one presentation per vertical blank period. But I have only worked with WebGL (in terms of OpenGL) for the last several years, so I am pretty far behind and very rusty for that matter.
EDITED: If the presentation is arranged to happen immediately (not synchronized) then multiple render targets would surely definitely work. Not sure if “synchronizing” in the subject means that the windows represent traditional frame buffers or not.
I do not want to hijack the “thread”.
Then why didn’t you just make your own thread? It’s not like threads are a scarce resource or something…
Though I still do not know if a Present will take control of the device interface’s critical section or not.
What is a “Present”?
[QUOTE=Alfonse Reinheart;1242305]Then why didn’t you just make your own thread? It’s not like threads are a scarce resource or something…
What is a “Present”?[/QUOTE]
Because I am also interested in threads with respect to OpenGL which amounts to the same issue.
Present would be the equivalent to SwapBuffers I guess in Windows. Not sure about X. With Direct3D (9; why use anything else) you can target an arbitrary region in any window with any sub region of the back buffer. With copy (double buffer) semantics and immediate refresh interval it basically feels like a blit, if that is not what it is. With “discard” you must transfer the back buffer corner to corner over the entire window (from what I can see that looks like all OpenGL is able to do; but I probably need updated documentation)
Fig.34.1 in OpenGL Insights has nothing with multi-context execution. That figure just illustrates pipelined and asynchronous execution of multiple draw calls.
Using a single GL context removes need for the synchronization, since GL guaranties in order execution (except data transfers, and maybe something else, but it is properly handled and optimized by the drivers). Using multiple contexts is required when pixel formats of the windows differ. If the pixel format is the same for all windows a single context can be used. Sometimes multiple contexts are used for asynchronous update. A benefit from such update is questionable and heavily depends on the certain implementation. Be aware that OpenGL serializes calls targeting a single context, but cannot over multiple contexts. In the case of multiple contexts additional synchronization is necessary (like you do, with both critical sections for the CPU and sync objects for the GPU). Also, multiple contexts do not execute in parallel. They do it concurrently.
Does anyone know of a good resource pertaining to multi threaded OpenGL. I am totally ignorant. I see the wiki here. I will see if I can find anything later.
So can a thread take control of a context? Or is it better to share resources? Can the final write to the display be done without being the current context?
I would just like to know. But I reckon these questions are pertinent to the discussion. I’m sorry. I’ve been working with Direct3D for way too long due to project constraints.
An interesting artical about the topic can be find in chapter 10 - “Exploiting Parallelism in Resource Preparation” from the “3D Engine Design for Virtual Globes” by Patrick Cozzi and Kevin Ring.
A thread has to “take control” and make GL context current in order to issue any of the commands. If you have several contexts, making a share-group is the only way to prevent data multiplication if they use the same resources. Otherwise, you have no particular reason to make uploading data through another context. Of course, data creation and/or download to main memory should be done in a separeta thread. Personally, I like to leave upload data to GPU memory to a drawing thread, but have quotas for update in a single frame to make frame-rate consistent.
Of course! SwapBuffers (on MS Windows) is not an OpenGL command. Under the hood, it flushes all drawing commands from all threads drawing to the same window.
^Thanks (but no thanks on recommending offline resources
What I meant by taking control (I apologize) was not a thread making its context the current context, but rather a thread taking control of a context that originated on another thread or is passed around amongst multiple threads (to use the linear raster facilities as necessary)
PS: I am assuming this information is all supplemental to the OP as it is very open ended (I would personally be bewildered if someone created a post with an identical line of questioning to my own post; so I won’t do that, even though it has been suggested that I should)
EDITED: Oh I see now.
I was under the impression (read: I had imagined) that the contexts belonged to a physical device of which there can be only one current context. Sorry.
The docs I am looking at do not say what happens if a thread makes an in use context current. Does wglMakeCurrent block until it is not current? Or does it return 0 (failure) and whatever the case how costly is it allowed to be if you were to regularly trade a context between threads?
If I have not already said so. I am basically wondering if I will have to implement a marshaled queue for all of the pertinent API calls in order to allow threads flexible access to a shared context (without forking the context ideally) or if I can just swap the context between threads without much penalty.
Also I am wondering. Is the pixel format of the HDC really the only requirement? What happens if the HDC is on the display of another physical device (with the same pixel format) ? I don’t see anything selecting a device in my docs anyway. But my docs are very old. I apologize. I favor them because they are offline.
One thing OpenGL has is SwapBuffers. It’s not obvious that the Present method of the D3D (9) device will not block all access to the device, because it is a method of the device interface, and the docs only mention that there is a global per device (interface surely) critical section. I asked the question in Microsoft’s forums and got no answers. But every MS forum is an absolute ghost town anyway. Even compared to this place
On the other hand it would seem completely bone headed for the D3D Present operation to block the rest of the methods (while it waits for the vertical blank period)
wglMakeCurrent fails if the context is in use. You may need to wait and check whether it succeeds. But… Why would you do that?
I have to admit that I did it long time ago, but now it seems to me that it is a better practice to use GL context only from a single thread. That thread owns context and issues commands exclusively. All other threads just post messages to a drawing thread.
Refer to a previous suggestion.
You can use GL context with all windows having the same pixel format without any problem. Pixel format dictates how framebuffer have to be created. Anyway you can check whether it works or not. I’m just encouraging you to try. It worked for me.
I wouldn’t agree with you that opengl.org is a ghost town. This is the most lively discussion forum about OpenGL in the universe.
No this forum is pretty good as forums go. But its not exactly bustling. But then again I tend to not venture out of this sub forum much
On the other hand you’d expect something like OpenGL to attract a whole lot more attention world wide. But then again forums for things that are really popular on a planet with 7billion people are practically unusable
PS: Many thanks for all of the insight BTW. I promise it will be put to good use. And you’d be surprised how many people find threads like these by way of searches. I see another thread about multithread has popped up…