-
Notifications
You must be signed in to change notification settings - Fork 30
Multithreading using contexts
Loading large amount of data in the main thread might lead to many stutters. Therefore it is benefical to use several threads. There is just one issue: Graphics API object can't be simply shared across multiple threads. That's where context come to use: After you bind a context everything loaded afterwards will belong to that context. Without a context bound the engine wouldn't work. That's why every engine instance object has a context it can access. This context is bound by default. You can test the effects of the context yourself by unbinding it:
void App::LoadContent() {
...
context.Unbind();
...
}
The results are lots of errors and a black screen, if not even worse. Every context is associated with a window. The window won't work without a context and the context wouldn't work without a window. That's why you need to attach a context to every new window you create. You also need to attach a window to every context if you want to use that context.
void App::LoadContent() {
...
Atlas::Window otherWindow = ...
context.AttachTo(&otherWindow);
...
}
Note: For the default window the context available by the engine instance is already attached.
A context can only be attached to one window in one thread at a time. That means if you would wan't to draw in two windows simultaneously you need two contexts.
When you want to use several threads and share data between threads you need the same number of context as there are threads. Contexts only share data with other contexts if the contexts were created in the same thread.
Warning: All data of a context becomes inaccessible to the graphics API if the context is destructed.
There is one more interesting thing to note: Contexts of different threads can still use the same window.
void SomeThread(Atlas::Context* context) {
context->Bind();
...
context->Unbind();
}
void App::LoadContent() {
...
Atlas::Context otherThreadContext;
otherThreadContext.AttachTo(&window);
context.Bind();
...
// Start thread somehow
...
}
As you can see we have to bind the default context again. That's because attaching a context to a window will result in the context being bound in the current thread.
Note: Not all engine objects will be shared across multiple context. Here is a list of all the classes which don't support it:
- Meshes (but MeshData is supported)
- RenderTargets
Rendering across multiple threads is not recommended. Every time the main thread finishes the Render() method, all rendering commands will be executed. This includes all commands issued by other threads.
As you can see it is fairly easy to use multithreading. Don't hesitate to use that feature, it might make your application less CPU bound in the rendering thread.