Try to avoid crashes if memory allocations fail

Deal with cases exceeding allocations of bodies/shapes above the limits set in b3Config
(work-in-progress )
This commit is contained in:
erwincoumans 2013-06-17 15:55:41 -07:00
parent e179d5882e
commit 561a44e5d8
8 changed files with 203 additions and 80 deletions

View File

@ -163,6 +163,8 @@ void BasicGpuDemo::exitCL()
BasicGpuDemo::BasicGpuDemo()
{
m_np=0;
m_bp=0;
m_clData = new btInternalData;
setCameraDistance(btScalar(SCALING*60.));
this->setAzi(45);
@ -207,15 +209,14 @@ void BasicGpuDemo::initPhysics()
}
b3Config config;
b3GpuNarrowPhase* np = new b3GpuNarrowPhase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue,config);
b3GpuSapBroadphase* bp = new b3GpuSapBroadphase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
//m_data->m_np = np;
//m_data->m_bp = bp;
m_np = new b3GpuNarrowPhase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue,config);
m_bp = new b3GpuSapBroadphase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
b3DynamicBvhBroadphase* broadphaseDbvt = new b3DynamicBvhBroadphase(config.m_maxConvexBodies);
b3GpuRigidBodyPipeline* rbp = new b3GpuRigidBodyPipeline(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue, np, bp,broadphaseDbvt,config);
m_rbp = new b3GpuRigidBodyPipeline(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue, m_np, m_bp,broadphaseDbvt,config);
m_dynamicsWorld = new b3GpuDynamicsWorld(bp,np,rbp);
m_dynamicsWorld = new b3GpuDynamicsWorld(m_bp,m_np,m_rbp);
m_dynamicsWorld->setDebugDrawer(&gDebugDraw);
@ -333,9 +334,9 @@ void BasicGpuDemo::initPhysics()
np->writeAllBodiesToGpu();
bp->writeAabbsToGpu();
rbp->writeAllInstancesToGpu();
m_np->writeAllBodiesToGpu();
m_bp->writeAabbsToGpu();
m_rbp->writeAllInstancesToGpu();
}
void BasicGpuDemo::clientResetScene()
@ -382,7 +383,11 @@ void BasicGpuDemo::exitPhysics()
delete m_collisionConfiguration;
delete m_np;
delete m_bp;
delete m_rbp;
}

View File

@ -48,6 +48,12 @@ class BasicGpuDemo : public PlatformDemoApplication
btDefaultCollisionConfiguration* m_collisionConfiguration;
class b3GpuNarrowPhase* m_np;
class b3GpuSapBroadphase* m_bp;
class b3GpuRigidBodyPipeline* m_rbp;
struct btInternalData* m_clData;
void initCL(int d, int p);

View File

