From 561a44e5d8b48bf3e5f2c27211d48fe1baa192de Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Mon, 17 Jun 2013 15:55:41 -0700 Subject: [PATCH] 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 ) --- Demos3/BasicGpuDemo/BasicGpuDemo.cpp | 23 ++-- Demos3/BasicGpuDemo/BasicGpuDemo.h | 6 + demos3/BasicGpuDemo/b3GpuDynamicsWorld.cpp | 60 ++++++---- src/Bullet3Common/b3AlignedObjectArray.h | 7 +- .../ParallelPrimitives/b3OpenCLArray.h | 50 +++++--- .../RigidBody/b3GpuNarrowPhase.cpp | 108 ++++++++++++++---- .../RigidBody/b3GpuNarrowPhase.h | 8 +- .../RigidBody/b3GpuRigidBodyPipeline.cpp | 21 ++-- 8 files changed, 203 insertions(+), 80 deletions(-) diff --git a/Demos3/BasicGpuDemo/BasicGpuDemo.cpp b/Demos3/BasicGpuDemo/BasicGpuDemo.cpp index a88606a28..1d8f8fc43 100644 --- a/Demos3/BasicGpuDemo/BasicGpuDemo.cpp +++ b/Demos3/BasicGpuDemo/BasicGpuDemo.cpp @@ -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; } diff --git a/Demos3/BasicGpuDemo/BasicGpuDemo.h b/Demos3/BasicGpuDemo/BasicGpuDemo.h index 2cd950df4..a7b377790 100644 --- a/Demos3/BasicGpuDemo/BasicGpuDemo.h +++ b/Demos3/BasicGpuDemo/BasicGpuDemo.h @@ -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); diff --git a/demos3/BasicGpuDemo/b3GpuDynamicsWorld.cpp b/demos3/BasicGpuDemo/b3GpuDynamicsWorld.cpp index 5554a26d6..6cca67ebf 100644 --- a/demos3/BasicGpuDemo/b3GpuDynamicsWorld.cpp +++ b/demos3/BasicGpuDemo/b3GpuDynamicsWorld.cpp @@ -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;im_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: diff --git a/src/Bullet3Common/b3AlignedObjectArray.h b/src/Bullet3Common/b3AlignedObjectArray.h index 5ff9876e7..cc510fc41 100644 --- a/src/Bullet3Common/b3AlignedObjectArray.h +++ b/src/Bullet3Common/b3AlignedObjectArray.h @@ -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()); diff --git a/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h b/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h index 7497ba70d..23249014d 100644 --- a/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h +++ b/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h @@ -131,7 +131,13 @@ public: //for (size_t i=curSize;i* m_pBufPairsCPU; - b3OpenCLArray* m_convexPairsOutGPU; - b3OpenCLArray* m_planePairs; + //b3OpenCLArray* m_convexPairsOutGPU; + //b3OpenCLArray* m_planePairs; b3OpenCLArray* m_pBufContactOutGPU; b3AlignedObjectArray* m_pBufContactOutCPU; @@ -100,8 +100,8 @@ m_queue(queue) m_data->m_pBufPairsCPU = new b3AlignedObjectArray; m_data->m_pBufPairsCPU->resize(config.m_maxBroadphasePairs); - m_data->m_convexPairsOutGPU = new b3OpenCLArray(ctx,queue,config.m_maxBroadphasePairs,false); - m_data->m_planePairs = new b3OpenCLArray(ctx,queue,config.m_maxBroadphasePairs,false); + //m_data->m_convexPairsOutGPU = new b3OpenCLArray(ctx,queue,config.m_maxBroadphasePairs,false); + //m_data->m_planePairs = new b3OpenCLArray(ctx,queue,config.m_maxBroadphasePairs,false); m_data->m_pBufContactOutCPU = new b3AlignedObjectArray(); 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 (curSizem_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* 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 && bodyIndexm_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 && bodyIndexm_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 && bodyIndexm_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; } diff --git a/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h b/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h index 3653cfdcb..80f0812a7 100644 --- a/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h +++ b/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h @@ -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; diff --git a/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp b/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp index b84507e38..296881e6f 100644 --- a/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp +++ b/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp @@ -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)