123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SpuGatheringCollisionDispatcher.h"
- #include "SpuCollisionTaskProcess.h"
- #include "bullet/BulletCollision//BroadphaseCollision/btOverlappingPairCache.h"
- #include "bullet/BulletCollision//CollisionDispatch/btEmptyCollisionAlgorithm.h"
- #include "SpuContactManifoldCollisionAlgorithm.h"
- #include "bullet/BulletCollision//CollisionDispatch/btCollisionObject.h"
- #include "bullet/BulletCollision//CollisionShapes/btCollisionShape.h"
- #include "bullet/LinearMath/btQuickprof.h"
- #include "bullet/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
- #include "bullet/BulletCollision//CollisionDispatch/btCollisionObjectWrapper.h"
- SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration)
- :btCollisionDispatcher(collisionConfiguration),
- m_spuCollisionTaskProcess(0),
- m_threadInterface(threadInterface),
- m_maxNumOutstandingTasks(maxNumOutstandingTasks)
- {
-
- }
- bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
- {
- bool supported0 = (
- (proxyType0 == BOX_SHAPE_PROXYTYPE) ||
- (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
- (proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
- (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
- (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
- // (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
- (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
- (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
- (proxyType0 == STATIC_PLANE_PROXYTYPE)||
- (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
- );
- bool supported1 = (
- (proxyType1 == BOX_SHAPE_PROXYTYPE) ||
- (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
- (proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
- (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
- (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
- // (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
- (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
- (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
- (proxyType1 == STATIC_PLANE_PROXYTYPE) ||
- (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
- );
-
- return supported0 && supported1;
- }
- SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
- {
- if (m_spuCollisionTaskProcess)
- delete m_spuCollisionTaskProcess;
-
- }
- #include "stdio.h"
- ///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
- ///this is useful for the collision dispatcher.
- class btSpuCollisionPairCallback : public btOverlapCallback
- {
- const btDispatcherInfo& m_dispatchInfo;
- SpuGatheringCollisionDispatcher* m_dispatcher;
- public:
- btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher)
- :m_dispatchInfo(dispatchInfo),
- m_dispatcher(dispatcher)
- {
- }
- virtual bool processOverlap(btBroadphasePair& collisionPair)
- {
- //PPU version
- //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
- //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
- btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
- //by default, Bullet will use this near callback
- {
- ///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
- if (!collisionPair.m_internalTmpValue)
- {
- collisionPair.m_internalTmpValue = 1;
- }
- if (!collisionPair.m_algorithm)
- {
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
- btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher1 = m_dispatcher;
- ci.m_manifold = 0;
- if (m_dispatcher->needsCollision(colObj0,colObj1))
- {
- int proxyType0 = colObj0->getCollisionShape()->getShapeType();
- int proxyType1 = colObj1->getCollisionShape()->getShapeType();
- bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1)
- && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0)
- && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0);
- if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
- {
- btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
- if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
- {
- //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
- supportsSpuDispatch = false;
- }
- }
- if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
- {
- btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
- if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
- {
- //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
- supportsSpuDispatch = false;
- }
- }
- if (supportsSpuDispatch)
- {
- int so = sizeof(SpuContactManifoldCollisionAlgorithm);
- #ifdef ALLOCATE_SEPARATELY
- void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
- #else
- void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
- #endif
- collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
- collisionPair.m_internalTmpValue = 2;
- } else
- {
- btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
- collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1);
- collisionPair.m_internalTmpValue = 3;
- }
- }
- }
- }
- return false;
- }
- };
- void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
- {
- if (dispatchInfo.m_enableSPU)
- {
- m_maxNumOutstandingTasks = m_threadInterface->getNumTasks();
- {
- BT_PROFILE("processAllOverlappingPairs");
- if (!m_spuCollisionTaskProcess)
- m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
-
- m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks);
- // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks);
- m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa);
-
-
- ///modified version of btCollisionDispatcher::dispatchAllCollisionPairs:
- {
- btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
- pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
- }
- }
- //send one big batch
- int numTotalPairs = pairCache->getNumOverlappingPairs();
- if (numTotalPairs)
- {
- btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
- int i;
- {
- int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
- if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS))
- {
- pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1;
- }
-
- BT_PROFILE("addWorkToTask");
- for (i=0;i<numTotalPairs;)
- {
- //Performance Hint: tweak this number during benchmarking
-
- int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
- m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
- i = endIndex;
- }
- }
- {
- BT_PROFILE("PPU fallback");
- //handle PPU fallback pairs
- for (i=0;i<numTotalPairs;i++)
- {
- btBroadphasePair& collisionPair = pairPtr[i];
- if (collisionPair.m_internalTmpValue == 3)
- {
- if (collisionPair.m_algorithm)
- {
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
-
- if (dispatcher->needsCollision(colObj0,colObj1))
- {
- //discrete collision detection query
- btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
- btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
- btManifoldResult contactPointResult(&ob0,&ob1);
-
- if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
- {
-
- collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult);
- } else
- {
- //continuous collision detection query, time of impact (toi)
- btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
- if (dispatchInfo.m_timeOfImpact > toi)
- dispatchInfo.m_timeOfImpact = toi;
-
- }
- }
- }
- }
- }
- }
- }
- {
- BT_PROFILE("flush2");
- //make sure all SPU work is done
- m_spuCollisionTaskProcess->flush2();
- }
- } else
- {
- ///PPU fallback
- ///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU
- btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher);
- }
- }
|