-
Notifications
You must be signed in to change notification settings - Fork 63
Multiple Contexts
John Chapman edited this page Aug 29, 2018
·
3 revisions
The core of Im3d is the context. All Im3d::
function calls operate on the currently bound context. In most cases it isn't required for an application to instantiate or bind a context; using the default context and the layers API is sufficient. However there are some use cases where multiple contexts are necessary.
Im3d provides no thread safety mechanisms per se. To safely make Im3d calls from multiple threads, each thread must have its own context. In order for this to work:
-
IM3D_THREAD_LOCAL_CONTEXT_PTR
must be defined (via the build system or modify im3d_config.h). This forces the internal context ptr declaration to bethread_local
. - The application is responsible for managing the
Context
instances and setting the context ptr on each thread viaSetContext()
.
The runtime order of operations for a per-thread context is the same as in a single threaded application, however there are some additional considerations to be made at each step:
- Fill the
AppData
struct. The simplest way to do this is to copy data from the main thread context. - Call
NewFrame()
(after setting the thread's context ptr). Applications may prefer to callreset()
directly on the context instance from the main thread - this is equivalent toNewFrame()
. - Draw the vertex data. There are several options here, but in general the application will synchronize threads towards the end of a frame and then use the
MergeContexts()
function to merge per-thread contexts into the main context and subsequently callDraw()
. Merging contexts preserves layer ordering and enables sorting between contexts.
A common pattern to avoid over-synchronizing is to combine the merge and reset operations:
synchronize();
auto& mainCtx = Im3d::GetContext();
for (auto& perThreadCtx : perThreadCtxList) {
Im3d::MergeContexts(mainCtx, perThreadCtx); // merge perThreadCtx -> mainCtx
perThreadCtx.getAppData() = mainCtx.getAppData();
perThreadCtx.reset();
}
unsynchronize();
Im3d::Draw(); // draw the merged context