Reduce waiting duration on locks when updating navmesh object in the main thread (#6193)
Fixes #6193 (closed).
Previously all operations were sequential. An object could be removed only before or after
RecastMesh creation is done for a given tile. A constant rate of updates (usually objects rotating by scripts) causes contention over the lock that keeps mentioned operations sequential. When
RecastMesh creation takes too much time this causes stuttering because the main thread waits on the lock.
A solution is to allow order of addition, updates and object removals to be independent from
RecastMesh creation. For this background thread needs to copy all objects under the lock and process them outside the critical section. The problem here is that
btCollisionShape can be removed while
RecastMesh creation is happening. So this MR extends
btCollisionShape lifetime via keeping
Water is still processed under the lock but with less scope because it will take the same amount of time to copy it. Potentially
Heightfield can be processed outside the lock but usually there is only 1 and the performance benefit might not be worth the cost of code complexity. Copying objects still takes time so the main thread may wait on the lock plus the main thread needs to find all changed tiles. But now it takes much less time in total. Before it was ~30ms at max, now it's ~400us at max.
There is still room for improvement that requires much more changes. All additions, updates and removals could be asynchronous, scheduled via a queue from the main thread. But this may increase total load on the CPU and the latency in exchange for much less probability of stuttering. But let’s find the content that causes issues with this MR first.
Comparison for the
Frame duration and
script_time_taken. Just staying in the
Karthwasten, Docks location from Skyrim Home Of The Nords mod:
script_time_taken are present even with disabled navigator.
Also it improves FPS for
Pelagiad location with Pelagiad - the cozy imperial town mod.
This MR can't be easily backported to the openmw-47 brach because there are conflicting changes in the master. So I'll prepare another MR for it.