bool FPhysScene::SubstepSimulation(uint32 SceneType, FGraphEventRef &InOutCompletionEvent) { #if WITH_PHYSX check(SceneType != PST_Cloth); //we don't bother sub-stepping cloth float UseDelta = UseSyncTime(SceneType)? SyncDeltaSeconds : DeltaSeconds; float SubTime = PhysSubSteppers[SceneType]->UpdateTime(UseDelta); PxScene* PScene = GetPhysXScene(SceneType); if(SubTime <= 0.f) { return false; }else { //we have valid scene and subtime so enqueue task PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager()); ENamedThreads::Type NamedThread = PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread; DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.SubstepSimulationImp"), STAT_FSimpleDelegateGraphTask_SubstepSimulationImp, STATGROUP_TaskGraphTasks); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateRaw(PhysSubSteppers[SceneType], &FPhysSubstepTask::StepSimulation, Task), GET_STATID(STAT_FSimpleDelegateGraphTask_SubstepSimulationImp), NULL, NamedThread ); return true; } #endif }
bool FPhysScene::SubstepSimulation(uint32 SceneType, FGraphEventRef &InOutCompletionEvent) { float UseDelta = UseSyncTime(SceneType)? SyncDeltaSeconds : DeltaSeconds; float SubTime = PhysSubSteppers[SceneType]->UpdateTime(UseDelta); PxScene* PScene = GetPhysXScene(SceneType); #if WITH_APEX NxApexScene* ApexScene = GetApexScene(SceneType); if(!ApexScene || SubTime <= 0.f) { return false; }else { //we have valid scene and subtime so enqueue task PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager()); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(FSimpleDelegateGraphTask::FDelegate::CreateRaw(PhysSubSteppers[SceneType], &FPhysSubstepTask::StepSimulation, ApexScene, Task), TEXT("SubstepSimulationImp")); return true; } #endif }
RenderParticleSystemActor::RenderParticleSystemActor(SampleRenderer::Renderer& renderer, ParticleSystem* ps, bool _mesh_instancing, bool _fading, PxReal fadingPeriod, PxReal debriScaleFactor) : mRenderer(renderer), mPS(ps), mUseMeshInstancing(_mesh_instancing), mFading(_fading) { pxtask::CudaContextManager* ctxMgr = NULL; #if defined(RENDERER_ENABLE_CUDA_INTEROP) PxScene* scene = ps->getPxParticleBase()->getScene(); if (scene) { pxtask::GpuDispatcher* dispatcher = scene->getTaskManager()->getGpuDispatcher(); // contxt must be created in at least one valid interop mode if (dispatcher && (ctxMgr = dispatcher->getCudaContextManager()) && ctxMgr->getInteropMode() != pxtask::CudaInteropMode::D3D9_INTEROP && ctxMgr->getInteropMode() != pxtask::CudaInteropMode::D3D10_INTEROP && ctxMgr->getInteropMode() != pxtask::CudaInteropMode::D3D11_INTEROP) { ctxMgr = NULL; } } #endif RendererShape* rs = new SampleRenderer::RendererParticleSystemShape(mRenderer, mPS->getPxParticleBase()->getMaxParticles(), mUseMeshInstancing, mFading, fadingPeriod, debriScaleFactor, ctxMgr); setRenderShape(rs); }
/** Exposes ticking of physics-engine scene outside Engine. */ void FPhysScene::TickPhysScene(uint32 SceneType, FGraphEventRef& InOutCompletionEvent) { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_PhysicsKickOffDynamicsTime); check(SceneType < NumPhysScenes); if (bPhysXSceneExecuting[SceneType] != 0) { // Already executing this scene, must call WaitPhysScene before calling this function again. UE_LOG(LogPhysics, Log, TEXT("TickPhysScene: Already executing scene (%d) - aborting."), SceneType); return; } #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) //we don't bother sub-stepping cloth { //We're about to start stepping so swap buffers. Might want to find a better place for this? PhysSubSteppers[SceneType]->SwapBuffers(); } #endif /** * clamp down... if this happens we are simming physics slower than real-time, so be careful with it. * it can improve framerate dramatically (really, it is the same as scaling all velocities down and * enlarging all timesteps) but at the same time, it will screw with networking (client and server will * diverge a lot more.) */ float UseDelta = FMath::Min(UseSyncTime(SceneType) ? SyncDeltaSeconds : DeltaSeconds, MaxPhysicsDeltaTime); // Only simulate a positive time step. if (UseDelta <= 0.f) { if (UseDelta < 0.f) { // only do this if negative. Otherwise, whenever we pause, this will come up UE_LOG(LogPhysics, Warning, TEXT("TickPhysScene: Negative timestep (%f) - aborting."), UseDelta); } return; } #if WITH_PHYSX GatherPhysXStats(GetPhysXScene(SceneType), SceneType); #endif /** * Weight frame time according to PhysScene settings. */ AveragedFrameTime[SceneType] *= FrameTimeSmoothingFactor[SceneType]; AveragedFrameTime[SceneType] += (1.0f - FrameTimeSmoothingFactor[SceneType])*UseDelta; // Set execution flag bPhysXSceneExecuting[SceneType] = true; check(!InOutCompletionEvent.GetReference()); // these should be gone because nothing is outstanding InOutCompletionEvent = FGraphEvent::CreateGraphEvent(); bool bTaskOutstanding = false; #if WITH_PHYSX #if WITH_VEHICLE if (VehicleManager && SceneType == PST_Sync) { float TickTime = AveragedFrameTime[SceneType]; #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) { TickTime = UseSyncTime(SceneType) ? SyncDeltaSeconds : DeltaSeconds; } #endif VehicleManager->PreTick(TickTime); #if WITH_SUBSTEPPING if (IsSubstepping(SceneType) == false) #endif { VehicleManager->Update(AveragedFrameTime[SceneType]); } } #endif #if !WITH_APEX PxScene* PScene = GetPhysXScene(SceneType); if (PScene && (UseDelta > 0.f)) { PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager()); PScene->lockWrite(); PScene->simulate(AveragedFrameTime[SceneType], Task); PScene->unlockWrite(); Task->removeReference(); bTaskOutstanding = true; } #else // #if !WITH_APEX // The APEX scene calls the simulate function for the PhysX scene, so we only call ApexScene->simulate(). NxApexScene* ApexScene = GetApexScene(SceneType); if(ApexScene && UseDelta > 0.f) { #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) //we don't bother sub-stepping cloth { bTaskOutstanding = SubstepSimulation(SceneType, InOutCompletionEvent); }else #endif { PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, ApexScene->getTaskManager()); ApexScene->simulate(AveragedFrameTime[SceneType], true, Task); Task->removeReference(); bTaskOutstanding = true; } } #endif // #if !WITH_APEX #endif // WITH_PHYSX if (!bTaskOutstanding) { InOutCompletionEvent->DispatchSubsequents(); // nothing to do, so nothing to wait for } #if WITH_SUBSTEPPING bSubstepping = UPhysicsSettings::Get()->bSubstepping; bSubsteppingAsync = UPhysicsSettings::Get()->bSubsteppingAsync; #endif }
void ClothingScene::setModulePhysXScene(NxScene* newPhysXScene) { if (mPhysXScene == newPhysXScene) { return; } // init has not been called yet on mModule, so canUseGpuPhysics is not yet initialized!! // if (mModule->canUseGpuPhysics()) // PH: This is somewhat unsatisfying. // 1) We cannot release compartments because there's no API for that // 2) We cannot reuse compartments from an existing scene because we can't tell which ones were created by APEX and which ones by the user // 3) There is a maximum number of compartments a scene can hold (at least sw compartments) // if the user gives us NULL scene and then again the same scene as before it will contain more and more compartments, even though only // the ones created most recently are actually used. And it can run out of compartment space... mClothHwCompartments.clear(); mNextClothHwCompartmentId = 0; mClothSwCompartments.clear(); mNextClothSwCompartmentId = 0; NxScene* oldPhysXScene = mPhysXScene; #elif NX_SDK_VERSION_MAJOR == 3 void ClothingScene::setModulePhysXScene(PxScene* newPhysXScene) { if (mPhysXScene == newPhysXScene) { return; } PxScene* oldPhysXScene = mPhysXScene; #endif mPhysXScene = newPhysXScene; for (PxU32 i = 0; i < mActorArray.size(); ++i) { // downcast ClothingActor* actor = static_cast<ClothingActor*>(mActorArray[i]); actor->setPhysXScene(newPhysXScene); } mClothingAssetsMutex.lock(); for (PxU32 i = 0 ; i < mClothingAssets.size(); i++) { mClothingAssets[i]->hintSceneDeletion(oldPhysXScene); mClothingAssets[i]->releaseCookedInstances(); } mClothingAssets.clear(); mClothingAssetsMutex.unlock(); #ifdef PX_WINDOWS { if (mGpuFactory.factory != NULL && oldPhysXScene != NULL) { mSimulationTask->clearGpuSolver(); #if NX_SDK_VERSION_MAJOR == 2 mModule->releaseClothFactory(mApexScene->getTaskManager()->getGpuDispatcher()->getCudaContextManager()); #elif NX_SDK_VERSION_MAJOR == 3 PX_ASSERT(mApexScene->getTaskManager() == oldPhysXScene->getTaskManager()); mModule->releaseClothFactory(oldPhysXScene->getTaskManager()->getGpuDispatcher()->getCudaContextManager()); #endif mGpuFactory.clear(); } } #endif } void ClothingScene::release() { mModule->releaseNiModuleScene(*this); }