# Secondary Thread for Loading

**URL:** <https://discourse.glfw.org/t/secondary-thread-for-loading/1724>\
**Category:** support\
**Created:** [January 2, 2021, 12:00am UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724 "2021-01-02T00:00:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![whitwhoa](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/whitwhoa/32/425_2.png) [@whitwhoa](https://discourse.glfw.org/u/whitwhoa)\
**Post date:** [January 2, 2021, 12:00am UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/1 "2021-01-02T00:00:35Z")

</div>

Been working on a little hobby engine for the past year or so which uses GLFW, and have a question about using multiple threads for loading. For example, my engine uses classes of `Scene` objects which contain all of the data for objects as well as a `GPU` class which is responsible for managing all `gl*` functions and tracking what’s currently loaded into the gpu.

I recently sought out to implement a feature that would allow one Scene to continue to play while loading another Scene in a separate thread. After implementing this I quickly hit an Exception due to one of the gl calls not returning a valid int id. I was able to reason out that this was more than likely due to the opengl calls being made from a thread other than the main thread where the context was initialized.

So I suppose my question is then: How can I allow my current scene to continue to be responsive while creating a new scene? (Think a loading screen that shows a progress bar, connection status, etc while the actual level loads)

I suppose I could refactor some things so that I can load everything into memory in the separate thread and then once that’s complete, make the opengl calls to load the buffers using the preloaded data. My only concern with that would be the amount of time it takes to saturate the opengl buffers, as the users screen would be unresponsive for this duration.

Any advice/recommendations greatly appreciated!

---

<div class="post-metadata">

**Author:** ![mmozeiko](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/mmozeiko/32/29_2.png) [@mmozeiko](https://discourse.glfw.org/u/mmozeiko)\
**Post date:** [January 2, 2021, 1:21am UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/2 "2021-01-02T01:21:19Z")

</div>

Hello.

Just so we are on same page - this has nothing to do with GLFW, it just a general way how OpenGL works. GL requires context to be available in thread you are calling GL functions from.

One way to fix this is to create multiple GL contexts and make them available in separate threads. When you create GL context you can make it to share its resources (textures, buffers, …) with other context - so you make loader thread GL context to be shared with your main GL context. Then everything will “work”.

But - I would strongly recommend against this. Multiple GL contexts are well known source of many bugs depending on GPU driver version & OS.

Another way to minimize time spent in GL is to map buffers in main GL thread and pass pointer to loader thread. Basically do this:

1. in main thread allocate buffer & map it to get pointer - glGenBuffer, glBindBuffer, glBufferData (with NULL data), glMapBuffer
2. pass pointer to loader thread
3. wait until loader thread finishes writing its data to this pointer
4. now back in the main thread call glUnmapBuffer and you’re ready to use buffer
5. for textures this would require extra copy from PBO buffer to texture - but that is async call, should be quick

If you use a bit more modern GL versions that has persistent buffers (GL\_ARB\_buffer\_storage extension or GL 4.4 version & up) then you can map buffers persistently and skip step 4. All you need is to map buffer at startup, and leave it mapped. Just finish writing to it before using. You can even have just one huge buffer for any data you want to sent to GPU - vertex buffer, index buffer, etc - your code can which parts in this buffer means what data, all you need is to calculate correct offsets in pointers to data in these buffers (pointer argument in glVertexPointer or glDrawElements functions).

---

<div class="post-metadata">

**Author:** ![whitwhoa](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/whitwhoa/32/425_2.png) [@whitwhoa](https://discourse.glfw.org/u/whitwhoa)\
**Post date:** [January 2, 2021, 3:48pm UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/3 "2021-01-02T15:48:18Z")

</div>

Thank you for taking the time to explain this. It has really helped me. I’ve been looking into persistent mapped buffers and everything is starting to click!

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [January 2, 2021, 6:58pm UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/4 "2021-01-02T18:58:00Z")

</div>

There is a related issue for multi contexts from a single window which may be of interest:

> <https://github.com/glfw/glfw/issues/1687#issuecomment-638399075>
>
> The following thread on discourse discusses a need for multiple contexts for a w…indow:
> https://discourse.glfw.org/t/fullscreen-window-blinking/1538/4
> 
> I am unsure about the overall benefit of multiple contexts for OpenGL these days, and I think it's best to keep GLFW as lean as possible, however this is something which is currently not possible to do with GLFW without altering core GLFW code so I think it's reasonable to consider.
> 
> Potential approaches:
> 
> 1. Expose the required OS specific information via the GLFW native API, for example on Windows WGL requires the device context \`window-\>context.wgl.dc\` which is not currently exposed. Users could then write their own OS specific code to create contexts.
> 2. Add \`GLFWUserContext\* glfwCreateUserGLContext(GLFWwindow\* window)\` and supporting functions, see below. I have named these User Contexts to differentiate from the GLFW context created along with the window.
> 
> For 2 we would need
> \`\`\`
> // Create a new context for a window
> GLFWUserContext\* glfwCreateUserGLContext(GLFWwindow\* window);
> 
> // Delete a context
> void glfwDestroyUserContext(GLFWUserContext\* context);
> 
> // Make a context current
> void glfwMakeUserContextCurrent(GLFWUserContext\* context);
> 
> // Get current context - returns NULL if primary window context is current,
> // in which case glfwGetCurrentContext would return window, and
> // glfwGetCurrentContext will return NULL if a user context is current.
> GLFWUserContext\* glfwGetCurrentUserContext(void);
> \`\`\`
> 
> I can create the Windows versions of the API, and sdegrande can help with the GLX and potentially Mac.
> 
> This is potentially related to #1501

along with a question on this forum:

> [@Fullscreen window blinking](https://discourse.glfw.org/t/fullscreen-window-blinking/1538):
>
> Hi. I’m using GLFW for a VR painting project at work. I use threads to async-load heavy 3D Models, with their own opengl context, created using an invisible window, as proposed in the GLFW doc. The temp windows are created and destructed in the main thread. It works well. But, on windows (10), if the main window (main thread) is fullscreen, there is a black blink when a temp window is destructed. There is no such issue on Linux. I traced it down to the call to win32 DestroyWindow(). So my qu…

I have an in-progress branch:

> **[Commits · dougbinks/glfw](https://github.com/dougbinks/glfw/commits/multi-context-windows)**
>
> A multi-platform library for OpenGL, window and input - Commits · dougbinks/glfw

The functionality is mostly complete, but I need to update the docs and choose a better name prior to submitting a PR.

---

<div class="post-metadata">

**Author:** ![whitwhoa](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/whitwhoa/32/425_2.png) [@whitwhoa](https://discourse.glfw.org/u/whitwhoa)\
**Post date:** [January 3, 2021, 6:11am UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/5 "2021-01-03T06:11:56Z")

</div>

This is beautiful! I will definitely check this out as this is exactly what I was hoping was available. Thank you!

---

<div class="post-metadata">

**Author:** ![whitwhoa](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/whitwhoa/32/425_2.png) [@whitwhoa](https://discourse.glfw.org/u/whitwhoa)\
**Post date:** [January 4, 2021, 9:48pm UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/6 "2021-01-04T21:48:06Z")

</div>

Can confirm, this works wonders! I was able to create a separate `GLFWusercontext` to use in the thread that’s loading a new scene, then once that thread has finished, set the main thread context to the new user context. Thank you again for mentioning this!

---

<div class="post-metadata">

**Author:** ![dougbinks](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.glfw.org/dougbinks/32/39_2.png) [@dougbinks](https://discourse.glfw.org/u/dougbinks)\
**Post date:** [January 5, 2021, 11:41am UTC](https://discourse.glfw.org/t/secondary-thread-for-loading/1724/7 "2021-01-05T11:41:56Z")

</div>

Excellent!

I’m considering renaming `UserContext`to `GLAuxContext` before submitting the PR, so be aware you might need to change the function names when this arrives. I plan to try to submit the PR sometime this month.
