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 }
void FPhysSubstepTask::SubstepSimulationStart() { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_SubstepSimulationStart); #if WITH_PHYSX check(SubTime > 0.f); check(DeltaSeconds > 0.f); check(!CompletionEvent.GetReference()); //should be done CompletionEvent = FGraphEvent::CreateGraphEvent(); PhysXCompletionTask* SubstepTask = new PhysXCompletionTask(CompletionEvent, PST_MAX //we don't care about sub-step time. The full time is recorded by FullSimulationTask ,PAScene->getTaskManager()); ENamedThreads::Type NamedThread = PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread; DECLARE_CYCLE_STAT(TEXT("FDelegateGraphTask.ProcessPhysSubstepSimulation"), STAT_FDelegateGraphTask_ProcessPhysSubstepSimulation, STATGROUP_TaskGraphTasks); FDelegateGraphTask::CreateAndDispatchWhenReady( FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysSubstepTask::SubstepSimulationEnd), GET_STATID(STAT_FDelegateGraphTask_ProcessPhysSubstepSimulation), CompletionEvent, NamedThread, NamedThread); ++CurrentSubStep; bool bLastSubstep = CurrentSubStep >= NumSubsteps; if (!bLastSubstep) { Alpha += StepScale; TotalSubTime += SubTime; } float DeltaTime = bLastSubstep ? (DeltaSeconds - TotalSubTime) : SubTime; float Interpolation = bLastSubstep ? 1.f : Alpha; #if WITH_VEHICLE if (VehicleManager) { VehicleManager->Update(DeltaTime); } #endif SubstepInterpolation(Interpolation, DeltaTime); #if WITH_APEX PAScene->simulate(DeltaTime, bLastSubstep, SubstepTask); #else PAScene->lockWrite(); PAScene->simulate(DeltaTime, SubstepTask); PAScene->unlockWrite(); #endif SubstepTask->removeReference(); #endif }
void FPhysScene::StartFrame() { FGraphEventArray FinishPrerequisites; // Run the sync scene TickPhysScene(PST_Sync, PhysicsSubsceneCompletion[PST_Sync]); { FGraphEventArray MainScenePrerequisites; if (FrameLagAsync() && bAsyncSceneEnabled) { if (FrameLaggedPhysicsSubsceneCompletion[PST_Async].GetReference() && !FrameLaggedPhysicsSubsceneCompletion[PST_Async]->IsComplete()) { MainScenePrerequisites.Add(FrameLaggedPhysicsSubsceneCompletion[PST_Async]); FinishPrerequisites.Add(FrameLaggedPhysicsSubsceneCompletion[PST_Async]); } } if (PhysicsSubsceneCompletion[PST_Sync].GetReference()) { MainScenePrerequisites.Add(PhysicsSubsceneCompletion[PST_Sync]); new (FinishPrerequisites) FGraphEventRef(FDelegateGraphTask::CreateAndDispatchWhenReady(FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysScene::SceneCompletionTask, PST_Sync), TEXT("ProcessPhysScene_Sync"), &MainScenePrerequisites, ENamedThreads::GameThread, ENamedThreads::GameThread)); } } if (!FrameLagAsync() && bAsyncSceneEnabled) { TickPhysScene(PST_Async, PhysicsSubsceneCompletion[PST_Async]); if (PhysicsSubsceneCompletion[PST_Async].GetReference()) { new (FinishPrerequisites) FGraphEventRef(FDelegateGraphTask::CreateAndDispatchWhenReady(FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysScene::SceneCompletionTask, PST_Async), TEXT("ProcessPhysScene_Async"), PhysicsSubsceneCompletion[PST_Async], ENamedThreads::GameThread, ENamedThreads::GameThread)); } } check(!PhysicsSceneCompletion.GetReference()); // this should have been cleared if (FinishPrerequisites.Num()) { if (FinishPrerequisites.Num() > 1) // we don't need to create a new task if we only have one prerequisite { PhysicsSceneCompletion = TGraphTask<FNullGraphTask>::CreateTask(&FinishPrerequisites, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(TEXT("ProcessPhysScene_Join"), PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread); } else { PhysicsSceneCompletion = FinishPrerequisites[0]; // we don't need a join } } // Record the sync tick time for use with the async tick SyncDeltaSeconds = DeltaSeconds; }
void FPhysScene::StartFrame() { FGraphEventArray FinishPrerequisites; //Update the collision disable table before ticking FlushDeferredCollisionDisableTableQueue(); #if WITH_PHYSX // Flush list of deferred actors to add to the scene FlushDeferredActors(); #endif // Run the sync scene TickPhysScene(PST_Sync, PhysicsSubsceneCompletion[PST_Sync]); { FGraphEventArray MainScenePrerequisites; if (FrameLagAsync() && bAsyncSceneEnabled) { if (FrameLaggedPhysicsSubsceneCompletion[PST_Async].GetReference() && !FrameLaggedPhysicsSubsceneCompletion[PST_Async]->IsComplete()) { MainScenePrerequisites.Add(FrameLaggedPhysicsSubsceneCompletion[PST_Async]); FinishPrerequisites.Add(FrameLaggedPhysicsSubsceneCompletion[PST_Async]); } } if (PhysicsSubsceneCompletion[PST_Sync].GetReference()) { MainScenePrerequisites.Add(PhysicsSubsceneCompletion[PST_Sync]); DECLARE_CYCLE_STAT(TEXT("FDelegateGraphTask.ProcessPhysScene_Sync"), STAT_FDelegateGraphTask_ProcessPhysScene_Sync, STATGROUP_TaskGraphTasks); new (FinishPrerequisites)FGraphEventRef( FDelegateGraphTask::CreateAndDispatchWhenReady( FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysScene::SceneCompletionTask, PST_Sync), GET_STATID(STAT_FDelegateGraphTask_ProcessPhysScene_Sync), &MainScenePrerequisites, ENamedThreads::GameThread, ENamedThreads::GameThread ) ); } } if (!FrameLagAsync() && bAsyncSceneEnabled) { TickPhysScene(PST_Async, PhysicsSubsceneCompletion[PST_Async]); if (PhysicsSubsceneCompletion[PST_Async].GetReference()) { DECLARE_CYCLE_STAT(TEXT("FDelegateGraphTask.ProcessPhysScene_Async"), STAT_FDelegateGraphTask_ProcessPhysScene_Async, STATGROUP_TaskGraphTasks); new (FinishPrerequisites)FGraphEventRef( FDelegateGraphTask::CreateAndDispatchWhenReady( FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysScene::SceneCompletionTask, PST_Async), GET_STATID(STAT_FDelegateGraphTask_ProcessPhysScene_Async), PhysicsSubsceneCompletion[PST_Async], ENamedThreads::GameThread, ENamedThreads::GameThread ) ); } } check(!PhysicsSceneCompletion.GetReference()); // this should have been cleared if (FinishPrerequisites.Num()) { if (FinishPrerequisites.Num() > 1) // we don't need to create a new task if we only have one prerequisite { DECLARE_CYCLE_STAT(TEXT("FNullGraphTask.ProcessPhysScene_Join"), STAT_FNullGraphTask_ProcessPhysScene_Join, STATGROUP_TaskGraphTasks); PhysicsSceneCompletion = TGraphTask<FNullGraphTask>::CreateTask(&FinishPrerequisites, ENamedThreads::GameThread).ConstructAndDispatchWhenReady( GET_STATID(STAT_FNullGraphTask_ProcessPhysScene_Join), PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread); } else { PhysicsSceneCompletion = FinishPrerequisites[0]; // we don't need a join } } // Record the sync tick time for use with the async tick SyncDeltaSeconds = DeltaSeconds; }
/** Exposes creation of physics-engine scene outside Engine (for use with PhAT for example). */ FPhysScene::FPhysScene() #if WITH_APEX : PendingApexDamageManager(new FPendingApexDamageManager) #endif { LineBatcher = NULL; OwningWorld = NULL; #if WITH_PHYSX #if WITH_VEHICLE VehicleManager = NULL; #endif PhysxUserData = FPhysxUserData(this); // Create dispatcher for tasks if (PhysSingleThreadedMode()) { CPUDispatcher = new FPhysXCPUDispatcherSingleThread(); } else { CPUDispatcher = new FPhysXCPUDispatcher(); } // Create sim event callback SimEventCallback = new FPhysXSimEventCallback(); #endif //#if WITH_PHYSX // initialize console variable - this console variable change requires it to restart scene. static bool bInitializeConsoleVariable = true; static float InitialAverageFrameRate = 0.016f; UPhysicsSettings * PhysSetting = UPhysicsSettings::Get(); if (bInitializeConsoleVariable) { InitialAverageFrameRate = PhysSetting->InitialAverageFrameRate; FrameTimeSmoothingFactor[PST_Sync] = PhysSetting->SyncSceneSmoothingFactor; FrameTimeSmoothingFactor[PST_Async] = PhysSetting->AsyncSceneSmoothingFactor; bInitializeConsoleVariable = false; } #if WITH_SUBSTEPPING bSubstepping = PhysSetting->bSubstepping; bSubsteppingAsync = PhysSetting->bSubsteppingAsync; #endif bAsyncSceneEnabled = PhysSetting->bEnableAsyncScene; NumPhysScenes = bAsyncSceneEnabled ? PST_Async + 1 : PST_Cloth + 1; // Create scenes of all scene types for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType) { // Create the physics scene InitPhysScene(SceneType); // Also initialize scene data bPhysXSceneExecuting[SceneType] = false; // Initialize to a value which would be acceptable if FrameTimeSmoothingFactor[i] = 1.0f, i.e. constant simulation substeps AveragedFrameTime[SceneType] = InitialAverageFrameRate; // gets from console variable, and clamp to [0, 1] - 1 should be fixed time as 30 fps FrameTimeSmoothingFactor[SceneType] = FMath::Clamp<float>(FrameTimeSmoothingFactor[SceneType], 0.f, 1.f); } if (!bAsyncSceneEnabled) { PhysXSceneIndex[PST_Async] = 0; } // Make sure we use the sync scene for apex world support of destructibles in the async scene #if WITH_APEX NxApexScene* ApexScene = GetApexScene(bAsyncSceneEnabled ? PST_Async : PST_Sync); check(ApexScene); PxScene* SyncPhysXScene = GetPhysXScene(PST_Sync); check(SyncPhysXScene); check(GApexModuleDestructible); GApexModuleDestructible->setWorldSupportPhysXScene(*ApexScene, SyncPhysXScene); GApexModuleDestructible->setDamageApplicationRaycastFlags(NxDestructibleActorRaycastFlags::AllChunks, *ApexScene); #endif }