removed SpuRaycaster and SpuParallelSolver, both were obsolete: slow, broken and unsupported

This commit is contained in:
erwin.coumans
2009-09-06 20:58:40 +00:00
parent 2d1777c899
commit 4e2cef2c69
11 changed files with 1 additions and 3539 deletions

View File

@@ -45,11 +45,6 @@ ADD_LIBRARY(BulletMultiThreaded
SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp
SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h
SpuParallelSolver.cpp
SpuParallelSolver.h
SpuSolverTask/SpuParallellSolverTask.cpp
SpuSolverTask/SpuParallellSolverTask.h
#Some GPU related stuff, mainly CUDA and perhaps OpenCL
btGpu3DGridBroadphase.cpp

View File

@@ -2,7 +2,7 @@ SubDir TOP src BulletMultiThreaded ;
#IncludeDir src/BulletMultiThreaded ;
Library bulletmultithreaded : [ Wildcard . : *.h *.cpp ] [ Wildcard MiniCLTask : *.h *.cpp ] [ Wildcard SpuNarrowPhaseCollisionTask : *.h *.cpp ] [ Wildcard SpuSolverTask : *.h *.cpp ] : noinstall ;
Library bulletmultithreaded : [ Wildcard . : *.h *.cpp ] [ Wildcard MiniCLTask : *.h *.cpp ] [ Wildcard SpuNarrowPhaseCollisionTask : *.h *.cpp ] : noinstall ;
CFlags bulletmultithreaded : [ FIncludes $(TOP)/src/BulletMultiThreaded ] [ FIncludes $(TOP)/src/BulletMultiThreaded/vectormath/scalar/cpp ] ;
LibDepends bulletmultithreaded : ;

View File

@@ -1,151 +0,0 @@
/*
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 <new>
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "LinearMath/btAlignedAllocator.h"
#include "SpuBatchRaycaster.h"
SpuBatchRaycaster::SpuBatchRaycaster (class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks)
{
m_threadInterface = threadInterface;
castUponObjectWrappers = NULL;
numCastUponObjectWrappers = 0;
m_spuRaycastTaskProcess = new SpuRaycastTaskProcess(m_threadInterface,maxNumOutstandingTasks); // FIXME non constant
}
SpuBatchRaycaster::~SpuBatchRaycaster ()
{
if (castUponObjectWrappers)
{
btAlignedFree (castUponObjectWrappers);
castUponObjectWrappers = NULL;
}
}
void
SpuBatchRaycaster::setCollisionObjects (btCollisionObjectArray& castUponObjects, int numCastUponObjects)
{
if (castUponObjectWrappers)
{
btAlignedFree (castUponObjectWrappers);
castUponObjectWrappers = NULL;
}
castUponObjectWrappers = (SpuCollisionObjectWrapper*)btAlignedAlloc (sizeof(SpuCollisionObjectWrapper) * numCastUponObjects,16);
numCastUponObjectWrappers = numCastUponObjects;
for (int i = 0; i < numCastUponObjectWrappers; i++)
{
castUponObjectWrappers[i] = SpuCollisionObjectWrapper(castUponObjects[i]);
}
}
void
SpuBatchRaycaster::setCollisionObjectsSkipPE (btCollisionObjectArray& castUponObjects, int numCastUponObjects)
{
if (castUponObjectWrappers)
{
btAlignedFree (castUponObjectWrappers);
castUponObjectWrappers = NULL;
}
int numNonPEShapes = 0;
for (int i = 0; i < numCastUponObjects; i++)
{
const btCollisionShape* shape = castUponObjects[i]->getCollisionShape();
if (shape->getShapeType () == BOX_SHAPE_PROXYTYPE ||
shape->getShapeType () == SPHERE_SHAPE_PROXYTYPE ||
shape->getShapeType () == CAPSULE_SHAPE_PROXYTYPE)
{
continue;
}
numNonPEShapes++;
}
castUponObjectWrappers = (SpuCollisionObjectWrapper*)btAlignedAlloc (sizeof(SpuCollisionObjectWrapper) * numNonPEShapes,16);
numCastUponObjectWrappers = numNonPEShapes;
int index = 0;
for (int i = 0; i < numCastUponObjects; i++)
{
const btCollisionShape* shape = castUponObjects[i]->getCollisionShape();
if (shape->getShapeType () == BOX_SHAPE_PROXYTYPE ||
shape->getShapeType () == SPHERE_SHAPE_PROXYTYPE ||
shape->getShapeType () == CAPSULE_SHAPE_PROXYTYPE)
{
continue;
}
castUponObjectWrappers[index] = SpuCollisionObjectWrapper(castUponObjects[i]);
index++;
}
// printf("Number of shapes bullet is casting against: %d\n", numNonPEShapes);
btAssert (index == numNonPEShapes);
}
void
SpuBatchRaycaster::addRay (const btVector3& rayFrom, const btVector3& rayTo, const btScalar hitFraction)
{
SpuRaycastTaskWorkUnitOut workUnitOut;
workUnitOut.hitFraction = hitFraction;
workUnitOut.hitNormal = btVector3(0.0, 1.0, 0.0);
rayBatchOutput.push_back (workUnitOut);
SpuRaycastTaskWorkUnit workUnit;
workUnit.rayFrom = rayFrom;
workUnit.rayTo = rayTo;
rayBatch.push_back (workUnit);
}
void
SpuBatchRaycaster::clearRays ()
{
rayBatch.clear ();
rayBatchOutput.clear ();
}
void
SpuBatchRaycaster::performBatchRaycast ()
{
m_spuRaycastTaskProcess->initialize2 (castUponObjectWrappers, numCastUponObjectWrappers);
for (int i = 0; i < rayBatch.size(); i++)
{
rayBatch[i].output = &rayBatchOutput[i]; // assign output memory location
m_spuRaycastTaskProcess->addWorkToTask(rayBatch[i]);
}
m_spuRaycastTaskProcess->flush2 ();
}
const SpuRaycastTaskWorkUnitOut&
SpuBatchRaycaster::operator [] (int i) const
{
return rayBatchOutput[i];
}
int
SpuBatchRaycaster::getNumRays () const
{
return rayBatchOutput.size();
}

View File

@@ -1,49 +0,0 @@
/*
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.
*/
#ifndef SPU_BATCH_RAYCASTER_H
#define SPU_BATCH_RAYCASTER_H
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "SpuRaycastTaskProcess.h"
#include "SpuRaycastTask/SpuRaycastTask.h"
#include "SpuCollisionObjectWrapper.h"
/* FIXME:
* Need to decide how callbacks are performed...
*/
class SpuBatchRaycaster
{
protected:
SpuCollisionObjectWrapper* castUponObjectWrappers;
int numCastUponObjectWrappers;
btAlignedObjectArray<SpuRaycastTaskWorkUnit> rayBatch;
btAlignedObjectArray<SpuRaycastTaskWorkUnitOut> rayBatchOutput;
SpuRaycastTaskProcess* m_spuRaycastTaskProcess;
class btThreadSupportInterface* m_threadInterface;
public:
SpuBatchRaycaster (class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks);
~SpuBatchRaycaster ();
void setCollisionObjects (btCollisionObjectArray& castUponObjects, int numCastUponObjects);
void setCollisionObjectsSkipPE (btCollisionObjectArray& castUponObjects, int numCastUponObjects);
void addRay (const btVector3& rayFrom, const btVector3& rayTo, const btScalar hitFraction = 1.0);
void clearRays ();
void performBatchRaycast ();
const SpuRaycastTaskWorkUnitOut& operator [] (int i) const;
int getNumRays () const;
};
#endif

View File

@@ -1,643 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library - Parallel solver
Copyright (c) 2007 Starbreeze Studios
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.
Written by: Marten Svanfeldt
*/
#include "SpuParallelSolver.h"
//#include "SpuFakeDma.h"
#include "SpuSync.h"
#include "LinearMath/btVector3.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
#include "LinearMath/btMinMax.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include "LinearMath/btQuickprof.h"
#include "SpuSolverTask/SpuParallellSolverTask.h"
#include <stdio.h>
enum
{
PARALLEL_SOLVER_BODIES_PER_TASK = 64,
PARALLEL_SOLVER_CELLS_PER_TASK = SPU_HASH_NUMCELLS >> 3
};
//-- Hash handling
static void recordDependency(SpuSolverHash* hash, unsigned int i, unsigned int j)
{
hash->m_dependencyMatrix[i][j >> 5] |= (1 << (j & 31));
hash->m_dependencyMatrix[j][i >> 5] |= (1 << (i & 31));
}
// Clear the given hash
static void clearHash (SpuSolverHash* hash)
{
size_t hashSize = sizeof(SpuSolverHash);
memset(hash, 0, hashSize);
int i;
// Setup basic dependency
for ( i = 0; i < SPU_HASH_NUMCELLS; ++i)
{
hash->m_dependencyMatrix[i][i >> 5] |= (1 << (i & 31));
}
// Set some ones to "unused cells"
for ( i = SPU_HASH_WORDWIDTH-SPU_HASH_NUMUNUSEDBITS; i < SPU_HASH_WORDWIDTH; ++i)
{
hash->m_currentMask[0][SPU_HASH_NUMCELLDWORDS-1] |= (1 << i);
}
}
/*
static bool getDependency(SpuSolverHash* hash, unsigned int i, unsigned int j)
{
return (hash->m_dependencyMatrix[i][j >> 5] & (1 << (j & 31))) != 0;
}
*/
static unsigned int getObjectIndex (btCollisionObject* object)
{
btVector3 center = object->getWorldTransform().getOrigin();
int cx = (int)floorf(center.x() / SPU_HASH_PHYSSIZE);
int cy = (int)floorf(center.y() / SPU_HASH_PHYSSIZE);
int cz = (int)floorf(center.z() / SPU_HASH_PHYSSIZE);
return spuGetHashCellIndex(cx, cy, cz);
}
btParallelSequentialImpulseSolver::btParallelSequentialImpulseSolver (btThreadSupportInterface* threadIf, int maxOutstandingTasks)
: m_numberOfContacts(0), m_taskScheduler (threadIf, maxOutstandingTasks)
{
m_solverHash = new SpuSolverHash;
clearHash(m_solverHash);
}
btParallelSequentialImpulseSolver::~btParallelSequentialImpulseSolver ()
{
delete m_solverHash;
}
void btParallelSequentialImpulseSolver::prepareSolve(int numBodies, int numManifolds)
{
m_sortedManifolds.reserve(numManifolds);
m_allObjects.reserve(numBodies);
}
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)
{
BT_PROFILE("parallel_solveGroup");
if (!numManifolds && !numConstraints)
return 0;
int i;
///refresh contact points is not needed anymore, it has been moved into the processCollision detection part.
#ifdef FORCE_REFESH_CONTACT_MANIFOLDS
for ( i = 0; i < numManifolds; ++i)
{
btPersistentManifold* currManifold = manifold[i];
btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0();
btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1();
currManifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
}
#endif //FORCE_REFESH_CONTACT_MANIFOLDS
// Record and mark the manifolds to the cells
for ( i = 0; i < numManifolds; ++i)
{
// Compute a hash cell for this manifold
btPersistentManifold* currManifold = manifold[i];
btCollisionObject *ownerObject, *otherObject;
btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0();
btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1();
if (rb0->getIslandTag() >= 0)
{
ownerObject = rb0;
otherObject = rb1;
}
else
{
ownerObject = rb1;
otherObject = rb0;
}
// Save the cell
unsigned int ownerCellIdx = getObjectIndex(ownerObject);
ManifoldCellHolder holder = {ownerCellIdx, currManifold};
m_sortedManifolds.push_back(holder);
m_solverHash->m_Hash[ownerCellIdx].m_numManifolds++;
// Record dependency
if (rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0)
{
unsigned int otherCellIdx = getObjectIndex(otherObject);
recordDependency(m_solverHash, ownerCellIdx, otherCellIdx);
}
// Save statistics
int numContacts = currManifold->getNumContacts();
m_solverHash->m_Hash[ownerCellIdx].m_numContacts += numContacts;
m_numberOfContacts += numContacts;
}
// Record and mark constraints to the cells
for ( i = 0; i < numConstraints; ++i)
{
// Compute a hash cell for this manifold
btTypedConstraint* currConstraint = constraints[i];
if (!constraintTypeSupported(currConstraint->getConstraintType()))
continue;
btCollisionObject *ownerObject, *otherObject;
btRigidBody* rb0 = &currConstraint->getRigidBodyA();
btRigidBody* rb1 = &currConstraint->getRigidBodyB();
if (rb0->getIslandTag() >= 0)
{
ownerObject = rb0;
otherObject = rb1;
}
else
{
ownerObject = rb1;
otherObject = rb0;
}
// Save the cell
unsigned int ownerCellIdx = getObjectIndex(ownerObject);
ConstraintCellHolder holder = {ownerCellIdx, currConstraint->getConstraintType(), currConstraint};
m_sortedConstraints.push_back(holder);
m_solverHash->m_Hash[ownerCellIdx].m_numConstraints++;
// Record dependency
if (rb0 && rb1 && rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0)
{
unsigned int otherCellIdx = getObjectIndex(otherObject);
recordDependency(m_solverHash, ownerCellIdx, otherCellIdx);
}
}
// Save all RBs
for ( i = 0; i < numBodies; ++i)
{
btCollisionObject* obj = bodies[i];
//unsigned int cellIdx = getObjectIndex(obj);
btRigidBody* rb = btRigidBody::upcast(obj);
m_allObjects.push_back(rb);
}
return 0;
}
template<typename T>
class CellHolderPredicate
{
public:
SIMD_FORCE_INLINE bool operator() ( const T& lhs, const T& rhs )
{
return lhs.m_hashCellIndex < rhs.m_hashCellIndex;
}
};
/*static void printDependencyMatrix(SpuSolverHash* hash)
{
for (int r = 0; r < SPU_HASH_NUMCELLS; ++r)
{
for (int c = 0; c < SPU_HASH_NUMCELLS; ++c)
{
if (getDependency(hash, r, c))
{
printf("1");
}
else
{
printf("0");
}
}
printf("\n");
}
printf("\n");
fflush(stdout);
}
*/
// Solver caches
btAlignedObjectArray<btSolverBody> solverBodyPool_persist;
btAlignedObjectArray<uint32_t> solverBodyOffsetList_persist;
btAlignedObjectArray<btSolverConstraint> solverInternalConstraintPool_persist;
btAlignedObjectArray<btSolverConstraint> solverConstraintPool_persist;
void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc)
{
BT_PROFILE("parallel_allSolved");
if (!m_numberOfContacts && !m_sortedConstraints.size())
{
m_sortedManifolds.clear();
m_sortedConstraints.clear();
m_allObjects.clear();
clearHash(m_solverHash);
return;
}
//printDependencyMatrix(m_solverHash);
// Sort the manifolds list
int numManifolds = m_sortedManifolds.size();
m_sortedManifolds.quickSort(CellHolderPredicate<ManifoldCellHolder>());
// Sort the constraint list
int numConstraints = m_sortedConstraints.size();
m_sortedConstraints.quickSort(CellHolderPredicate<ConstraintCellHolder>());
// Sort the body list
int numBodies = m_allObjects.size();
// Reassign the hash offset
uint32_t emptyCellMask[SPU_HASH_NUMCELLDWORDS] = {0};
int numBodyOffsets = 0;
{
int manifoldRunner = 0;
int bodyOffsetRunner = 0;
int internalConstraintRunner = 0;
int constraintRunner = 0;
for (int i = 0; i < SPU_HASH_NUMCELLS; ++i)
{
bool empty = true;
SpuSolverHashCell& hashCell = m_solverHash->m_Hash[i];
hashCell.m_solverBodyOffsetListOffset = bodyOffsetRunner;
if (hashCell.m_numManifolds)
{
hashCell.m_manifoldListOffset = manifoldRunner;
manifoldRunner += hashCell.m_numManifolds;
bodyOffsetRunner += hashCell.m_numManifolds*2;
}
if (hashCell.m_numContacts)
{
hashCell.m_internalConstraintListOffset = internalConstraintRunner*3;
internalConstraintRunner += hashCell.m_numContacts;
empty = false;
}
if (hashCell.m_numConstraints)
{
hashCell.m_constraintListOffset = constraintRunner;
constraintRunner += hashCell.m_numConstraints;
bodyOffsetRunner += hashCell.m_numConstraints*2;
empty = false;
}
emptyCellMask[i >> 5] |= (empty ? (1 << (i&31)) : 0);
// Align the bodyOffsetRunner to a whole number of 4 for right alignment in the list
bodyOffsetRunner = (bodyOffsetRunner+3)&~0x3;
}
numBodyOffsets = bodyOffsetRunner;
}
// Setup rigid bodies
// Allocate temporary data
solverBodyPool_persist.resize(numBodies + numManifolds + numConstraints);
btSolverBody* solverBodyPool = &solverBodyPool_persist[0];
solverBodyOffsetList_persist.resize(numBodyOffsets);
uint32_t* solverBodyOffsetList = &solverBodyOffsetList_persist[0];
solverInternalConstraintPool_persist.resize(m_numberOfContacts*3);
btSolverConstraint* solverInternalConstraintPool = &solverInternalConstraintPool_persist[0];
solverConstraintPool_persist.resize(numConstraints);
btSolverConstraint* solverConstraintPool = &solverConstraintPool_persist[0];
// Setup all the moving rigid bodies
{
BT_PROFILE("setup moving rigidbodies");
int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK;
int bodiesToSchedule = numBodies;
int startBody = 0;
while (bodiesToSchedule > 0)
{
// Schedule a bunch of hash cells
int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule;
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
desc->m_solverCommand = CMD_SOLVER_SETUP_BODIES;
desc->m_solverData.m_solverHash = m_solverHash;
desc->m_solverData.m_solverBodyList = solverBodyPool;
desc->m_commandData.m_bodySetup.m_startBody = startBody;
desc->m_commandData.m_bodySetup.m_numBodies = numBodiesInTask;
desc->m_commandData.m_bodySetup.m_rbList = &m_allObjects[0];
m_taskScheduler.issueTask();
bodiesToSchedule -= numBodiesInTask;
startBody += numBodiesInTask;
}
m_taskScheduler.flushTasks();
}
// Manifold setup
{
int cellsPerTask = PARALLEL_SOLVER_CELLS_PER_TASK;
int cellsToSchedule = SPU_HASH_NUMCELLS;
int startCell = 0;
while (cellsToSchedule > 0)
{
int numCellsInTask = cellsToSchedule > cellsPerTask ? cellsPerTask : cellsToSchedule;
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
desc->m_solverCommand = CMD_SOLVER_MANIFOLD_SETUP;
desc->m_solverData.m_solverHash = m_solverHash;
desc->m_solverData.m_solverBodyList = solverBodyPool;
desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList;
desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool;
desc->m_solverData.m_solverConstraintList = solverConstraintPool;
desc->m_commandData.m_manifoldSetup.m_startCell = startCell;
desc->m_commandData.m_manifoldSetup.m_numCells = numCellsInTask;
desc->m_commandData.m_manifoldSetup.m_numBodies = numBodies;
desc->m_commandData.m_manifoldSetup.m_numManifolds = numManifolds;
desc->m_commandData.m_manifoldSetup.m_manifoldHolders = &m_sortedManifolds[0];
desc->m_commandData.m_manifoldSetup.m_constraintHolders = &m_sortedConstraints[0];
desc->m_commandData.m_manifoldSetup.m_solverInfo = info;
m_taskScheduler.issueTask();
cellsToSchedule -= numCellsInTask;
startCell += numCellsInTask;
}
m_taskScheduler.flushTasks();
}
{
BT_PROFILE("parallel_solve_iterations");
btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128);
for (int iter = 0; iter < info.m_numIterations; ++iter)
{
btSpinlock lock (spinVar);
lock.Init();
// Clear the "processed cells" part of the hash
memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS);
for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task)
{
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
desc->m_solverCommand = CMD_SOLVER_SOLVE_ITERATE;
desc->m_solverData.m_solverHash = m_solverHash;
desc->m_solverData.m_solverBodyList = solverBodyPool;
desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList;
desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool;
desc->m_solverData.m_solverConstraintList = solverConstraintPool;
desc->m_commandData.m_iterate.m_spinLockVar = spinVar;
m_taskScheduler.issueTask();
}
m_taskScheduler.flushTasks();
}
btAlignedFree((void*)spinVar);
}
// Write back velocity
{
int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK;
int bodiesToSchedule = numBodies;
int startBody = 0;
while (bodiesToSchedule > 0)
{
// Schedule a bunch of hash cells
int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule;
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
desc->m_solverCommand = CMD_SOLVER_COPYBACK_BODIES;
desc->m_solverData.m_solverHash = m_solverHash;
desc->m_solverData.m_solverBodyList = solverBodyPool;
desc->m_commandData.m_bodyCopyback.m_startBody = startBody;
desc->m_commandData.m_bodyCopyback.m_numBodies = numBodiesInTask;
desc->m_commandData.m_bodyCopyback.m_rbList = &m_allObjects[0];
m_taskScheduler.issueTask();
bodiesToSchedule -= numBodiesInTask;
startBody += numBodiesInTask;
}
m_taskScheduler.flushTasks();
}
{
BT_PROFILE("warmstart_writeback");
btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128);
for (int iter = 0; iter < info.m_numIterations; ++iter)
{
btSpinlock lock (spinVar);
lock.Init();
// Clear the "processed cells" part of the hash
memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS);
for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task)
{
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
desc->m_solverCommand = CMD_SOLVER_MANIFOLD_WARMSTART_WRITEBACK;
desc->m_solverData.m_solverHash = m_solverHash;
desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool;
desc->m_solverData.m_solverConstraintList = solverConstraintPool;
desc->m_commandData.m_manifoldSetup.m_manifoldHolders = &m_sortedManifolds[0];
desc->m_commandData.m_iterate.m_spinLockVar = spinVar;
m_taskScheduler.issueTask();
}
m_taskScheduler.flushTasks();
}
btAlignedFree((void*)spinVar);
}
// Clean up
m_sortedManifolds.resize(0);
m_sortedConstraints.resize(0);
m_allObjects.resize(0);
clearHash(m_solverHash);
m_numberOfContacts = 0;
}
void btParallelSequentialImpulseSolver::reset()
{
m_sortedManifolds.clear();
m_allObjects.clear();
m_numberOfContacts = 0;
clearHash(m_solverHash);
solverBodyPool_persist.clear();
solverBodyOffsetList_persist.clear();
solverConstraintPool_persist.clear();
solverInternalConstraintPool_persist.clear();
}
SolverTaskScheduler::SolverTaskScheduler(btThreadSupportInterface* threadIf, int maxOutstandingTasks)
: m_threadInterface (threadIf), m_maxNumOutstandingTasks (maxOutstandingTasks > SPU_MAX_SPUS ? SPU_MAX_SPUS : maxOutstandingTasks),
m_currentTask (0), m_numBusyTasks (0)
{
m_taskDescriptors.resize(m_maxNumOutstandingTasks);
m_taskBusy.resize(m_maxNumOutstandingTasks);
m_threadInterface->startSPU();
}
SolverTaskScheduler::~SolverTaskScheduler()
{
m_threadInterface->stopSPU();
}
SpuSolverTaskDesc* SolverTaskScheduler::getTask()
{
int taskIdx = -1;
if (m_taskBusy[m_currentTask])
{
//try to find a new one
for (int i = 0; i < m_maxNumOutstandingTasks; ++i)
{
if (!m_taskBusy[i])
{
taskIdx = i;
break;
}
}
if (taskIdx < 0)
{
// Have to wait
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
m_threadInterface->waitForResponse(&taskId, &outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
taskIdx = taskId;
}
m_currentTask = taskIdx;
}
SpuSolverTaskDesc* result = &m_taskDescriptors[m_currentTask];
int so = sizeof(SpuSolverTaskDesc);
memset(result, 0, so);
result->m_taskId = m_currentTask;
return result;
}
void SolverTaskScheduler::issueTask()
{
m_taskBusy[m_currentTask] = true;
m_numBusyTasks++;
SpuSolverTaskDesc& desc = m_taskDescriptors[m_currentTask];
m_threadInterface->sendRequest(1, (ppu_address_t)&desc, m_currentTask);
}
void SolverTaskScheduler::flushTasks()
{
while (m_numBusyTasks > 0)
{
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
m_threadInterface->waitForResponse(&taskId, &outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
}
}

View File

@@ -1,75 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library - Parallel solver
Copyright (c) 2007 Starbreeze Studios
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.
Written by: Marten Svanfeldt
*/
#ifndef SPU_PARALLELSOLVER_H
#define SPU_PARALLELSOLVER_H
#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
#include "btThreadSupportInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
class SolverTaskScheduler
{
protected:
class btThreadSupportInterface* m_threadInterface;
int m_maxNumOutstandingTasks;
unsigned int m_currentTask;
unsigned int m_numBusyTasks;
btAlignedObjectArray<struct SpuSolverTaskDesc> m_taskDescriptors;
btAlignedObjectArray<bool> m_taskBusy;
public:
SolverTaskScheduler (btThreadSupportInterface* threadIf, int maxOutstandingTasks);
~SolverTaskScheduler ();
struct SpuSolverTaskDesc* getTask ();
void issueTask();
void flushTasks();
int getMaxOutstandingTasks()
{
return m_maxNumOutstandingTasks;
}
};
class btParallelSequentialImpulseSolver : public btConstraintSolver
{
protected:
struct SpuSolverHash* m_solverHash;
btAlignedObjectArray<struct ManifoldCellHolder> m_sortedManifolds;
btAlignedObjectArray<struct ConstraintCellHolder> m_sortedConstraints;
btAlignedObjectArray<class btRigidBody*> m_allObjects;
int m_numberOfContacts;
SolverTaskScheduler m_taskScheduler;
public:
btParallelSequentialImpulseSolver (btThreadSupportInterface* threadIf, int maxOutstandingTasks);
virtual ~btParallelSequentialImpulseSolver();
virtual void prepareSolve (int numBodies, int numManifolds);
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher);
virtual void allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc);
virtual void reset ();
};
#endif

