2021-09-29 02:36:08 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MassExecutor.h"
2021-09-30 14:29:32 -04:00
# include "MassProcessingTypes.h"
2021-09-29 02:36:08 -04:00
# include "MassProcessor.h"
2021-09-30 14:29:32 -04:00
# include "MassCommandBuffer.h"
2023-01-11 03:01:44 -05:00
# include "MassExecutionContext.h"
2021-09-29 02:36:08 -04:00
# include "ProfilingDebugging/CpuProfilerTrace.h"
2021-10-01 09:27:27 -04:00
namespace UE : : Mass : : Executor
2021-09-29 02:36:08 -04:00
{
2024-06-11 06:21:11 -04:00
FORCEINLINE void ExecuteProcessors ( FMassEntityManager & EntityManager , TArrayView < UMassProcessor * const > Processors , FMassExecutionContext & ExecutionContext )
{
for ( UMassProcessor * Proc : Processors )
{
Proc - > CallExecute ( EntityManager , ExecutionContext ) ;
}
}
2021-10-01 13:37:08 -04:00
void Run ( FMassRuntimePipeline & RuntimePipeline , FMassProcessingContext & ProcessingContext )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
if ( ! ensure ( ProcessingContext . EntityManager ) | |
2021-10-01 13:37:08 -04:00
! ensure ( ProcessingContext . DeltaSeconds > = 0.f ) | |
2023-01-12 06:21:43 -05:00
! ensure ( RuntimePipeline . GetProcessors ( ) . Find ( nullptr ) = = INDEX_NONE ) )
2021-09-29 02:36:08 -04:00
{
return ;
}
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor Run Pipeline " )
2023-01-12 06:21:43 -05:00
RunProcessorsView ( RuntimePipeline . GetMutableProcessors ( ) , ProcessingContext ) ;
2021-09-29 02:36:08 -04:00
}
2022-01-26 03:42:44 -05:00
void RunSparse ( FMassRuntimePipeline & RuntimePipeline , FMassProcessingContext & ProcessingContext , FMassArchetypeHandle Archetype , TConstArrayView < FMassEntityHandle > Entities )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
if ( ! ensure ( ProcessingContext . EntityManager ) | |
2023-01-12 06:21:43 -05:00
! ensure ( RuntimePipeline . GetProcessors ( ) . Find ( nullptr ) = = INDEX_NONE ) | |
RuntimePipeline . Num ( ) = = 0 | |
2021-10-01 09:27:27 -04:00
! ensureMsgf ( Archetype . IsValid ( ) , TEXT ( " The Archetype passed in to UE::Mass::Executor::RunSparse is invalid " ) ) )
2021-09-29 02:36:08 -04:00
{
return ;
}
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor RunSparseEntities " ) ;
2021-09-29 02:36:08 -04:00
2022-03-08 10:30:07 -05:00
const FMassArchetypeEntityCollection EntityCollection ( Archetype , Entities , FMassArchetypeEntityCollection : : NoDuplicates ) ;
2024-06-11 06:21:11 -04:00
RunProcessorsView ( RuntimePipeline . GetMutableProcessors ( ) , ProcessingContext , MakeArrayView ( & EntityCollection , 1 ) ) ;
2021-09-29 02:36:08 -04:00
}
2022-03-08 10:30:07 -05:00
void RunSparse ( FMassRuntimePipeline & RuntimePipeline , FMassProcessingContext & ProcessingContext , const FMassArchetypeEntityCollection & EntityCollection )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
if ( ! ensure ( ProcessingContext . EntityManager ) | |
2023-01-12 06:21:43 -05:00
! ensure ( RuntimePipeline . GetProcessors ( ) . Find ( nullptr ) = = INDEX_NONE ) | |
RuntimePipeline . Num ( ) = = 0 | |
2022-03-08 10:30:07 -05:00
! ensureMsgf ( EntityCollection . GetArchetype ( ) . IsValid ( ) , TEXT ( " The Archetype of EntityCollection passed in to UE::Mass::Executor::RunSparse is invalid " ) ) )
2021-09-29 02:36:08 -04:00
{
return ;
}
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor RunSparse " ) ;
2021-09-29 02:36:08 -04:00
2024-06-11 06:21:11 -04:00
RunProcessorsView ( RuntimePipeline . GetMutableProcessors ( ) , ProcessingContext , MakeArrayView ( & EntityCollection , 1 ) ) ;
2021-09-29 02:36:08 -04:00
}
2021-10-01 13:37:08 -04:00
void Run ( UMassProcessor & Processor , FMassProcessingContext & ProcessingContext )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
if ( ! ensure ( ProcessingContext . EntityManager ) | | ! ensure ( ProcessingContext . DeltaSeconds > = 0.f ) )
2021-09-29 02:36:08 -04:00
{
return ;
}
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor Run " )
2021-09-29 02:36:08 -04:00
2021-09-30 10:09:03 -04:00
UMassProcessor * ProcPtr = & Processor ;
2021-10-01 13:37:08 -04:00
RunProcessorsView ( MakeArrayView ( & ProcPtr , 1 ) , ProcessingContext ) ;
2021-09-29 02:36:08 -04:00
}
2024-06-11 06:21:11 -04:00
void RunProcessorsView ( TArrayView < UMassProcessor * const > Processors , FMassProcessingContext & ProcessingContext , TConstArrayView < FMassArchetypeEntityCollection > EntityCollections )
2021-09-29 02:36:08 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( RunProcessorsView ) ;
2022-08-12 07:56:27 -04:00
if ( ! ProcessingContext . EntityManager )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
UE_LOG ( LogMass , Error , TEXT ( " %s ProcessingContext.EntityManager is null. Baling out. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2021-09-29 02:36:08 -04:00
return ;
}
2021-09-30 06:22:59 -04:00
# if WITH_MASSENTITY_DEBUG
2021-09-29 02:36:08 -04:00
if ( Processors . Find ( nullptr ) ! = INDEX_NONE )
{
2021-10-01 13:37:08 -04:00
UE_LOG ( LogMass , Error , TEXT ( " %s input Processors contains nullptr. Baling out. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2021-09-29 02:36:08 -04:00
return ;
}
2021-09-30 06:22:59 -04:00
# endif // WITH_MASSENTITY_DEBUG
2021-09-29 02:36:08 -04:00
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor RunProcessorsView " )
2021-09-29 02:36:08 -04:00
2023-01-11 03:01:44 -05:00
FMassExecutionContext ExecutionContext ( * ProcessingContext . EntityManager . Get ( ) , ProcessingContext . DeltaSeconds ) ;
2024-06-11 06:21:11 -04:00
2021-12-16 19:27:47 -05:00
// 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 ) ;
2021-09-29 02:36:08 -04:00
ExecutionContext . SetFlushDeferredCommands ( false ) ;
2021-10-01 13:37:08 -04:00
ExecutionContext . SetAuxData ( ProcessingContext . AuxData ) ;
2022-05-13 07:07:16 -04:00
ExecutionContext . SetExecutionType ( EMassExecutionContextType : : Processor ) ;
2021-09-29 02:36:08 -04:00
2022-08-12 07:56:27 -04:00
FMassEntityManager & EntityManager = * ProcessingContext . EntityManager . Get ( ) ;
2021-09-29 02:36:08 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " Execute Processors " )
2022-08-12 07:56:27 -04:00
FMassEntityManager : : FScopedProcessing ProcessingScope = EntityManager . NewProcessingScope ( ) ;
2021-09-29 02:36:08 -04:00
2024-06-11 06:21:11 -04:00
if ( EntityCollections . Num ( ) = = 0 )
2021-09-29 02:36:08 -04:00
{
2024-06-11 06:21:11 -04:00
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 ) ;
2024-06-12 11:14:36 -04:00
ExecutionContext . ClearEntityCollection ( ) ;
2024-06-11 06:21:11 -04:00
}
2021-09-29 02:36:08 -04:00
}
}
2021-12-16 19:27:47 -05:00
if ( ProcessingContext . bFlushCommandBuffer )
2021-09-29 02:36:08 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " Flush Deferred Commands " )
ExecutionContext . SetFlushDeferredCommands ( true ) ;
// append the commands added from other, non-processor sources (like MassAgentSubsystem)
2022-08-12 07:56:27 -04:00
ensure ( ! EntityManager . Defer ( ) . IsFlushing ( ) ) ;
2022-02-03 09:14:35 -05:00
ensure ( ! ExecutionContext . Defer ( ) . IsFlushing ( ) ) ;
2022-08-12 07:56:27 -04:00
ExecutionContext . Defer ( ) . MoveAppend ( EntityManager . Defer ( ) ) ;
2022-08-29 07:35:29 -04:00
ExecutionContext . FlushDeferred ( ) ;
2021-09-29 02:36:08 -04:00
}
2022-02-03 09:14:35 -05:00
// else make sure we don't just lose the commands. Append to the command buffer requested via
2022-08-12 07:56:27 -04:00
// ProcessingContext.CommandBuffer or to the default EntityManager's command buffer.
2024-04-16 08:12:45 -04:00
else if ( CommandBuffer - > HasPendingCommands ( ) & & CommandBuffer ! = ProcessingContext . CommandBuffer )
2022-02-03 09:14:35 -05:00
{
if ( ProcessingContext . CommandBuffer )
{
ProcessingContext . CommandBuffer - > MoveAppend ( * CommandBuffer . Get ( ) ) ;
}
2022-08-12 07:56:27 -04:00
else if ( CommandBuffer . Get ( ) ! = & EntityManager . Defer ( ) )
2022-02-03 09:14:35 -05:00
{
2024-02-28 05:12:13 -05:00
EntityManager . AppendCommands ( CommandBuffer ) ;
2022-02-03 09:14:35 -05:00
}
}
2021-09-29 02:36:08 -04:00
}
2021-10-07 16:57:44 -04:00
struct FMassExecutorDoneTask
2021-09-29 02:36:08 -04:00
{
2022-08-29 07:35:29 -04:00
FMassExecutorDoneTask ( const FMassExecutionContext & InExecutionContext , TFunction < void ( ) > InOnDoneNotification , const FString & InDebugName )
2021-09-29 02:36:08 -04:00
: ExecutionContext ( InExecutionContext )
, OnDoneNotification ( InOnDoneNotification )
, DebugName ( InDebugName )
{
}
static TStatId GetStatId ( )
{
2021-10-07 16:57:44 -04:00
RETURN_QUICK_DECLARE_CYCLE_STAT ( FMassExecutorDoneTask , STATGROUP_TaskGraphTasks ) ;
2021-09-29 02:36:08 -04:00
}
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 " ) ;
2023-08-29 03:04:59 -04:00
SCOPE_CYCLE_COUNTER ( STAT_Mass_Total ) ;
2021-09-29 02:36:08 -04:00
2022-08-29 07:35:29 -04:00
FMassEntityManager & EntityManagerRef = ExecutionContext . GetEntityManagerChecked ( ) ;
2022-08-12 07:56:27 -04:00
if ( & ExecutionContext . Defer ( ) ! = & EntityManagerRef . Defer ( ) )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
ExecutionContext . Defer ( ) . MoveAppend ( EntityManagerRef . Defer ( ) ) ;
2021-09-29 02:36:08 -04:00
}
2022-05-18 05:20:23 -04:00
UE_LOG ( LogMass , Verbose , TEXT ( " MassExecutor %s tasks DONE " ) , * DebugName ) ;
2021-09-29 02:36:08 -04:00
ExecutionContext . SetFlushDeferredCommands ( true ) ;
2022-08-29 07:35:29 -04:00
ExecutionContext . FlushDeferred ( ) ;
2021-09-29 02:36:08 -04:00
OnDoneNotification ( ) ;
}
private :
2021-09-30 10:09:03 -04:00
FMassExecutionContext ExecutionContext ;
2021-09-29 02:36:08 -04:00
TFunction < void ( ) > OnDoneNotification ;
FString DebugName ;
} ;
2021-10-01 13:37:08 -04:00
FGraphEventRef TriggerParallelTasks ( UMassProcessor & Processor , FMassProcessingContext & ProcessingContext , TFunction < void ( ) > OnDoneNotification )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
if ( ! ProcessingContext . EntityManager )
2021-09-29 02:36:08 -04:00
{
2022-08-12 07:56:27 -04:00
UE_LOG ( LogMass , Error , TEXT ( " %s ProcessingContext.EntityManager is null. Baling out. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2021-09-29 02:36:08 -04:00
return FGraphEventRef ( ) ;
}
2021-10-07 16:57:44 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " MassExecutor RunParallel " )
2021-09-29 02:36:08 -04:00
2022-08-12 07:56:27 -04:00
// not going through FMassEntityManager::CreateExecutionContext on purpose - we do need a separate command buffer
2023-01-11 03:01:44 -05:00
FMassExecutionContext ExecutionContext ( * ProcessingContext . EntityManager . Get ( ) , ProcessingContext . DeltaSeconds ) ;
2021-12-16 19:27:47 -05:00
TSharedPtr < FMassCommandBuffer > CommandBuffer = ProcessingContext . CommandBuffer
? ProcessingContext . CommandBuffer : MakeShareable ( new FMassCommandBuffer ( ) ) ;
ExecutionContext . SetDeferredCommandBuffer ( CommandBuffer ) ;
2021-09-29 02:36:08 -04:00
ExecutionContext . SetFlushDeferredCommands ( false ) ;
2021-10-01 13:37:08 -04:00
ExecutionContext . SetAuxData ( ProcessingContext . AuxData ) ;
2022-05-18 05:20:23 -04:00
ExecutionContext . SetExecutionType ( EMassExecutionContextType : : Processor ) ;
2021-09-29 02:36:08 -04:00
FGraphEventRef CompletionEvent ;
{
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( " Dispatch Processors " )
2022-08-12 07:56:27 -04:00
CompletionEvent = Processor . DispatchProcessorTasks ( ProcessingContext . EntityManager , ExecutionContext , { } ) ;
2021-09-29 02:36:08 -04:00
}
if ( CompletionEvent . IsValid ( ) )
{
const FGraphEventArray Prerequisites = { CompletionEvent } ;
2021-10-07 16:57:44 -04:00
CompletionEvent = TGraphTask < FMassExecutorDoneTask > : : CreateTask ( & Prerequisites )
2022-08-29 07:35:29 -04:00
. ConstructAndDispatchWhenReady ( ExecutionContext , OnDoneNotification , Processor . GetName ( ) ) ;
2021-09-29 02:36:08 -04:00
}
return CompletionEvent ;
}
2024-06-11 06:21:11 -04:00
//-----------------------------------------------------------------------------
// DEPRECATED
//-----------------------------------------------------------------------------
void RunProcessorsView ( TArrayView < UMassProcessor * const > Processors , FMassProcessingContext & ProcessingContext , const FMassArchetypeEntityCollection * EntityCollection )
{
if ( EntityCollection )
{
RunProcessorsView ( Processors , ProcessingContext , MakeArrayView ( EntityCollection , 1 ) ) ;
}
else
{
RunProcessorsView ( Processors , ProcessingContext ) ;
}
}
2021-10-01 09:27:27 -04:00
} // namespace UE::Mass::Executor