virtual bool	processOverlap(btBroadphasePair& collisionPair)
	{


		//PPU version
		//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);

		//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
		btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);

		//by default, Bullet will use this near callback
		{
			///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
			if (!collisionPair.m_internalTmpValue)
			{
				collisionPair.m_internalTmpValue = 1;
			}
			if (!collisionPair.m_algorithm)
			{
				btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
				btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;

				btCollisionAlgorithmConstructionInfo ci;
				ci.m_dispatcher1 = m_dispatcher;
				ci.m_manifold = 0;

				if (m_dispatcher->needsCollision(colObj0,colObj1))
				{
					int	proxyType0 = colObj0->getCollisionShape()->getShapeType();
					int	proxyType1 = colObj1->getCollisionShape()->getShapeType();
					if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1))
					{
						int so = sizeof(SpuContactManifoldCollisionAlgorithm);
#ifdef ALLOCATE_SEPARATELY
						void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
#else
						void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
#endif
						collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
						collisionPair.m_internalTmpValue =  2;
					} else
					{
						collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
						collisionPair.m_internalTmpValue = 3;
					}
				} 
			}
		}
		return false;
	}
	virtual bool	processOverlap(btBroadphasePair& collisionPair)
	{


		//PPU version
		//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);

		//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
		btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);

		//by default, Bullet will use this near callback
		{
			///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
			if (!collisionPair.m_internalTmpValue)
			{
				collisionPair.m_internalTmpValue = 1;
			}
			if (!collisionPair.m_algorithm)
			{
				btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
				btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;

				btCollisionAlgorithmConstructionInfo ci;
				ci.m_dispatcher1 = m_dispatcher;
				ci.m_manifold = 0;

				if (m_dispatcher->needsCollision(colObj0,colObj1))
				{
					int	proxyType0 = colObj0->getCollisionShape()->getShapeType();
					int	proxyType1 = colObj1->getCollisionShape()->getShapeType();
					bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) 
						&& ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0)
						&& ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0);

					if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
					{
						btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
						if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
						{
							//printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
							supportsSpuDispatch = false;
						}
					}

					if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
					{
						btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
						if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
						{
							//printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
							supportsSpuDispatch = false;
						}
					}

					if (supportsSpuDispatch)
					{

						int so = sizeof(SpuContactManifoldCollisionAlgorithm);
#ifdef ALLOCATE_SEPARATELY
						void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
#else
						void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
#endif
						collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
						collisionPair.m_internalTmpValue =  2;
					} else
					{
						btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform());
						btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform());

						collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1);
						collisionPair.m_internalTmpValue = 3;
					}
				} 
			}
		}
		return false;
	}