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());
170  btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform());
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());
249  btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform());
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 }