@ -72,9 +72,15 @@ int b3GpuDynamicsWorld::stepSimulation( btScalar timeStepUnused, int maxSubStep
b3Assert(m_np->getNumRigidBodies() == m_bodyUpdateRevisions.size());
#endif //BT_USE_BODY_UPDATE_REVISION
b3RigidBodyCL* bodiesCL = m_np->getBodiesCpu();
for (int i=0;i<this->m_collisionObjects.size();i++)
{
if (i>=m_np->getNumRigidBodies())
{
b3Error("bodiesCL out-of-range\n");
continue;
}
#ifdef BT_USE_BODY_UPDATE_REVISION
if (m_bodyUpdateRevisions[i] != m_collisionObjects[i]->getUpdateRevisionInternal())
#endif//BT_USE_BODY_UPDATE_REVISION
@ -85,14 +91,19 @@ int b3GpuDynamicsWorld::stepSimulation( btScalar timeStepUnused, int maxSubStep
m_bodyUpdateRevisions[i] = m_collisionObjects[i]->getUpdateRevisionInternal();
#endif
bodiesCL[i].m_pos = (const b3Vector3&)m_collisionObjects[i]->getWorldTransform().getOrigin();
bodiesCL[i].m_quat = (const b3Quaternion&)m_collisionObjects[i]->getWorldTransform().getRotation();
btRigidBody* body = btRigidBody::upcast(m_collisionObjects[i]);
if (body)
{
b3Vector3 pos = (const b3Vector3&)m_collisionObjects[i]->getWorldTransform().getOrigin();
b3Quaternion orn = (const b3Quaternion&)m_collisionObjects[i]->getWorldTransform().getRotation();
body->integrateVelocities(fixedTimeStep);
bodiesCL[i].m_linVel = (const b3Vector3&)body->getLinearVelocity();
bodiesCL[i].m_angVel = (const b3Vector3&)body->getAngularVelocity();
m_np->setObjectTransformCpu(&pos[0],&orn[0],i);
b3Vector3 linVel = (const b3Vector3&)body->getLinearVelocity();
b3Vector3 angVel = (const b3Vector3&)body->getAngularVelocity();
m_np->setObjectVelocityCpu(&linVel[0],&angVel[0],i);
}
}
@ -140,19 +151,21 @@ int b3GpuDynamicsWorld::stepSimulation( btScalar timeStepUnused, int maxSubStep
{
btVector3 pos;
btQuaternion orn;
m_np->getObjectTransformFromCpu(&pos[0],&orn[0],i);
btTransform newTrans;
newTrans.setOrigin(pos);
newTrans.setRotation(orn);
btCollisionObject* colObj = this->m_collisionObjects[i];
colObj->setWorldTransform(newTrans);
btRigidBody* body = btRigidBody::upcast(m_collisionObjects[i]);
if (body)
if (m_np->getObjectTransformFromCpu(&pos[0],&orn[0],i))
{
body->setLinearVelocity((btVector3&)bodiesCL[i].m_linVel);
body->setAngularVelocity((btVector3&)bodiesCL[i].m_angVel);
btTransform newTrans;
newTrans.setOrigin(pos);
newTrans.setRotation(orn);
btCollisionObject* colObj = this->m_collisionObjects[i];
colObj->setWorldTransform(newTrans);
btRigidBody* body = btRigidBody::upcast(m_collisionObjects[i]);
if (body)
{
body->setLinearVelocity((btVector3&)bodiesCL[i].m_linVel);
body->setAngularVelocity((btVector3&)bodiesCL[i].m_angVel);
}
}
@ -512,9 +525,16 @@ void b3GpuDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool disab
int rbA = p->getRigidBodyA().getUserIndex();
int rbB = p->getRigidBodyB().getUserIndex();
b3Point2PointConstraint* p2p = new b3Point2PointConstraint(rbA,rbB, (const b3Vector3&)p->getPivotInA(),(const b3Vector3&)p->getPivotInB());
constraint->setUserConstraintPtr(p2p);
m_rigidBodyPipeline->addConstraint(p2p);
if (rbA>=0 && rbB>=0)
{
b3Point2PointConstraint* p2p = new b3Point2PointConstraint(rbA,rbB, (const b3Vector3&)p->getPivotInA(),(const b3Vector3&)p->getPivotInB());
constraint->setUserConstraintPtr(p2p);
m_rigidBodyPipeline->addConstraint(p2p);
} else
{
constraint->setUserConstraintPtr(0);
b3Error("invalid body index in addConstraint.\n");
}
break;
}
default:

View File

@ -303,7 +303,12 @@ protected:
{ // not enough room, reallocate
T* s = (T*)allocate(_Count);
b3Assert(s);
if (s==0)
{
b3Error("b3AlignedObjectArray reserve out-of-memory\n");
_Count=0;
m_size=0;
}
copy(0, size(), s);
destroy(0,size());

View File

@ -131,7 +131,13 @@ public:
//for (size_t i=curSize;i<newsize;i++) ...
}
m_size = newsize;
if (result)
{
m_size = newsize;
} else
{
m_size = 0;
}
return result;
}
@ -161,6 +167,7 @@ public:
b3Assert(ciErrNum==CL_SUCCESS);
if (ciErrNum!=CL_SUCCESS)
{
_Count = 0;
result = false;
}
//#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
@ -241,14 +248,19 @@ public:
{
b3Assert(numElems+destFirstElem <= capacity());
cl_int status = 0;
size_t sizeInBytes=sizeof(T)*numElems;
status = clEnqueueWriteBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*destFirstElem, sizeInBytes,
src, 0,0,0 );
b3Assert(status == CL_SUCCESS );
if (waitForCompletion)
clFinish(m_commandQueue);
if (numElems+destFirstElem)
{
cl_int status = 0;
size_t sizeInBytes=sizeof(T)*numElems;
status = clEnqueueWriteBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*destFirstElem, sizeInBytes,
src, 0,0,0 );
b3Assert(status == CL_SUCCESS );
if (waitForCompletion)
clFinish(m_commandQueue);
} else
{
b3Error("copyFromHostPointer invalid range\n");
}
}
@ -262,14 +274,20 @@ public:
void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem=0, bool waitForCompletion=true) const
{
b3Assert(numElem+srcFirstElem <= capacity());
if(numElem+srcFirstElem <= capacity())
{
cl_int status = 0;
status = clEnqueueReadBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*srcFirstElem, sizeof(T)*numElem,
destPtr, 0,0,0 );
b3Assert( status==CL_SUCCESS );
cl_int status = 0;
status = clEnqueueReadBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*srcFirstElem, sizeof(T)*numElem,
destPtr, 0,0,0 );
b3Assert( status==CL_SUCCESS );
if (waitForCompletion)
clFinish(m_commandQueue);
if (waitForCompletion)
clFinish(m_commandQueue);
} else
{
b3Error("copyToHostPointer invalid range\n");
}
}
void copyFromOpenCLArray(const b3OpenCLArray& src)

