From 45fd4acf6eb69389f9a600903a7b7bf8e813815f Mon Sep 17 00:00:00 2001 From: Lunkhound Date: Mon, 5 Mar 2018 20:05:38 -0800 Subject: [PATCH] dynamicsWorldMt: make island mgr aware of whether a parallel solver is present and make handoff from parallel solver to solver-pool more explicit --- .../CommonRigidBodyMTBase.cpp | 28 ++++- .../Dynamics/btDiscreteDynamicsWorldMt.cpp | 88 +++----------- .../Dynamics/btDiscreteDynamicsWorldMt.h | 4 +- .../Dynamics/btSimulationIslandManagerMt.cpp | 110 ++++++++++-------- .../Dynamics/btSimulationIslandManagerMt.h | 36 +++--- 5 files changed, 116 insertions(+), 150 deletions(-) diff --git a/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp index b11cd7691..f9e0c209a 100644 --- a/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp +++ b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp @@ -200,11 +200,11 @@ public: /// /// myParallelIslandDispatch -- wrap default parallel dispatch for profiling and to get the number of simulation islands // -void myParallelIslandDispatch( btAlignedObjectArray* islandsPtr, btSimulationIslandManagerMt::IslandCallback* callback ) +void myParallelIslandDispatch( btAlignedObjectArray* islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams) { ProfileHelper prof( Profiler::kRecordDispatchIslands ); gNumIslands = islandsPtr->size(); - btSimulationIslandManagerMt::parallelIslandDispatch( islandsPtr, callback ); + btSimulationIslandManagerMt::parallelIslandDispatch( islandsPtr, solverParams ); } @@ -239,9 +239,10 @@ public: MyDiscreteDynamicsWorld( btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, + btSequentialImpulseConstraintSolverMt* constraintSolverMt, btCollisionConfiguration* collisionConfiguration ) : - btDiscreteDynamicsWorldMt( dispatcher, pairCache, constraintSolver, collisionConfiguration ) + btDiscreteDynamicsWorldMt( dispatcher, pairCache, constraintSolver, constraintSolverMt, collisionConfiguration ) { btSimulationIslandManagerMt* islandMgr = static_cast( m_islandManager ); islandMgr->setIslandDispatchFunction( myParallelIslandDispatch ); @@ -347,11 +348,12 @@ static btTaskSchedulerManager gTaskSchedulerMgr; #if BT_THREADSAFE static bool gMultithreadedWorld = true; static bool gDisplayProfileInfo = true; +static SolverType gSolverType = SOLVER_TYPE_SEQUENTIAL_IMPULSE_MT; #else static bool gMultithreadedWorld = false; static bool gDisplayProfileInfo = false; +static SolverType gSolverType = SOLVER_TYPE_SEQUENTIAL_IMPULSE; #endif -static SolverType gSolverType = SOLVER_TYPE_SEQUENTIAL_IMPULSE_MT; static int gSolverMode = SOLVER_SIMD | SOLVER_USE_WARMSTARTING | // SOLVER_RANDMIZE_ORDER | @@ -547,16 +549,28 @@ void CommonRigidBodyMTBase::createEmptyDynamicsWorld() btConstraintSolverPoolMt* solverPool; { + SolverType poolSolverType = m_solverType; + if (poolSolverType == SOLVER_TYPE_SEQUENTIAL_IMPULSE_MT) + { + // pool solvers shouldn't be parallel solvers, we don't allow that kind of + // nested parallelism because of performance issues + poolSolverType = SOLVER_TYPE_SEQUENTIAL_IMPULSE; + } btConstraintSolver* solvers[ BT_MAX_THREAD_COUNT ]; int maxThreadCount = BT_MAX_THREAD_COUNT; for ( int i = 0; i < maxThreadCount; ++i ) { - solvers[ i ] = createSolverByType( m_solverType ); + solvers[ i ] = createSolverByType( poolSolverType ); } solverPool = new btConstraintSolverPoolMt( solvers, maxThreadCount ); m_solver = solverPool; } - btDiscreteDynamicsWorld* world = new MyDiscreteDynamicsWorld( m_dispatcher, m_broadphase, solverPool, m_collisionConfiguration ); + btSequentialImpulseConstraintSolverMt* solverMt = NULL; + if ( m_solverType == SOLVER_TYPE_SEQUENTIAL_IMPULSE_MT ) + { + solverMt = new MySequentialImpulseConstraintSolverMt(); + } + btDiscreteDynamicsWorld* world = new MyDiscreteDynamicsWorld( m_dispatcher, m_broadphase, solverPool, solverMt, m_collisionConfiguration ); m_dynamicsWorld = world; m_multithreadedWorld = true; btAssert( btGetTaskScheduler() != NULL ); @@ -579,6 +593,8 @@ void CommonRigidBodyMTBase::createEmptyDynamicsWorld() SolverType solverType = m_solverType; if ( solverType == SOLVER_TYPE_SEQUENTIAL_IMPULSE_MT ) { + // using the parallel solver with the single-threaded world works, but is + // disabled here to avoid confusion solverType = SOLVER_TYPE_SEQUENTIAL_IMPULSE; } m_solver = createSolverByType( solverType ); diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp index 330bccb87..d705bf238 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp @@ -50,63 +50,6 @@ subject to the following restrictions: #include "LinearMath/btSerializer.h" -struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::IslandCallback -{ - btContactSolverInfo* m_solverInfo; - btConstraintSolver* m_solver; - btIDebugDraw* m_debugDrawer; - btDispatcher* m_dispatcher; - - InplaceSolverIslandCallbackMt( - btConstraintSolver* solver, - btStackAlloc* stackAlloc, - btDispatcher* dispatcher) - :m_solverInfo(NULL), - m_solver(solver), - m_debugDrawer(NULL), - m_dispatcher(dispatcher) - { - - } - - InplaceSolverIslandCallbackMt& operator=(InplaceSolverIslandCallbackMt& other) - { - btAssert(0); - (void)other; - return *this; - } - - SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btIDebugDraw* debugDrawer) - { - btAssert(solverInfo); - m_solverInfo = solverInfo; - m_debugDrawer = debugDrawer; - } - - - virtual void processIsland( btCollisionObject** bodies, - int numBodies, - btPersistentManifold** manifolds, - int numManifolds, - btTypedConstraint** constraints, - int numConstraints, - int islandId - ) - { - m_solver->solveGroup( bodies, - numBodies, - manifolds, - numManifolds, - constraints, - numConstraints, - *m_solverInfo, - m_debugDrawer, - m_dispatcher - ); - } - -}; - /// /// btConstraintSolverPoolMt @@ -209,7 +152,12 @@ void btConstraintSolverPoolMt::reset() /// btDiscreteDynamicsWorldMt /// -btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, btCollisionConfiguration* collisionConfiguration) +btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, + btBroadphaseInterface* pairCache, + btConstraintSolverPoolMt* constraintSolver, + btConstraintSolver* constraintSolverMt, + btCollisionConfiguration* collisionConfiguration +) : btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) { if (m_ownsIslandManager) @@ -217,31 +165,18 @@ btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, b m_islandManager->~btSimulationIslandManager(); btAlignedFree( m_islandManager); } - { - void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallbackMt),16); - m_solverIslandCallbackMt = new (mem) InplaceSolverIslandCallbackMt (m_constraintSolver, 0, dispatcher); - } { void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16); btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt(); im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize ); m_islandManager = im; } + m_constraintSolverMt = constraintSolverMt; } btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt() { - if (m_solverIslandCallbackMt) - { - m_solverIslandCallbackMt->~InplaceSolverIslandCallbackMt(); - btAlignedFree(m_solverIslandCallbackMt); - } - if (m_ownsConstraintSolver) - { - m_constraintSolver->~btConstraintSolver(); - btAlignedFree(m_constraintSolver); - } } @@ -249,12 +184,17 @@ void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo { BT_PROFILE("solveConstraints"); - m_solverIslandCallbackMt->setup(&solverInfo, getDebugDrawer()); m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island btSimulationIslandManagerMt* im = static_cast(m_islandManager); - im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, m_solverIslandCallbackMt ); + btSimulationIslandManagerMt::SolverParams solverParams; + solverParams.m_solverPool = m_constraintSolver; + solverParams.m_solverMt = m_constraintSolverMt; + solverParams.m_solverInfo = &solverInfo; + solverParams.m_debugDrawer = m_debugDrawer; + solverParams.m_dispatcher = getCollisionWorld()->getDispatcher(); + im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, solverParams ); m_constraintSolver->allSolved(solverInfo, m_debugDrawer); } diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h index a8cc22dd0..667fe5800 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h @@ -21,7 +21,6 @@ subject to the following restrictions: #include "btSimulationIslandManagerMt.h" #include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" -struct InplaceSolverIslandCallbackMt; /// /// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them. @@ -88,7 +87,7 @@ private: ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld { protected: - InplaceSolverIslandCallbackMt* m_solverIslandCallbackMt; + btConstraintSolver* m_constraintSolverMt; virtual void solveConstraints(btContactSolverInfo& solverInfo) BT_OVERRIDE; @@ -126,6 +125,7 @@ public: btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, // Note this should be a solver-pool for multi-threading + btConstraintSolver* constraintSolverMt, // single multi-threaded solver for large islands (or NULL) btCollisionConfiguration* collisionConfiguration ); virtual ~btDiscreteDynamicsWorldMt(); diff --git a/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp index 54ac39aaf..fc54f0ba6 100644 --- a/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp +++ b/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp @@ -276,7 +276,7 @@ btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld ) { - BT_PROFILE("islandUnionFindAndQuickSort"); + BT_PROFILE("buildIslands"); btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); @@ -545,53 +545,58 @@ void btSimulationIslandManagerMt::mergeIslands() } -void btSimulationIslandManagerMt::serialIslandDispatch( btAlignedObjectArray* islandsPtr, IslandCallback* callback ) +void btSimulationIslandManagerMt::solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams) +{ + btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[ 0 ] : NULL; + btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[ 0 ] : NULL; + solver->solveGroup( &island.bodyArray[ 0 ], + island.bodyArray.size(), + manifolds, + island.manifoldArray.size(), + constraintsPtr, + island.constraintArray.size(), + *solverParams.m_solverInfo, + solverParams.m_debugDrawer, + solverParams.m_dispatcher + ); +} + + +void btSimulationIslandManagerMt::serialIslandDispatch( btAlignedObjectArray* islandsPtr, const SolverParams& solverParams ) { BT_PROFILE( "serialIslandDispatch" ); // serial dispatch btAlignedObjectArray& islands = *islandsPtr; + btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool; for ( int i = 0; i < islands.size(); ++i ) { - Island* island = islands[ i ]; - btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL; - btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL; - callback->processIsland( &island->bodyArray[ 0 ], - island->bodyArray.size(), - manifolds, - island->manifoldArray.size(), - constraintsPtr, - island->constraintArray.size(), - island->id - ); + solveIsland(solver, *islands[ i ], solverParams); } } + struct UpdateIslandDispatcher : public btIParallelForBody { - btAlignedObjectArray* islandsPtr; - btSimulationIslandManagerMt::IslandCallback* callback; + btAlignedObjectArray& m_islandsPtr; + const btSimulationIslandManagerMt::SolverParams& m_solverParams; + + UpdateIslandDispatcher(btAlignedObjectArray& islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams) + : m_islandsPtr(islandsPtr), m_solverParams(solverParams) + {} void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE { + btConstraintSolver* solver = m_solverParams.m_solverPool; for ( int i = iBegin; i < iEnd; ++i ) { - btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ i ]; - btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL; - btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL; - callback->processIsland( &island->bodyArray[ 0 ], - island->bodyArray.size(), - manifolds, - island->manifoldArray.size(), - constraintsPtr, - island->constraintArray.size(), - island->id - ); + btSimulationIslandManagerMt::Island* island = m_islandsPtr[ i ]; + btSimulationIslandManagerMt::solveIsland( solver, *island, m_solverParams ); } } }; -void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray* islandsPtr, IslandCallback* callback ) +void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray* islandsPtr, const SolverParams& solverParams ) { BT_PROFILE( "parallelIslandDispatch" ); // @@ -617,24 +622,25 @@ void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArraysize()) + if (solverParams.m_solverMt) { - btSimulationIslandManagerMt::Island* island = (*islandsPtr)[ iBegin ]; - if (island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching) + while ( iBegin < islandsPtr->size() ) { - // OK to submit the rest of the array in parallel - break; + btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ iBegin ]; + if ( island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching ) + { + // OK to submit the rest of the array in parallel + break; + } + // serial dispatch to parallel solver for large islands (if any) + solveIsland(solverParams.m_solverMt, *island, solverParams); + ++iBegin; } - ++iBegin; } - // serial dispatch for large islands (if any) - dispatcher.forLoop(0, iBegin); - // parallel dispatch for rest + // parallel dispatch to sequential solvers for rest btParallelFor( iBegin, islandsPtr->size(), 1, dispatcher ); } @@ -643,15 +649,14 @@ void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray& constraints, - IslandCallback* callback + const SolverParams& solverParams ) { + BT_PROFILE("buildAndProcessIslands"); btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); buildIslands(dispatcher,collisionWorld); - BT_PROFILE("processIslands"); - if(!getSplitIslands()) { btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer(); @@ -683,14 +688,17 @@ void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatch } } btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL; - callback->processIsland(&collisionObjects[0], - collisionObjects.size(), - manifolds, - maxNumManifolds, - constraintsPtr, - constraints.size(), - -1 - ); + btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool; + solver->solveGroup(&collisionObjects[0], + collisionObjects.size(), + manifolds, + maxNumManifolds, + constraintsPtr, + constraints.size(), + *solverParams.m_solverInfo, + solverParams.m_debugDrawer, + solverParams.m_dispatcher + ); } else { @@ -710,6 +718,6 @@ void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatch mergeIslands(); } // dispatch islands to solver - m_islandDispatch( &m_activeIslands, callback ); + m_islandDispatch( &m_activeIslands, solverParams ); } } diff --git a/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h index 31a2053b4..563577a6f 100644 --- a/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h +++ b/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h @@ -19,7 +19,9 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" class btTypedConstraint; - +class btConstraintSolver; +struct btContactSolverInfo; +class btIDebugDraw; /// /// SimulationIslandManagerMt -- Multithread capable version of SimulationIslandManager @@ -45,22 +47,19 @@ public: void append( const Island& other ); // add bodies, manifolds, constraints to my own }; - struct IslandCallback + struct SolverParams { - virtual ~IslandCallback() {}; - - virtual void processIsland( btCollisionObject** bodies, - int numBodies, - btPersistentManifold** manifolds, - int numManifolds, - btTypedConstraint** constraints, - int numConstraints, - int islandId - ) = 0; + btConstraintSolver* m_solverPool; + btConstraintSolver* m_solverMt; + btContactSolverInfo* m_solverInfo; + btIDebugDraw* m_debugDrawer; + btDispatcher* m_dispatcher; }; - typedef void( *IslandDispatchFunc ) ( btAlignedObjectArray* islands, IslandCallback* callback ); - static void serialIslandDispatch( btAlignedObjectArray* islandsPtr, IslandCallback* callback ); - static void parallelIslandDispatch( btAlignedObjectArray* islandsPtr, IslandCallback* callback ); + static void solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams); + + typedef void( *IslandDispatchFunc ) ( btAlignedObjectArray* islands, const SolverParams& solverParams ); + static void serialIslandDispatch( btAlignedObjectArray* islandsPtr, const SolverParams& solverParams ); + static void parallelIslandDispatch( btAlignedObjectArray* islandsPtr, const SolverParams& solverParams ); protected: btAlignedObjectArray m_allocatedIslands; // owner of all Islands btAlignedObjectArray m_activeIslands; // islands actively in use @@ -83,7 +82,11 @@ public: btSimulationIslandManagerMt(); virtual ~btSimulationIslandManagerMt(); - virtual void buildAndProcessIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld, btAlignedObjectArray& constraints, IslandCallback* callback ); + virtual void buildAndProcessIslands( btDispatcher* dispatcher, + btCollisionWorld* collisionWorld, + btAlignedObjectArray& constraints, + const SolverParams& solverParams + ); virtual void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); @@ -106,7 +109,6 @@ public: } }; -extern int gLargeIslandManifoldCount; #endif //BT_SIMULATION_ISLAND_MANAGER_H