1 | /* |
---|
2 | Bullet Continuous Collision Detection and Physics Library - Parallel solver |
---|
3 | Copyright (c) 2007 Starbreeze Studios |
---|
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 | Written by: Marten Svanfeldt |
---|
16 | */ |
---|
17 | |
---|
18 | #include "SpuParallelSolver.h" |
---|
19 | |
---|
20 | //#include "SpuFakeDma.h" |
---|
21 | #include "SpuSync.h" |
---|
22 | |
---|
23 | #include "LinearMath/btVector3.h" |
---|
24 | #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" |
---|
25 | #include "BulletDynamics/Dynamics/btRigidBody.h" |
---|
26 | #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" |
---|
27 | #include "LinearMath/btMinMax.h" |
---|
28 | #include "BulletCollision/CollisionShapes/btCollisionShape.h" |
---|
29 | #include "BulletCollision/CollisionDispatch/btCollisionObject.h" |
---|
30 | #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" |
---|
31 | #include "LinearMath/btQuickprof.h" |
---|
32 | |
---|
33 | #include "SpuSolverTask/SpuParallellSolverTask.h" |
---|
34 | |
---|
35 | #include <stdio.h> |
---|
36 | |
---|
37 | enum |
---|
38 | { |
---|
39 | PARALLEL_SOLVER_BODIES_PER_TASK = 64, |
---|
40 | PARALLEL_SOLVER_CELLS_PER_TASK = SPU_HASH_NUMCELLS >> 3 |
---|
41 | }; |
---|
42 | |
---|
43 | |
---|
44 | //-- Hash handling |
---|
45 | static void recordDependency(SpuSolverHash* hash, unsigned int i, unsigned int j) |
---|
46 | { |
---|
47 | hash->m_dependencyMatrix[i][j >> 5] |= (1 << (j & 31)); |
---|
48 | hash->m_dependencyMatrix[j][i >> 5] |= (1 << (i & 31)); |
---|
49 | } |
---|
50 | |
---|
51 | |
---|
52 | // Clear the given hash |
---|
53 | static void clearHash (SpuSolverHash* hash) |
---|
54 | { |
---|
55 | size_t hashSize = sizeof(SpuSolverHash); |
---|
56 | memset(hash, 0, hashSize); |
---|
57 | int i; |
---|
58 | |
---|
59 | // Setup basic dependency |
---|
60 | for ( i = 0; i < SPU_HASH_NUMCELLS; ++i) |
---|
61 | { |
---|
62 | hash->m_dependencyMatrix[i][i >> 5] |= (1 << (i & 31)); |
---|
63 | } |
---|
64 | |
---|
65 | // Set some ones to "unused cells" |
---|
66 | for ( i = SPU_HASH_WORDWIDTH-SPU_HASH_NUMUNUSEDBITS; i < SPU_HASH_WORDWIDTH; ++i) |
---|
67 | { |
---|
68 | hash->m_currentMask[0][SPU_HASH_NUMCELLDWORDS-1] |= (1 << i); |
---|
69 | } |
---|
70 | } |
---|
71 | /* |
---|
72 | static bool getDependency(SpuSolverHash* hash, unsigned int i, unsigned int j) |
---|
73 | { |
---|
74 | return (hash->m_dependencyMatrix[i][j >> 5] & (1 << (j & 31))) != 0; |
---|
75 | } |
---|
76 | */ |
---|
77 | |
---|
78 | |
---|
79 | static unsigned int getObjectIndex (btCollisionObject* object) |
---|
80 | { |
---|
81 | btVector3 center = object->getWorldTransform().getOrigin(); |
---|
82 | int cx = (int)floorf(center.x() / SPU_HASH_PHYSSIZE); |
---|
83 | int cy = (int)floorf(center.y() / SPU_HASH_PHYSSIZE); |
---|
84 | int cz = (int)floorf(center.z() / SPU_HASH_PHYSSIZE); |
---|
85 | |
---|
86 | return spuGetHashCellIndex(cx, cy, cz); |
---|
87 | }; |
---|
88 | |
---|
89 | |
---|
90 | |
---|
91 | |
---|
92 | |
---|
93 | btParallelSequentialImpulseSolver::btParallelSequentialImpulseSolver (btThreadSupportInterface* threadIf, int maxOutstandingTasks) |
---|
94 | : m_numberOfContacts(0), m_taskScheduler (threadIf, maxOutstandingTasks) |
---|
95 | { |
---|
96 | m_solverHash = new SpuSolverHash; |
---|
97 | clearHash(m_solverHash); |
---|
98 | } |
---|
99 | |
---|
100 | btParallelSequentialImpulseSolver::~btParallelSequentialImpulseSolver () |
---|
101 | { |
---|
102 | delete m_solverHash; |
---|
103 | } |
---|
104 | |
---|
105 | |
---|
106 | void btParallelSequentialImpulseSolver::prepareSolve(int numBodies, int numManifolds) |
---|
107 | { |
---|
108 | m_sortedManifolds.reserve(numManifolds); |
---|
109 | m_allObjects.reserve(numBodies); |
---|
110 | } |
---|
111 | |
---|
112 | btScalar btParallelSequentialImpulseSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) |
---|
113 | { |
---|
114 | BT_PROFILE("parallel_solveGroup"); |
---|
115 | |
---|
116 | if (!numManifolds && !numConstraints) |
---|
117 | return 0; |
---|
118 | int i; |
---|
119 | |
---|
120 | ///refresh contact points is not needed anymore, it has been moved into the processCollision detection part. |
---|
121 | #ifdef FORCE_REFESH_CONTACT_MANIFOLDS |
---|
122 | for ( i = 0; i < numManifolds; ++i) |
---|
123 | { |
---|
124 | btPersistentManifold* currManifold = manifold[i]; |
---|
125 | btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0(); |
---|
126 | btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1(); |
---|
127 | |
---|
128 | currManifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); |
---|
129 | } |
---|
130 | #endif //FORCE_REFESH_CONTACT_MANIFOLDS |
---|
131 | |
---|
132 | // Record and mark the manifolds to the cells |
---|
133 | for ( i = 0; i < numManifolds; ++i) |
---|
134 | { |
---|
135 | // Compute a hash cell for this manifold |
---|
136 | btPersistentManifold* currManifold = manifold[i]; |
---|
137 | |
---|
138 | btCollisionObject *ownerObject, *otherObject; |
---|
139 | |
---|
140 | btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0(); |
---|
141 | btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1(); |
---|
142 | |
---|
143 | if (rb0->getIslandTag() >= 0) |
---|
144 | { |
---|
145 | ownerObject = rb0; |
---|
146 | otherObject = rb1; |
---|
147 | } |
---|
148 | else |
---|
149 | { |
---|
150 | ownerObject = rb1; |
---|
151 | otherObject = rb0; |
---|
152 | } |
---|
153 | |
---|
154 | // Save the cell |
---|
155 | unsigned int ownerCellIdx = getObjectIndex(ownerObject); |
---|
156 | ManifoldCellHolder holder = {ownerCellIdx, currManifold}; |
---|
157 | m_sortedManifolds.push_back(holder); |
---|
158 | m_solverHash->m_Hash[ownerCellIdx].m_numManifolds++; |
---|
159 | |
---|
160 | // Record dependency |
---|
161 | if (rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0) |
---|
162 | { |
---|
163 | unsigned int otherCellIdx = getObjectIndex(otherObject); |
---|
164 | recordDependency(m_solverHash, ownerCellIdx, otherCellIdx); |
---|
165 | } |
---|
166 | |
---|
167 | // Save statistics |
---|
168 | int numContacts = currManifold->getNumContacts(); |
---|
169 | m_solverHash->m_Hash[ownerCellIdx].m_numContacts += numContacts; |
---|
170 | m_numberOfContacts += numContacts; |
---|
171 | } |
---|
172 | |
---|
173 | // Record and mark constraints to the cells |
---|
174 | for ( i = 0; i < numConstraints; ++i) |
---|
175 | { |
---|
176 | // Compute a hash cell for this manifold |
---|
177 | btTypedConstraint* currConstraint = constraints[i]; |
---|
178 | |
---|
179 | if (!constraintTypeSupported(currConstraint->getConstraintType())) |
---|
180 | continue; |
---|
181 | |
---|
182 | btCollisionObject *ownerObject, *otherObject; |
---|
183 | |
---|
184 | btRigidBody* rb0 = &currConstraint->getRigidBodyA(); |
---|
185 | btRigidBody* rb1 = &currConstraint->getRigidBodyB(); |
---|
186 | |
---|
187 | if (rb0->getIslandTag() >= 0) |
---|
188 | { |
---|
189 | ownerObject = rb0; |
---|
190 | otherObject = rb1; |
---|
191 | } |
---|
192 | else |
---|
193 | { |
---|
194 | ownerObject = rb1; |
---|
195 | otherObject = rb0; |
---|
196 | } |
---|
197 | |
---|
198 | // Save the cell |
---|
199 | unsigned int ownerCellIdx = getObjectIndex(ownerObject); |
---|
200 | ConstraintCellHolder holder = {ownerCellIdx, currConstraint->getConstraintType(), currConstraint}; |
---|
201 | m_sortedConstraints.push_back(holder); |
---|
202 | m_solverHash->m_Hash[ownerCellIdx].m_numConstraints++; |
---|
203 | |
---|
204 | // Record dependency |
---|
205 | if (rb0 && rb1 && rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0) |
---|
206 | { |
---|
207 | unsigned int otherCellIdx = getObjectIndex(otherObject); |
---|
208 | recordDependency(m_solverHash, ownerCellIdx, otherCellIdx); |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | // Save all RBs |
---|
213 | for ( i = 0; i < numBodies; ++i) |
---|
214 | { |
---|
215 | btCollisionObject* obj = bodies[i]; |
---|
216 | //unsigned int cellIdx = getObjectIndex(obj); |
---|
217 | |
---|
218 | btRigidBody* rb = btRigidBody::upcast(obj); |
---|
219 | m_allObjects.push_back(rb); |
---|
220 | } |
---|
221 | |
---|
222 | return 0; |
---|
223 | } |
---|
224 | |
---|
225 | template<typename T> |
---|
226 | class CellHolderPredicate |
---|
227 | { |
---|
228 | public: |
---|
229 | SIMD_FORCE_INLINE bool operator() ( const T& lhs, const T& rhs ) |
---|
230 | { |
---|
231 | return lhs.m_hashCellIndex < rhs.m_hashCellIndex; |
---|
232 | } |
---|
233 | }; |
---|
234 | |
---|
235 | |
---|
236 | /*static void printDependencyMatrix(SpuSolverHash* hash) |
---|
237 | { |
---|
238 | for (int r = 0; r < SPU_HASH_NUMCELLS; ++r) |
---|
239 | { |
---|
240 | for (int c = 0; c < SPU_HASH_NUMCELLS; ++c) |
---|
241 | { |
---|
242 | if (getDependency(hash, r, c)) |
---|
243 | { |
---|
244 | printf("1"); |
---|
245 | } |
---|
246 | else |
---|
247 | { |
---|
248 | printf("0"); |
---|
249 | } |
---|
250 | } |
---|
251 | |
---|
252 | printf("\n"); |
---|
253 | } |
---|
254 | printf("\n"); |
---|
255 | fflush(stdout); |
---|
256 | } |
---|
257 | */ |
---|
258 | |
---|
259 | // Solver caches |
---|
260 | btAlignedObjectArray<SpuSolverBody> solverBodyPool_persist; |
---|
261 | btAlignedObjectArray<uint32_t> solverBodyOffsetList_persist; |
---|
262 | btAlignedObjectArray<SpuSolverInternalConstraint> solverInternalConstraintPool_persist; |
---|
263 | btAlignedObjectArray<SpuSolverConstraint> solverConstraintPool_persist; |
---|
264 | |
---|
265 | |
---|
266 | void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) |
---|
267 | { |
---|
268 | BT_PROFILE("parallel_allSolved"); |
---|
269 | |
---|
270 | if (!m_numberOfContacts && !m_sortedConstraints.size()) |
---|
271 | { |
---|
272 | m_sortedManifolds.clear(); |
---|
273 | m_sortedConstraints.clear(); |
---|
274 | m_allObjects.clear(); |
---|
275 | clearHash(m_solverHash); |
---|
276 | return; |
---|
277 | } |
---|
278 | |
---|
279 | |
---|
280 | //printDependencyMatrix(m_solverHash); |
---|
281 | |
---|
282 | // Sort the manifolds list |
---|
283 | int numManifolds = m_sortedManifolds.size(); |
---|
284 | m_sortedManifolds.quickSort(CellHolderPredicate<ManifoldCellHolder>()); |
---|
285 | |
---|
286 | // Sort the constraint list |
---|
287 | int numConstraints = m_sortedConstraints.size(); |
---|
288 | m_sortedConstraints.quickSort(CellHolderPredicate<ConstraintCellHolder>()); |
---|
289 | |
---|
290 | |
---|
291 | // Sort the body list |
---|
292 | int numBodies = m_allObjects.size(); |
---|
293 | |
---|
294 | // Reassign the hash offset |
---|
295 | uint32_t emptyCellMask[SPU_HASH_NUMCELLDWORDS] = {0}; |
---|
296 | int numBodyOffsets = 0; |
---|
297 | { |
---|
298 | int manifoldRunner = 0; |
---|
299 | int bodyOffsetRunner = 0; |
---|
300 | int internalConstraintRunner = 0; |
---|
301 | int constraintRunner = 0; |
---|
302 | |
---|
303 | for (int i = 0; i < SPU_HASH_NUMCELLS; ++i) |
---|
304 | { |
---|
305 | bool empty = true; |
---|
306 | |
---|
307 | SpuSolverHashCell& hashCell = m_solverHash->m_Hash[i]; |
---|
308 | hashCell.m_solverBodyOffsetListOffset = bodyOffsetRunner; |
---|
309 | |
---|
310 | if (hashCell.m_numManifolds) |
---|
311 | { |
---|
312 | hashCell.m_manifoldListOffset = manifoldRunner; |
---|
313 | manifoldRunner += hashCell.m_numManifolds; |
---|
314 | |
---|
315 | bodyOffsetRunner += hashCell.m_numManifolds*2; |
---|
316 | } |
---|
317 | if (hashCell.m_numContacts) |
---|
318 | { |
---|
319 | hashCell.m_internalConstraintListOffset = internalConstraintRunner*3; |
---|
320 | internalConstraintRunner += hashCell.m_numContacts; |
---|
321 | empty = false; |
---|
322 | } |
---|
323 | |
---|
324 | if (hashCell.m_numConstraints) |
---|
325 | { |
---|
326 | hashCell.m_constraintListOffset = constraintRunner; |
---|
327 | constraintRunner += hashCell.m_numConstraints; |
---|
328 | |
---|
329 | bodyOffsetRunner += hashCell.m_numConstraints*2; |
---|
330 | |
---|
331 | empty = false; |
---|
332 | } |
---|
333 | |
---|
334 | |
---|
335 | emptyCellMask[i >> 5] |= (empty ? (1 << (i&31)) : 0); |
---|
336 | // Align the bodyOffsetRunner to a whole number of 4 for right alignment in the list |
---|
337 | bodyOffsetRunner = (bodyOffsetRunner+3)&~0x3; |
---|
338 | } |
---|
339 | |
---|
340 | numBodyOffsets = bodyOffsetRunner; |
---|
341 | } |
---|
342 | |
---|
343 | // Setup rigid bodies |
---|
344 | // Allocate temporary data |
---|
345 | solverBodyPool_persist.resize(numBodies + numManifolds + numConstraints); |
---|
346 | SpuSolverBody* solverBodyPool = &solverBodyPool_persist[0]; |
---|
347 | |
---|
348 | solverBodyOffsetList_persist.resize(numBodyOffsets); |
---|
349 | uint32_t* solverBodyOffsetList = &solverBodyOffsetList_persist[0]; |
---|
350 | |
---|
351 | solverInternalConstraintPool_persist.resize(m_numberOfContacts*3); |
---|
352 | SpuSolverInternalConstraint* solverInternalConstraintPool = &solverInternalConstraintPool_persist[0]; |
---|
353 | |
---|
354 | solverConstraintPool_persist.resize(numConstraints); |
---|
355 | SpuSolverConstraint* solverConstraintPool = &solverConstraintPool_persist[0]; |
---|
356 | |
---|
357 | // Setup all the moving rigid bodies |
---|
358 | { |
---|
359 | BT_PROFILE("setup moving rigidbodies"); |
---|
360 | |
---|
361 | int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK; |
---|
362 | int bodiesToSchedule = numBodies; |
---|
363 | int startBody = 0; |
---|
364 | |
---|
365 | while (bodiesToSchedule > 0) |
---|
366 | { |
---|
367 | // Schedule a bunch of hash cells |
---|
368 | int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule; |
---|
369 | |
---|
370 | SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); |
---|
371 | |
---|
372 | desc->m_solverCommand = CMD_SOLVER_SETUP_BODIES; |
---|
373 | desc->m_solverData.m_solverHash = m_solverHash; |
---|
374 | desc->m_solverData.m_solverBodyList = solverBodyPool; |
---|
375 | |
---|
376 | desc->m_commandData.m_bodySetup.m_startBody = startBody; |
---|
377 | desc->m_commandData.m_bodySetup.m_numBodies = numBodiesInTask; |
---|
378 | desc->m_commandData.m_bodySetup.m_rbList = &m_allObjects[0]; |
---|
379 | |
---|
380 | m_taskScheduler.issueTask(); |
---|
381 | bodiesToSchedule -= numBodiesInTask; |
---|
382 | startBody += numBodiesInTask; |
---|
383 | } |
---|
384 | |
---|
385 | m_taskScheduler.flushTasks(); |
---|
386 | } |
---|
387 | |
---|
388 | // Manifold setup |
---|
389 | { |
---|
390 | int cellsPerTask = PARALLEL_SOLVER_CELLS_PER_TASK; |
---|
391 | int cellsToSchedule = SPU_HASH_NUMCELLS; |
---|
392 | int startCell = 0; |
---|
393 | |
---|
394 | while (cellsToSchedule > 0) |
---|
395 | { |
---|
396 | int numCellsInTask = cellsToSchedule > cellsPerTask ? cellsPerTask : cellsToSchedule; |
---|
397 | |
---|
398 | SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); |
---|
399 | |
---|
400 | desc->m_solverCommand = CMD_SOLVER_MANIFOLD_SETUP; |
---|
401 | desc->m_solverData.m_solverHash = m_solverHash; |
---|
402 | desc->m_solverData.m_solverBodyList = solverBodyPool; |
---|
403 | desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList; |
---|
404 | desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool; |
---|
405 | desc->m_solverData.m_solverConstraintList = solverConstraintPool; |
---|
406 | |
---|
407 | desc->m_commandData.m_manifoldSetup.m_startCell = startCell; |
---|
408 | desc->m_commandData.m_manifoldSetup.m_numCells = numCellsInTask; |
---|
409 | desc->m_commandData.m_manifoldSetup.m_numBodies = numBodies; |
---|
410 | desc->m_commandData.m_manifoldSetup.m_numManifolds = numManifolds; |
---|
411 | desc->m_commandData.m_manifoldSetup.m_manifoldHolders = &m_sortedManifolds[0]; |
---|
412 | desc->m_commandData.m_manifoldSetup.m_constraintHolders = &m_sortedConstraints[0]; |
---|
413 | desc->m_commandData.m_manifoldSetup.m_solverInfo = info; |
---|
414 | |
---|
415 | m_taskScheduler.issueTask(); |
---|
416 | cellsToSchedule -= numCellsInTask; |
---|
417 | startCell += numCellsInTask; |
---|
418 | } |
---|
419 | m_taskScheduler.flushTasks(); |
---|
420 | } |
---|
421 | |
---|
422 | { |
---|
423 | BT_PROFILE("parallel_solve_iterations"); |
---|
424 | |
---|
425 | btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128); |
---|
426 | for (int iter = 0; iter < info.m_numIterations; ++iter) |
---|
427 | { |
---|
428 | btSpinlock lock (spinVar); |
---|
429 | lock.Init(); |
---|
430 | |
---|
431 | // Clear the "processed cells" part of the hash |
---|
432 | memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS); |
---|
433 | |
---|
434 | for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task) |
---|
435 | { |
---|
436 | SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); |
---|
437 | desc->m_solverCommand = CMD_SOLVER_SOLVE_ITERATE; |
---|
438 | |
---|
439 | desc->m_solverData.m_solverHash = m_solverHash; |
---|
440 | desc->m_solverData.m_solverBodyList = solverBodyPool; |
---|
441 | desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList; |
---|
442 | desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool; |
---|
443 | desc->m_solverData.m_solverConstraintList = solverConstraintPool; |
---|
444 | |
---|
445 | desc->m_commandData.m_iterate.m_spinLockVar = spinVar; |
---|
446 | |
---|
447 | m_taskScheduler.issueTask(); |
---|
448 | } |
---|
449 | m_taskScheduler.flushTasks(); |
---|
450 | } |
---|
451 | btAlignedFree((void*)spinVar); |
---|
452 | } |
---|
453 | |
---|
454 | // Write back velocity |
---|
455 | { |
---|
456 | int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK; |
---|
457 | int bodiesToSchedule = numBodies; |
---|
458 | int startBody = 0; |
---|
459 | |
---|
460 | while (bodiesToSchedule > 0) |
---|
461 | { |
---|
462 | // Schedule a bunch of hash cells |
---|
463 | int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule; |
---|
464 | |
---|
465 | SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); |
---|
466 | |
---|
467 | desc->m_solverCommand = CMD_SOLVER_COPYBACK_BODIES; |
---|
468 | desc->m_solverData.m_solverHash = m_solverHash; |
---|
469 | desc->m_solverData.m_solverBodyList = solverBodyPool; |
---|
470 | |
---|
471 | desc->m_commandData.m_bodyCopyback.m_startBody = startBody; |
---|
472 | desc->m_commandData.m_bodyCopyback.m_numBodies = numBodiesInTask; |
---|
473 | desc->m_commandData.m_bodyCopyback.m_rbList = &m_allObjects[0]; |
---|
474 | |
---|
475 | m_taskScheduler.issueTask(); |
---|
476 | bodiesToSchedule -= numBodiesInTask; |
---|
477 | startBody += numBodiesInTask; |
---|
478 | } |
---|
479 | |
---|
480 | m_taskScheduler.flushTasks(); |
---|
481 | } |
---|
482 | |
---|
483 | |
---|
484 | // Clean up |
---|
485 | m_sortedManifolds.resize(0); |
---|
486 | m_sortedConstraints.resize(0); |
---|
487 | m_allObjects.resize(0); |
---|
488 | clearHash(m_solverHash); |
---|
489 | |
---|
490 | |
---|
491 | m_numberOfContacts = 0; |
---|
492 | } |
---|
493 | |
---|
494 | void btParallelSequentialImpulseSolver::reset() |
---|
495 | { |
---|
496 | m_sortedManifolds.clear(); |
---|
497 | m_allObjects.clear(); |
---|
498 | m_numberOfContacts = 0; |
---|
499 | clearHash(m_solverHash); |
---|
500 | |
---|
501 | solverBodyPool_persist.clear(); |
---|
502 | solverBodyOffsetList_persist.clear(); |
---|
503 | solverConstraintPool_persist.clear(); |
---|
504 | solverInternalConstraintPool_persist.clear(); |
---|
505 | } |
---|
506 | |
---|
507 | |
---|
508 | SolverTaskScheduler::SolverTaskScheduler(btThreadSupportInterface* threadIf, int maxOutstandingTasks) |
---|
509 | : m_threadInterface (threadIf), m_maxNumOutstandingTasks (maxOutstandingTasks > SPU_MAX_SPUS ? SPU_MAX_SPUS : maxOutstandingTasks), |
---|
510 | m_currentTask (0), m_numBusyTasks (0) |
---|
511 | { |
---|
512 | m_taskDescriptors.resize(m_maxNumOutstandingTasks); |
---|
513 | m_taskBusy.resize(m_maxNumOutstandingTasks); |
---|
514 | |
---|
515 | m_threadInterface->startSPU(); |
---|
516 | } |
---|
517 | |
---|
518 | |
---|
519 | SolverTaskScheduler::~SolverTaskScheduler() |
---|
520 | { |
---|
521 | m_threadInterface->stopSPU(); |
---|
522 | } |
---|
523 | |
---|
524 | SpuSolverTaskDesc* SolverTaskScheduler::getTask() |
---|
525 | { |
---|
526 | int taskIdx = -1; |
---|
527 | |
---|
528 | if (m_taskBusy[m_currentTask]) |
---|
529 | { |
---|
530 | //try to find a new one |
---|
531 | for (int i = 0; i < m_maxNumOutstandingTasks; ++i) |
---|
532 | { |
---|
533 | if (!m_taskBusy[i]) |
---|
534 | { |
---|
535 | taskIdx = i; |
---|
536 | break; |
---|
537 | } |
---|
538 | } |
---|
539 | |
---|
540 | if (taskIdx < 0) |
---|
541 | { |
---|
542 | // Have to wait |
---|
543 | unsigned int taskId; |
---|
544 | unsigned int outputSize; |
---|
545 | |
---|
546 | for (int i=0;i<m_maxNumOutstandingTasks;i++) |
---|
547 | { |
---|
548 | if (m_taskBusy[i]) |
---|
549 | { |
---|
550 | taskId = i; |
---|
551 | break; |
---|
552 | } |
---|
553 | } |
---|
554 | |
---|
555 | m_threadInterface->waitForResponse(&taskId, &outputSize); |
---|
556 | |
---|
557 | m_taskBusy[taskId] = false; |
---|
558 | m_numBusyTasks--; |
---|
559 | |
---|
560 | taskIdx = taskId; |
---|
561 | } |
---|
562 | |
---|
563 | m_currentTask = taskIdx; |
---|
564 | } |
---|
565 | |
---|
566 | |
---|
567 | SpuSolverTaskDesc* result = &m_taskDescriptors[m_currentTask]; |
---|
568 | memset(result, 0, sizeof(SpuSolverTaskDesc)); |
---|
569 | result->m_taskId = m_currentTask; |
---|
570 | |
---|
571 | return result; |
---|
572 | } |
---|
573 | |
---|
574 | void SolverTaskScheduler::issueTask() |
---|
575 | { |
---|
576 | m_taskBusy[m_currentTask] = true; |
---|
577 | m_numBusyTasks++; |
---|
578 | |
---|
579 | SpuSolverTaskDesc& desc = m_taskDescriptors[m_currentTask]; |
---|
580 | |
---|
581 | m_threadInterface->sendRequest(1, (uint32_t)&desc, m_currentTask); |
---|
582 | } |
---|
583 | |
---|
584 | void SolverTaskScheduler::flushTasks() |
---|
585 | { |
---|
586 | while (m_numBusyTasks > 0) |
---|
587 | { |
---|
588 | unsigned int taskId; |
---|
589 | unsigned int outputSize; |
---|
590 | for (int i=0;i<m_maxNumOutstandingTasks;i++) |
---|
591 | { |
---|
592 | if (m_taskBusy[i]) |
---|
593 | { |
---|
594 | taskId = i; |
---|
595 | break; |
---|
596 | } |
---|
597 | } |
---|
598 | |
---|
599 | m_threadInterface->waitForResponse(&taskId, &outputSize); |
---|
600 | |
---|
601 | m_taskBusy[taskId] = false; |
---|
602 | m_numBusyTasks--; |
---|
603 | } |
---|
604 | } |
---|