View File

@ -42,8 +42,8 @@ struct b3GpuNarrowPhaseInternalData
b3AlignedObjectArray<b3Int2>* m_pBufPairsCPU;
b3OpenCLArray<b3Int2>* m_convexPairsOutGPU;
b3OpenCLArray<b3Int2>* m_planePairs;
//b3OpenCLArray<b3Int2>* m_convexPairsOutGPU;
//b3OpenCLArray<b3Int2>* m_planePairs;
b3OpenCLArray<b3Contact4>* m_pBufContactOutGPU;
b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
@ -100,8 +100,8 @@ m_queue(queue)
m_data->m_pBufPairsCPU = new b3AlignedObjectArray<b3Int2>;
m_data->m_pBufPairsCPU->resize(config.m_maxBroadphasePairs);
m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
//m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
//m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
@ -176,8 +176,8 @@ b3GpuNarrowPhase::~b3GpuNarrowPhase()
{
delete m_data->m_gpuSatCollision;
delete m_data->m_pBufPairsCPU;
delete m_data->m_convexPairsOutGPU;
delete m_data->m_planePairs;
//delete m_data->m_convexPairsOutGPU;
//delete m_data->m_planePairs;
delete m_data->m_pBufContactOutCPU;
delete m_data->m_bodyBufferCPU;
delete m_data->m_inertiaBufferCPU;
@ -213,8 +213,17 @@ b3GpuNarrowPhase::~b3GpuNarrowPhase()
int b3GpuNarrowPhase::allocateCollidable()
{
int curSize = m_data->m_collidablesCPU.size();
m_data->m_collidablesCPU.expand();
return curSize;
if (curSize<m_data->m_config.m_maxConvexShapes)
{
m_data->m_collidablesCPU.expand();
return curSize;
}
else
{
b3Error("allocateCollidable out-of-range %d\n",m_data->m_config.m_maxConvexShapes);
}
return -1;
}
@ -224,6 +233,9 @@ int b3GpuNarrowPhase::allocateCollidable()
int b3GpuNarrowPhase::registerSphereShape(float radius)
{
int collidableIndex = allocateCollidable();
if (collidableIndex<0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_SPHERE;
@ -269,6 +281,9 @@ int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConsta
int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
{
int collidableIndex = allocateCollidable();
if (collidableIndex<0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_PLANE;
@ -391,6 +406,9 @@ int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int stride
int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
{
int collidableIndex = allocateCollidable();
if (collidableIndex<0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_CONVEX_HULL;
col.m_shapeIndex = -1;
@ -440,6 +458,9 @@ int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShap
{
int collidableIndex = allocateCollidable();
if (collidableIndex<0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_COMPOUND_OF_CONVEX_HULLS;
@ -512,6 +533,9 @@ int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vert
b3Vector3 scaling(scaling1[0],scaling1[1],scaling1[2]);
int collidableIndex = allocateCollidable();
if (collidableIndex<0)
return collidableIndex;
b3Collidable& col = getCollidableCpu(collidableIndex);
col.m_shapeType = SHAPE_CONCAVE_TRIMESH;
@ -677,10 +701,7 @@ const struct b3RigidBodyCL* b3GpuNarrowPhase::getBodiesCpu() const
return &m_data->m_bodyBufferCPU->at(0);
};
struct b3RigidBodyCL* b3GpuNarrowPhase::getBodiesCpu()
{
return &m_data->m_bodyBufferCPU->at(0);
};
int b3GpuNarrowPhase::getNumBodiesGpu() const
@ -716,7 +737,9 @@ cl_mem b3GpuNarrowPhase::getCollidablesGpu()
const struct b3Collidable* b3GpuNarrowPhase::getCollidablesCpu() const
{
return &m_data->m_collidablesCPU[0];
if (m_data->m_collidablesCPU.size())
return &m_data->m_collidablesCPU[0];
return 0;
}
@ -806,7 +829,12 @@ int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const f
b3Vector3 aabbMin(aabbMinPtr[0],aabbMinPtr[1],aabbMinPtr[2]);
b3Vector3 aabbMax (aabbMaxPtr[0],aabbMaxPtr[1],aabbMaxPtr[2]);
b3Assert(m_data->m_numAcceleratedRigidBodies< (m_data->m_config.m_maxConvexBodies-1));
if (m_data->m_numAcceleratedRigidBodies >= (m_data->m_config.m_maxConvexBodies))
{
b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n",m_data->m_numAcceleratedRigidBodies,m_data->m_config.m_maxConvexBodies);
return -1;
}
m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies+1);
@ -961,15 +989,47 @@ void b3GpuNarrowPhase::readbackAllBodiesToCpu()
{
m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
}
void b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const
{
position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
position[3] = 1.f;//or 1
orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
orientation[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.z;
orientation[3] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.w;
void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation , int bodyIndex)
{
if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
{
m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.setValue(position[0],position[1],position[2]);
m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
}
else
{
b3Warning("setObjectVelocityCpu out of range.\n");
}
}
void b3GpuNarrowPhase::setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex)
{
if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
{
m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel.setValue(linVel[0],linVel[1],linVel[2]);
m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel.setValue(angVel[0],angVel[1],angVel[2]);
} else
{
b3Warning("setObjectVelocityCpu out of range.\n");
}
}
bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const
{
if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
{
position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
position[3] = 1.f;//or 1
orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
orientation[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.z;
orientation[3] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.w;
return true;
}
b3Warning("getObjectTransformFromCpu out of range.\n");
return false;
}

View File

@ -50,14 +50,18 @@ public:
void writeAllBodiesToGpu();
void reset();
void readbackAllBodiesToCpu();
void getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
bool getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
void setObjectTransformCpu(float* position, float* orientation , int bodyIndex);
void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbs, int numObjects);
cl_mem getBodiesGpu();
const struct b3RigidBodyCL* getBodiesCpu() const;
struct b3RigidBodyCL* getBodiesCpu();
//struct b3RigidBodyCL* getBodiesCpu();
int getNumBodiesGpu() const;

View File

@ -392,8 +392,6 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
b3Vector3 aabbMin(0,0,0),aabbMax(0,0,0);
int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
if (collidableIndex>=0)
{
@ -407,6 +405,19 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
t.setOrigin(b3Vector3(position[0],position[1],position[2]));
t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
b3TransformAabb(localAabbMin,localAabbMax, margin,t,aabbMin,aabbMax);
} else
{
b3Error("registerPhysicsInstance using invalid collidableIndex\n");
return -1;
}
bool writeToGpu = false;
int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex,mass,position,orientation,&aabbMin.getX(),&aabbMax.getX(),writeToGpu);
if (bodyIndex>=0)
{
if (useDbvt)
{
m_data->m_broadphaseDbvt->createProxy(aabbMin,aabbMax,bodyIndex,0,1,1);
@ -433,12 +444,6 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
}
}
}
bool writeToGpu = false;
bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex,mass,position,orientation,&aabbMin.getX(),&aabbMax.getX(),writeToGpu);
/*
if (mass>0.f)