Bullet Collision Detection & Physics Library
SpuGatheringCollisionDispatcher.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
18 
19 
25 #include "LinearMath/btQuickprof.h"
28 
29 
30 
31 
32 SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration)
33 :btCollisionDispatcher(collisionConfiguration),
34 m_spuCollisionTaskProcess(0),
35 m_threadInterface(threadInterface),
36 m_maxNumOutstandingTasks(maxNumOutstandingTasks)
37 {
38 
39 }
40 
41 
43 {
44  bool supported0 = (
45  (proxyType0 == BOX_SHAPE_PROXYTYPE) ||
46  (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
47  (proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
48  (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
49  (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
50 // (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
51  (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
52  (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
53  (proxyType0 == STATIC_PLANE_PROXYTYPE)||
54  (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
55  );
56 
57  bool supported1 = (
58  (proxyType1 == BOX_SHAPE_PROXYTYPE) ||
59  (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
60  (proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
61  (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
62  (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
63 // (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
64  (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
65  (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
66  (proxyType1 == STATIC_PLANE_PROXYTYPE) ||
67  (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
68  );
69 
70 
71  return supported0 && supported1;
72 }
73 
74 
75 
77 {
80 
81 }
82 
83 #include "stdio.h"
84 
85 
86 
90 {
93 
94 public:
95 
97  :m_dispatchInfo(dispatchInfo),
98  m_dispatcher(dispatcher)
99  {
100  }
101 
102  virtual bool processOverlap(btBroadphasePair& collisionPair)
103  {
104 
105 
106  //PPU version
107  //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
108 
109  //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
111 
112  //by default, Bullet will use this near callback
113  {
115  if (!collisionPair.m_internalTmpValue)
116  {
117  collisionPair.m_internalTmpValue = 1;
118  }
119  if (!collisionPair.m_algorithm)
120  {
121  btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
122  btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
123 
126  ci.m_manifold = 0;
127 
128  if (m_dispatcher->needsCollision(colObj0,colObj1))
129  {
130  int proxyType0 = colObj0->getCollisionShape()->getShapeType();
131  int proxyType1 = colObj1->getCollisionShape()->getShapeType();
132  bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1)
134  && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0);
135 
136  if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
137  {
138  btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
140  {
141  //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
142  supportsSpuDispatch = false;
143  }
144  }
145 
146  if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
147  {
148  btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
150  {
151  //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
152  supportsSpuDispatch = false;
153  }
154  }
155 
156  if (supportsSpuDispatch)
157  {
158 
159  int so = sizeof(SpuContactManifoldCollisionAlgorithm);
160 #ifdef ALLOCATE_SEPARATELY
161  void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
162 #else
163  void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
164 #endif
165  collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
166  collisionPair.m_internalTmpValue = 2;
167  } else
168  {
169  btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
170  btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
171 
172  collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1);
173  collisionPair.m_internalTmpValue = 3;
174  }
175  }
176  }
177  }
178  return false;
179  }
180 };
181 
183 {
184 
185  if (dispatchInfo.m_enableSPU)
186  {
188 
189  {
190  BT_PROFILE("processAllOverlappingPairs");
191 
194 
196  // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks);
197 
199 
200 
202  {
203  btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
204 
205  pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
206  }
207  }
208 
209  //send one big batch
210  int numTotalPairs = pairCache->getNumOverlappingPairs();
211  if (numTotalPairs)
212  {
213  btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
214  int i;
215  {
216  int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
218  {
219  pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1;
220  }
221 
222  BT_PROFILE("addWorkToTask");
223  for (i=0;i<numTotalPairs;)
224  {
225  //Performance Hint: tweak this number during benchmarking
226 
227  int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
228  m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
229  i = endIndex;
230  }
231  }
232  {
233  BT_PROFILE("PPU fallback");
234  //handle PPU fallback pairs
235  for (i=0;i<numTotalPairs;i++)
236  {
237  btBroadphasePair& collisionPair = pairPtr[i];
238  if (collisionPair.m_internalTmpValue == 3)
239  {
240  if (collisionPair.m_algorithm)
241  {
242  btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
243  btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
244 
245  if (dispatcher->needsCollision(colObj0,colObj1))
246  {
247  //discrete collision detection query
248  btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
249  btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
250 
251  btManifoldResult contactPointResult(&ob0,&ob1);
252 
254  {
255 
256  collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult);
257  } else
258  {
259  //continuous collision detection query, time of impact (toi)
260  btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
261  if (dispatchInfo.m_timeOfImpact > toi)
262  dispatchInfo.m_timeOfImpact = toi;
263 
264  }
265  }
266  }
267  }
268  }
269  }
270  }
271  {
272  BT_PROFILE("flush2");
273  //make sure all SPU work is done
275  }
276 
277  } else
278  {
281  btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher);
282  }
283 }
virtual btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
int getShapeType() const
void setNumTasks(int maxNumTasks)
set the maximum number of SPU tasks allocated
virtual int getNumTasks() const =0
bool supportsDispatchPairOnSpu(int proxyType0, int proxyType1)
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
SpuCollisionTaskProcess handles SPU processing of collision pairs.
#define btAssert(x)
Definition: btScalar.h:101
void initialize2(bool useEpa=false)
call initialize in the beginning of the frame, before addCollisionPairToTask
btCollisionConfiguration allows to configure Bullet collision detection stack allocator size...
btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs...
void flush2()
call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished...
#define SPU_BATCHSIZE_BROADPHASE_PAIRS
Tuning value to optimized SPU utilization Too small value means Task overhead is large compared to co...
SpuGatheringCollisionDispatcher * m_dispatcher
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)
int getCollisionFlags() const
btManifoldResult is a helper class to manage contact results.
The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1)
btTransform & getWorldTransform()
btScalar m_timeOfImpact
Definition: btDispatcher.h:56
void addWorkToTask(void *pairArrayPtr, int startIndex, int endIndex)
batch up additional work to a current task for SPU processing. When batch is full, it issues the task.
btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold=0)
btCollisionObject can be used to manage collision detection objects.
virtual int getNumOverlappingPairs() const =0
virtual bool processOverlap(btBroadphasePair &collisionPair)
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
class btThreadSupportInterface * m_threadInterface
btBroadphaseProxy * m_pProxy0
#define BT_PROFILE(name)
Definition: btQuickprof.h:191
interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array...
SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU...
SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection Time of Impac...
SpuCollisionTaskProcess * m_spuCollisionTaskProcess
SpuGatheringCollisionDispatcher(class btThreadSupportInterface *threadInterface, unsigned int maxNumOutstandingTasks, btCollisionConfiguration *collisionConfiguration)
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)
btSpuCollisionPairCallback(const btDispatcherInfo &dispatchInfo, SpuGatheringCollisionDispatcher *dispatcher)
#define btAlignedAlloc(size, alignment)
The btCompoundShape allows to store multiple other btCollisionShapes This allows for moving concave c...
virtual void * allocateCollisionAlgorithm(int size)
virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1)=0
virtual btBroadphasePair * getOverlappingPairArrayPtr()=0
#define MAX_SPU_COMPOUND_SUBSHAPES
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:69
const btCollisionShape * getCollisionShape() const
virtual void processAllOverlappingPairs(btOverlapCallback *, btDispatcher *dispatcher)=0
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
int getNumChildShapes() const
The btBroadphasePair class contains a pair of aabb-overlapping objects.