如果使用GPU,PhysX - simulate()永远不会结束

时间:2013-12-23 22:52:17

标签: c++ gpu-programming physx

我还在研究用于模拟流体的物理系统。我重写了我的应用程序以使用PhysX 3.3.0并且更加客观,现在我遇到了一个问题,我无法解决一两个星期。

这是我对PhysX上下文的启动:

void PhysXSPH::initContext(void){
    static LogPxErrorCallback gLogPxErrorCallback;
    static PxDefaultAllocator gDefaultAllocatorCallback;

    mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gLogPxErrorCallback);
    check(mFoundation, "PxFoundation creating failed!");

    static PxProfileZoneManager *mProfileZoneManager = &PxProfileZoneManager::createProfileZoneManager(mFoundation);
    check(mProfileZoneManager, "PxProfileZoneManager creation failed!");

    bool recordMemoryAllocations = true;
    mPhysics = PxCreateBasePhysics(PX_PHYSICS_VERSION, *mFoundation,
        PxTolerancesScale(), recordMemoryAllocations, mProfileZoneManager );
    check(mPhysics, "PxPhysics creating failed!");

    PxRegisterParticles(*mPhysics);
    if(!PxInitExtensions(*mPhysics)){
        check(NULL, "PxInitExtensions failed!");
    }

    static PxSimulationFilterShader gDefaultFilterShader = PxDefaultSimulationFilterShader;
    PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());

    sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);

    if(!sceneDesc.cpuDispatcher){
        mCpuDispatcher = PxDefaultCpuDispatcherCreate(4);
        check(mCpuDispatcher, "PxDefaultCpuDispatcherCreate failed!");
        sceneDesc.cpuDispatcher = mCpuDispatcher;
    }
    if(!sceneDesc.filterShader){
        sceneDesc.filterShader = gDefaultFilterShader;
    }

#ifdef PX_WINDOWS

    PxCudaContextManagerDesc cudaContextManagerDesc;
    mCudaContextManager = PxCreateCudaContextManager(*mFoundation, cudaContextManagerDesc, mProfileZoneManager);
    if( mCudaContextManager ){
        if( !mCudaContextManager->contextIsValid() ){
            mCudaContextManager->release();
            mCudaContextManager = NULL;
            CLOG(ERROR, "physX")<<"Invalid CUDA context.";
            exit(EXIT_FAILURE);
        }

        if(!sceneDesc.gpuDispatcher){
            sceneDesc.gpuDispatcher = mCudaContextManager->getGpuDispatcher();
        }
        CLOG(INFO, "physX")<<"CUDA context created.";
    } else {
        CLOG(ERROR, "physX")<<"Creating CUDA context manager failed.";
        exit(EXIT_FAILURE);
    }

#endif

    mScene = mPhysics->createScene(sceneDesc);
    check(mScene, "createScene failed!");

    createScene(mScene);
}

并启动一个physX场景,但即使是空场景也会出现问题:

void PhysXSPH::createScene(PxScene *mScene){
    mScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0);
    mScene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
    createPlanes(mScene);
    createParticles(mScene);
    CLOG(INFO, "physX") << "PhysX scene created.";
}

void PhysXSPH::createPlanes(PxScene *mScene){
    PxMaterial* mMaterial = mPhysics->createMaterial(0.5,0.5,0.5);

    //Create actors 
    //1) Create ground plane
    PxReal d = 0.0f;     
    PxTransform pose = PxTransform(PxVec3(0.0f, 0, 0.0f),PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f)));

    PxRigidStatic* plane = mPhysics->createRigidStatic(pose);
    check(plane, "Creating plane failed!");

    //create 4 more planes for aquarium

    PxRigidStatic* plane2 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(-4.0f, 0.0, 0.0), PxVec3(1.0, 0.0, 0.0)), *mMaterial);

    PxRigidStatic* plane3 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(4.0f, 0.0, 0.0), PxVec3(-1.0, 0.0, 0.0)), *mMaterial);

    PxRigidStatic* plane4 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(0.0f, 0.0, -4.0f), PxVec3(0.0, 0.0, 1.0)), *mMaterial);

    PxRigidStatic* plane5 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(0.0f, 0.0, 4.0f), PxVec3(0.0, 0.0, -1.0)), *mMaterial);

    // create shape
    PxShape* shape = plane->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape, "Creating shape failed!");

    mScene->addActor(*plane);

    PxShape* shape2 = plane2->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape2, "Creating shape failed!");
    mScene->addActor(*plane2);


    PxShape* shape3 = plane3->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape3, "Creating shape failed!");
    mScene->addActor(*plane3);

    PxShape* shape4 = plane4->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape4, "Creating shape failed!");
    mScene->addActor(*plane4);

    PxShape* shape5 = plane5->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape5, "Creating shape failed!");
    mScene->addActor(*plane5);
}

