- Edited
According to godot docs (https://docs.godotengine.org/en/stable/tutorials/performance/threads/thread_safe_apis.html), instancing scenes on a thread other than the main one is possible:
However, creating scene chunks (nodes in tree arrangement) outside the active tree is fine. This way, parts of a scene can be built or instantiated in a thread, then added in the main thread:
var enemy_scene = load("res://enemy_scene.scn")
var enemy = enemy_scene.instance()
enemy.add_child(weapon) # Set a weapon.
world.call_deferred("add_child", enemy)
The closest thing I got working:
if(m_busy) {
Chunk* chunk = nullptr;
m_prefabManagerMutex->lock();
// -- instancing a scene in the main thread, super dirty way
m_prefabManager->call_deferred("RequestPrefab", PREFAB_ID_CHUNK);
while(chunk == nullptr) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(1ms);
chunk = cast_to<Chunk>(m_prefabManager->requestedPrefab);
}
m_prefabManager->requestedPrefab = nullptr;
// --
m_prefabManagerMutex->unlock();
chunk->coordinates = m_chunkToRenderCoordinates;
m_bakedChunksMutex->lock();
m_bakedChunks->push(chunk);
m_bakedChunksMutex->unlock();
m_freeThreadsMutex->lock();
m_freeThreads->push(this);
m_freeThreadsMutex->unlock();
m_busy = false;
}
using namespace std::chrono_literals;
std::this_thread::sleep_for(sleepTime * 1ms);
}
This way everything works great, no problems occur whatsoever.
But, when I change the code so that the instancing is done on a thread, after some time the game freezes (not instantly).
if(m_busy) { // spinlock
m_prefabManagerMutex->lock();
// -- instancing a scene in the worker thread
Chunk* chunk = cast_to<Chunk>(chunkScene->instance());
// --
m_prefabManagerMutex->unlock();
chunk->coordinates = m_chunkToRenderCoordinates;
m_bakedChunksMutex->lock();
m_bakedChunks->push(chunk);
m_bakedChunksMutex->unlock();
m_freeThreadsMutex->lock();
m_freeThreads->push(this);
m_freeThreadsMutex->unlock();
m_busy = false;
}
using namespace std::chrono_literals;
std::this_thread::sleep_for(sleepTime * 1ms);
}
I've seen that others also had problems instancing scenes on a worker thread.
Just to be clear: I'm certain that I'm adding my chunks to the active scene tree in the main thread (And instancing in the first code example, too). My worker thread(s) just take(s) care of setting chunks up.
Has anyone managed to get it working with GDNative?
If needed, I can post entire source code on a pasting site.
Edit:
If I remove every node that has anything to do with rendering from the scene I'm instancing it seems to work just fine.
Plus the error I'm getting while the game hangs:
I've already set rendering to multithreaded, doesn't help.