Sign in to follow this  

OpenGL openGL and threads

Recommended Posts

kRogue    100
All right, here goes the (evil) question: what is safe to do in openGL via threads and what is not? I ask becuase straight from Apple we have: "The Mac OS X OpenGL implementation is not thread-safe but you can still split your processing onto multiple threads. It is extremely important for developers not to issue OpenGL commands for a single context from multiple threads without proper thread synchronization." from maybe my question is a touch too broad... lets start with a (few) examples: 1) loading geomerty (i.e. VBO) and texture data to the card. Can this be done in a thread if the textures and geomerty being loaded are not at all used by any other threads while the loading thread is alive? my concern is that the driver may have some funky logic in it to decide when to send the data to the card, so if you are in thread A drawing stuff (but not using the VBO's and textures affected by thread B) and thread B starts it's loading thing and the driver may decided to move some stuff from card to memory or vica-versa which thread A is playing with, and then thread A might get trashed (i.e. a draw command is issues by thread A when the stuff is (say) in card memory, but when the card actaully does the command it has gotten moved back to system memory) Typical example of doing this is "nicer loading screens" and possible some "load stuff while playing scenarios" 2) FBO's and a simple windowing system: idea: each window renders to a texture .. now admittedly a fixed window may play with the openGL stte alot, so I am not saying do the drawing of each window in it's own thread, but, for each windows there is a Do() and Draw() function. The Do() function does stuff that _should_ not affect the openGL state that touches other windows, i.e. it can do things like change VBOs ann textures it owns, but it does not do any openGL state stuff (i.e. drawing, glMatrix*, ect). So the windowing system does the Do() in threads but the Draw()'s one at a time... would that be safe at all even? Best Regards -kRogue

Share this post

Link to post
Share on other sites
BlackGhost    116
What they say about the OpenGL implementation not being thread safe means that you should use synchronization objects around all OpenGL API calls that might be called from multiple threads. What other processing you are doing with your data is up to you to choose how to synchronize.

I don't know anything about MAC, but in Windows OpenGL will crash badly if you don't do synchronizations across API calls. I hope in a future version you can set some flag to make OpenGL thread safe (like in DirectX), because the way I see it, implementors might have more access to lower synchronization overhead.

Share this post

Link to post
Share on other sites
Promit    13246
The long and short of the story is, don't make gl* calls, wgl* calls, glx* calls, or anything else of the sort from more than one thread. It doesn't matter what the usage patterns are. Just don't do it.

Share this post

Link to post
Share on other sites
udaykv    126
Well, Quake 3 is a nice example of using OpenGL in a threaded model :). I have been looking into the code only since yesterday so don't know much about it yet, but the idea I get is that carmack is not trying to call two gl functions in different threads without making sure that only one of them executes at any time.

Q3 is using Win32 events to achieve the functionality in the win32 version.

Also, making gl functions thread safe would be more than just making function calls thread safe. The entire states need to be made thread safe. What if one thread is in a glBegin/glEnd and the other one says glGet (no crashes, but invalid operation)?

Instead letting the programmer plan the synchronization constructs works better for me.

Share this post

Link to post
Share on other sites
_the_phantom_    11250
As Promit says, its just not a good idea todo it.
About the only place you could possibly gain a performance increase is by loading data, HOWEVER an OpenGL context is only current in one thread at a time (win32 at least), as such you'd have to swap the context between threads to upload the data, this is going to cost you performance wise.

Share this post

Link to post
Share on other sites
kRogue    100
so, therefore, the idea of doing this with threads is just begging for trouble:

Draw a bar via openGL of % stuff loaded.

actually load the stuff from disk and put then into openGL

or what I'd really like to do:

while game is running:
the game, if a needed resource is not loaded then pause game and wait.

checks if there are resources needed now or soon that have not been loaded yet, and loads them to openGL,

so this would be bad ;(

but this should be ok then:
conceptionally owns the openGL

checks if there are resources needed now or soon that have not been loaded yet, and loads them to memory, when a resource is ready in memory "send a message to threadA" saying to move the data from memory to openGL...

Share this post

Link to post
Share on other sites
pleopard    120
Let me see if I can shed some light on this ... Problems with multi-threading in OpenGL stem from its state machine architecture. When the GL context is created, it is done so from within one thread. That thread is given its own stack space where the GL state variables are stored. If you attempt to access those state variables (e.g. gl*, wgl*, glx*) from a separate thread then the calling thread references the variables of the same name in their own stack space ... not in the thread of the GL context ... a completely different set of state variables.

This is why successful threaded GL apps typically use some sort of messaging or command loop running in the primary thread where external threads can post commands to be processed by the primary thread.

Multi-threading can be a great thing for a viz and can help in many ways. However, you had better know what you are doing or you will be in for a world of hurt. A guy I used to work for said it best ... "multithreading with OpenGl separates the men from the boys".

Share this post

Link to post
Share on other sites
RichardS    298
The slightly longer version is (on Mac OS X): Don't make any gl* or CGL* calls into same context from different threads, without synchronizing those calls. ie, it is OK to issue GL commands into the same context from multiple threads, BUT you must ensure that no more than one thread is actually in a gl* function at any time.

If each thread has a different current context (but those contexts are not shared), then you don't have to worry about anything.

What you want to do is to load resources in one thread, while rendering from the other. This can be done with shared contexts, although I'm not sure about the exact synchronization requirements.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
    • By Picpenguin
      I'm new to learning OpenGL and still learning C. I'm using SDL2, glew, OpenGL 3.3, linmath and stb_image.
      I started following through and got through it until I had to load models. The problem is, it uses Assimp for loading models. Assimp is C++ and uses things I don't want in my program (boost for example) and C support doesn't seem that good.
      Things like glVertexAttribPointer and shaders are still confusing to me, but I have to start somewhere right?
      I can't seem to find any good loading/rendering tutorials or source code that is simple to use and easy to understand.
      I have tried this for over a week by myself, searching for solutions but so far no luck. With tinyobjloader-c and project that uses it, FantasyGolfSimulator, I was able to actually load the model with plain color (always the same color no matter what I do) on screen and move it around, but cannot figure out how to use textures or use its multiple textures with it.
      I don't ask much: I just want to load models with textures in them, maybe have lights affect them (directional spotlight etc). Also, some models have multiple parts and multiple textures in them, how can I handle those?
      Are there solutions anywhere?
      Thank you for your time. Sorry if this is a bit confusing, English isn't my native language
    • By dpadam450
      FINALLY, upgrading my engine to openGL 4. I was having some trouble so I started with a stripped down application and was wondering if VAO's are required, because I have a sample working, but if I remove the VAO then it doesn't seem to like drawing my triangle.
  • Popular Now