| FAutoConsoleCommand GDumpPSCStateCommand(TEXT("fx.DumpPSCTickStateInfo"), TEXT("Dumps state information for all current Particle System Components."), FConsoleCommandDelegate::CreateStatic([]() { struct FPSCInfo { UParticleSystemComponent *PSC; bool bIsActive; bool bIsSignificant; bool bIsVisible; int32 NumActiveParticles; FPSCInfo() :PSC((UParticleSystemComponent *) 0xDEADBEEFDEADBEEF), bIsActive(false), bIsSignificant(false), bIsVisible(false), NumActiveParticles(0) {} }; struct FPSCInfoSummary { TArray< FPSCInfo > Components; int32 NumTicking; int32 NumManaged; int32 NumTickingNoTemplate; int32 NumTickingButInactive; int32 NumTickingButInvisible; int32 NumTickingButNonSignificant; int32 NumTickingNoEmitters; int32 NumPooled; FPSCInfoSummary() :NumTicking(0), NumManaged(0), NumTickingNoTemplate(0), NumTickingButInactive(0), NumTickingButInvisible(0), NumTickingButNonSignificant(0), NumTickingNoEmitters(0), NumPooled(0) {} }; struct FPSCWorldInfo { TMap< UParticleSystem *, FPSCInfoSummary > SummaryMap; int32 TotalPSCs; int32 TotalTicking; int32 TotalManaged; int32 TotalTickingNoTemplate; int32 TotalTickingButInactive; int32 TotalTickingButInvisible; int32 TotalTickingButNonSignificant; int32 TotalTickingNoEmitters; int32 TotalPooled; FPSCWorldInfo() :TotalPSCs(0), TotalTicking(0), TotalManaged(0), TotalTickingNoTemplate(0), TotalTickingButInactive(0), TotalTickingButInvisible(0), TotalTickingButNonSignificant(0), TotalTickingNoEmitters(0), TotalPooled(0) {} }; TMap< UWorld *, FPSCWorldInfo > InfoMap; for(TObjectIterator< UParticleSystemComponent > PSCIt;PSCIt;++PSCIt) { UParticleSystemComponent *PSC=*PSCIt; check(PSC); UWorld *World=PSC->GetWorld(); UParticleSystem *Sys=PSC->Template; FPSCWorldInfo &WorldInfo=InfoMap.FindOrAdd(World); FPSCInfoSummary &Info=WorldInfo.SummaryMap.FindOrAdd(Sys); int32 PSCInfoIndex=Info.Components.AddDefaulted(); FPSCInfo &PSCInfo=Info.Components[PSCInfoIndex]; PSCInfo.PSC=PSC;++WorldInfo.TotalPSCs; if(PSC->IsComponentTickEnabled()) { int32 NumParticles=PSC->GetNumActiveParticles(); PSCInfo.NumActiveParticles=NumParticles; if(PSC->IsTickManaged()) {++Info.NumManaged;++WorldInfo.TotalManaged; } else {++Info.NumTicking;++WorldInfo.TotalTicking; } if(PSC->Template==nullptr) {++Info.NumTickingNoTemplate;++WorldInfo.TotalTickingNoTemplate; } if(PSC->EmitterInstances.Num()==0) {++Info.NumTickingNoEmitters;++WorldInfo.TotalTickingNoEmitters; } if(PSC->IsActive()) { PSCInfo.bIsActive=true; } else {++Info.NumTickingButInactive;++WorldInfo.TotalTickingButInactive; PSCInfo.bIsActive=false; } PSCInfo.bIsVisible=!PSC->CanConsiderInvisible(); if(!PSCInfo.bIsVisible) {++Info.NumTickingButInvisible;++WorldInfo.TotalTickingButInvisible; } if(PSC->bIsManagingSignificance) { uint32 NumSignificantEmitters=0; for(UParticleEmitter *Emitter :PSC->Template->Emitters) { if(Emitter->IsSignificant(PSC->RequiredSignificance)) {++NumSignificantEmitters; } } PSCInfo.bIsSignificant=NumSignificantEmitters > 0; if(NumSignificantEmitters==0 &&NumParticles==0) {++Info.NumTickingButNonSignificant;++WorldInfo.TotalTickingButNonSignificant; } } else { PSCInfo.bIsSignificant=true; } } } auto PrintPSCInfo=[](const UParticleSystem *Sys, FPSCInfoSummary &Info) { float KBUsed=(sizeof(UParticleSystemComponent) *Info.Components.Num())/1024.0f; FString MaxSigName; if(Sys) { switch(Sys->GetHighestSignificance()) { case EParticleSignificanceLevel::Critical:MaxSigName=TEXT("Crit");break; case EParticleSignificanceLevel::High:MaxSigName=TEXT("High");break; case EParticleSignificanceLevel::Medium:MaxSigName=TEXT("Med");break; case EParticleSignificanceLevel::Low:MaxSigName=TEXT("Low");break; } } UE_LOG(LogParticles, Log, TEXT("| %5u | %7.2f | %7u | %7u | %8u | %9u || %4d | %6s |%s"), Info.Components.Num(), KBUsed, Info.NumTicking, Info.NumManaged, Info.NumTickingButInactive, Info.NumTickingButInvisible, Sys ? Sys->IsLooping() :0, *MaxSigName, Sys ? *Sys->GetFullName() :TEXT("NULL SYSTEM!")); }; for(TPair< UWorld *, FPSCWorldInfo > InfoMapPair :InfoMap) { UWorld *World=InfoMapPair.Key; FPSCWorldInfo &WorldInfo=InfoMapPair.Value; FString WorldInfoString; if(World) { #define WORLD_TYPE_CASE(WorldType) switch(World->WorldType) { }; WorldInfoString+=TEXT(" | "); WorldInfoString+=World->GetFullName(); } float KBUsed=(sizeof(UParticleSystemComponent) *WorldInfo.TotalPSCs)/1024.0f; UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Particle System Component Tick State Info |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| World: 0x%p - %s |"), World, *WorldInfoString); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Inactive = Ticking but is not active and has no active particles. This should be investigated. |")); UE_LOG(LogParticles, Log, TEXT("| Invisible = Ticking but is not visible. Ideally these systems could be culled by the significance manager but this requires them to be non critical. |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Summary |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Total | Mem(KB) | Ticking | Managed | Inactive | Invisible | Template |---------||")); UE_LOG(LogParticles, Log, TEXT("| %5u | %7.2f | %7u | %7u | %8u | %9u|| Loop | MaxSig | Name |"), WorldInfo.TotalPSCs, KBUsed, WorldInfo.TotalTicking, WorldInfo.TotalManaged, WorldInfo.TotalTickingButInactive, WorldInfo.TotalTickingButInvisible); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); WorldInfo.SummaryMap.ValueSort([](const FPSCInfoSummary &A, const FPSCInfoSummary &B) { return((A.Components.Num()/1000.0f)+(A.NumManaged+A.NumTicking)) >((B.Components.Num()/1000.0f)+(B.NumManaged+B.NumTicking));}); for(TPair< UParticleSystem *, FPSCInfoSummary > &Pair :WorldInfo.SummaryMap) { const UParticleSystem *Sys=Pair.Key; FPSCInfoSummary &Info=Pair.Value; { PrintPSCInfo(Sys, Info); } } UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("|-- All Ticking or Managed Components By System --------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------|")); for(TPair< UParticleSystem *, FPSCInfoSummary > &Pair :WorldInfo.SummaryMap) { const UParticleSystem *Sys=Pair.Key; FPSCInfoSummary &Info=Pair.Value; if(Info.NumManaged > 0||Info.NumTicking > 0) { UE_LOG(LogParticles, Log, TEXT("|-- Sys: %s -------------------------------------------------------|"), Sys ? *Sys->GetFullName() :TEXT("null")); Info.Components.Sort([](const FPSCInfo &A, const FPSCInfo &B) { return !A.bIsActive+!A.bIsSignificant+!A.bIsVisible< !B.bIsActive+!B.bIsSignificant+!B.bIsVisible;}); for(FPSCInfo &PSCInfo :Info.Components) { bool bTickManaged=PSCInfo.PSC->IsTickManaged(); if(PSCInfo.PSC->IsComponentTickEnabled()) { UE_LOG(LogParticles, Log, TEXT("| PSC: %p | Ticking: %d | Managed: %d | Active: %d | Sig: %d | Vis: %d | Num: %d | %s"), PSCInfo.PSC, !bTickManaged, bTickManaged, PSCInfo.bIsActive, PSCInfo.bIsSignificant, PSCInfo.bIsVisible, PSCInfo.NumActiveParticles, *PSCInfo.PSC->GetFullName()); } } } } } })) |
( |
TEXT("fx.DumpPSCTickStateInfo") |
, |
|
|
FConsoleCommandDelegate::CreateStatic([](){ struct FPSCInfo { UParticleSystemComponent *PSC; bool bIsActive; bool bIsSignificant; bool bIsVisible; int32 NumActiveParticles; FPSCInfo() :PSC((UParticleSystemComponent *) 0xDEADBEEFDEADBEEF), bIsActive(false), bIsSignificant(false), bIsVisible(false), NumActiveParticles(0) {} };struct FPSCInfoSummary { TArray< FPSCInfo > Components; int32 NumTicking; int32 NumManaged; int32 NumTickingNoTemplate; int32 NumTickingButInactive; int32 NumTickingButInvisible; int32 NumTickingButNonSignificant; int32 NumTickingNoEmitters; int32 NumPooled; FPSCInfoSummary() :NumTicking(0), NumManaged(0), NumTickingNoTemplate(0), NumTickingButInactive(0), NumTickingButInvisible(0), NumTickingButNonSignificant(0), NumTickingNoEmitters(0), NumPooled(0) {} };struct FPSCWorldInfo { TMap< UParticleSystem *, FPSCInfoSummary > SummaryMap; int32 TotalPSCs; int32 TotalTicking; int32 TotalManaged; int32 TotalTickingNoTemplate; int32 TotalTickingButInactive; int32 TotalTickingButInvisible; int32 TotalTickingButNonSignificant; int32 TotalTickingNoEmitters; int32 TotalPooled; FPSCWorldInfo() :TotalPSCs(0), TotalTicking(0), TotalManaged(0), TotalTickingNoTemplate(0), TotalTickingButInactive(0), TotalTickingButInvisible(0), TotalTickingButNonSignificant(0), TotalTickingNoEmitters(0), TotalPooled(0) {} }; TMap< UWorld *, FPSCWorldInfo > InfoMap;for(TObjectIterator< UParticleSystemComponent > PSCIt;PSCIt;++PSCIt) { UParticleSystemComponent *PSC=*PSCIt; check(PSC); UWorld *World=PSC->GetWorld(); UParticleSystem *Sys=PSC->Template; FPSCWorldInfo &WorldInfo=InfoMap.FindOrAdd(World); FPSCInfoSummary &Info=WorldInfo.SummaryMap.FindOrAdd(Sys); int32 PSCInfoIndex=Info.Components.AddDefaulted(); FPSCInfo &PSCInfo=Info.Components[PSCInfoIndex]; PSCInfo.PSC=PSC;++WorldInfo.TotalPSCs; if(PSC->IsComponentTickEnabled()) { int32 NumParticles=PSC->GetNumActiveParticles(); PSCInfo.NumActiveParticles=NumParticles; if(PSC->IsTickManaged()) {++Info.NumManaged;++WorldInfo.TotalManaged; } else {++Info.NumTicking;++WorldInfo.TotalTicking; } if(PSC->Template==nullptr) {++Info.NumTickingNoTemplate;++WorldInfo.TotalTickingNoTemplate; } if(PSC->EmitterInstances.Num()==0) {++Info.NumTickingNoEmitters;++WorldInfo.TotalTickingNoEmitters; } if(PSC->IsActive()) { PSCInfo.bIsActive=true; } else {++Info.NumTickingButInactive;++WorldInfo.TotalTickingButInactive; PSCInfo.bIsActive=false; } PSCInfo.bIsVisible=!PSC->CanConsiderInvisible(); if(!PSCInfo.bIsVisible) {++Info.NumTickingButInvisible;++WorldInfo.TotalTickingButInvisible; } if(PSC->bIsManagingSignificance) { uint32 NumSignificantEmitters=0; for(UParticleEmitter *Emitter :PSC->Template->Emitters) { if(Emitter->IsSignificant(PSC->RequiredSignificance)) {++NumSignificantEmitters; } } PSCInfo.bIsSignificant=NumSignificantEmitters > 0; if(NumSignificantEmitters==0 &&NumParticles==0) {++Info.NumTickingButNonSignificant;++WorldInfo.TotalTickingButNonSignificant; } } else { PSCInfo.bIsSignificant=true; } } } auto PrintPSCInfo=[](const UParticleSystem *Sys, FPSCInfoSummary &Info) { float KBUsed=(sizeof(UParticleSystemComponent) *Info.Components.Num())/1024.0f; FString MaxSigName; if(Sys) { switch(Sys->GetHighestSignificance()) { case EParticleSignificanceLevel::Critical:MaxSigName=TEXT("Crit");break; case EParticleSignificanceLevel::High:MaxSigName=TEXT("High");break; case EParticleSignificanceLevel::Medium:MaxSigName=TEXT("Med");break; case EParticleSignificanceLevel::Low:MaxSigName=TEXT("Low");break; } } UE_LOG(LogParticles, Log, TEXT("| %5u | %7.2f | %7u | %7u | %8u | %9u || %4d | %6s |%s"), Info.Components.Num(), KBUsed, Info.NumTicking, Info.NumManaged, Info.NumTickingButInactive, Info.NumTickingButInvisible, Sys ? Sys->IsLooping() :0, *MaxSigName, Sys ? *Sys->GetFullName() :TEXT("NULL SYSTEM!"));};for(TPair< UWorld *, FPSCWorldInfo > InfoMapPair :InfoMap) { UWorld *World=InfoMapPair.Key; FPSCWorldInfo &WorldInfo=InfoMapPair.Value; FString WorldInfoString; if(World) {#define WORLD_TYPE_CASE(WorldType) switch(World->WorldType) { }; WorldInfoString+=TEXT(" | "); WorldInfoString+=World->GetFullName(); } float KBUsed=(sizeof(UParticleSystemComponent) *WorldInfo.TotalPSCs)/1024.0f; UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Particle System Component Tick State Info |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| World: 0x%p - %s |"), World, *WorldInfoString); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Inactive = Ticking but is not active and has no active particles. This should be investigated. |")); UE_LOG(LogParticles, Log, TEXT("| Invisible = Ticking but is not visible. Ideally these systems could be culled by the significance manager but this requires them to be non critical. |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Summary |")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("| Total | Mem(KB) | Ticking | Managed | Inactive | Invisible | Template |---------||")); UE_LOG(LogParticles, Log, TEXT("| %5u | %7.2f | %7u | %7u | %8u | %9u|| Loop | MaxSig | Name |"), WorldInfo.TotalPSCs, KBUsed, WorldInfo.TotalTicking, WorldInfo.TotalManaged, WorldInfo.TotalTickingButInactive, WorldInfo.TotalTickingButInvisible); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------------------|")); WorldInfo.SummaryMap.ValueSort([](const FPSCInfoSummary &A, const FPSCInfoSummary &B) { return((A.Components.Num()/1000.0f)+(A.NumManaged+A.NumTicking)) >((B.Components.Num()/1000.0f)+(B.NumManaged+B.NumTicking));}); for(TPair< UParticleSystem *, FPSCInfoSummary > &Pair :WorldInfo.SummaryMap) { const UParticleSystem *Sys=Pair.Key; FPSCInfoSummary &Info=Pair.Value; { PrintPSCInfo(Sys, Info); } } UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("|-- All Ticking or Managed Components By System --------------------------------------------|")); UE_LOG(LogParticles, Log, TEXT("|-------------------------------------------------------------------------------------------|")); for(TPair< UParticleSystem *, FPSCInfoSummary > &Pair :WorldInfo.SummaryMap) { const UParticleSystem *Sys=Pair.Key; FPSCInfoSummary &Info=Pair.Value; if(Info.NumManaged > 0||Info.NumTicking > 0) { UE_LOG(LogParticles, Log, TEXT("|-- Sys: %s -------------------------------------------------------|"), Sys ? *Sys->GetFullName() :TEXT("null")); Info.Components.Sort([](const FPSCInfo &A, const FPSCInfo &B) { return !A.bIsActive+!A.bIsSignificant+!A.bIsVisible< !B.bIsActive+!B.bIsSignificant+!B.bIsVisible;}); for(FPSCInfo &PSCInfo :Info.Components) { bool bTickManaged=PSCInfo.PSC->IsTickManaged(); if(PSCInfo.PSC->IsComponentTickEnabled()) { UE_LOG(LogParticles, Log, TEXT("| PSC: %p | Ticking: %d | Managed: %d | Active: %d | Sig: %d | Vis: %d | Num: %d | %s"), PSCInfo.PSC, !bTickManaged, bTickManaged, PSCInfo.bIsActive, PSCInfo.bIsSignificant, PSCInfo.bIsVisible, PSCInfo.NumActiveParticles, *PSCInfo.PSC->GetFullName()); } } } } }}) |
|