Index
- Part 1: Exploring Multi-Threading in C++
- Part 2: Exploring Multi-Threading in C++ Cont.
- Part 3: Exploring Multi-Threading in C++: Loading Textures
- Part 4: Exploring Multi-Threading in C++: Parallelizing Ray Tracing
Problem Overview
Let’s say we have a game engine that uses OpenGL and we need to load textures asynchronously so that we don’t block the main thread, and we can load the editor or game much faster.
Now as previously demonstrated, I could launch a new set of threads and have them load up the textures ( I’m using stb_image for that ) and generate textures with glGenTextures. The main issue here is that OpenGL context is only availabe in the main thread so if we want to take advantage of multi-threading texture loading we need to split the loading and generating for textures.
Loading is going to be done in worker threads, and generating textures will be done in the main thread. The following diagram shows a simplified workflow of what we’ll achieve.
In our main thread we have a method that will check our processing textures queue for a job. If it finds one, Generates the OpengGL texture and assigns it back to the material.
void AssetManager::Update()
{
if (!m_processingTexturesQueue.Empty())
{
TextureLoadJob assetJob;
if (m_processingTexturesQueue.TryPop(assetJob))
{
// Generate OpenGL texture
Texture outputTexture = GenerateTexture(assetJob.loadedData, assetJob.textureType);
// Update Material
assetJob.materialOwner->AddTexture(outputTexture);
}
}
}
The loader thread will continuously run and check the loading textures queue for jobs. In this case, I load the texture from a file path and assigning the result into the loaded data.
void AssetManager::LoaderThread()
{
while (m_loadingThreadActive)
{
if (!m_loadingTexturesQueue.Empty())
{
TextureLoadJob assetJob;
if (m_loadingTexturesQueue.TryPop(assetJob))
{
// Load texture data into asset job
assetJob.loadedData = LoadTextureData(assetJob.texturePath);
// push job into processing queue
m_processingTexturesQueue.Push(assetJob);
}
}
// ....
}
}
This architecture allows me to load textures while the game is running without blocking the main thread. Its a bit pointless to compare times here since I’m using my own sandbox instead of a sample program to test only this matter. See Part 1 and [Part 2](({{ ‘2019/10/exploring-multi-threading-in-c-part-2/’) for more info and code you can follow along.
Full source code can be found on GitHub ( commit )
In the next part, we’ll parallelize a toy Ray Tracer. This a different problem on its own where we need to use the resulting values of multiple threads or jobs to build a final image.