* Reorder unlock and notify_all calls to avoid notifying when not all worker
threads are waiting.
* Make sure main thread does not attempt to exclusively lock mSimulationMutex
while not all workers are done with previous frame.
* Replace mNewFrame flag by counter to avoid modification from multiple
threads.
Maybe fix#6071Closes#6071
See merge request OpenMW/openmw!1010
(cherry picked from commit 64750820957773a00d449d29551bb15fbf5fe08b)
1650dabe Assign the return value of weak_ptr::lock() to a variable, so that the
In this case, the actor mPreviousPosition is not updated, so the actor
position is interpolated between an old (stucked) position and the new
(unstucked) position. The new position is most likely "stucked", so the
unstuck code strikes again, making the actor "vibrates".
That's exactly what the sync code path does, and it doesn't exhibit this
behavior.
What happened is that the last handle to an Actor shared_ptr was a
promoted weak_ptr. When the shared_ptr goes out of scope, the Actor dtor
is invoked. That involves removing the Actor collision object after
exclusively locking mCollisionWorldMutex. In this case, the lock was
already held in the outter scope of the promoted weak_ptr.
Reduce the scope of the mCollisionWorldMutex to never encompass the
lifetime of a promoted weak_ptr.
One of the issue since the introduction of async physics is the quirky
handling of scripted moves. Previous attempt to account for them was
based on detecting changes in actor position while the physics thread is
running. To this end, semantics of Actor::updatePosition() (which is
responsible for set the absolute position of an actor in the world) was
toned down to merely store the desired position, with the physics system
actually responsible for moving the actor. For the cases were complete
override of the physics simulation was needed, I introduced
Actor::resetPosition(), which actually have same semantics as
original updatePosition(). This in turn introduced a loads of new bugs
when the weakened semantics broke key assumptions inside the engine
(spawning, summoning, teleport, etc).
Instead of tracking them down, count on the newly introduced support for
object relative movements in the engine (World::moveObjectBy) to
register relative movements and restore original handling of absolute positionning.
Changes are relatively small:
- move resetPosition() content into updatePosition()
- call updatePosition() everywhere it was called before
- remove all added calls to the now non-existing resetPosition()
tldr; ditch last month worth of bug introduction and eradication and redo
it properly
This gives finer control over reseting positions (switch off tcl is no
longer glitchy) and solve most of the erroneous usage of stale World::Ptr
indicated by:
"Error in frame: moveTo: object is not in this cell"
its current position.
Use it in relevant MWScripts opcode (move and moveworld).
Remove the fragile detection of scripted translation from PhysicsTaskScheduler.
No user visible change, just a more robust mechanism.
position being used under heavy load, I introduced a regression that
prevented the position to be updated in case of teleport.
Move the logic in its own function and decide in PhysicsSystem whether a
reset is needed.
be sure the simulation is over. Otherwise, if the simulation is too slow
the position is wrong, and the actors would jump back and forth between
old and new position instead of actually moving.
Before this change, if an actor position was changed while the physics
simulation was running, the simulation result would be discarded. It is
fine in case of one off event such as teleport, but in the case of
scripts making use of this functionality to make lifts or conveyor (such
as Sotha Sil Expanded mod) it broke actor movement.
To alleviate this issue, at the end of the simulation, the position of the Actor
in the world is compared to the position it had at the beginning of the
simulation. A difference indicate a force move occured. In this case,
the Actor mPosition and mPreviousPosition are translated by the difference of position.
Since the Actor position will be really set while the next simulation runs, we
save it in the mNextPosition field.
Before movement calculation, the main thread prepare a
vector of ActorFrameData, which contains all data necessary to perform
the simulation, and feed it to the solver. At the same time it fetches
the result from the previous background simulation, which in turn is
used by the game mechanics.
Other functions of the physics system (weapon hit for instance)
interrupt the background simulation, with some exceptions described
below.
The number of threads is controlled by the numeric setting
[Physics]
async num threads
In case 'async num threads' > 1 and Bullet doesn't support multiple threads,
1 async thread will be used. 0 means synchronous solver.
Additional settings (will be silently switched off if async num threads = 0)
[Physics]
defer aabb update
Update AABBs of actors and objects in the background thread(s). It is not an especially
costly operation, but it needs exclusive access to the collision world, which blocks
other operations. Since AABB needs to be updated for collision detection, one can queue
them to defer update before start of the movement solver. Extensive tests on as much
as one installation (mine) show no drawback having that switched on.
[Physics]
lineofsight keep inactive cache
Control for how long (how many frames) the line of sight (LOS) request will be kept updated.
When a request for LOS is made for the first time, the background threads are stopped to
service it. From now on, the LOS will be refreshed preemptively as part of the background
routine until it is not required for lineofsight keep inactive cache frames. This mean
that subsequent request will not interrupt the background computation.