Add NavigationServer Performance Monitor

Adds Performance Monitor for NavigationServer3D.
This commit is contained in:
smix8 2022-12-30 05:19:15 +01:00
parent bb08997b87
commit 9802914f97
11 changed files with 315 additions and 22 deletions

View File

@ -133,6 +133,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 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.
</description> </description>
</method> </method>
<method name="get_process_info" qualifiers="const">
<return type="int" />
<param index="0" name="process_info" type="int" enum="NavigationServer3D.ProcessInfo" />
<description>
Returns information about the current state of the NavigationServer. See [enum ProcessInfo] for a list of available states.
</description>
</method>
<method name="link_create"> <method name="link_create">
<return type="RID" /> <return type="RID" />
<description> <description>
@ -592,4 +599,33 @@
</description> </description>
</signal> </signal>
</signals> </signals>
<constants>
<constant name="INFO_ACTIVE_MAPS" value="0" enum="ProcessInfo">
Constant to get the number of active navigation maps.
</constant>
<constant name="INFO_REGION_COUNT" value="1" enum="ProcessInfo">
Constant to get the number of active navigation regions.
</constant>
<constant name="INFO_AGENT_COUNT" value="2" enum="ProcessInfo">
Constant to get the number of active navigation agents processing avoidance.
</constant>
<constant name="INFO_LINK_COUNT" value="3" enum="ProcessInfo">
Constant to get the number of active navigation links.
</constant>
<constant name="INFO_POLYGON_COUNT" value="4" enum="ProcessInfo">
Constant to get the number of navigation mesh polygons.
</constant>
<constant name="INFO_EDGE_COUNT" value="5" enum="ProcessInfo">
Constant to get the number of navigation mesh polygon edges.
</constant>
<constant name="INFO_EDGE_MERGE_COUNT" value="6" enum="ProcessInfo">
Constant to get the number of navigation mesh polygon edges that were merged due to edge key overlap.
</constant>
<constant name="INFO_EDGE_CONNECTION_COUNT" value="7" enum="ProcessInfo">
Constant to get the number of navigation mesh polygon edges that are considered connected by edge proximity.
</constant>
<constant name="INFO_EDGE_FREE_COUNT" value="8" enum="ProcessInfo">
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.
</constant>
</constants>
</class> </class>

View File

