Files
UnrealEngine/Engine/Source/Runtime/MassEntity/Private/MassEntityTrace.cpp
2025-05-18 13:04:45 +08:00

398 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MassEntityTrace.h"
#if UE_MASS_TRACE_ENABLED
#include "MassArchetypeData.h"
#include "MassEntityTypes.h"
#include "MassEntityQuery.h"
#include "MassEntityUtils.h"
#include "MassProcessor.h"
#include "MassDebugger.h"
#include "Trace/Trace.inl"
#include "TraceFilter.h"
UE_TRACE_CHANNEL_DEFINE(MassChannel);
UE_TRACE_EVENT_BEGIN(MassTrace, MassPhaseBegin)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(UE::Trace::WideString, PhaseName)
UE_TRACE_EVENT_FIELD(uint64, PhaseId)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassPhaseEnd)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(UE::Trace::WideString, PhaseName)
UE_TRACE_EVENT_FIELD(uint64, PhaseId)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, RegisterMassArchetype)
UE_TRACE_EVENT_FIELD(uint64, ArchetypeID)
UE_TRACE_EVENT_FIELD(uint64[], Fragments)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, RegisterMassFragment)
UE_TRACE_EVENT_FIELD(uint64, FragmentId)
UE_TRACE_EVENT_FIELD(UE::Trace::WideString, FragmentName)
UE_TRACE_EVENT_FIELD(uint32, FragmentSize)
UE_TRACE_EVENT_FIELD(uint8, FragmentType)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassPhaseExecutionBegin)
UE_TRACE_EVENT_FIELD(uint64, PhaseId)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassPhaseExecutionEnd)
UE_TRACE_EVENT_FIELD(uint64, PhaseId)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassExecuteChunk)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, ChunkId)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_FIELD(int32, EntityCount)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassExecuteChunkEnd)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, ChunkId)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassBulkAddEntity)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64[], Entities)
UE_TRACE_EVENT_FIELD(uint64[], ArchetypeIDs)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassBulkEntityDestroyed)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64[], Entities)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, MassEntityMoved)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, Entity)
UE_TRACE_EVENT_FIELD(uint64, NewArchetypeID)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryCreated)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_FIELD(UE::Trace::WideString, Name)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryDestroyed)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryRegisteredToProcessor)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_FIELD(uint64, ProcessorID)
UE_TRACE_EVENT_FIELD(UE::Trace::WideString, ProcessorName)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryArchetypeAdded)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_FIELD(uint64, ArchetypeID)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryForEachStarted)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_END()
UE_TRACE_EVENT_BEGIN(MassTrace, QueryForEachComplete)
UE_TRACE_EVENT_FIELD(uint64, Cycle)
UE_TRACE_EVENT_FIELD(uint64, QueryID)
UE_TRACE_EVENT_FIELD(int32, ArchetypeCount)
UE_TRACE_EVENT_FIELD(int32, ChunkCount)
UE_TRACE_EVENT_FIELD(int32, EntityCount)
UE_TRACE_EVENT_END()
enum class FFragmentType : uint8
{
Unknown = 0,
Fragment,
Tag,
SharedFragment
};
void FMassTrace::QueryCreated(const FMassEntityQuery* Query)
{
UE_TRACE_LOG(MassTrace, QueryCreated, MassChannel)
<< QueryCreated.Cycle(FPlatformTime::Cycles64())
<< QueryCreated.QueryID(reinterpret_cast<uint64>(Query));
}
void FMassTrace::QueryDestroyed(const FMassEntityQuery* Query)
{
UE_TRACE_LOG(MassTrace, QueryDestroyed, MassChannel)
<< QueryDestroyed.Cycle(FPlatformTime::Cycles64())
<< QueryDestroyed.QueryID(reinterpret_cast<uint64>(Query));
}
void FMassTrace::QueryRegisteredToProcessor(const FMassEntityQuery* Query, TNotNull<const UMassProcessor*> Processor)
{
UE_TRACE_LOG(MassTrace, QueryRegisteredToProcessor, MassChannel)
<< QueryRegisteredToProcessor.QueryID(reinterpret_cast<uint64>(Query))
<< QueryRegisteredToProcessor.ProcessorID(reinterpret_cast<uint64>((const UMassProcessor*)(Processor)))
<< QueryRegisteredToProcessor.ProcessorName(*Processor->GetProcessorName());
}
void FMassTrace::QueryArchetypeAdded(const FMassEntityQuery* Query, const FMassArchetypeHandle& Archetype)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
uint64 ArchetypeID = reinterpret_cast<uint64>(FMassArchetypeHelper::ArchetypeDataFromHandle(Archetype));
UE_TRACE_LOG(MassTrace, QueryArchetypeAdded, MassChannel)
<< QueryArchetypeAdded.QueryID(reinterpret_cast<uint64>(Query))
<< QueryArchetypeAdded.ArchetypeID(ArchetypeID);
}
}
FMassTrace::FScopedQueryForEachTrace::FScopedQueryForEachTrace(const FMassEntityQuery* InQuery)
: Query(InQuery)
, ArchetypeCount(0)
, ChunkCount(0)
, EntityCount(0)
{
UE_TRACE_LOG(MassTrace, QueryForEachStarted, MassChannel)
<< QueryForEachStarted.Cycle(FPlatformTime::Cycles64())
<< QueryForEachStarted.QueryID(reinterpret_cast<uint64>(Query));
}
FMassTrace::FScopedQueryForEachTrace::~FScopedQueryForEachTrace()
{
UE_TRACE_LOG(MassTrace, QueryForEachComplete, MassChannel)
<< QueryForEachComplete.Cycle(FPlatformTime::Cycles64())
<< QueryForEachComplete.QueryID(reinterpret_cast<uint64>(Query))
<< QueryForEachComplete.ArchetypeCount(ArchetypeCount)
<< QueryForEachComplete.ChunkCount(ChunkCount)
<< QueryForEachComplete.EntityCount(EntityCount);
}
void FMassTrace::FScopedQueryForEachTrace::ReportArchetype(const FMassArchetypeData& Archetype)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
++ArchetypeCount;
ChunkCount += Archetype.GetChunkCount();
EntityCount += Archetype.GetNumEntities();
}
}
void FMassTrace::OutputRegisterFragment(const UScriptStruct* Struct)
{
const uint64 FragmentId = reinterpret_cast<uint64>(Struct);
const FFragmentType FragmentType = [](const UScriptStruct* Struct)
{
if (Struct->IsChildOf<FMassFragment>())
{
return FFragmentType::Fragment;
}
else if (Struct->IsChildOf<FMassTag>())
{
return FFragmentType::Tag;
}
else if (Struct->IsChildOf<FMassSharedFragment>())
{
return FFragmentType::SharedFragment;
}
else
{
return FFragmentType::Unknown;
}
}(Struct);
UE_TRACE_LOG(MassTrace, RegisterMassFragment, MassChannel)
<< RegisterMassFragment.FragmentId(FragmentId)
<< RegisterMassFragment.FragmentName(*Struct->GetName())
<< RegisterMassFragment.FragmentSize(Struct->GetStructureSize())
<< RegisterMassFragment.FragmentType(static_cast<uint8>(FragmentType));
}
void FMassTrace::OnPhaseBegin(uint64 PhaseId)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const FString EnumName = StaticEnum<EMassProcessingPhase>()->GetNameStringByValue(PhaseId);
OutputBeginPhaseRegion(*EnumName);
}
}
void FMassTrace::OnPhaseEnd(uint64 PhaseId)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const FString EnumName = StaticEnum<EMassProcessingPhase>()->GetNameStringByValue(PhaseId);
OutputEndPhaseRegion(*EnumName);
}
}
uint64 FMassTrace::OutputRegisterArchetype(uint64 ArchetypeID, const FMassArchetypeCompositionDescriptor& CompositionDescriptor)
{
TArray<uint64> FragmentsScratch;
FragmentsScratch.Reserve(CompositionDescriptor.Fragments.CountStoredTypes() + CompositionDescriptor.Tags.CountStoredTypes());
auto FragmentIterator = CompositionDescriptor.Fragments.GetIndexIterator();
while (FragmentIterator)
{
const UScriptStruct* FragmentStruct = CompositionDescriptor.Fragments.GetTypeAtIndex(*FragmentIterator);
OutputRegisterFragment(FragmentStruct);
// TODO Should have utility function to go from UScriptStruct to the fragment ID
FragmentsScratch.Add(reinterpret_cast<uint64>(FragmentStruct));
++FragmentIterator;
}
auto TagIterator = CompositionDescriptor.Tags.GetIndexIterator();
while (TagIterator)
{
const UScriptStruct* FragmentStruct = CompositionDescriptor.Tags.GetTypeAtIndex(*TagIterator);
{
OutputRegisterFragment(FragmentStruct);
}
// TODO Should have utility function to go from UScriptStruct to the fragment ID
FragmentsScratch.Add(reinterpret_cast<uint64>(FragmentStruct));
++TagIterator;
}
UE_TRACE_LOG(MassTrace, RegisterMassArchetype, MassChannel)
<< RegisterMassArchetype.ArchetypeID(ArchetypeID)
<< RegisterMassArchetype.Fragments(FragmentsScratch.GetData(), FragmentsScratch.Num());
return ArchetypeID;
}
uint64 FMassTrace::RegisterArchetype(const FMassArchetypeHandle& ArchetypeHandle)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const FMassArchetypeCompositionDescriptor& CompositionDescriptor = FMassDebugger::GetArchetypeComposition(ArchetypeHandle);
const uint64 ArchetypeID = FMassDebugger::GetArchetypeTraceID(ArchetypeHandle);
return OutputRegisterArchetype(ArchetypeID, CompositionDescriptor);
}
return 0;
}
uint64 FMassTrace::RegisterArchetype(const FMassArchetypeData& Data)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const FMassArchetypeCompositionDescriptor& CompositionDescriptor = Data.GetCompositionDescriptor();
const uint64 ArchetypeID = FMassDebugger::GetArchetypeTraceID(Data);
return OutputRegisterArchetype(ArchetypeID, CompositionDescriptor);
}
return 0;
}
void FMassTrace::RegisterFragment(const UScriptStruct* Struct)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
OutputRegisterFragment(Struct);
}
}
void FMassTrace::EntityCreated(FMassEntityHandle Entity, const FMassArchetypeData& Archetype)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const uint64 Cycle = FPlatformTime::Cycles64();
const uint64 EntityAsU64 = Entity.AsNumber();
const uint64 ArchetypeID = FMassDebugger::GetArchetypeTraceID(Archetype);
UE_TRACE_LOG(MassTrace, MassBulkAddEntity, MassChannel)
<< MassBulkAddEntity.Cycle(Cycle)
<< MassBulkAddEntity.Entities(&EntityAsU64, 1)
<< MassBulkAddEntity.ArchetypeIDs(&ArchetypeID, 1);
}
}
void FMassTrace::EntityMoved(FMassEntityHandle Entity, const FMassArchetypeData& NewArchetype)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const uint64 Cycle = FPlatformTime::Cycles64();
const uint64 EntityAsU64 = Entity.AsNumber();
UE_TRACE_LOG(MassTrace, MassEntityMoved, MassChannel)
<< MassEntityMoved.Cycle(Cycle)
<< MassEntityMoved.Entity(EntityAsU64)
<< MassEntityMoved.NewArchetypeID(FMassDebugger::GetArchetypeTraceID(NewArchetype));
}
}
void FMassTrace::EntityDestroyed(FMassEntityHandle Entity)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const uint64 Cycle = FPlatformTime::Cycles64();
const uint64 EntityAsU64 = Entity.AsNumber();
UE_TRACE_LOG(MassTrace, MassBulkEntityDestroyed, MassChannel)
<< MassBulkEntityDestroyed.Cycle(Cycle)
<< MassBulkEntityDestroyed.Entities(&EntityAsU64, 1);
}
}
void FMassTrace::EntitiesDestroyed(TConstArrayView<FMassEntityHandle> Entities)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const uint64 Cycle = FPlatformTime::Cycles64();
TConstArrayView<uint64> EntitiesAsU64(
reinterpret_cast<const uint64*>(Entities.GetData()),
Entities.Num());
UE_TRACE_LOG(MassTrace, MassBulkEntityDestroyed, MassChannel)
<< MassBulkEntityDestroyed.Cycle(Cycle)
<< MassBulkEntityDestroyed.Entities(EntitiesAsU64.GetData(), EntitiesAsU64.Num());
}
}
uint64_t FMassTrace::OutputBeginPhaseWithID(const TCHAR* PhaseName)
{
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(MassChannel))
{
const uint64 PhaseId = FPlatformTime::Cycles64();
UE_TRACE_LOG(MassTrace, MassPhaseBegin, MassChannel)
<< MassPhaseBegin.Cycle(FPlatformTime::Cycles64())
<< MassPhaseBegin.PhaseName(PhaseName)
<< MassPhaseBegin.PhaseId(PhaseId);
return PhaseId;
}
return 0;
}
void FMassTrace::OutputBeginPhaseRegion(const TCHAR* PhaseName)
{
UE_TRACE_LOG(MassTrace, MassPhaseBegin, MassChannel)
<< MassPhaseBegin.Cycle(FPlatformTime::Cycles64())
<< MassPhaseBegin.PhaseName(PhaseName)
<< MassPhaseBegin.PhaseId(0);
}
void FMassTrace::OutputEndPhaseRegion(const TCHAR* PhaseName)
{
UE_TRACE_LOG(MassTrace, MassPhaseEnd, MassChannel)
<< MassPhaseEnd.Cycle(FPlatformTime::Cycles64())
<< MassPhaseEnd.PhaseName(PhaseName)
<< MassPhaseEnd.PhaseId(0);
}
void FMassTrace::OutputEndPhaseRegion(uint64 PhaseId)
{
UE_TRACE_LOG(MassTrace, MassPhaseEnd, MassChannel)
<< MassPhaseEnd.Cycle(FPlatformTime::Cycles64())
<< MassPhaseEnd.PhaseId(PhaseId);
}
#endif //UE_MASS_TRACE_ENABLED