1 // Copyright Epic Games, Inc. All Rights Reserved.
   2 
   3 #pragma once
   4 
   5 #include "CoreTypes.h"
   6 #include "Trace/Trace.h"
   7 #include "Trace/Detail/Channel.h"
   8 #include "Trace/Detail/Channel.inl"
   9 
  10 #if !defined(CPUPROFILERTRACE_ENABLED)
  11 #if UE_TRACE_ENABLED && !UE_BUILD_SHIPPING
  12 #define CPUPROFILERTRACE_ENABLED 1
  13 #else
  14 #define CPUPROFILERTRACE_ENABLED 0
  15 #endif
  16 #endif
  17 
  18 #if CPUPROFILERTRACE_ENABLED
  19 
  20 UE_TRACE_CHANNEL_EXTERN(CpuChannel, CORE_API);
  21 
  22 /*
  23  * Facilities for tracing timed cpu events. Two types of events are supported, static events where the identifier is
  24  * known at compile time, and dynamic event were identifiers can be constructed in runtime. Static events have lower overhead
  25  * so always prefer to use them if possible.
  26  *
  27  * Events are tracked per thread, so begin/end calls must be matched and called on the same thread. It is possible to use any channel
  28  * to emit the events, but both that channel and the CpuChannel must then be enabled.
  29  *
  30  * Usage of the scope macros is highly encouraged in order to avoid mistakes.
  31  */
  32 struct FCpuProfilerTrace
  33 {
  34         CORE_API static void Shutdown();
  35         /*
  36          * Output cpu event definition (spec).
  37          * @param Name Event name
  38          * @return Event definition id
  39          */
  40         FORCENOINLINE CORE_API static uint32 OutputEventType(const ANSICHAR* Name);
  41         /*
  42          * Output cpu event definition (spec).
  43          * @param Name Event name
  44          * @return Event definition id
  45          */
  46         FORCENOINLINE CORE_API static uint32 OutputEventType(const TCHAR* Name);
  47         /*
  48          * Output begin event marker for a given spec. Must always be matched with an end event.
  49          * @param SpecId Event definition id.
  50          */
  51         CORE_API static void OutputBeginEvent(uint32 SpecId);
  52         /*
  53          * Output begin event marker for a dynamic event name. This is more expensive than statically known event
  54          * names using \ref OutputBeginEvent. Must always be matched with an end event.
  55          * @param Name Name of event
  56          */
  57         CORE_API static void OutputBeginDynamicEvent(const ANSICHAR* Name);
  58         /*
  59          * Output begin event marker for a dynamic event name. This is more expensive than statically known event
  60          * names using \ref OutputBeginEvent. Must always be matched with an end event.
  61          * @param Name Name of event
  62          */
  63         CORE_API static void OutputBeginDynamicEvent(const TCHAR* Name);
  64         /*
  65          * Output end event marker for static or dynamic event for the currently open scope.
  66          */
  67         CORE_API static void OutputEndEvent();
  68 
  69         struct FEventScope
  70         {
  71                 FEventScope(uint32 InSpecId, const Trace::FChannel& Channel)
  72                         : bEnabled(Channel | CpuChannel)
  73                 {
  74                         if (bEnabled)
  75                         {
  76                                 OutputBeginEvent(InSpecId);
  77                         }
  78                 }
  79 
  80                 ~FEventScope()
  81                 {
  82                         if (bEnabled)
  83                         {
  84                                 OutputEndEvent();
  85                         }
  86                 }
  87 
  88                 bool bEnabled;
  89         };
  90 
  91         struct FDynamicEventScope
  92         {
  93                 FDynamicEventScope(const ANSICHAR* InEventName, const Trace::FChannel& Channel)
  94                         : bEnabled(Channel | CpuChannel)
  95                 {
  96                         if (bEnabled)
  97                         {
  98                                 OutputBeginDynamicEvent(InEventName);
  99                         }
 100                 }
 101 
 102                 FDynamicEventScope(const TCHAR* InEventName, const Trace::FChannel& Channel)
 103                         : bEnabled(Channel | CpuChannel)
 104                 {
 105                         if (bEnabled)
 106                         {
 107                                 OutputBeginDynamicEvent(InEventName);
 108                         }
 109                 }
 110 
 111                 ~FDynamicEventScope()
 112                 {
 113                         if (bEnabled)
 114                         {
 115                                 OutputEndEvent();
 116                         }
 117                 }
 118 
 119                 bool bEnabled;
 120         };
 121 };
 122 
 123 #define TRACE_CPUPROFILER_SHUTDOWN() \
 124         FCpuProfilerTrace::Shutdown();
 125 
 126 // Trace a scoped cpu timing event providing a static string (const ANSICHAR* or const TCHAR*)
 127 // as the scope name and a trace channel.
 128 // Example: TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL_STR("My Scoped Timer A", CpuChannel)
 129 // Note: The event will be emitted only if both the given channel and CpuChannel is enabled.
 130 #define TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL_STR(NameStr, Channel) \
 131         static uint32 PREPROCESSOR_JOIN(__CpuProfilerEventSpecId, __LINE__); \
 132         if (bool(Channel|CpuChannel) && PREPROCESSOR_JOIN(__CpuProfilerEventSpecId, __LINE__) == 0) { \
 133                 PREPROCESSOR_JOIN(__CpuProfilerEventSpecId, __LINE__) = FCpuProfilerTrace::OutputEventType(NameStr); \
 134         } \
 135         FCpuProfilerTrace::FEventScope PREPROCESSOR_JOIN(__CpuProfilerEventScope, __LINE__)(PREPROCESSOR_JOIN(__CpuProfilerEventSpecId, __LINE__), Channel);
 136 
 137 // Trace a scoped cpu timing event providing a scope name (plain text) and a trace channel.
 138 // Example: TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL(MyScopedTimer::A, CpuChannel)
 139 // Note: Do not use this macro with a static string because, in that case, additional quotes will
 140 //       be added around the event scope name.
 141 // Note: The event will be emitted only if both the given channel and CpuChannel is enabled.
 142 #define TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL(Name, Channel) \
 143         TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL_STR(#Name, Channel)
 144 
 145 // Trace a scoped cpu timing event providing a static string (const ANSICHAR* or const TCHAR*)
 146 // as the scope name. It will use the Cpu trace channel.
 147 // Example: TRACE_CPUPROFILER_EVENT_SCOPE_STR("My Scoped Timer A")
 148 #define TRACE_CPUPROFILER_EVENT_SCOPE_STR(NameStr) \
 149         TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL_STR(NameStr, CpuChannel)
 150 
 151 // Trace a scoped cpu timing event providing a scope name (plain text) and a trace channel.
 152 // It will use the Cpu trace channel.
 153 // Example: TRACE_CPUPROFILER_EVENT_SCOPE(MyScopedTimer::A)
 154 // Note: Do not use this macro with a static string because, in that case, additional quotes will
 155 //       be added around the event scope name.
 156 #define TRACE_CPUPROFILER_EVENT_SCOPE(Name) \
 157         TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL(Name, CpuChannel)
 158 
 159 // Trace a scoped cpu timing event providing a dynamic string (const ANSICHAR* or const TCHAR*)
 160 // as the scope name and a trace channel.
 161 // Example: TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_ON_CHANNEL(*MyScopedTimerNameString, CpuChannel)
 162 // Note: This macro has a larger overhead compared to macro that accepts a plain text name
 163 //       or a static string. Use it only if scope name really needs to be a dynamic string.
 164 #define TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_ON_CHANNEL(Name, Channel) \
 165         FCpuProfilerTrace::FDynamicEventScope PREPROCESSOR_JOIN(__CpuProfilerEventScope, __LINE__)(Name, Channel);
 166 
 167 // Trace a scoped cpu timing event providing a dynamic string (const ANSICHAR* or const TCHAR*)
 168 // as the scope name. It will use the Cpu trace channel.
 169 // Example: TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*MyScopedTimerNameString)
 170 // Note: This macro has a larger overhead compared to macro that accepts a plain text name
 171 //       or a static string. Use it only if scope name really needs to be a dynamic string.
 172 #define TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(Name) \
 173         TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_ON_CHANNEL(Name, CpuChannel)
 174 
 175 #else
 176 
 177 #define TRACE_CPUPROFILER_SHUTDOWN()
 178 #define TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL_STR(NameStr, Channel)
 179 #define TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL(Name, Channel)
 180 #define TRACE_CPUPROFILER_EVENT_SCOPE_STR(NameStr)
 181 #define TRACE_CPUPROFILER_EVENT_SCOPE(Name)
 182 #define TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_ON_CHANNEL(Name, Channel)
 183 #define TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(Name)
 184 
 185 #endif
 186 

UE4/UE4.27-Source/Engine\Source\Runtime\Core\Public\ProfilingDebugging\CpuProfilerTrace.h (last edited 2021-11-02 03:56:41 by zbjxb)