@ -131,67 +131,97 @@
<constant name="TIME_PHYSICS_PROCESS" value="2" enum="Monitor"> <constant name="TIME_PHYSICS_PROCESS" value="2" enum="Monitor">
Time it took to complete one physics frame, in seconds. [i]Lower is better.[/i] Time it took to complete one physics frame, in seconds. [i]Lower is better.[/i]
</constant> </constant>
<constant name="MEMORY_STATIC" value="3" enum="Monitor"> <constant name="TIME_NAVIGATION_PROCESS" value="3" enum="Monitor">
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]
</constant>
<constant name="MEMORY_STATIC" value="4" enum="Monitor">
Static memory currently used, in bytes. Not available in release builds. [i]Lower is better.[/i] Static memory currently used, in bytes. Not available in release builds. [i]Lower is better.[/i]
</constant> </constant>
<constant name="MEMORY_STATIC_MAX" value="4" enum="Monitor"> <constant name="MEMORY_STATIC_MAX" value="5" enum="Monitor">
Available static memory. Not available in release builds. [i]Lower is better.[/i] Available static memory. Not available in release builds. [i]Lower is better.[/i]
</constant> </constant>
<constant name="MEMORY_MESSAGE_BUFFER_MAX" value="5" enum="Monitor"> <constant name="MEMORY_MESSAGE_BUFFER_MAX" value="6" enum="Monitor">
Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications. [i]Lower is better.[/i] Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications. [i]Lower is better.[/i]
</constant> </constant>
<constant name="OBJECT_COUNT" value="6" enum="Monitor"> <constant name="OBJECT_COUNT" value="7" enum="Monitor">
Number of objects currently instantiated (including nodes). [i]Lower is better.[/i] Number of objects currently instantiated (including nodes). [i]Lower is better.[/i]
</constant> </constant>
<constant name="OBJECT_RESOURCE_COUNT" value="7" enum="Monitor"> <constant name="OBJECT_RESOURCE_COUNT" value="8" enum="Monitor">
Number of resources currently used. [i]Lower is better.[/i] Number of resources currently used. [i]Lower is better.[/i]
</constant> </constant>
<constant name="OBJECT_NODE_COUNT" value="8" enum="Monitor"> <constant name="OBJECT_NODE_COUNT" value="9" enum="Monitor">
Number of nodes currently instantiated in the scene tree. This also includes the root node. [i]Lower is better.[/i] Number of nodes currently instantiated in the scene tree. This also includes the root node. [i]Lower is better.[/i]
</constant> </constant>
<constant name="OBJECT_ORPHAN_NODE_COUNT" value="9" enum="Monitor"> <constant name="OBJECT_ORPHAN_NODE_COUNT" value="10" enum="Monitor">
Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. [i]Lower is better.[/i] Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_TOTAL_OBJECTS_IN_FRAME" value="10" enum="Monitor"> <constant name="RENDER_TOTAL_OBJECTS_IN_FRAME" value="11" enum="Monitor">
The total number of objects in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling). [i]Lower is better.[/i] The total number of objects in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling). [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_TOTAL_PRIMITIVES_IN_FRAME" value="11" enum="Monitor"> <constant name="RENDER_TOTAL_PRIMITIVES_IN_FRAME" value="12" enum="Monitor">
The total number of vertices or indices rendered in the last rendered frame. This metric doesn't include primitives from culled objects (either via hiding nodes, frustum culling or occlusion culling). Due to the depth prepass and shadow passes, the number of primitives is always higher than the actual number of vertices in the scene (typically double or triple the original vertex count). [i]Lower is better.[/i] The total number of vertices or indices rendered in the last rendered frame. This metric doesn't include primitives from culled objects (either via hiding nodes, frustum culling or occlusion culling). Due to the depth prepass and shadow passes, the number of primitives is always higher than the actual number of vertices in the scene (typically double or triple the original vertex count). [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_TOTAL_DRAW_CALLS_IN_FRAME" value="12" enum="Monitor"> <constant name="RENDER_TOTAL_DRAW_CALLS_IN_FRAME" value="13" enum="Monitor">
The total number of draw calls performed in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling), since they do not result in draw calls. [i]Lower is better.[/i] The total number of draw calls performed in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling), since they do not result in draw calls. [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_VIDEO_MEM_USED" value="13" enum="Monitor"> <constant name="RENDER_VIDEO_MEM_USED" value="14" enum="Monitor">
The amount of video memory used (texture and vertex memory combined, in bytes). Since this metric also includes miscellaneous allocations, this value is always greater than the sum of [constant RENDER_TEXTURE_MEM_USED] and [constant RENDER_BUFFER_MEM_USED]. [i]Lower is better.[/i] The amount of video memory used (texture and vertex memory combined, in bytes). Since this metric also includes miscellaneous allocations, this value is always greater than the sum of [constant RENDER_TEXTURE_MEM_USED] and [constant RENDER_BUFFER_MEM_USED]. [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_TEXTURE_MEM_USED" value="14" enum="Monitor"> <constant name="RENDER_TEXTURE_MEM_USED" value="15" enum="Monitor">
The amount of texture memory used (in bytes). [i]Lower is better.[/i] The amount of texture memory used (in bytes). [i]Lower is better.[/i]
</constant> </constant>
<constant name="RENDER_BUFFER_MEM_USED" value="15" enum="Monitor"> <constant name="RENDER_BUFFER_MEM_USED" value="16" enum="Monitor">
The amount of render buffer memory used (in bytes). [i]Lower is better.[/i] The amount of render buffer memory used (in bytes). [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="16" enum="Monitor"> <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="17" enum="Monitor">
Number of active [RigidBody2D] nodes in the game. [i]Lower is better.[/i] Number of active [RigidBody2D] nodes in the game. [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_2D_COLLISION_PAIRS" value="17" enum="Monitor"> <constant name="PHYSICS_2D_COLLISION_PAIRS" value="18" enum="Monitor">
Number of collision pairs in the 2D physics engine. [i]Lower is better.[/i] Number of collision pairs in the 2D physics engine. [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_2D_ISLAND_COUNT" value="18" enum="Monitor"> <constant name="PHYSICS_2D_ISLAND_COUNT" value="19" enum="Monitor">
Number of islands in the 2D physics engine. [i]Lower is better.[/i] Number of islands in the 2D physics engine. [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="19" enum="Monitor"> <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="20" enum="Monitor">
Number of active [RigidBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] Number of active [RigidBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_3D_COLLISION_PAIRS" value="20" enum="Monitor"> <constant name="PHYSICS_3D_COLLISION_PAIRS" value="21" enum="Monitor">
Number of collision pairs in the 3D physics engine. [i]Lower is better.[/i] Number of collision pairs in the 3D physics engine. [i]Lower is better.[/i]
</constant> </constant>
<constant name="PHYSICS_3D_ISLAND_COUNT" value="21" enum="Monitor"> <constant name="PHYSICS_3D_ISLAND_COUNT" value="22" enum="Monitor">
Number of islands in the 3D physics engine. [i]Lower is better.[/i] Number of islands in the 3D physics engine. [i]Lower is better.[/i]
</constant> </constant>
<constant name="AUDIO_OUTPUT_LATENCY" value="22" enum="Monitor"> <constant name="AUDIO_OUTPUT_LATENCY" value="23" enum="Monitor">
Output latency of the [AudioServer]. [i]Lower is better.[/i] Output latency of the [AudioServer]. [i]Lower is better.[/i]
</constant> </constant>
<constant name="MONITOR_MAX" value="23" enum="Monitor"> <constant name="NAVIGATION_ACTIVE_MAPS" value="24" enum="Monitor">
Number of active navigation maps in the [NavigationServer3D]. This also includes the two empty default navigation maps created by World2D and World3D.
</constant>
<constant name="NAVIGATION_REGION_COUNT" value="25" enum="Monitor">
Number of active navigation regions in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_AGENT_COUNT" value="26" enum="Monitor">
Number of active navigation agents processing avoidance in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_LINK_COUNT" value="27" enum="Monitor">
Number of active navigation links in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_POLYGON_COUNT" value="28" enum="Monitor">
Number of navigation mesh polygons in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_EDGE_COUNT" value="29" enum="Monitor">
Number of navigation mesh polygon edges in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_EDGE_MERGE_COUNT" value="30" enum="Monitor">
Number of navigation mesh polygon edges that were merged due to edge key overlap in the [NavigationServer3D].
</constant>
<constant name="NAVIGATION_EDGE_CONNECTION_COUNT" value="31" enum="Monitor">
Number of polygon edges that are considered connected by edge proximity [NavigationServer3D].
</constant>
<constant name="NAVIGATION_EDGE_FREE_COUNT" value="32" enum="Monitor">
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.
</constant>
<constant name="MONITOR_MAX" value="33" enum="Monitor">
Represents the size of the [enum Monitor] enum. Represents the size of the [enum Monitor] enum.
</constant> </constant>
</constants> </constants>

View File

@ -2968,6 +2968,7 @@ bool Main::is_iterating() {
// For performance metrics. // For performance metrics.
static uint64_t physics_process_max = 0; static uint64_t physics_process_max = 0;
static uint64_t process_max = 0; static uint64_t process_max = 0;
static uint64_t navigation_process_max = 0;
bool Main::iteration() { bool Main::iteration() {
//for now do not error on this //for now do not error on this
@ -2996,6 +2997,7 @@ bool Main::iteration() {
uint64_t physics_process_ticks = 0; uint64_t physics_process_ticks = 0;
uint64_t process_ticks = 0; uint64_t process_ticks = 0;
uint64_t navigation_process_ticks = 0;
frame += ticks_elapsed; frame += ticks_elapsed;
@ -3033,6 +3035,12 @@ bool Main::iteration() {
} }
NavigationServer3D::get_singleton()->process(physics_step * time_scale); NavigationServer3D::get_singleton()->process(physics_step * time_scale);
uint64_t navigation_begin = OS::get_singleton()->get_ticks_usec();
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);
message_queue->flush(); message_queue->flush();
@ -3112,8 +3120,10 @@ bool Main::iteration() {
Engine::get_singleton()->_fps = frames; Engine::get_singleton()->_fps = frames;
performance->set_process_time(USEC_TO_SEC(process_max)); performance->set_process_time(USEC_TO_SEC(process_max));
performance->set_physics_process_time(USEC_TO_SEC(physics_process_max)); performance->set_physics_process_time(USEC_TO_SEC(physics_process_max));
performance->set_navigation_process_time(USEC_TO_SEC(navigation_process_max));
process_max = 0; process_max = 0;
physics_process_max = 0; physics_process_max = 0;
navigation_process_max = 0;
frame %= 1000000; frame %= 1000000;
frames = 0; frames = 0;

View File

@ -36,6 +36,7 @@
#include "scene/main/node.h" #include "scene/main/node.h"
#include "scene/main/scene_tree.h" #include "scene/main/scene_tree.h"
#include "servers/audio_server.h" #include "servers/audio_server.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h" #include "servers/physics_server_2d.h"
#include "servers/physics_server_3d.h" #include "servers/physics_server_3d.h"
#include "servers/rendering_server.h" #include "servers/rendering_server.h"
@ -54,6 +55,7 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(TIME_FPS); BIND_ENUM_CONSTANT(TIME_FPS);
BIND_ENUM_CONSTANT(TIME_PROCESS); BIND_ENUM_CONSTANT(TIME_PROCESS);
BIND_ENUM_CONSTANT(TIME_PHYSICS_PROCESS); BIND_ENUM_CONSTANT(TIME_PHYSICS_PROCESS);
BIND_ENUM_CONSTANT(TIME_NAVIGATION_PROCESS);
BIND_ENUM_CONSTANT(MEMORY_STATIC); BIND_ENUM_CONSTANT(MEMORY_STATIC);
BIND_ENUM_CONSTANT(MEMORY_STATIC_MAX); BIND_ENUM_CONSTANT(MEMORY_STATIC_MAX);
BIND_ENUM_CONSTANT(MEMORY_MESSAGE_BUFFER_MAX); BIND_ENUM_CONSTANT(MEMORY_MESSAGE_BUFFER_MAX);
@ -74,7 +76,15 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(PHYSICS_3D_COLLISION_PAIRS); BIND_ENUM_CONSTANT(PHYSICS_3D_COLLISION_PAIRS);
BIND_ENUM_CONSTANT(PHYSICS_3D_ISLAND_COUNT); BIND_ENUM_CONSTANT(PHYSICS_3D_ISLAND_COUNT);
BIND_ENUM_CONSTANT(AUDIO_OUTPUT_LATENCY); 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); BIND_ENUM_CONSTANT(MONITOR_MAX);
} }
@ -93,6 +103,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"time/fps", "time/fps",
"time/process", "time/process",
"time/physics_process", "time/physics_process",
"time/navigation_process",
"memory/static", "memory/static",
"memory/static_max", "memory/static_max",
"memory/msg_buf_max", "memory/msg_buf_max",
@ -113,6 +124,15 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"physics_3d/collision_pairs", "physics_3d/collision_pairs",
"physics_3d/islands", "physics_3d/islands",
"audio/driver/output_latency", "audio/driver/output_latency",
"navigation/active_maps",
"navigation/regions",
"navigation/agents",
"navigation/links",
"navigation/polygons",
"navigation/edges",
"navigation/edges_merged",
"navigation/edges_connected",
"navigation/edges_free",
}; };
@ -127,6 +147,8 @@ double Performance::get_monitor(Monitor p_monitor) const {
return _process_time; return _process_time;
case TIME_PHYSICS_PROCESS: case TIME_PHYSICS_PROCESS:
return _physics_process_time; return _physics_process_time;
case TIME_NAVIGATION_PROCESS:
return _navigation_process_time;
case MEMORY_STATIC: case MEMORY_STATIC:
return Memory::get_mem_usage(); return Memory::get_mem_usage();
case MEMORY_STATIC_MAX: case MEMORY_STATIC_MAX:
@ -167,6 +189,24 @@ double Performance::get_monitor(Monitor p_monitor) const {
return PhysicsServer3D::get_singleton()->get_process_info(PhysicsServer3D::INFO_ISLAND_COUNT); return PhysicsServer3D::get_singleton()->get_process_info(PhysicsServer3D::INFO_ISLAND_COUNT);
case AUDIO_OUTPUT_LATENCY: case AUDIO_OUTPUT_LATENCY:
return AudioServer::get_singleton()->get_output_latency(); return AudioServer::get_singleton()->get_output_latency();
case NAVIGATION_ACTIVE_MAPS:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_ACTIVE_MAPS);
case NAVIGATION_REGION_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_REGION_COUNT);
case NAVIGATION_AGENT_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_AGENT_COUNT);
case NAVIGATION_LINK_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_LINK_COUNT);
case NAVIGATION_POLYGON_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_POLYGON_COUNT);
case NAVIGATION_EDGE_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_EDGE_COUNT);
case NAVIGATION_EDGE_MERGE_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_EDGE_MERGE_COUNT);
case NAVIGATION_EDGE_CONNECTION_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_EDGE_CONNECTION_COUNT);
case NAVIGATION_EDGE_FREE_COUNT:
return NavigationServer3D::get_singleton()->get_process_info(NavigationServer3D::INFO_EDGE_FREE_COUNT);
default: { default: {
} }
@ -182,6 +222,7 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_TIME, MONITOR_TYPE_TIME,
MONITOR_TYPE_TIME, MONITOR_TYPE_TIME,
MONITOR_TYPE_TIME,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,
@ -202,6 +243,12 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_TIME, MONITOR_TYPE_TIME,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
}; };
@ -216,6 +263,10 @@ void Performance::set_physics_process_time(double p_pt) {
_physics_process_time = p_pt; _physics_process_time = p_pt;
} }
void Performance::set_navigation_process_time(double p_pt) {
_navigation_process_time = p_pt;
}
void Performance::add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args) { void Performance::add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args) {
ERR_FAIL_COND_MSG(has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' already exists."); ERR_FAIL_COND_MSG(has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' already exists.");
_monitor_map.insert(p_id, MonitorCall(p_callable, p_args)); _monitor_map.insert(p_id, MonitorCall(p_callable, p_args));

View File

@ -50,6 +50,7 @@ class Performance : public Object {
double _process_time; double _process_time;
double _physics_process_time; double _physics_process_time;
double _navigation_process_time;
class MonitorCall { class MonitorCall {
Callable _callable; Callable _callable;
@ -69,6 +70,7 @@ public:
TIME_FPS, TIME_FPS,
TIME_PROCESS, TIME_PROCESS,
TIME_PHYSICS_PROCESS, TIME_PHYSICS_PROCESS,
TIME_NAVIGATION_PROCESS,
MEMORY_STATIC, MEMORY_STATIC,
MEMORY_STATIC_MAX, MEMORY_STATIC_MAX,
MEMORY_MESSAGE_BUFFER_MAX, MEMORY_MESSAGE_BUFFER_MAX,
@ -89,6 +91,15 @@ public:
PHYSICS_3D_COLLISION_PAIRS, PHYSICS_3D_COLLISION_PAIRS,
PHYSICS_3D_ISLAND_COUNT, PHYSICS_3D_ISLAND_COUNT,
AUDIO_OUTPUT_LATENCY, 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 MONITOR_MAX
}; };
@ -105,6 +116,7 @@ public:
void set_process_time(double p_pt); void set_process_time(double p_pt);
void set_physics_process_time(double p_pt); void set_physics_process_time(double p_pt);
void set_navigation_process_time(double p_pt);
void add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args); void add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args);
void remove_custom_monitor(const StringName &p_id); void remove_custom_monitor(const StringName &p_id);

View File

@ -829,6 +829,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
return; 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 // In c++ we can't be sure that this is performed in the main thread
// even with mutable functions. // even with mutable functions.
MutexLock lock(operations_mutex); MutexLock lock(operations_mutex);
@ -837,6 +846,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
active_maps[i]->step(p_delta_time); active_maps[i]->step(p_delta_time);
active_maps[i]->dispatch_callbacks(); 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. // Emit a signal if a map changed.
const uint32_t new_map_update_id = active_maps[i]->get_map_update_id(); const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
if (new_map_update_id != active_maps_update_id[i]) { if (new_map_update_id != active_maps_update_id[i]) {
@ -844,6 +862,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
active_maps_update_id[i] = new_map_update_id; 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;
} }
PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_parameters) const { PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_parameters) const {
@ -886,6 +913,40 @@ PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_
return r_query_result; return r_query_result;
} }
int GodotNavigationServer::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_1
#undef COMMAND_2 #undef COMMAND_2
#undef COMMAND_4 #undef COMMAND_4

