I'm making my OpenGL application multithreaded, because I want to load resources (models, textures, shaders and fonts) asynchronously, without blocking the application (the main thread).
Resource management works, but my texture is not passed to my compute shader.
I don't know why. If I load my texture on the main thread, it works, but not in the other thread.
This works:
Image * img = new Image("noiseTex1");
noiseTex[0] = Texture::CreateTexture(img);
delete img;
This does not work:
ResourceManager::RequestResource(new QueueElement(std::string("noiseTex1"), &noiseTex[0]));
The method RequestResource adds the requested resource to a std::queue, protected with mutexes, which will be iterated by the other thread which loads resources.
So, essentially this method does the working code written above, after checking if it has been already loaded or not.
I can confirm the texture is loaded. I can use it in fragment shaders.
Why the second code does not work? Am I missing something about multithreaded OpenGL? Should I revert my graphic driver? Or my code is broken?
Thanks in advance!
EDIT: I have two mutexes, one for the main thread (RequestResource method), and another into the detached thread (which iterate through the queue to load resources).
If I use the same mutex for all the two threads, I can use my texture in my compute shader, but my program will not be truly multithreaded anymore.
Why this? This is how I protect my queues:
std::mutex mutexMain, mutexAsync;
Main thread:
mutexMain.lock();
<Add requested resource>
mutexMain.unlock();
The site suggests using multiple contexts, which I agree with.
If you were to use a single GL context, each texture creation (and mipmap creation as well) would cause things to halt for a split second. It would be noticeable to the user.
Ever seen that nasty stuttering when things are loading in games? Let's try to avoid that :D
The problem is this:
I can use the texture in my fragment shader, but not in compute shader. Why? Maybe it's a driver problem? But I don't thing so, otherwise someone should have already noticed this!
Anyone doing CPU threading with OpenGL should now switch to Vulkan, which has native support for threading, and also supports real modern GPU computing, (beyond OpenGL compute shaders). https://www.khronos.org/vulkan/
Does a pretty decent job of explaining what you have to do and why. It's not quite as terse as the documentation, but it's good.
It doesn't cover everything, but it's a good start.
Vulkan is a much more verbose API, and far more powerful, but with that comes some more complexity.