diff options
Diffstat (limited to 'extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp')
-rw-r--r-- | extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp new file mode 100644 index 00000000000..ee0832f12e2 --- /dev/null +++ b/extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp @@ -0,0 +1,251 @@ +/* +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 "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btQuickprof.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(); + if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) + && (colObj0->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) + && (colObj1->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) + ) + { + 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 + { + collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1); + 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(); + + 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)) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,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); + } +} |