View File

@ -81,6 +81,16 @@ class GodotNavigationServer : public NavigationServer3D {
LocalVector<NavMap *> active_maps; LocalVector<NavMap *> active_maps;
LocalVector<uint32_t> active_maps_update_id; LocalVector<uint32_t> 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: public:
GodotNavigationServer(); GodotNavigationServer();
virtual ~GodotNavigationServer(); virtual ~GodotNavigationServer();
@ -182,6 +192,8 @@ public:
virtual void process(real_t p_delta_time) override; virtual void process(real_t p_delta_time) override;
virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override; virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override;
int get_process_info(ProcessInfo p_info) const override;
}; };
#undef COMMAND_1 #undef COMMAND_1

View File

@ -611,6 +611,16 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
} }
void NavMap::sync() { 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. // Check if we need to update the links.
if (regenerate_polygons) { if (regenerate_polygons) {
for (uint32_t r = 0; r < regions.size(); r++) { for (uint32_t r = 0; r < regions.size(); r++) {
@ -632,6 +642,12 @@ void NavMap::sync() {
} }
if (regenerate_links) { 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. // Remove regions connections.
for (uint32_t r = 0; r < regions.size(); r++) { for (uint32_t r = 0; r < regions.size(); r++) {
regions[r]->get_connections().clear(); regions[r]->get_connections().clear();
@ -654,6 +670,8 @@ void NavMap::sync() {
count += regions[r]->get_polygons().size(); count += regions[r]->get_polygons().size();
} }
_new_pm_polygon_count = polygons.size();
// Group all edges per key. // Group all edges per key.
HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections; HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections;
for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) { for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) {
@ -666,6 +684,7 @@ void NavMap::sync() {
HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek); HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek);
if (!connection) { if (!connection) {
connections[ek] = Vector<gd::Edge::Connection>(); connections[ek] = Vector<gd::Edge::Connection>();
_new_pm_edge_count += 1;
} }
if (connections[ek].size() <= 1) { if (connections[ek].size() <= 1) {
// Add the polygon/edge tuple to this key. // Add the polygon/edge tuple to this key.
@ -691,6 +710,7 @@ void NavMap::sync() {
c1.polygon->edges[c1.edge].connections.push_back(c2); c1.polygon->edges[c1.edge].connections.push_back(c2);
c2.polygon->edges[c2.edge].connections.push_back(c1); 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. // Note: The pathway_start/end are full for those connection and do not need to be modified.
_new_pm_edge_merge_count += 1;
} else { } else {
CRASH_COND_MSG(E.value.size() != 1, vformat("Number of connection != 1. Found: %d", E.value.size())); CRASH_COND_MSG(E.value.size() != 1, vformat("Number of connection != 1. Found: %d", E.value.size()));
free_edges.push_back(E.value[0]); free_edges.push_back(E.value[0]);
@ -704,6 +724,8 @@ void NavMap::sync() {
// to be connected, create new polygons to remove that small gap is // to be connected, create new polygons to remove that small gap is
// not really useful and would result in wasteful computation during // not really useful and would result in wasteful computation during
// connection, integration and path finding. // connection, integration and path finding.
_new_pm_edge_free_count = free_edges.size();
for (int i = 0; i < free_edges.size(); i++) { for (int i = 0; i < free_edges.size(); i++) {
const gd::Edge::Connection &free_edge = free_edges[i]; const gd::Edge::Connection &free_edge = free_edges[i];
Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos; Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos;
@ -757,6 +779,7 @@ void NavMap::sync() {
// Add the connection to the region_connection map. // Add the connection to the region_connection map.
((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection); ((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection);
_new_pm_edge_connection_count += 1;
} }
} }
@ -892,6 +915,16 @@ void NavMap::sync() {
regenerate_polygons = false; regenerate_polygons = false;
regenerate_links = false; regenerate_links = false;
agents_dirty = 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) { void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) {

View File

@ -89,6 +89,16 @@ class NavMap : public NavRid {
/// Change the id each time the map is updated. /// Change the id each time the map is updated.
uint32_t map_update_id = 0; uint32_t map_update_id = 0;
// 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: public:
NavMap(); NavMap();
~NavMap(); ~NavMap();
@ -152,6 +162,16 @@ public:
void step(real_t p_deltatime); void step(real_t p_deltatime);
void dispatch_callbacks(); 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: private:
void compute_single_step(uint32_t index, RvoAgent **agent); void compute_single_step(uint32_t index, RvoAgent **agent);
void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const; void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const;

View File

@ -123,6 +123,18 @@ void NavigationServer3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map"))); ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
ADD_SIGNAL(MethodInfo("navigation_debug_changed")); ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &NavigationServer3D::get_process_info);
BIND_ENUM_CONSTANT(INFO_ACTIVE_MAPS);
BIND_ENUM_CONSTANT(INFO_REGION_COUNT);
BIND_ENUM_CONSTANT(INFO_AGENT_COUNT);
BIND_ENUM_CONSTANT(INFO_LINK_COUNT);
BIND_ENUM_CONSTANT(INFO_POLYGON_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_MERGE_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_CONNECTION_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_FREE_COUNT);
} }
NavigationServer3D *NavigationServer3D::get_singleton() { NavigationServer3D *NavigationServer3D::get_singleton() {

View File

@ -260,6 +260,20 @@ public:
NavigationServer3D(); NavigationServer3D();
virtual ~NavigationServer3D(); virtual ~NavigationServer3D();
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;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
private: private:
bool debug_enabled = false; bool debug_enabled = false;
@ -357,4 +371,6 @@ public:
static NavigationServer3D *new_default_server(); static NavigationServer3D *new_default_server();
}; };
VARIANT_ENUM_CAST(NavigationServer3D::ProcessInfo);
#endif // NAVIGATION_SERVER_3D_H #endif // NAVIGATION_SERVER_3D_H