void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) { for (FTaskArray::TIterator It(*Components); It; ++It) { UActorComponent* Component = *It; if (!Component->IsPendingKill() && Component->IsRegistered() && !Component->IsTemplate()) { FScopeCycleCounterUObject ComponentScope(Component); FScopeCycleCounterUObject AdditionalScope(STATS ? Component->AdditionalStatObject() : NULL); Component->DoDeferredRenderUpdates_Concurrent(); } } }
/** * Send all render updates to the rendering thread. */ void UWorld::SendAllEndOfFrameUpdates(FGraphEventArray* OutCompletion) { SCOPE_CYCLE_COUNTER(STAT_PostTickComponentUpdate); // update all dirty components. bPostTickComponentUpdate = true; if (!OutCompletion) { // this is a viewer or something, just do everything on the gamethread for (TSet<TWeakObjectPtr<UActorComponent> >::TIterator It(ComponentsThatNeedEndOfFrameUpdate); It; ++It) { ComponentsThatNeedEndOfFrameUpdate_OnGameThread.Add(*It); } ComponentsThatNeedEndOfFrameUpdate.Empty(ComponentsThatNeedEndOfFrameUpdate.Num()); } else { // remove any gamethread updates from the async update list for (TSet<TWeakObjectPtr<UActorComponent> >::TIterator It(ComponentsThatNeedEndOfFrameUpdate_OnGameThread); It; ++It) { ComponentsThatNeedEndOfFrameUpdate.Remove(*It); } } // Game thread updates need to happen before we go wide on the other threads. // These updates are things that have said that they are NOT SAFE to run concurrently. for (TSet<TWeakObjectPtr<UActorComponent> >::TIterator It(ComponentsThatNeedEndOfFrameUpdate_OnGameThread); It; ++It) { UActorComponent* Component = It->Get(); if (Component && !Component->IsPendingKill() && Component->IsRegistered() && !Component->IsTemplate()) { FScopeCycleCounterUObject ComponentScope(Component); FScopeCycleCounterUObject AdditionalScope(STATS ? Component->AdditionalStatObject() : NULL); Component->DoDeferredRenderUpdates_Concurrent(); } } if (ComponentsThatNeedEndOfFrameUpdate.Num()) { check(OutCompletion); enum { NUM_COMPONENTS_PER_TASK = 20 }; typedef TArray<UActorComponent*, TInlineAllocator<NUM_COMPONENTS_PER_TASK> > FTaskArray; /** Helper class define the task of calling DoDeferredRenderUpdates_Concurrent on an array of components **/ class FDoRenderthreadUpdatesTask { /** Array of components to process, owned by the task **/ TScopedPointer<FTaskArray> Components; public: FDoRenderthreadUpdatesTask(FTaskArray* InComponents) : Components(InComponents) { } FORCEINLINE TStatId GetStatId() const { RETURN_QUICK_DECLARE_CYCLE_STAT(DoRenderthreadUpdatesTask, STATGROUP_TaskGraphTasks); } static ENamedThreads::Type GetDesiredThread() { return ENamedThreads::AnyThread; } static ESubsequentsMode::Type GetSubsequentsMode() { return ESubsequentsMode::TrackSubsequents; } void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) { for (FTaskArray::TIterator It(*Components); It; ++It) { UActorComponent* Component = *It; if (!Component->IsPendingKill() && Component->IsRegistered() && !Component->IsTemplate()) { FScopeCycleCounterUObject ComponentScope(Component); FScopeCycleCounterUObject AdditionalScope(STATS ? Component->AdditionalStatObject() : NULL); Component->DoDeferredRenderUpdates_Concurrent(); } } } }; { //@todo optimization, this loop could be done on another thread // First get the async transform and render data updates underway FTaskArray* Array = NULL; for (TSet<TWeakObjectPtr<UActorComponent> >::TIterator It(ComponentsThatNeedEndOfFrameUpdate); It; ++It) { UActorComponent* NextComponent = It->Get(); if (NextComponent && !NextComponent->IsPendingKill() && NextComponent->IsRegistered() && !NextComponent->IsTemplate()) { if (!Array) { Array = new FTaskArray; } Array->Add(NextComponent); if (Array->Num() == NUM_COMPONENTS_PER_TASK) { new (*OutCompletion) FGraphEventRef(TGraphTask<FDoRenderthreadUpdatesTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(Array)); Array = NULL; // Array belongs to the task } } } if (Array) // partial array if we had one { new (*OutCompletion) FGraphEventRef(TGraphTask<FDoRenderthreadUpdatesTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(Array)); Array = NULL; // Array belongs to the task } } } bPostTickComponentUpdate = false; ComponentsThatNeedEndOfFrameUpdate.Empty(ComponentsThatNeedEndOfFrameUpdate.Num()); ComponentsThatNeedEndOfFrameUpdate_OnGameThread.Empty(ComponentsThatNeedEndOfFrameUpdate_OnGameThread.Num()); }