View File

@@ -1,189 +0,0 @@
/*
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 "SpuRaycastTaskProcess.h"
SpuRaycastTaskProcess::SpuRaycastTaskProcess(class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks)
:m_threadInterface(threadInterface),
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
{
m_workUnitTaskBuffers = (unsigned char *)0;
m_taskBusy.resize(m_maxNumOutstandingTasks);
m_spuRaycastTaskDesc.resize(m_maxNumOutstandingTasks);
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
m_threadInterface->startSPU();
//printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
//printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", sizeof(SpuGatherAndProcessWorkUnitInput));
}
SpuRaycastTaskProcess::~SpuRaycastTaskProcess()
{
if (m_workUnitTaskBuffers != 0)
{
btAlignedFree(m_workUnitTaskBuffers);
m_workUnitTaskBuffers = 0;
}
m_threadInterface->stopSPU();
}
void SpuRaycastTaskProcess::initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers)
{
m_spuCollisionObjectWrappers = spuCollisionObjectsWrappers;
m_numSpuCollisionObjectWrappers = numSpuCollisionObjectWrappers;
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
#ifdef DEBUG_SpuRaycastTaskProcess
m_initialized = true;
#endif
}
void SpuRaycastTaskProcess::issueTask2()
{
m_taskBusy[m_currentTask] = true;
m_numBusyTasks++;
SpuRaycastTaskDesc& taskDesc = m_spuRaycastTaskDesc[m_currentTask];
taskDesc.taskId = m_currentTask;
m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc,m_currentTask);
//printf("send thread requested for task %d\n", m_currentTask);
// if all tasks busy, wait for spu event to clear the task.
if (m_numBusyTasks >= m_maxNumOutstandingTasks)
{
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
m_threadInterface->waitForResponse(&taskId, &outputSize);
//printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
} else {
//printf("Sent request, not enough busy tasks\n");
}
}
void SpuRaycastTaskProcess::addWorkToTask(SpuRaycastTaskWorkUnit& workunit)
{
m_spuRaycastTaskDesc[m_currentTask].workUnits[m_currentWorkUnitInTask] = workunit;
m_currentWorkUnitInTask++;
if (m_currentWorkUnitInTask == SPU_RAYCAST_WORK_UNITS_PER_TASK)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
//printf("Task buffer full, issuing\n");
issueTask2 ();
//printf("Returned from issueTask2()\n");
m_currentWorkUnitInTask = 0;
// find new task buffer
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
if (!m_taskBusy[i])
{
m_currentTask = i;
//init the task data
break;
}
}
//printf("next task = %d\n", m_currentTask);
}
}
void
SpuRaycastTaskProcess::flush2()
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("\nSpuRaycastTaskProcess::flush()\n");
#endif //DEBUG_SPU_TASK_SCHEDULING
// if there's a partially filled task buffer, submit that task
//printf("Flushing... %d remaining\n", m_currentWorkUnitInTask);
if (m_currentWorkUnitInTask > 0)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
issueTask2();
m_currentWorkUnitInTask = 0;
}
// all tasks are issued, wait for all tasks to be complete
while(m_numBusyTasks > 0)
{
// Consolidating SPU code
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
//printf("Busy tasks... %d\n", m_numBusyTasks);
{
// SPURS support.
m_threadInterface->waitForResponse(&taskId, &outputSize);
}
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
//postProcess(taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
}
}

View File

@@ -1,72 +0,0 @@
/*
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.
*/
#ifndef SPU_RAY_TASK_PROCESS_H
#define SPU_RAY_TASK_PROCESS_H
#include <assert.h>
#include <string.h>
#include <LinearMath/btScalar.h>
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include <LinearMath/btAlignedAllocator.h>
#include "PlatformDefinitions.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "SpuRaycastTask/SpuRaycastTask.h"
#include "btThreadSupportInterface.h"
/// SpuRaycastTaskProcess handles SPU processing of raycast requests
class SpuRaycastTaskProcess
{
unsigned char *m_workUnitTaskBuffers;
// track task buffers that are being used, and total busy tasks
btAlignedObjectArray<bool> m_taskBusy;
btAlignedObjectArray<SpuRaycastTaskDesc> m_spuRaycastTaskDesc;
btThreadSupportInterface* m_threadInterface;
int m_maxNumOutstandingTasks;
int m_numBusyTasks;
// the current task and the current entry to insert a new work unit
int m_currentTask;
int m_currentWorkUnitInTask;
int m_numSpuCollisionObjectWrappers;
void* m_spuCollisionObjectWrappers;
void issueTask2();
//void postProcess(unsigned int taskId, int outputSize);
public:
SpuRaycastTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks);
~SpuRaycastTaskProcess();
/// call initialize in the beginning of the frame, before addCollisionPairToTask
void initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers);
/// batch up additional work to a current task for SPU processing. When batch is full, it issues the task.
void addWorkToTask(struct SpuRaycastTaskWorkUnit&);
/// call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished
void flush2();
};
#endif // SPU_COLLISION_TASK_PROCESS_H

