Running surface tools from thread

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By alektron

Hey
I’m working on an algorithm for terrain generation in C++ which needs quite a bit of computation power. Luckily it can be parallelized rather easily.
By separating the terrain in multiple chunks, I can calculate each chunk in a separate thread while every thread has its own SurfaceTool object and return its own mesh so I’m not running in any trouble there.

I call all the SurfaceTool functions I need (e.g. add vertex, add index etc.) from thread, then join the thread, then get the mesh by calling commit() and then add it to a MeshInstance. So far so good. I managed to decrease computation time by a factor which is great. But now the actual creation of the mesh (calling commit()) for each SurfaceTool takes more time than my actual computation.
So I thought I might call commit() from inside the thread as well (I already guessed that there might be problems with multithreading so I didn’t even try it at first).
And, you guessed it, it crashes.

EDIT: I just tried it again and noticed it doesn’t even crash, it just never finishes

Now before digging any deeper and wasting hours I wanted to ask if anyone already tried creating meshes with SurfaceTool from thread and/or can tell me if it is actually possible. Or is there some internal code being called that tries to access the main thread?
I was already looking into the source code of the SurfaceTool and the commit function is actually rather short and seems to me like it should actually work in a thread but I’m not entirely sure

:bust_in_silhouette: Reply From: alektron

“Solved” the problem.
I created a debug build of Godot to see what’s wrong and while I can’t exactly tell what the problem is (it goes pretty far down and ends on a wait call that seems to never continue, presumably a deadlock), I did find a way to avoid it.

When calling commit() a new mesh instance is created. The call to instance() is where the trouble begins. Luckily it does NOT create a new mesh when u pass an existing mesh to the commit function.
It is actually used to build upon an existing mesh but I’m now passing in an empty mesh that I created in the main thread. So it never calls instance() and everything else works fine.

TL;DR:
Pass an empty Ref<ArrayMesh> when calling commit()