At the beginning of my game, I want to build a world. This process is slow enough to warrant a separate thread. I successfully implemented it with threading from direct.stdpy (yay!) but it is limited in capability and doesn’t fully exploit the taskMgr or other native capabilities. It does use a Task to check if the thread is finished or not, but that’s about it.
Question 1 - Should I call it good and be happy with the threading? Or should I look for a more panda-native solution?
This matters because I started wanting to monitor the thread progress by updating the scene as it progresses. But, because of multiple frequent reparent_to operations, it has major lags.
Question 2 - Are there good tricks for asynchronously reparenting, or otherwise limiting the lags, during dynamic world creation or other reparent-heavy operations?
I found TaskThreaded and it claims to be good for “CPU-intensive processing” – I thought I was on to something, but I can’t even figure out how to use it. When I subclass from it and try to add it to the taskMgr, it throws this error:
Exception: add: Tried to add a task that was not a Task or a func
When I try to run it directly, it just blocks the rest of the loop.
Question 3 - Is TaskThreaded a good solution for this particular application? If so, is there a good example I can look at to see how to properly implement it? If not, when is it a good tool to use?
You can use threaded task chains, which allow you to run tasks on other threads. See this page:
However, note that using threaded tasks doesn’t magically solve any problems; it’s really just a slightly different way to schedule your work compared to a thread.
Does the lag occur in the reparentTo call itself, or does it occur the first time that the objects are rendered? If the latter, you can probably help by calling prepareScene and premungeScene before parenting.
I did try the prepareScene and premungeScene, neither seemed to make a difference. But I tried something else: instead of reparenting to the rendering scene graph, I reparented to another node that I attached to render only once all of the geometries were built and added. That took a nearly identical amount of time and still caused dramatic framerate stutters (120 -> 8) even without being attached to the render node. So I think it’s more related to how I’m running the thread instead of the reparent operation? Unless the reparent is blocking even when it’s not attached to the main render node?
I didn’t try the threaded task chains yet, I’ll look at it next chance I get.
I don’t think that threaded task chains will solve the stutter issue. I find it a little strange that reparentTo to an inactive render graph would cause any stutter at all, especially if you’re doing it in a thread. I wonder if Panda is grabbing some sort of a global lock during that operation that causes a wait in the render thread.
Could you try replacing your np.reparentTo call with
np.node().resetPrevTransform(), and check whether that is also stuttering, or if it’s really the reparentTo call specifically?
I replaced that call, it still stutters.
So I removed both calls, just running the thread and then ignoring the result–still stutters. I tried profiling it a bit, I think I was incorrect to blame reparent. It’s looking likely that I’m doing something bad somewhere else in the code, I’ll dig around a bit.