Skip to content

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.

Multithreaded Applications

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 be thread_local.
  • The application is responsible for managing the Context instances and setting the context ptr on each thread via SetContext().

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:

  1. Fill the AppData struct. The simplest way to do this is to copy data from the main thread context.
  2. Call NewFrame() (after setting the thread's context ptr). Applications may prefer to call reset() directly on the context instance from the main thread - this is equivalent to NewFrame().
  3. 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 call Draw(). 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

See examples/MultiContext.

Clone this wiki locally