diff --git a/.gitmodules b/.gitmodules index 6185d962d15f..a31ffb2720d1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "modules/jolt/thirdparty/mimalloc"] path = modules/jolt/thirdparty/mimalloc url = https://github.com/microsoft/mimalloc.git +[submodule "modules/godot_tracy"] + path = modules/godot_tracy + url = https://github.com/AndreaCatania/godot_tracy.git diff --git a/core/object/object.cpp b/core/object/object.cpp index e5d771844b1b..ccb79f7db174 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -43,6 +43,12 @@ #include "core/templates/local_vector.h" #include "core/variant/typed_array.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#endif // MODULE_GODOT_TRACY_ENABLED + #ifdef DEBUG_ENABLED struct _ObjectDebugLock { @@ -780,6 +786,12 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) { } Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef MODULE_GODOT_TRACY_ENABLED + ZoneScoped; + CharString c = Profiler::stringify_method(p_method, p_args, p_argcount); + ZoneName(c.ptr(), c.size()); +#endif // MODULE_GODOT_TRACY_ENABLED + r_error.error = Callable::CallError::CALL_OK; if (p_method == CoreStringNames::get_singleton()->_free) { @@ -843,6 +855,12 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_ } Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef MODULE_GODOT_TRACY_ENABLED + ZoneScoped; + CharString c = Profiler::stringify_method(p_method, p_args, p_argcount); + ZoneName(c.ptr(), c.size()); +#endif // MODULE_GODOT_TRACY_ENABLED + r_error.error = Callable::CallError::CALL_OK; if (p_method == CoreStringNames::get_singleton()->_free) { diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 1c9fa4d42704..ff312a8ae27f 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -40,6 +40,12 @@ #include "core/templates/local_vector.h" #include "core/templates/oa_hash_map.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#endif // MODULE_GODOT_TRACY_ENABLED + typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args); typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); @@ -1195,6 +1201,12 @@ static void register_builtin_method(const Vector &p_argnames, const Vect } void Variant::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +#ifdef MODULE_GODOT_TRACY_ENABLED + ZoneScoped; + CharString c = Profiler::stringify_method(p_method, p_args, p_argcount); + ZoneName(c.ptr(), c.size()); +#endif // MODULE_GODOT_TRACY_ENABLED + if (type == Variant::OBJECT) { //call object Object *obj = _get_obj().obj; diff --git a/main/main.cpp b/main/main.cpp index 5a607a7c8cfb..de52f2fa2e74 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -110,7 +110,7 @@ #endif // DISABLE_DEPRECATED #endif // TOOLS_ENABLED -#include "modules/modules_enabled.gen.h" // For mono. +#include "modules/modules_enabled.gen.h" #if defined(MODULE_MONO_ENABLED) && defined(TOOLS_ENABLED) #include "modules/mono/editor/bindings_generator.h" @@ -128,6 +128,14 @@ #include "modules/app_protocol/app_protocol.h" #endif // MODULE_APP_PROTOCOL_ENABLED +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define ZoneScoped +#define ZoneScopedN(a) +#endif // MODULE_GODOT_TRACY_ENABLED + /* Static members */ // Singletons @@ -3941,6 +3949,7 @@ static uint64_t process_max = 0; static uint64_t navigation_process_max = 0; bool Main::iteration() { + ZoneScoped; //for now do not error on this //ERR_FAIL_COND_V(iterating, false); @@ -3989,57 +3998,79 @@ bool Main::iteration() { NavigationServer2D::get_singleton()->sync(); NavigationServer3D::get_singleton()->sync(); - for (int iters = 0; iters < advance.physics_steps; ++iters) { - if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { - Input::get_singleton()->flush_buffered_events(); - } + { + ZoneScopedN("PHYSICS LOOP"); + for (int iters = 0; iters < advance.physics_steps; ++iters) { + if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { + Input::get_singleton()->flush_buffered_events(); + } - Engine::get_singleton()->_in_physics = true; + Engine::get_singleton()->_in_physics = true; - uint64_t physics_begin = OS::get_singleton()->get_ticks_usec(); + uint64_t physics_begin = OS::get_singleton()->get_ticks_usec(); #ifndef _3D_DISABLED - PhysicsServer3D::get_singleton()->sync(); - PhysicsServer3D::get_singleton()->flush_queries(); + { + ZoneScopedN("Godot physics 3D - sync"); + PhysicsServer3D::get_singleton()->sync(); + PhysicsServer3D::get_singleton()->flush_queries(); + } #endif // _3D_DISABLED - PhysicsServer2D::get_singleton()->sync(); - PhysicsServer2D::get_singleton()->flush_queries(); + { + ZoneScopedN("Godot physics 2D - sync"); + PhysicsServer2D::get_singleton()->sync(); + PhysicsServer2D::get_singleton()->flush_queries(); + } + + { + ZoneScopedN("physics_process"); - if (OS::get_singleton()->get_main_loop()->physics_process(physics_step * time_scale)) { + if (OS::get_singleton()->get_main_loop()->physics_process(physics_step * time_scale)) { #ifndef _3D_DISABLED - PhysicsServer3D::get_singleton()->end_sync(); + PhysicsServer3D::get_singleton()->end_sync(); #endif // _3D_DISABLED - PhysicsServer2D::get_singleton()->end_sync(); + PhysicsServer2D::get_singleton()->end_sync(); - exit = true; - break; - } + exit = true; + break; + } + } - uint64_t navigation_begin = OS::get_singleton()->get_ticks_usec(); + uint64_t navigation_begin = OS::get_singleton()->get_ticks_usec(); - NavigationServer3D::get_singleton()->process(physics_step * time_scale); + { + ZoneScopedN("Navigation process"); + NavigationServer3D::get_singleton()->process(physics_step * time_scale); + } - navigation_process_ticks = MAX(navigation_process_ticks, OS::get_singleton()->get_ticks_usec() - navigation_begin); // keep the largest one for reference - navigation_process_max = MAX(OS::get_singleton()->get_ticks_usec() - navigation_begin, navigation_process_max); + navigation_process_ticks = MAX(navigation_process_ticks, OS::get_singleton()->get_ticks_usec() - navigation_begin); // keep the largest one for reference + navigation_process_max = MAX(OS::get_singleton()->get_ticks_usec() - navigation_begin, navigation_process_max); - message_queue->flush(); + message_queue->flush(); #ifndef _3D_DISABLED - PhysicsServer3D::get_singleton()->end_sync(); - PhysicsServer3D::get_singleton()->step(physics_step * time_scale); + { + ZoneScopedN("Godot physics 3D - step"); + PhysicsServer3D::get_singleton()->end_sync(); + PhysicsServer3D::get_singleton()->step(physics_step * time_scale); + } #endif // _3D_DISABLED - PhysicsServer2D::get_singleton()->end_sync(); - PhysicsServer2D::get_singleton()->step(physics_step * time_scale); + { + ZoneScopedN("Godot physics 2D - step"); + PhysicsServer2D::get_singleton()->end_sync(); + PhysicsServer2D::get_singleton()->step(physics_step * time_scale); + } - message_queue->flush(); + message_queue->flush(); - physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference - physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max); - Engine::get_singleton()->_physics_frames++; + physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference + physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max); + Engine::get_singleton()->_physics_frames++; - Engine::get_singleton()->_in_physics = false; + Engine::get_singleton()->_in_physics = false; + } } if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { @@ -4048,24 +4079,30 @@ bool Main::iteration() { uint64_t process_begin = OS::get_singleton()->get_ticks_usec(); - if (OS::get_singleton()->get_main_loop()->process(process_step * time_scale)) { - exit = true; + { + ZoneScopedN("Main process"); + if (OS::get_singleton()->get_main_loop()->process(process_step * time_scale)) { + exit = true; + } } message_queue->flush(); - RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames. - - if (DisplayServer::get_singleton()->can_any_window_draw() && - RenderingServer::get_singleton()->is_render_loop_enabled()) { - if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { - if (RenderingServer::get_singleton()->has_changed()) { + { + ZoneScopedN("Main::iteration - Draw"); + RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames. + + if (DisplayServer::get_singleton()->can_any_window_draw() && + RenderingServer::get_singleton()->is_render_loop_enabled()) { + if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { + if (RenderingServer::get_singleton()->has_changed()) { + RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands + Engine::get_singleton()->frames_drawn++; + } + } else { RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands Engine::get_singleton()->frames_drawn++; + force_redraw_requested = false; } - } else { - RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands - Engine::get_singleton()->frames_drawn++; - force_redraw_requested = false; } } @@ -4073,11 +4110,17 @@ bool Main::iteration() { process_max = MAX(process_ticks, process_max); uint64_t frame_time = OS::get_singleton()->get_ticks_usec() - ticks; - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->frame(); + { + ZoneScopedN("Languages update"); + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->frame(); + } } - AudioServer::get_singleton()->update(); + { + ZoneScopedN("Audio update"); + AudioServer::get_singleton()->update(); + } if (EngineDebugger::is_active()) { EngineDebugger::get_singleton()->iteration(frame_time, process_ticks, physics_process_ticks, physics_step); @@ -4131,7 +4174,10 @@ bool Main::iteration() { return exit; } - OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw()); + { + ZoneScopedN("Frame delay"); + OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw()); + } #ifdef TOOLS_ENABLED if (auto_build_solutions) { diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 8e74de424212..da1fedfb208a 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -60,6 +60,12 @@ #include +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#endif // MODULE_GODOT_TRACY_ENABLED + /////////////////////////// GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) { @@ -1951,6 +1957,12 @@ int GDScriptInstance::get_method_argument_count(const StringName &p_method, bool } Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef MODULE_GODOT_TRACY_ENABLED + ZoneScoped; + CharString c = Profiler::stringify_method(p_method, p_args, p_argcount); + ZoneName(c.ptr(), c.size()); +#endif // MODULE_GODOT_TRACY_ENABLED + GDScript *sptr = script.ptr(); if (unlikely(p_method == SNAME("_ready"))) { // Call implicit ready first, including for the super classes. diff --git a/modules/godot_tracy b/modules/godot_tracy new file mode 160000 index 000000000000..cfa757816fb0 --- /dev/null +++ b/modules/godot_tracy @@ -0,0 +1 @@ +Subproject commit cfa757816fb0985d5bfe87778e204f5a16db3274 diff --git a/modules/jolt/jolt.cpp b/modules/jolt/jolt.cpp index 5b0e566ea539..d9427faafe5c 100644 --- a/modules/jolt/jolt.cpp +++ b/modules/jolt/jolt.cpp @@ -43,6 +43,16 @@ #include "scene/resources/physics_material.h" #include "state_recorder_sync.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define ZoneScoped +#define ZoneScopedN(a) +#endif // MODULE_GODOT_TRACY_ENABLED + Jolt *Jolt::the_singleton = nullptr; Jolt *Jolt::singleton() { @@ -239,6 +249,7 @@ void Jolt::world_unregister_sensor(JBody3D *p_sensor) { } void Jolt::world_process(uint32_t p_world_id, double p_delta) { + ZoneScoped; JPH::PhysicsSystem *physics_system = worlds[p_world_id]; if (worlds_need_broadphase_opt[p_world_id]) { @@ -304,12 +315,14 @@ bool Jolt::world_is_processing(uint32_t p_world_id) const { } void Jolt::world_get_state(uint32_t p_world_id, class StateRecorderSync &p_state, JPH::EStateRecorderState p_recorder_state, const JPH::StateRecorderFilter *p_filter) { + ZoneScoped; JPH::PhysicsSystem *physics_system = worlds[p_world_id]; CRASH_COND_MSG(p_state.IsFailed(), "The state shound not be failed at this point."); p_state.Clear(); { + ZoneScopedN("PhysicsSystem::SaveState"); physics_system->SaveState(p_state, p_recorder_state, p_filter); } @@ -386,6 +399,7 @@ JPH::Body *Jolt::create_body( real_t p_max_angular_velocity_deg, real_t p_gravity_scale, bool p_use_ccd) { + ZoneScoped; JPH::RVec3 origin = convert_r(p_body_initial_transform.get_origin()); JPH::Quat rot = convert(p_body_initial_transform.get_basis().get_rotation_quaternion()); JPH::Vec3 scale = convert(p_body_initial_transform.get_basis().get_scale_abs()); @@ -1059,6 +1073,7 @@ void Jolt::collide_sphere_broad_phase( JPH::Ref Jolt::create_character_virtual( const JPH::RMat44 &p_transform, JPH::CharacterVirtualSettings *p_settings) { + ZoneScoped; JPH::PhysicsSystem *physics_system = worlds[0]; return JPH::Ref( @@ -1075,6 +1090,7 @@ void Jolt::character_virtual_pre_step( JPH::CharacterVirtual *p_character, JPH::ObjectLayer p_layer_id, const LocalVector &p_ignore_bodies) { + ZoneScoped; const JPH::DefaultBroadPhaseLayerFilter broad_phase_layer_filter(object_vs_broad_phase_layer_filter, p_layer_id); TableObjectLayerFilter object_layer_filter; object_layer_filter.layer = p_layer_id; @@ -1096,6 +1112,7 @@ void Jolt::character_virtual_step( JPH::CharacterVirtual::ExtendedUpdateSettings &p_update_settings, JPH::ObjectLayer p_layer_id, const LocalVector &p_ignore_bodies) { + ZoneScoped; JPH::PhysicsSystem *physics_system = worlds[0]; const JPH::DefaultBroadPhaseLayerFilter broad_phase_layer_filter(object_vs_broad_phase_layer_filter, p_layer_id); diff --git a/modules/jolt/state_recorder_sync.cpp b/modules/jolt/state_recorder_sync.cpp index a9a4b18a4ee7..2ad4e7e99e14 100644 --- a/modules/jolt/state_recorder_sync.cpp +++ b/modules/jolt/state_recorder_sync.cpp @@ -3,16 +3,29 @@ #include "modules/network_synchronizer/core/core.h" #include "modules/network_synchronizer/core/scene_synchronizer_debugger.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define ZoneScoped +#define ZoneScopedN(a) +#endif // MODULE_GODOT_TRACY_ENABLED + void StateRecorderSync::WriteBytes(const void *inData, size_t inNumBytes) { + ZoneScoped; const uint32_t start = data.size(); data.resize(data.size() + inNumBytes); memcpy(data.ptr() + start, inData, inNumBytes); } void StateRecorderSync::ReadBytes(void *outData, size_t inNumBytes) { + ZoneScoped; // Verify bounds. const size_t next_offset = read_offset + inNumBytes; if (next_offset > data.size()) { + ZoneScopedN("Add debug error."); SceneSynchronizerDebugger::singleton()->print(NS::ERROR, "[FATAL] StateRecorderSync is trying to read more bytes than it contains."); failed = true; return; @@ -20,6 +33,7 @@ void StateRecorderSync::ReadBytes(void *outData, size_t inNumBytes) { // Read if (IsValidating()) { + ZoneScopedN("ReadBytes - Validating"); // Read data in temporary buffer to compare with current value void *tmp_data = JPH_STACK_ALLOC(inNumBytes); memcpy(tmp_data, data.ptr() + read_offset, inNumBytes); @@ -28,6 +42,7 @@ void StateRecorderSync::ReadBytes(void *outData, size_t inNumBytes) { failed = true; } } else { + ZoneScopedN("Mem copy"); memcpy(outData, data.ptr() + read_offset, inNumBytes); } read_offset = next_offset; @@ -41,6 +56,7 @@ bool StateRecorderSync::IsFailed() const { } bool StateRecorderSync::IsEqual(const StateRecorderSync &p_other) const { + ZoneScoped; if (data.size() != p_other.data.size()) { return false; } @@ -48,16 +64,19 @@ bool StateRecorderSync::IsEqual(const StateRecorderSync &p_other) const { } void StateRecorderSync::BeginRead() { + ZoneScoped; read_offset = 0; } void StateRecorderSync::Clear() { + ZoneScoped; failed = false; read_offset = 0; data.clear(); } void StateRecorderSync::set_data(const Vector &p_data) { + ZoneScoped; failed = false; read_offset = 0; data = p_data; diff --git a/modules/the_mirror/physics/tm_state_recorder_filter.cpp b/modules/the_mirror/physics/tm_state_recorder_filter.cpp index a2aa39699efb..276141c3f1a0 100644 --- a/modules/the_mirror/physics/tm_state_recorder_filter.cpp +++ b/modules/the_mirror/physics/tm_state_recorder_filter.cpp @@ -3,27 +3,42 @@ #include "modules/jolt/thirdparty/JoltPhysics/Jolt/Physics/Body/Body.h" #include "modules/network_synchronizer/core/net_utilities.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define ZoneScoped +#endif // MODULE_GODOT_TRACY_ENABLED + void TMStateRecorderFilter::Clear() { + ZoneScoped; bodies_to_sync_buffer.clear(); } void TMStateRecorderFilter::MarkAsSync(const JPH::BodyID &inBodyID) { + ZoneScoped; NS::VecFunc::insert_at_position_expand(bodies_to_sync_buffer, inBodyID.GetIndex(), true, false); } bool TMStateRecorderFilter::ShouldSaveBody(const JPH::BodyID &inBodyID) const { + ZoneScoped; return NS::VecFunc::at(bodies_to_sync_buffer, inBodyID.GetIndex(), false); } bool TMStateRecorderFilter::ShouldSaveBody(const JPH::Body &inBody) const { + ZoneScoped; return ShouldSaveBody(inBody.GetID()); } bool TMStateRecorderFilter::ShouldSaveConstraint(const JPH::Constraint &inConstraint) const { + ZoneScoped; // Constraint sync is not yet implemented. return false; } bool TMStateRecorderFilter::ShouldSaveContact(const JPH::BodyID &inBody1, const JPH::BodyID &inBody2) const { + ZoneScoped; return ShouldSaveBody(inBody1) || ShouldSaveBody(inBody2); } diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index f29275c910a0..acfa1e0fcfc0 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -58,6 +58,16 @@ #include #include +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define FrameMark +#define ZoneScoped +#endif // MODULE_GODOT_TRACY_ENABLED + #ifdef HAVE_MNTENT #include #endif @@ -931,6 +941,9 @@ void OS_LinuxBSD::run() { //uint64_t frame=0; while (true) { + FrameMark; + ZoneScoped; + DisplayServer::get_singleton()->process_events(); // get rid of pending events #ifdef JOYDEV_ENABLED joypad->process_joypads(); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 152b9ac10fab..63ef5b879cd5 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -64,6 +64,16 @@ #pragma pack(pop, before_imagehlp) #endif +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_GODOT_TRACY_ENABLED +#include "modules/godot_tracy/profiler.h" +#else +// Dummy defines to allow compiling without tracy. +#define FrameMark +#define ZoneScoped +#endif // MODULE_GODOT_TRACY_ENABLED + extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 1; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; @@ -1472,6 +1482,9 @@ void OS_Windows::run() { main_loop->initialize(); while (true) { + FrameMark; + ZoneScoped; + DisplayServer::get_singleton()->process_events(); // get rid of pending events if (Main::iteration()) { break;