void PhysXSPH::createParticles(PxScene *mScene){
    // set immutable properties.
    bool perParticleRestOffset = false;

    //get data from scene model
    int maxParticles = scene->getMaxParticles();
    int xDim = scene->getXDim();
    int yDim = scene->getYDim();
    int zDim = scene->getZDim();

    // create particle system in PhysX SDK
    particleSystem = mPhysics->createParticleFluid(maxParticles, perParticleRestOffset);
    check(particleSystem, "Creating particle system failed!");

    particleSystem->setRestOffset(particleRadius);
    particleSystem->setRestParticleDistance(particleRadius);
    particleSystem->setParticleBaseFlag(PxParticleBaseFlag::eGPU,true);
    // TODO set fluid parameters


    // add particle system to scene, in case creation was successful
    if (particleSystem)
        mScene->addActor(*particleSystem);

    indexes = new PxU32[maxParticles];
    particle_positions = new PxVec3[maxParticles];

    int index=0;
    for(int x=0; x<xDim ;x++){
        for(int y=0; y<yDim ;y++){
            for(int z=0; z<zDim; z++){
                indexes[index]=(PxU32)index;
                int v=3*index;

                particle_positions[index]=PxVec3((physx::PxReal)(scene->m_vPos[v]), (physx::PxReal)(scene->m_vPos[v+1]), (physx::PxReal)(scene->m_vPos[v+2]));

                //CLOG(INFO, "physX")<<index<<"["<<particle_positions[index].x<<"; "<<particle_positions[index].y<<"; "<<particle_positions[index].z<<"]";
                index++;
            }
        }
    }

    PxParticleCreationData particleCreationData;
    particleCreationData.numParticles = maxParticles;
    particleCreationData.indexBuffer = PxStrideIterator<const PxU32>(indexes);
    particleCreationData.positionBuffer = PxStrideIterator<const PxVec3>(particle_positions);

    // create particles in *PxParticleSystem* ps
    bool success = particleSystem->createParticles(particleCreationData);
    if(!success){
        CLOG(ERROR, "physX")<<"Creating particles failed.";
        exit(EXIT_FAILURE);
    }
}

如果#ifdef PX_WINDOWS中的代码被注释,一切正常。流体像它应该流动。但是当我尝试使用我的GPU时,应用程序会在第一次fetchResult()调用时冻结(simulate()方法永远不会完成它的工作)。我没有错误日志,它只是冻结。无论是DEBUG还是RELEASE,如果它是32或64版本都会发生。

我有一台GeForce 560Ti。我使用Physx SDK 3.3.0。我链接(例如,在win64调试版本上)vs:

  

opengl32.lib glew32.lib glfw3.lib PhysX3DEBUG_x64.lib   PhysX3CommonDEBUG_x64.lib PxTaskDEBUG.lib PhysX3ExtensionsDEBUG.lib   PhysXProfileSDKDEBUG.lib

使用:

  

nvToolsExt64_1.dll PhysX3XHECKED_x64.dll PhysX3CommonCHECKED_x64.dll   PhysX3GpuCHECKED_x64.dll PhysX3GpuDEBUG_x64.dll

我尝试使用不同版本的.libs并添加应用程序所需的.dll,但每一组最终都冻结了fetchResult()。

我不知道在哪里寻找错误。一切都很好看。我会感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

我知道这是一个旧线程,但当我从3.2.5切换到3.3.0时,我遇到了完全相同的问题。

我确实找到了解决方案。问题是你在这里初始化扩展两次。您正在使用PxCreateBasePhysics创建SDK对象,该对象在后台执行一些额外的工作。即如果我没有弄错的话,它会调用PxInitExtensions

修复方法是只使用完全相同的参数将PxCreateBasePhysics函数更改为标准PxCreatePhysics调用。这个没有在场景后面做任何额外的设置。只是省略InitExtensions电话可能也会有效,但我只尝试了第一个想法。

奇怪的是,如果使用GPU,这只会导致冻结,也许nVidia应该看一下。