Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp')
-rw-r--r--extern/bullet2/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp251
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);
+ }
+}