View File

@@ -1,183 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library - Parallel solver
Copyright (c) 2007 Starbreeze Studios
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.
Written by: Marten Svanfeldt
*/
#ifndef SPU_PARALLELSOLVERTASK_H
#define SPU_PARALLELSOLVERTASK_H
#include "../PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
#include "../SpuSync.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include "LinearMath/btAlignedAllocator.h"
#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
ATTRIBUTE_ALIGNED16(struct) ManifoldCellHolder
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_hashCellIndex;
class btPersistentManifold* m_manifold;
};
ATTRIBUTE_ALIGNED16(struct) ConstraintCellHolder
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_hashCellIndex;
uint32_t m_constraintType;
class btTypedConstraint* m_constraint;
};
enum
{
SPU_HASH_NUMCELLS = 128,
SPU_HASH_WORDWIDTH = sizeof(uint32_t)*8,
SPU_HASH_NUMCELLDWORDS = ((SPU_HASH_NUMCELLS + SPU_HASH_WORDWIDTH - 1) / SPU_HASH_WORDWIDTH),
SPU_HASH_NUMUNUSEDBITS = (SPU_HASH_NUMCELLDWORDS * SPU_HASH_WORDWIDTH) - SPU_HASH_NUMCELLS,
SPU_HASH_PHYSSIZE = 4, //TODO: MAKE CONFIGURABLE
SPU_MAX_BODIES_PER_CELL = 1024,
SPU_MAX_SPUS = 6
};
enum
{
CMD_SOLVER_SETUP_BODIES = 1,
CMD_SOLVER_MANIFOLD_SETUP,
CMD_SOLVER_CONSTRAINT_SETUP,
CMD_SOLVER_SOLVE_ITERATE,
CMD_SOLVER_COPYBACK_BODIES,
CMD_SOLVER_MANIFOLD_WARMSTART_WRITEBACK
};
struct SpuSolverHashCell
{
uint16_t m_numLocalBodies;
uint16_t m_solverBodyOffsetListOffset;
uint16_t m_numManifolds;
uint16_t m_manifoldListOffset;
uint16_t m_numContacts;
uint16_t m_internalConstraintListOffset;
uint16_t m_numConstraints;
uint16_t m_constraintListOffset;
};
// Shared data structures
struct SpuSolverHash
{
// Dependency matrix
ATTRIBUTE_ALIGNED16(uint32_t m_dependencyMatrix[SPU_HASH_NUMCELLS][SPU_HASH_NUMCELLDWORDS]);
ATTRIBUTE_ALIGNED16(uint32_t m_currentMask[SPU_MAX_SPUS+1][SPU_HASH_NUMCELLDWORDS]);
// The hash itself
ATTRIBUTE_ALIGNED16(SpuSolverHashCell m_Hash[SPU_HASH_NUMCELLS]);
// Hash meta-data
};
inline unsigned int spuHash(unsigned int k) { return k*2654435769u; }
inline unsigned int spuGetHashCellIndex(int x, int y, int z)
{
//int n = 0x8da6b343 * x + 0xd8163841 * y + 0xcb1ab31f * z;
int n = x ^ spuHash(y ^ spuHash (z));
return ((unsigned int)n) & (SPU_HASH_NUMCELLS-1);
}
ATTRIBUTE_ALIGNED16(struct) SpuSolverDataDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
SpuSolverHash* m_solverHash;
btSolverBody* m_solverBodyList;
btSolverConstraint* m_solverInternalConstraintList;
btSolverConstraint* m_solverConstraintList;
uint32_t* m_solverBodyOffsetList;
};
ATTRIBUTE_ALIGNED16(struct) SpuSolverTaskDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_solverCommand;
uint32_t m_taskId;
SpuSolverDataDesc m_solverData;
// command specific data
union
{
// Body setup
struct
{
uint32_t m_startBody;
uint32_t m_numBodies;
class btRigidBody** m_rbList;
} m_bodySetup, m_bodyCopyback;
struct
{
uint32_t m_startCell;
uint32_t m_numCells;
uint32_t m_numBodies;
uint32_t m_numManifolds;
ManifoldCellHolder* m_manifoldHolders;
ConstraintCellHolder* m_constraintHolders;
btContactSolverInfoData m_solverInfo;
} m_manifoldSetup;
struct
{
btSpinlock::SpinVariable* m_spinLockVar;
} m_iterate;
} m_commandData;
};
void processSolverTask(void* userPtr, void* lsMemory);
void* createSolverLocalStoreMemory();
// Helper
inline bool constraintTypeSupported(btTypedConstraintType type)
{
return type == POINT2POINT_CONSTRAINT_TYPE ||
type == HINGE_CONSTRAINT_TYPE ||
type == CONETWIST_CONSTRAINT_TYPE ||
type == D6_CONSTRAINT_TYPE;
}
#endif