From b940854ca9a1c154243dcd3aaef1ab9b5daa2470 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 9 Jun 2023 10:17:43 +0200 Subject: [PATCH] Ported from godot4: Add NavigationServer Performance Monitor Adds Performance Monitor for NavigationServer3D. - smix8 https://github.com/godotengine/godot/commit/9802914f9793b6888cc70e3d7f0d815bdd5188bb --- doc/classes/NavigationServer.xml | 34 +++++++ doc/classes/Performance.xml | 88 +++++++++++++------ main/performance.cpp | 53 +++++++++++ main/performance.h | 13 ++- modules/navigation/nav_map.cpp | 43 +++++++++ modules/navigation/nav_map.h | 20 +++++ .../pandemonium_navigation_server.cpp | 61 +++++++++++++ .../pandemonium_navigation_server.h | 12 +++ .../dummy_navigation_server.h | 2 + servers/navigation_server.h | 16 ++++ 10 files changed, 312 insertions(+), 30 deletions(-) diff --git a/doc/classes/NavigationServer.xml b/doc/classes/NavigationServer.xml index eb2f51136..cd80869c7 100644 --- a/doc/classes/NavigationServer.xml +++ b/doc/classes/NavigationServer.xml @@ -140,6 +140,13 @@ Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them. + + + + + Returns information about the current state of the NavigationServer. See [enum ProcessInfo] for a list of available states. + + @@ -577,5 +584,32 @@ + + Constant to get the number of active navigation maps. + + + Constant to get the number of active navigation regions. + + + Constant to get the number of active navigation agents processing avoidance. + + + Constant to get the number of active navigation links. + + + Constant to get the number of navigation mesh polygons. + + + Constant to get the number of navigation mesh polygon edges. + + + Constant to get the number of navigation mesh polygon edges that were merged due to edge key overlap. + + + Constant to get the number of navigation mesh polygon edges that are considered connected by edge proximity. + + + Constant to get the number of navigation mesh polygon edges that could not be merged but may be still connected by edge proximity or with links. + diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 1d182ec4e..ac4809384 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -32,91 +32,121 @@ Time it took to complete one physics frame, in seconds. - + + Time it took to complete one navigation step, in seconds. This includes navigation map updates as well as agent avoidance calculations. [i]Lower is better.[/i] + + Static memory currently used, in bytes. Not available in release builds. - + Dynamic memory currently used, in bytes. Not available in release builds. - + Available static memory. Not available in release builds. - + Available dynamic memory. Not available in release builds. - + Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications. - + Number of objects currently instanced (including nodes). - + Number of resources currently used. - + Number of nodes currently instanced in the scene tree. This also includes the root node. - + Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. - + 3D objects drawn per frame. - + Vertices drawn per frame. 3D only. - + Material changes per frame. 3D only. - + Shader changes per frame. 3D only. - + Render surface changes per frame. 3D only. - + Draw calls per frame. 3D only. - + Items or joined items drawn per frame. - + Draw calls per frame. - + The amount of video memory used, i.e. texture and vertex memory combined. - + The amount of texture memory used. - + The amount of vertex memory used. - + Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0. - + Number of active [RigidBody2D] nodes in the game. - + Number of collision pairs in the 2D physics engine. - + Number of islands in the 2D physics engine. - + Number of active [RigidBody] and [VehicleBody] nodes in the game. - + Number of collision pairs in the 3D physics engine. - + Number of islands in the 3D physics engine. - + Output latency of the [AudioServer]. - + + Number of active navigation maps in the [NavigationServer3D]. This also includes the two empty default navigation maps created by World2D and World3D. + + + Number of active navigation regions in the [NavigationServer3D]. + + + Number of active navigation agents processing avoidance in the [NavigationServer3D]. + + + Number of active navigation links in the [NavigationServer3D]. + + + Number of navigation mesh polygons in the [NavigationServer3D]. + + + Number of navigation mesh polygon edges in the [NavigationServer3D]. + + + Number of navigation mesh polygon edges that were merged due to edge key overlap in the [NavigationServer3D]. + + + Number of polygon edges that are considered connected by edge proximity [NavigationServer3D]. + + + Number of navigation mesh polygon edges that could not be merged in the [NavigationServer3D]. The edges still may be connected by edge proximity or with links. + + Represents the size of the [enum Monitor] enum. diff --git a/main/performance.cpp b/main/performance.cpp index f4e521380..52b826ed1 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -35,6 +35,7 @@ #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "servers/audio_server.h" +#include "servers/navigation_server.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" #include "servers/rendering_server.h" @@ -47,6 +48,7 @@ void Performance::_bind_methods() { BIND_ENUM_CONSTANT(TIME_FPS); BIND_ENUM_CONSTANT(TIME_PROCESS); BIND_ENUM_CONSTANT(TIME_PHYSICS_PROCESS); + BIND_ENUM_CONSTANT(TIME_NAVIGATION_PROCESS); BIND_ENUM_CONSTANT(MEMORY_STATIC); BIND_ENUM_CONSTANT(MEMORY_DYNAMIC); BIND_ENUM_CONSTANT(MEMORY_STATIC_MAX); @@ -75,6 +77,15 @@ void Performance::_bind_methods() { BIND_ENUM_CONSTANT(PHYSICS_3D_COLLISION_PAIRS); BIND_ENUM_CONSTANT(PHYSICS_3D_ISLAND_COUNT); BIND_ENUM_CONSTANT(AUDIO_OUTPUT_LATENCY); + BIND_ENUM_CONSTANT(NAVIGATION_ACTIVE_MAPS); + BIND_ENUM_CONSTANT(NAVIGATION_REGION_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_AGENT_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_LINK_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_POLYGON_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_EDGE_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_EDGE_MERGE_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_EDGE_CONNECTION_COUNT); + BIND_ENUM_CONSTANT(NAVIGATION_EDGE_FREE_COUNT); BIND_ENUM_CONSTANT(MONITOR_MAX); } @@ -95,6 +106,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const { "time/fps", "time/process", "time/physics_process", + "time/navigation_process", "memory/static", "memory/dynamic", "memory/static_max", @@ -123,6 +135,15 @@ String Performance::get_monitor_name(Monitor p_monitor) const { "physics_3d/collision_pairs", "physics_3d/islands", "audio/output_latency", + "navigation/active_maps", + "navigation/regions", + "navigation/agents", + "navigation/links", + "navigation/polygons", + "navigation/edges", + "navigation/edges_merged", + "navigation/edges_connected", + "navigation/edges_free", }; @@ -137,6 +158,8 @@ float Performance::get_monitor(Monitor p_monitor) const { return _process_time; case TIME_PHYSICS_PROCESS: return _physics_process_time; + case TIME_NAVIGATION_PROCESS: + return _navigation_process_time; case MEMORY_STATIC: return Memory::get_mem_usage(); case MEMORY_DYNAMIC: @@ -193,6 +216,24 @@ float Performance::get_monitor(Monitor p_monitor) const { return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ISLAND_COUNT); case AUDIO_OUTPUT_LATENCY: return AudioServer::get_singleton()->get_output_latency(); + case NAVIGATION_ACTIVE_MAPS: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_ACTIVE_MAPS); + case NAVIGATION_REGION_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_REGION_COUNT); + case NAVIGATION_AGENT_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_AGENT_COUNT); + case NAVIGATION_LINK_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_LINK_COUNT); + case NAVIGATION_POLYGON_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_POLYGON_COUNT); + case NAVIGATION_EDGE_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_EDGE_COUNT); + case NAVIGATION_EDGE_MERGE_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_EDGE_MERGE_COUNT); + case NAVIGATION_EDGE_CONNECTION_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_EDGE_CONNECTION_COUNT); + case NAVIGATION_EDGE_FREE_COUNT: + return NavigationServer::get_singleton()->get_process_info(NavigationServer::INFO_EDGE_FREE_COUNT); default: { } @@ -209,6 +250,7 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const MONITOR_TYPE_QUANTITY, MONITOR_TYPE_TIME, MONITOR_TYPE_TIME, + MONITOR_TYPE_TIME, MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY, @@ -237,6 +279,12 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_TIME, + MONITOR_TYPE_QUANTITY, + MONITOR_TYPE_QUANTITY, + MONITOR_TYPE_QUANTITY, + MONITOR_TYPE_QUANTITY, + MONITOR_TYPE_QUANTITY, + MONITOR_TYPE_QUANTITY, }; @@ -251,8 +299,13 @@ void Performance::set_physics_process_time(float p_pt) { _physics_process_time = p_pt; } +void Performance::set_navigation_process_time(float p_pt) { + _navigation_process_time = p_pt; +} + Performance::Performance() { _process_time = 0; _physics_process_time = 0; + _navigation_process_time = 0; singleton = this; } diff --git a/main/performance.h b/main/performance.h index 0717ad742..2e1603d91 100644 --- a/main/performance.h +++ b/main/performance.h @@ -45,6 +45,7 @@ class Performance : public Object { float _process_time; float _physics_process_time; + float _navigation_process_time; public: enum Monitor { @@ -52,6 +53,7 @@ public: TIME_FPS, TIME_PROCESS, TIME_PHYSICS_PROCESS, + TIME_NAVIGATION_PROCESS, MEMORY_STATIC, MEMORY_DYNAMIC, MEMORY_STATIC_MAX, @@ -79,8 +81,16 @@ public: PHYSICS_3D_ACTIVE_OBJECTS, PHYSICS_3D_COLLISION_PAIRS, PHYSICS_3D_ISLAND_COUNT, - //physics AUDIO_OUTPUT_LATENCY, + NAVIGATION_ACTIVE_MAPS, + NAVIGATION_REGION_COUNT, + NAVIGATION_AGENT_COUNT, + NAVIGATION_LINK_COUNT, + NAVIGATION_POLYGON_COUNT, + NAVIGATION_EDGE_COUNT, + NAVIGATION_EDGE_MERGE_COUNT, + NAVIGATION_EDGE_CONNECTION_COUNT, + NAVIGATION_EDGE_FREE_COUNT, MONITOR_MAX }; @@ -97,6 +107,7 @@ public: void set_process_time(float p_pt); void set_physics_process_time(float p_pt); + void set_navigation_process_time(float p_pt); static Performance *get_singleton() { return singleton; } diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 94c38fa10..c5aae67ef 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -547,6 +547,16 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) { } void NavMap::sync() { + // Performance Monitor + int _new_pm_region_count = regions.size(); + int _new_pm_agent_count = agents.size(); + int _new_pm_link_count = links.size(); + int _new_pm_polygon_count = pm_polygon_count; + int _new_pm_edge_count = pm_edge_count; + int _new_pm_edge_merge_count = pm_edge_merge_count; + int _new_pm_edge_connection_count = pm_edge_connection_count; + int _new_pm_edge_free_count = pm_edge_free_count; + // Check if we need to update the links. if (regenerate_polygons) { for (uint32_t r = 0; r < regions.size(); r++) { @@ -568,6 +578,12 @@ void NavMap::sync() { } if (regenerate_links) { + _new_pm_polygon_count = 0; + _new_pm_edge_count = 0; + _new_pm_edge_merge_count = 0; + _new_pm_edge_connection_count = 0; + _new_pm_edge_free_count = 0; + // Remove regions connections. for (uint32_t r = 0; r < regions.size(); r++) { regions[r]->get_connections().clear(); @@ -592,6 +608,8 @@ void NavMap::sync() { count += regions[r]->get_polygons().size(); } + _new_pm_polygon_count = polygons.size(); + // Group all edges per key. RBMap> connections; @@ -606,6 +624,7 @@ void NavMap::sync() { if (!connection) { connections[ek] = Vector(); + _new_pm_edge_count += 1; } if (connections[ek].size() <= 1) { @@ -632,6 +651,7 @@ void NavMap::sync() { c1.polygon->edges[c1.edge].connections.push_back(c2); c2.polygon->edges[c2.edge].connections.push_back(c1); // Note: The pathway_start/end are full for those connection and do not need to be modified. + _new_pm_edge_merge_count += 1; } else { CRASH_COND_MSG(E->get().size() != 1, vformat("Number of connection != 1. Found: %d", E->get().size())); free_edges.push_back(E->get()[0]); @@ -645,6 +665,8 @@ void NavMap::sync() { // to be connected, create new polygons to remove that small gap is // not really useful and would result in wasteful computation during // connection, integration and path finding. + _new_pm_edge_free_count = free_edges.size(); + for (int i = 0; i < free_edges.size(); i++) { const gd::Edge::Connection &free_edge = free_edges[i]; Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos; @@ -699,6 +721,7 @@ void NavMap::sync() { // Add the connection to the region_connection map. ((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection); + _new_pm_edge_connection_count += 1; } } @@ -835,6 +858,16 @@ void NavMap::sync() { regenerate_polygons = false; regenerate_links = false; agents_dirty = false; + + // Performance Monitor + pm_region_count = _new_pm_region_count; + pm_agent_count = _new_pm_agent_count; + pm_link_count = _new_pm_link_count; + pm_polygon_count = _new_pm_polygon_count; + pm_edge_count = _new_pm_edge_count; + pm_edge_merge_count = _new_pm_edge_merge_count; + pm_edge_connection_count = _new_pm_edge_connection_count; + pm_edge_free_count = _new_pm_edge_free_count; } void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) { @@ -915,6 +948,16 @@ NavMap::NavMap() { deltatime = 0.0; map_update_id = 0; link_connection_radius = 1.0; + + // Performance Monitor + pm_region_count = 0; + pm_agent_count = 0; + pm_link_count = 0; + pm_polygon_count = 0; + pm_edge_count = 0; + pm_edge_merge_count = 0; + pm_edge_connection_count = 0; + pm_edge_free_count = 0; } NavMap::~NavMap() { diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index fdcd8a6de..a05d93751 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -91,6 +91,16 @@ class NavMap : public NavRid { /// Change the id each time the map is updated. uint32_t map_update_id; + // Performance Monitor + int pm_region_count; + int pm_agent_count; + int pm_link_count; + int pm_polygon_count; + int pm_edge_count; + int pm_edge_merge_count; + int pm_edge_connection_count; + int pm_edge_free_count; + #ifndef NO_THREADS /// Pooled threads for computing steps ThreadWorkPool step_work_pool; @@ -164,6 +174,16 @@ public: void step(real_t p_deltatime); void dispatch_callbacks(); + // Performance Monitor + int get_pm_region_count() const { return pm_region_count; } + int get_pm_agent_count() const { return pm_agent_count; } + int get_pm_link_count() const { return pm_link_count; } + int get_pm_polygon_count() const { return pm_polygon_count; } + int get_pm_edge_count() const { return pm_edge_count; } + int get_pm_edge_merge_count() const { return pm_edge_merge_count; } + int get_pm_edge_connection_count() const { return pm_edge_connection_count; } + int get_pm_edge_free_count() const { return pm_edge_free_count; } + private: void compute_single_step(uint32_t index, RvoAgent **agent); void clip_path(const LocalVector &p_navigation_polys, Vector &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const; diff --git a/modules/navigation/pandemonium_navigation_server.cpp b/modules/navigation/pandemonium_navigation_server.cpp index 398559c2f..5dc83eec3 100644 --- a/modules/navigation/pandemonium_navigation_server.cpp +++ b/modules/navigation/pandemonium_navigation_server.cpp @@ -818,6 +818,15 @@ void PandemoniumNavigationServer::process(real_t p_delta_time) { return; } + int _new_pm_region_count = 0; + int _new_pm_agent_count = 0; + int _new_pm_link_count = 0; + int _new_pm_polygon_count = 0; + int _new_pm_edge_count = 0; + int _new_pm_edge_merge_count = 0; + int _new_pm_edge_connection_count = 0; + int _new_pm_edge_free_count = 0; + // In c++ we can't be sure that this is performed in the main thread // even with mutable functions. MutexLock lock(operations_mutex); @@ -826,6 +835,15 @@ void PandemoniumNavigationServer::process(real_t p_delta_time) { active_maps[i]->step(p_delta_time); active_maps[i]->dispatch_callbacks(); + _new_pm_region_count += active_maps[i]->get_pm_region_count(); + _new_pm_agent_count += active_maps[i]->get_pm_agent_count(); + _new_pm_link_count += active_maps[i]->get_pm_link_count(); + _new_pm_polygon_count += active_maps[i]->get_pm_polygon_count(); + _new_pm_edge_count += active_maps[i]->get_pm_edge_count(); + _new_pm_edge_merge_count += active_maps[i]->get_pm_edge_merge_count(); + _new_pm_edge_connection_count += active_maps[i]->get_pm_edge_connection_count(); + _new_pm_edge_free_count += active_maps[i]->get_pm_edge_free_count(); + // Emit a signal if a map changed. const uint32_t new_map_update_id = active_maps[i]->get_map_update_id(); if (new_map_update_id != active_maps_update_id[i]) { @@ -833,6 +851,15 @@ void PandemoniumNavigationServer::process(real_t p_delta_time) { active_maps_update_id[i] = new_map_update_id; } } + + pm_region_count = _new_pm_region_count; + pm_agent_count = _new_pm_agent_count; + pm_link_count = _new_pm_link_count; + pm_polygon_count = _new_pm_polygon_count; + pm_edge_count = _new_pm_edge_count; + pm_edge_merge_count = _new_pm_edge_merge_count; + pm_edge_connection_count = _new_pm_edge_connection_count; + pm_edge_free_count = _new_pm_edge_free_count; } NavigationUtilities::PathQueryResult PandemoniumNavigationServer::_query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const { @@ -872,6 +899,40 @@ NavigationUtilities::PathQueryResult PandemoniumNavigationServer::_query_path(co return r_query_result; } +int PandemoniumNavigationServer::get_process_info(ProcessInfo p_info) const { + switch (p_info) { + case INFO_ACTIVE_MAPS: { + return active_maps.size(); + } break; + case INFO_REGION_COUNT: { + return pm_region_count; + } break; + case INFO_AGENT_COUNT: { + return pm_agent_count; + } break; + case INFO_LINK_COUNT: { + return pm_link_count; + } break; + case INFO_POLYGON_COUNT: { + return pm_polygon_count; + } break; + case INFO_EDGE_COUNT: { + return pm_edge_count; + } break; + case INFO_EDGE_MERGE_COUNT: { + return pm_edge_merge_count; + } break; + case INFO_EDGE_CONNECTION_COUNT: { + return pm_edge_connection_count; + } break; + case INFO_EDGE_FREE_COUNT: { + return pm_edge_free_count; + } break; + } + + return 0; +} + #undef COMMAND_1 #undef COMMAND_2 #undef COMMAND_4 diff --git a/modules/navigation/pandemonium_navigation_server.h b/modules/navigation/pandemonium_navigation_server.h index baa8fdc44..20d3e865a 100644 --- a/modules/navigation/pandemonium_navigation_server.h +++ b/modules/navigation/pandemonium_navigation_server.h @@ -79,6 +79,16 @@ class PandemoniumNavigationServer : public NavigationServer { LocalVector active_maps; LocalVector active_maps_update_id; + // Performance Monitor + int pm_region_count = 0; + int pm_agent_count = 0; + int pm_link_count = 0; + int pm_polygon_count = 0; + int pm_edge_count = 0; + int pm_edge_merge_count = 0; + int pm_edge_connection_count = 0; + int pm_edge_free_count = 0; + public: PandemoniumNavigationServer(); virtual ~PandemoniumNavigationServer(); @@ -177,6 +187,8 @@ public: void flush_queries(); virtual void process(real_t p_delta_time); + virtual int get_process_info(ProcessInfo p_info) const; + virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const; }; diff --git a/modules/navigation_dummy/dummy_navigation_server.h b/modules/navigation_dummy/dummy_navigation_server.h index 848728719..9032bd152 100644 --- a/modules/navigation_dummy/dummy_navigation_server.h +++ b/modules/navigation_dummy/dummy_navigation_server.h @@ -88,6 +88,8 @@ public: virtual void process(real_t delta_time){}; + virtual int get_process_info(ProcessInfo p_info) const { return 0; }; + virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const; DummyNavigationServer(); diff --git a/servers/navigation_server.h b/servers/navigation_server.h index 8397e2e64..7006e6b10 100644 --- a/servers/navigation_server.h +++ b/servers/navigation_server.h @@ -260,6 +260,20 @@ public: virtual void init(); + enum ProcessInfo { + INFO_ACTIVE_MAPS, + INFO_REGION_COUNT, + INFO_AGENT_COUNT, + INFO_LINK_COUNT, + INFO_POLYGON_COUNT, + INFO_EDGE_COUNT, + INFO_EDGE_MERGE_COUNT, + INFO_EDGE_CONNECTION_COUNT, + INFO_EDGE_FREE_COUNT, + }; + + virtual int get_process_info(ProcessInfo p_info) const = 0; + NavigationServer(); virtual ~NavigationServer(); @@ -351,6 +365,8 @@ protected: #endif // DEBUG_ENABLED }; +VARIANT_ENUM_CAST(NavigationServer::ProcessInfo); + typedef NavigationServer *(*CreateNavigationServerCallback)(); /// Manager used for the server singleton registration