You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
246 lines
9.2 KiB
C++
246 lines
9.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MassExecutor.h"
|
|
#include "MassProcessingTypes.h"
|
|
#include "MassProcessor.h"
|
|
#include "MassCommandBuffer.h"
|
|
#include "MassExecutionContext.h"
|
|
#include "ProfilingDebugging/CpuProfilerTrace.h"
|
|
|
|
namespace UE::Mass::Executor
|
|
{
|
|
|
|
FORCEINLINE void ExecuteProcessors(FMassEntityManager& EntityManager, TArrayView<UMassProcessor* const> Processors, FMassExecutionContext& ExecutionContext)
|
|
{
|
|
for (UMassProcessor* Proc : Processors)
|
|
{
|
|
Proc->CallExecute(EntityManager, ExecutionContext);
|
|
}
|
|
}
|
|
|
|
void Run(FMassRuntimePipeline& RuntimePipeline, FMassProcessingContext& ProcessingContext)
|
|
{
|
|
if (!ensure(ProcessingContext.EntityManager) ||
|
|
!ensure(ProcessingContext.DeltaSeconds >= 0.f) ||
|
|
!ensure(RuntimePipeline.GetProcessors().Find(nullptr) == INDEX_NONE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor Run Pipeline")
|
|
RunProcessorsView(RuntimePipeline.GetMutableProcessors(), ProcessingContext);
|
|
}
|
|
|
|
void RunSparse(FMassRuntimePipeline& RuntimePipeline, FMassProcessingContext& ProcessingContext, FMassArchetypeHandle Archetype, TConstArrayView<FMassEntityHandle> Entities)
|
|
{
|
|
if (!ensure(ProcessingContext.EntityManager) ||
|
|
!ensure(RuntimePipeline.GetProcessors().Find(nullptr) == INDEX_NONE) ||
|
|
RuntimePipeline.Num() == 0 ||
|
|
!ensureMsgf(Archetype.IsValid(), TEXT("The Archetype passed in to UE::Mass::Executor::RunSparse is invalid")))
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor RunSparseEntities");
|
|
|
|
const FMassArchetypeEntityCollection EntityCollection(Archetype, Entities, FMassArchetypeEntityCollection::NoDuplicates);
|
|
RunProcessorsView(RuntimePipeline.GetMutableProcessors(), ProcessingContext, MakeArrayView(&EntityCollection, 1));
|
|
}
|
|
|
|
void RunSparse(FMassRuntimePipeline& RuntimePipeline, FMassProcessingContext& ProcessingContext, const FMassArchetypeEntityCollection& EntityCollection)
|
|
{
|
|
if (!ensure(ProcessingContext.EntityManager) ||
|
|
!ensure(RuntimePipeline.GetProcessors().Find(nullptr) == INDEX_NONE) ||
|
|
RuntimePipeline.Num() == 0 ||
|
|
!ensureMsgf(EntityCollection.GetArchetype().IsValid(), TEXT("The Archetype of EntityCollection passed in to UE::Mass::Executor::RunSparse is invalid")))
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor RunSparse");
|
|
|
|
RunProcessorsView(RuntimePipeline.GetMutableProcessors(), ProcessingContext, MakeArrayView(&EntityCollection, 1));
|
|
}
|
|
|
|
void Run(UMassProcessor& Processor, FMassProcessingContext& ProcessingContext)
|
|
{
|
|
if (!ensure(ProcessingContext.EntityManager) || !ensure(ProcessingContext.DeltaSeconds >= 0.f))
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor Run")
|
|
|
|
UMassProcessor* ProcPtr = &Processor;
|
|
RunProcessorsView(MakeArrayView(&ProcPtr, 1), ProcessingContext);
|
|
}
|
|
|
|
void RunProcessorsView(TArrayView<UMassProcessor* const> Processors, FMassProcessingContext& ProcessingContext, TConstArrayView<FMassArchetypeEntityCollection> EntityCollections)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(RunProcessorsView);
|
|
|
|
if (!ProcessingContext.EntityManager)
|
|
{
|
|
UE_LOG(LogMass, Error, TEXT("%s ProcessingContext.EntityManager is null. Baling out."), ANSI_TO_TCHAR(__FUNCTION__));
|
|
return;
|
|
}
|
|
#if WITH_MASSENTITY_DEBUG
|
|
if (Processors.Find(nullptr) != INDEX_NONE)
|
|
{
|
|
UE_LOG(LogMass, Error, TEXT("%s input Processors contains nullptr. Baling out."), ANSI_TO_TCHAR(__FUNCTION__));
|
|
return;
|
|
}
|
|
#endif // WITH_MASSENTITY_DEBUG
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor RunProcessorsView")
|
|
|
|
FMassExecutionContext ExecutionContext(*ProcessingContext.EntityManager.Get(), ProcessingContext.DeltaSeconds);
|
|
|
|
// if ProcessingContext points at a valid CommandBuffer use that one, otherwise manually create a new command buffer
|
|
// to let the default one still be used by code unaware of mass processing
|
|
TSharedPtr<FMassCommandBuffer> CommandBuffer = ProcessingContext.CommandBuffer
|
|
? ProcessingContext.CommandBuffer : MakeShareable(new FMassCommandBuffer());
|
|
ExecutionContext.SetDeferredCommandBuffer(CommandBuffer);
|
|
ExecutionContext.SetFlushDeferredCommands(false);
|
|
ExecutionContext.SetAuxData(ProcessingContext.AuxData);
|
|
ExecutionContext.SetExecutionType(EMassExecutionContextType::Processor);
|
|
|
|
FMassEntityManager& EntityManager = *ProcessingContext.EntityManager.Get();
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Execute Processors")
|
|
|
|
FMassEntityManager::FScopedProcessing ProcessingScope = EntityManager.NewProcessingScope();
|
|
|
|
if (EntityCollections.Num() == 0)
|
|
{
|
|
ExecuteProcessors(*ProcessingContext.EntityManager, Processors, ExecutionContext);
|
|
}
|
|
else
|
|
{
|
|
// @todo change ExecutionContext to contain a TConstArrayView of collections. Will lead up to changes in the entity query as well.
|
|
for (const FMassArchetypeEntityCollection& Collection : EntityCollections)
|
|
{
|
|
ExecutionContext.SetEntityCollection(Collection);
|
|
ExecuteProcessors(*ProcessingContext.EntityManager, Processors, ExecutionContext);
|
|
ExecutionContext.ClearEntityCollection();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ProcessingContext.bFlushCommandBuffer)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush Deferred Commands")
|
|
|
|
ExecutionContext.SetFlushDeferredCommands(true);
|
|
// append the commands added from other, non-processor sources (like MassAgentSubsystem)
|
|
ensure(!EntityManager.Defer().IsFlushing());
|
|
ensure(!ExecutionContext.Defer().IsFlushing());
|
|
ExecutionContext.Defer().MoveAppend(EntityManager.Defer());
|
|
ExecutionContext.FlushDeferred();
|
|
}
|
|
// else make sure we don't just lose the commands. Append to the command buffer requested via
|
|
// ProcessingContext.CommandBuffer or to the default EntityManager's command buffer.
|
|
else if (CommandBuffer->HasPendingCommands() && CommandBuffer != ProcessingContext.CommandBuffer)
|
|
{
|
|
if (ProcessingContext.CommandBuffer)
|
|
{
|
|
ProcessingContext.CommandBuffer->MoveAppend(*CommandBuffer.Get());
|
|
}
|
|
else if (CommandBuffer.Get() != &EntityManager.Defer())
|
|
{
|
|
EntityManager.AppendCommands(CommandBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct FMassExecutorDoneTask
|
|
{
|
|
FMassExecutorDoneTask(const FMassExecutionContext& InExecutionContext, TFunction<void()> InOnDoneNotification, const FString& InDebugName)
|
|
: ExecutionContext(InExecutionContext)
|
|
, OnDoneNotification(InOnDoneNotification)
|
|
, DebugName(InDebugName)
|
|
{
|
|
}
|
|
static TStatId GetStatId()
|
|
{
|
|
RETURN_QUICK_DECLARE_CYCLE_STAT(FMassExecutorDoneTask, STATGROUP_TaskGraphTasks);
|
|
}
|
|
|
|
static ENamedThreads::Type GetDesiredThread() { return ENamedThreads::GameThread; }
|
|
static ESubsequentsMode::Type GetSubsequentsMode() { return ESubsequentsMode::TrackSubsequents; }
|
|
void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush Deferred Commands Parallel");
|
|
SCOPE_CYCLE_COUNTER(STAT_Mass_Total);
|
|
|
|
FMassEntityManager& EntityManagerRef = ExecutionContext.GetEntityManagerChecked();
|
|
|
|
if (&ExecutionContext.Defer() != &EntityManagerRef.Defer())
|
|
{
|
|
ExecutionContext.Defer().MoveAppend(EntityManagerRef.Defer());
|
|
}
|
|
|
|
UE_LOG(LogMass, Verbose, TEXT("MassExecutor %s tasks DONE"), *DebugName);
|
|
ExecutionContext.SetFlushDeferredCommands(true);
|
|
ExecutionContext.FlushDeferred();
|
|
|
|
OnDoneNotification();
|
|
}
|
|
private:
|
|
FMassExecutionContext ExecutionContext;
|
|
TFunction<void()> OnDoneNotification;
|
|
FString DebugName;
|
|
};
|
|
|
|
FGraphEventRef TriggerParallelTasks(UMassProcessor& Processor, FMassProcessingContext& ProcessingContext, TFunction<void()> OnDoneNotification)
|
|
{
|
|
if (!ProcessingContext.EntityManager)
|
|
{
|
|
UE_LOG(LogMass, Error, TEXT("%s ProcessingContext.EntityManager is null. Baling out."), ANSI_TO_TCHAR(__FUNCTION__));
|
|
return FGraphEventRef();
|
|
}
|
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("MassExecutor RunParallel")
|
|
|
|
// not going through FMassEntityManager::CreateExecutionContext on purpose - we do need a separate command buffer
|
|
FMassExecutionContext ExecutionContext(*ProcessingContext.EntityManager.Get(), ProcessingContext.DeltaSeconds);
|
|
TSharedPtr<FMassCommandBuffer> CommandBuffer = ProcessingContext.CommandBuffer
|
|
? ProcessingContext.CommandBuffer : MakeShareable(new FMassCommandBuffer());
|
|
ExecutionContext.SetDeferredCommandBuffer(CommandBuffer);
|
|
ExecutionContext.SetFlushDeferredCommands(false);
|
|
ExecutionContext.SetAuxData(ProcessingContext.AuxData);
|
|
ExecutionContext.SetExecutionType(EMassExecutionContextType::Processor);
|
|
|
|
FGraphEventRef CompletionEvent;
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Dispatch Processors")
|
|
CompletionEvent = Processor.DispatchProcessorTasks(ProcessingContext.EntityManager, ExecutionContext, {});
|
|
}
|
|
|
|
if (CompletionEvent.IsValid())
|
|
{
|
|
const FGraphEventArray Prerequisites = { CompletionEvent };
|
|
CompletionEvent = TGraphTask<FMassExecutorDoneTask>::CreateTask(&Prerequisites)
|
|
.ConstructAndDispatchWhenReady(ExecutionContext, OnDoneNotification, Processor.GetName());
|
|
}
|
|
|
|
return CompletionEvent;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// DEPRECATED
|
|
//-----------------------------------------------------------------------------
|
|
void RunProcessorsView(TArrayView<UMassProcessor* const> Processors, FMassProcessingContext& ProcessingContext, const FMassArchetypeEntityCollection* EntityCollection)
|
|
{
|
|
if (EntityCollection)
|
|
{
|
|
RunProcessorsView(Processors, ProcessingContext, MakeArrayView(EntityCollection, 1));
|
|
}
|
|
else
|
|
{
|
|
RunProcessorsView(Processors, ProcessingContext);
|
|
}
|
|
}
|
|
|
|
} // namespace UE::Mass::Executor
|