@@ -97,12 +97,15 @@ void godot_cleanup_profiler();
9797// Use the perfetto profiler.
9898
9999#include " core/typedefs.h"
100+ #include " main/performance.h"
100101
101102#include < perfetto.h>
102103
103104PERFETTO_DEFINE_CATEGORIES (
104105 perfetto::Category (" godot" )
105- .SetDescription(" All Godot Events" ), );
106+ .SetDescription(" Godot Engine Events" ),
107+ perfetto::Category(" godot_scripting" )
108+ .SetDescription(" Godot Scripting Events" ), );
106109
107110// See PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER
108111struct PerfettoGroupedEventEnder {
@@ -115,7 +118,9 @@ struct PerfettoGroupedEventEnder {
115118 }
116119};
117120
118- #define GodotProfileFrameMark // TODO
121+ #define GodotProfileFrameMark \
122+ perfetto::CounterTrack __frame_time_track = perfetto::CounterTrack(" Frame time" , " ms" ).set_unit_multiplier(1000 ); \
123+ TRACE_COUNTER (" godot" , __frame_time_track, Performance::get_singleton()->get_monitor(Performance::Monitor::TIME_PROCESS ));
119124#define GodotProfileZone (m_zone_name ) TRACE_EVENT (" godot" , m_zone_name);
120125#define GodotProfileZoneGroupedFirst (m_group_name, m_zone_name ) \
121126 TRACE_EVENT_BEGIN (" godot" , m_zone_name); \
@@ -125,8 +130,45 @@ struct PerfettoGroupedEventEnder {
125130 __godot_perfetto_zone_##m_group_name._end_now(); \
126131 TRACE_EVENT_BEGIN (" godot" , m_zone_name);
127132
128- #define GodotProfileZoneScript (m_ptr, m_file, m_function, m_name, m_line )
129- #define GodotProfileZoneScriptSystemCall (m_ptr, m_file, m_function, m_name, m_line )
133+ static HashSet<StringName> __tracing_system_call;
134+
135+ /* *
136+ * Script tracing may cross function boundaries (tracing started in the caller script), so the logic below only triggers
137+ * a TRACE_EVENT_BEGIN for `GodotProfileZoneScript` if tracing hasn't already been initiated by
138+ * `GodotProfileZoneScriptSystemCall` in the caller.
139+ */
140+ struct PerfettoScriptTracer {
141+ StringName name;
142+ bool is_system_call;
143+ bool tracing;
144+
145+ PerfettoScriptTracer (const StringName &p_file, const StringName &p_function, const StringName &p_name, int p_line, bool p_system_call) : name(p_name), is_system_call(p_system_call) {
146+ if (is_system_call || !__tracing_system_call.erase (name)) {
147+ TRACE_EVENT_BEGIN (" godot_scripting" , perfetto::DynamicString (p_name.operator String ().utf8 ().get_data ()), " source file" , p_file.operator String ().utf8 ().get_data (), " line number" , p_line);
148+ tracing = true ;
149+ }
150+
151+ if (is_system_call) {
152+ __tracing_system_call.insert (name);
153+ }
154+ }
155+
156+ _FORCE_INLINE_ void _end_now () {
157+ if (tracing) {
158+ TRACE_EVENT_END (" godot_scripting" );
159+ }
160+ }
161+
162+ _FORCE_INLINE_ ~PerfettoScriptTracer () {
163+ _end_now ();
164+ if (is_system_call) {
165+ __tracing_system_call.erase (name);
166+ }
167+ }
168+ };
169+
170+ #define GodotProfileZoneScript (m_ptr, m_file, m_function, m_name, m_line ) PerfettoScriptTracer __godot_perfetto_script_tracer (m_file, m_function, m_name, m_line, false );
171+ #define GodotProfileZoneScriptSystemCall (m_ptr, m_file, m_function, m_name, m_line ) PerfettoScriptTracer __godot_perfetto_script_system_call_tracer (m_file, m_function, m_name, m_line, true );
130172
131173#define GodotProfileAlloc (m_ptr, m_size )
132174#define GodotProfileFree (m_ptr )
0 commit comments