MultiThreaded Demo:
- fixing various race conditions throughout (usage of static vars, etc)
- addition of a few lightweight mutexes (which are compiled out by default)
- slight code rearrangement in discreteDynamicsWorld to facilitate multithreading
- PoolAllocator::allocate() can now be called when pool is full without
crashing (null pointer returned)
- PoolAllocator allocate and freeMemory, are OPTIONALLY threadsafe
(default is un-threadsafe)
- CollisionDispatcher no longer checks if the pool allocator is full
before calling allocate(), instead it just calls allocate() and
checks if the return is null -- this avoids a race condition
- SequentialImpulseConstraintSolver OPTIONALLY uses different logic in
getOrInitSolverBody() to avoid a race condition with kinematic bodies
- addition of 2 classes which together allow simulation islands to be run
in parallel:
- btSimulationIslandManagerMt
- btDiscreteDynamicsWorldMt
- MultiThreadedDemo example in the example browser demonstrating use of
OpenMP, Microsoft PPL, and Intel TBB
- use multithreading for other demos
- benchmark demo: add parallel raycasting
This commit is contained in:
@@ -32,10 +32,12 @@ subject to the following restrictions:
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "../CommonInterfaces/ParallelFor.h"
|
||||
|
||||
class btDynamicsWorld;
|
||||
|
||||
#define NUMRAYS 500
|
||||
#define USE_PARALLEL_RAYCASTS 1
|
||||
|
||||
class btRigidBody;
|
||||
class btBroadphaseInterface;
|
||||
@@ -204,7 +206,39 @@ public:
|
||||
sign = -1.0;
|
||||
}
|
||||
|
||||
void cast (btCollisionWorld* cw)
|
||||
void castRays( btCollisionWorld* cw, int iBegin, int iEnd )
|
||||
{
|
||||
for ( int i = iBegin; i < iEnd; ++i )
|
||||
{
|
||||
btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
|
||||
|
||||
cw->rayTest (source[i], dest[i], cb);
|
||||
if (cb.hasHit ())
|
||||
{
|
||||
hit[i] = cb.m_hitPointWorld;
|
||||
normal[i] = cb.m_hitNormalWorld;
|
||||
normal[i].normalize ();
|
||||
} else {
|
||||
hit[i] = dest[i];
|
||||
normal[i] = btVector3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct CastRaysLoopBody
|
||||
{
|
||||
btRaycastBar2* mRaycasts;
|
||||
btCollisionWorld* mWorld;
|
||||
CastRaysLoopBody(btCollisionWorld* cw, btRaycastBar2* rb) : mWorld(cw), mRaycasts(rb) {}
|
||||
|
||||
void forLoop( int iBegin, int iEnd ) const
|
||||
{
|
||||
mRaycasts->castRays(mWorld, iBegin, iEnd);
|
||||
}
|
||||
};
|
||||
|
||||
void cast (btCollisionWorld* cw, bool multiThreading = false)
|
||||
{
|
||||
#ifdef USE_BT_CLOCK
|
||||
frame_timer.reset ();
|
||||
@@ -228,22 +262,19 @@ public:
|
||||
normal[i].normalize ();
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < NUMRAYS; i++)
|
||||
{
|
||||
btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
|
||||
|
||||
cw->rayTest (source[i], dest[i], cb);
|
||||
if (cb.hasHit ())
|
||||
{
|
||||
hit[i] = cb.m_hitPointWorld;
|
||||
normal[i] = cb.m_hitNormalWorld;
|
||||
normal[i].normalize ();
|
||||
} else {
|
||||
hit[i] = dest[i];
|
||||
normal[i] = btVector3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
#if USE_PARALLEL_RAYCASTS
|
||||
if ( multiThreading )
|
||||
{
|
||||
CastRaysLoopBody rayLooper(cw, this);
|
||||
int grainSize = 20; // number of raycasts per task
|
||||
parallelFor( 0, NUMRAYS, grainSize, rayLooper );
|
||||
}
|
||||
else
|
||||
#endif // USE_PARALLEL_RAYCASTS
|
||||
{
|
||||
// single threaded
|
||||
castRays(cw, 0, NUMRAYS);
|
||||
}
|
||||
#ifdef USE_BT_CLOCK
|
||||
ms += frame_timer.getTimeMilliseconds ();
|
||||
#endif //USE_BT_CLOCK
|
||||
@@ -354,42 +385,43 @@ void BenchmarkDemo::initPhysics()
|
||||
|
||||
setCameraDistance(btScalar(100.));
|
||||
|
||||
///collision configuration contains default setup for memory, collision setup
|
||||
btDefaultCollisionConstructionInfo cci;
|
||||
cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
|
||||
m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
|
||||
createEmptyDynamicsWorld();
|
||||
/////collision configuration contains default setup for memory, collision setup
|
||||
//btDefaultCollisionConstructionInfo cci;
|
||||
//cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
|
||||
//m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
|
||||
|
||||
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
|
||||
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||
|
||||
m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
|
||||
/////use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
|
||||
//m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||
//
|
||||
//m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
|
||||
|
||||
|
||||
|
||||
///the maximum size of the collision world. Make sure objects stay within these boundaries
|
||||
///Don't make the world AABB size too large, it will harm simulation quality and performance
|
||||
btVector3 worldAabbMin(-1000,-1000,-1000);
|
||||
btVector3 worldAabbMax(1000,1000,1000);
|
||||
|
||||
btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
|
||||
m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
|
||||
/////the maximum size of the collision world. Make sure objects stay within these boundaries
|
||||
/////Don't make the world AABB size too large, it will harm simulation quality and performance
|
||||
//btVector3 worldAabbMin(-1000,-1000,-1000);
|
||||
//btVector3 worldAabbMax(1000,1000,1000);
|
||||
//
|
||||
//btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
|
||||
//m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
|
||||
// m_broadphase = new btSimpleBroadphase();
|
||||
// m_broadphase = new btDbvtBroadphase();
|
||||
|
||||
|
||||
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
|
||||
btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
|
||||
//btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
|
||||
|
||||
|
||||
m_solver = sol;
|
||||
//m_solver = sol;
|
||||
|
||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
||||
m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
|
||||
//btDiscreteDynamicsWorld* dynamicsWorld;
|
||||
//m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
|
||||
|
||||
|
||||
///the following 3 lines increase the performance dramatically, with a little bit of loss of quality
|
||||
m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; //don't recalculate friction values each frame
|
||||
dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations
|
||||
m_dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations
|
||||
//m_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...);
|
||||
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||
|
||||
@@ -1242,7 +1274,7 @@ void BenchmarkDemo::initRays()
|
||||
|
||||
void BenchmarkDemo::castRays()
|
||||
{
|
||||
raycastBar.cast (m_dynamicsWorld);
|
||||
raycastBar.cast (m_dynamicsWorld, m_multithreadedWorld);
|
||||
}
|
||||
|
||||
void BenchmarkDemo::createTest7()
|
||||
|
||||
Reference in New Issue
Block a user