SpuGatheringCollisionDispatcher.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "SpuGatheringCollisionDispatcher.h"
00017 #include "SpuCollisionTaskProcess.h"
00018 
00019 
00020 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
00021 #include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
00022 #include "SpuContactManifoldCollisionAlgorithm.h"
00023 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00024 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
00025 #include "LinearMath/btQuickprof.h"
00026 #include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
00027 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
00028 
00029 
00030 
00031 
00032 SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class  btThreadSupportInterface*       threadInterface, unsigned int   maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration)
00033 :btCollisionDispatcher(collisionConfiguration),
00034 m_spuCollisionTaskProcess(0),
00035 m_threadInterface(threadInterface),
00036 m_maxNumOutstandingTasks(maxNumOutstandingTasks)
00037 {
00038         
00039 }
00040 
00041 
00042 bool    SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
00043 {
00044         bool supported0 = (
00045                 (proxyType0 == BOX_SHAPE_PROXYTYPE) ||
00046                 (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
00047                 (proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
00048                 (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
00049                 (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
00050 //              (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
00051                 (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
00052                 (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
00053                 (proxyType0 == STATIC_PLANE_PROXYTYPE)||
00054                 (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
00055                 );
00056 
00057         bool supported1 = (
00058                 (proxyType1 == BOX_SHAPE_PROXYTYPE) ||
00059                 (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
00060                 (proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
00061                 (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
00062                 (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
00063 //              (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
00064                 (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
00065                 (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
00066                 (proxyType1 == STATIC_PLANE_PROXYTYPE) ||
00067                 (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
00068                 );
00069 
00070         
00071         return supported0 && supported1;
00072 }
00073 
00074 
00075 
00076 SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
00077 {
00078         if (m_spuCollisionTaskProcess)
00079                 delete m_spuCollisionTaskProcess;
00080         
00081 }
00082 
00083 #include "stdio.h"
00084 
00085 
00086 
00089 class btSpuCollisionPairCallback : public btOverlapCallback
00090 {
00091         const btDispatcherInfo& m_dispatchInfo;
00092         SpuGatheringCollisionDispatcher*        m_dispatcher;
00093 
00094 public:
00095 
00096         btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher*       dispatcher)
00097         :m_dispatchInfo(dispatchInfo),
00098         m_dispatcher(dispatcher)
00099         {
00100         }
00101 
00102         virtual bool    processOverlap(btBroadphasePair& collisionPair)
00103         {
00104 
00105 
00106                 //PPU version
00107                 //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
00108 
00109                 //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
00110                 btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
00111 
00112                 //by default, Bullet will use this near callback
00113                 {
00115                         if (!collisionPair.m_internalTmpValue)
00116                         {
00117                                 collisionPair.m_internalTmpValue = 1;
00118                         }
00119                         if (!collisionPair.m_algorithm)
00120                         {
00121                                 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00122                                 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00123 
00124                                 btCollisionAlgorithmConstructionInfo ci;
00125                                 ci.m_dispatcher1 = m_dispatcher;
00126                                 ci.m_manifold = 0;
00127 
00128                                 if (m_dispatcher->needsCollision(colObj0,colObj1))
00129                                 {
00130                                         int     proxyType0 = colObj0->getCollisionShape()->getShapeType();
00131                                         int     proxyType1 = colObj1->getCollisionShape()->getShapeType();
00132                                         bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) 
00133                                                 && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0)
00134                                                 && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0);
00135 
00136                                         if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
00137                                         {
00138                                                 btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
00139                                                 if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
00140                                                 {
00141                                                         //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
00142                                                         supportsSpuDispatch = false;
00143                                                 }
00144                                         }
00145 
00146                                         if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
00147                                         {
00148                                                 btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
00149                                                 if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
00150                                                 {
00151                                                         //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
00152                                                         supportsSpuDispatch = false;
00153                                                 }
00154                                         }
00155 
00156                                         if (supportsSpuDispatch)
00157                                         {
00158 
00159                                                 int so = sizeof(SpuContactManifoldCollisionAlgorithm);
00160 #ifdef ALLOCATE_SEPARATELY
00161                                                 void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
00162 #else
00163                                                 void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
00164 #endif
00165                                                 collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
00166                                                 collisionPair.m_internalTmpValue =  2;
00167                                         } else
00168                                         {
00169                                                 btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
00170                                                 btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
00171 
00172                                                 collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1);
00173                                                 collisionPair.m_internalTmpValue = 3;
00174                                         }
00175                                 } 
00176                         }
00177                 }
00178                 return false;
00179         }
00180 };
00181 
00182 void    SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) 
00183 {
00184 
00185         if (dispatchInfo.m_enableSPU)
00186         {
00187                 m_maxNumOutstandingTasks = m_threadInterface->getNumTasks();
00188 
00189                 {
00190                         BT_PROFILE("processAllOverlappingPairs");
00191 
00192                         if (!m_spuCollisionTaskProcess)
00193                                 m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
00194                 
00195                         m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks);
00196         //              printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks);
00197 
00198                         m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa);
00199                         
00200                 
00202                         {
00203                                 btSpuCollisionPairCallback      collisionCallback(dispatchInfo,this);
00204 
00205                                 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00206                         }
00207                 }
00208 
00209                 //send one big batch
00210                 int numTotalPairs = pairCache->getNumOverlappingPairs();
00211                 if (numTotalPairs)
00212                 {
00213                         btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
00214                         int i;
00215                         {
00216                                 int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
00217                                 if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS))
00218                                 {
00219                                         pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1;
00220                                 }
00221         
00222                                 BT_PROFILE("addWorkToTask");
00223                                 for (i=0;i<numTotalPairs;)
00224                                 {
00225                                         //Performance Hint: tweak this number during benchmarking
00226                                         
00227                                         int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
00228                                         m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
00229                                         i = endIndex;
00230                                 }
00231                         }
00232                         {
00233                                 BT_PROFILE("PPU fallback");
00234                                 //handle PPU fallback pairs
00235                                 for (i=0;i<numTotalPairs;i++)
00236                                 {
00237                                         btBroadphasePair& collisionPair = pairPtr[i];
00238                                         if (collisionPair.m_internalTmpValue == 3)
00239                                         {
00240                                                 if (collisionPair.m_algorithm)
00241                                                 {
00242                                                         btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00243                                                         btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00244         
00245                                                         if (dispatcher->needsCollision(colObj0,colObj1))
00246                                                         {
00247                                                         //discrete collision detection query
00248                                                                 btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
00249                                                                 btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
00250 
00251                                                                 btManifoldResult contactPointResult(&ob0,&ob1);
00252                                                                 
00253                                                                 if (dispatchInfo.m_dispatchFunc ==              btDispatcherInfo::DISPATCH_DISCRETE)
00254                                                                 {
00255                                                                         
00256                                                                         collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult);
00257                                                                 } else
00258                                                                 {
00259                                                                         //continuous collision detection query, time of impact (toi)
00260                                                                         btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00261                                                                         if (dispatchInfo.m_timeOfImpact > toi)
00262                                                                                 dispatchInfo.m_timeOfImpact = toi;
00263         
00264                                                                 }
00265                                                         }
00266                                                 }
00267                                         }
00268                                 }
00269                         }
00270                 }
00271                 {
00272                         BT_PROFILE("flush2");
00273                         //make sure all SPU work is done
00274                         m_spuCollisionTaskProcess->flush2();
00275                 }
00276 
00277         } else
00278         {
00281                 btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher);
00282         }
00283 }