void FEngine::Run(FGameThread::FCreateGameSceneFunc CreateGameSceneFunc) { Init(CreateGameSceneFunc); F_Assert(IsValid(), "Engine failed to initialize."); const Float32 FramesPerSec = 120.f; const Float32 MaxDeltaTime = 1.f / FramesPerSec; TThreadSafeVector<FEvent>::ContainerT ReceivedEvents; Float32 AccumulatedTime = 0.f; FHighResolutionTimer Timer; Timer.Reset(); while (IsRunning) { Timer.Update(); const Float32 DeltaTimeSec = Timer.GetDeltaSeconds<Float32>(); AccumulatedTime += DeltaTimeSec; if (AccumulatedTime >= MaxDeltaTime) { AccumulatedTime = FMathf::Modulo(AccumulatedTime, MaxDeltaTime); Window->ProcessEvents(); GamePadUtility.ProcessEvents(EventHandler); OutgoingEvents.AddData(EventHandler.GetEvents()); EventHandler.GetEvents().clear(); IncomingEvents.GetDataAndClear(ReceivedEvents); for (SizeT I = 0; I < ReceivedEvents.size(); ++I) { const FEvent& Event = ReceivedEvents[I]; HandleEvent(Event); } ReceivedEvents.clear(); } NThread::SleepThread(1); } DeInit(); NThread::SleepThread(2000); }
void FGameThread::ThreadRun() { ThreadInit(); F_LogTrace(F_GetProfiler()); F_ResetProfiler(); const Float32 FramesPerSec = 60.f; const Float32 MaxDeltaTime = 1.f / FramesPerSec; const UInt32 MaxUpdateCountPerFrame = 4; TThreadSafeVector<FEvent>::ContainerT ReceivedEvents; FUpdateEvent UpdateEvent(0.f); Float32 NextFrameProgress = 0.f; Float32 AccumulatedTime = 0.f; UInt32 UpdateCount = 0; FHighResolutionTimer Timer; Timer.Reset(); while (IsRunning) { { F_Profile(); Timer.Update(); const Float32 DeltaTimeSec = Timer.GetDeltaSeconds<Float32>(); AccumulatedTime += DeltaTimeSec; UpdateCount = 0; NextFrameProgress = AccumulatedTime / MaxDeltaTime; while (AccumulatedTime >= MaxDeltaTime) { F_ProfileWithMsg("Update"); UpdateEvent.CurrentTimeS = Timer.GetTimeInSeconds(); AccumulatedTime -= MaxDeltaTime; const bool bIsFirstUpdateThisFrame = UpdateCount == 0; if (bIsFirstUpdateThisFrame) { const Float32 AccumTModDeltaT = FMathf::Modulo(AccumulatedTime, MaxDeltaTime); UpdateEvent.PreviousFrameTimeS = UpdateEvent.CurrentFrameTimeS; UpdateEvent.CurrentFrameTimeS = UpdateEvent.CurrentTimeS - AccumTModDeltaT; UpdateEvent.DeltaTimeS = MaxDeltaTime; NextFrameProgress = AccumTModDeltaT / MaxDeltaTime; } InitData.IncomingEvents->GetDataAndClear<false>(ReceivedEvents); ThreadHandleEvents(UpdateEvent, ReceivedEvents); GameScene->Update(UpdateEvent, ComponentManagerImpl->ComponentManager); ComponentManagerImpl->ComponentManager.UpdateSystems(UpdateEvent); ComponentManagerImpl->ComponentManager.Refresh(); ++UpdateCount; const UInt32 MinFramesBeforeWarning = 2; const bool TwoUpdatesForFrame = UpdateCount == MinFramesBeforeWarning; F_LogWarningIf(TwoUpdatesForFrame, "Two or more updates occurred. AccT: " << AccumulatedTime); if (UpdateCount >= MaxUpdateCountPerFrame) { AccumulatedTime = FMathf::Modulo(AccumulatedTime, MaxDeltaTime); NextFrameProgress = AccumulatedTime / MaxDeltaTime; F_LogError("Hit the maximum update count of " << MaxUpdateCountPerFrame << " for this frame. Reducing AccumulatedTime to " << AccumulatedTime); } } if (UpdateCount) { GFXEngine.SetUpNextRender(); } // Eliminate spin wait until we actually need the CPU usage. if (UpdateCount == 0) { NThread::SleepThread(1); } } F_ResetProfiler(); } ThreadDeInit(); }