summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp65
-rw-r--r--core/core_bind.h25
-rw-r--r--core/debugger/engine_profiler.cpp82
-rw-r--r--core/debugger/engine_profiler.h65
-rw-r--r--core/register_core_types.cpp3
-rw-r--r--doc/classes/EngineDebugger.xml9
-rw-r--r--doc/classes/EngineProfiler.xml39
7 files changed, 204 insertions, 84 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 8d03f35617..195292f7e6 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -2376,21 +2376,18 @@ bool EngineDebugger::is_active() {
return ::EngineDebugger::is_active();
}
-void EngineDebugger::register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
- ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler already registered: " + p_name);
- profilers.insert(p_name, ProfilerCallable(p_toggle, p_add, p_tick));
- ProfilerCallable &p = profilers[p_name];
- ::EngineDebugger::Profiler profiler(
- &p,
- &EngineDebugger::call_toggle,
- &EngineDebugger::call_add,
- &EngineDebugger::call_tick);
- ::EngineDebugger::register_profiler(p_name, profiler);
+void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) {
+ ERR_FAIL_COND(p_profiler.is_null());
+ ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered.");
+ ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler name already in use: " + p_name);
+ Error err = p_profiler->bind(p_name);
+ ERR_FAIL_COND_MSG(err != OK, "Profiler failed to register with error: " + itos(err));
+ profilers.insert(p_name, p_profiler);
}
void EngineDebugger::unregister_profiler(const StringName &p_name) {
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
- ::EngineDebugger::unregister_profiler(p_name);
+ profilers[p_name]->unbind();
profilers.erase(p_name);
}
@@ -2435,45 +2432,6 @@ void EngineDebugger::send_message(const String &p_msg, const Array &p_data) {
::EngineDebugger::get_singleton()->send_message(p_msg, p_data);
}
-void EngineDebugger::call_toggle(void *p_user, bool p_enable, const Array &p_opts) {
- Callable &toggle = ((ProfilerCallable *)p_user)->callable_toggle;
- if (toggle.is_null()) {
- return;
- }
- Variant enable = p_enable, opts = p_opts;
- const Variant *args[2] = { &enable, &opts };
- Variant retval;
- Callable::CallError err;
- toggle.call(args, 2, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'toggle' to callable: " + Variant::get_callable_error_text(toggle, args, 2, err));
-}
-
-void EngineDebugger::call_add(void *p_user, const Array &p_data) {
- Callable &add = ((ProfilerCallable *)p_user)->callable_add;
- if (add.is_null()) {
- return;
- }
- Variant data = p_data;
- const Variant *args[1] = { &data };
- Variant retval;
- Callable::CallError err;
- add.call(args, 1, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'add' to callable: " + Variant::get_callable_error_text(add, args, 1, err));
-}
-
-void EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- Callable &tick = ((ProfilerCallable *)p_user)->callable_tick;
- if (tick.is_null()) {
- return;
- }
- Variant frame_time = p_frame_time, idle_time = p_idle_time, physics_time = p_physics_time, physics_frame_time = p_physics_frame_time;
- const Variant *args[4] = { &frame_time, &idle_time, &physics_time, &physics_frame_time };
- Variant retval;
- Callable::CallError err;
- tick.call(args, 4, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'tick' to callable: " + Variant::get_callable_error_text(tick, args, 4, err));
-}
-
Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
Callable &capture = *(Callable *)p_user;
if (capture.is_null()) {
@@ -2495,10 +2453,6 @@ EngineDebugger::~EngineDebugger() {
::EngineDebugger::unregister_message_capture(E.key);
}
captures.clear();
- for (const KeyValue<StringName, ProfilerCallable> &E : profilers) {
- ::EngineDebugger::unregister_profiler(E.key);
- }
- profilers.clear();
}
EngineDebugger *EngineDebugger::singleton = nullptr;
@@ -2506,8 +2460,9 @@ EngineDebugger *EngineDebugger::singleton = nullptr;
void EngineDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_active"), &EngineDebugger::is_active);
- ClassDB::bind_method(D_METHOD("register_profiler", "name", "toggle", "add", "tick"), &EngineDebugger::register_profiler);
+ ClassDB::bind_method(D_METHOD("register_profiler", "name", "profiler"), &EngineDebugger::register_profiler);
ClassDB::bind_method(D_METHOD("unregister_profiler", "name"), &EngineDebugger::unregister_profiler);
+
ClassDB::bind_method(D_METHOD("is_profiling", "name"), &EngineDebugger::is_profiling);
ClassDB::bind_method(D_METHOD("has_profiler", "name"), &EngineDebugger::has_profiler);
diff --git a/core/core_bind.h b/core/core_bind.h
index ac0e92a87a..21a1fc2077 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -31,6 +31,7 @@
#ifndef CORE_BIND_H
#define CORE_BIND_H
+#include "core/debugger/engine_profiler.h"
#include "core/io/compression.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@@ -673,25 +674,8 @@ public:
class EngineDebugger : public Object {
GDCLASS(EngineDebugger, Object);
- class ProfilerCallable {
- friend class EngineDebugger;
-
- Callable callable_toggle;
- Callable callable_add;
- Callable callable_tick;
-
- public:
- ProfilerCallable() {}
-
- ProfilerCallable(const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
- callable_toggle = p_toggle;
- callable_add = p_add;
- callable_tick = p_tick;
- }
- };
-
Map<StringName, Callable> captures;
- Map<StringName, ProfilerCallable> profilers;
+ Map<StringName, Ref<EngineProfiler>> profilers;
protected:
static void _bind_methods();
@@ -702,7 +686,7 @@ public:
bool is_active();
- void register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick);
+ void register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler);
void unregister_profiler(const StringName &p_name);
bool is_profiling(const StringName &p_name);
bool has_profiler(const StringName &p_name);
@@ -715,9 +699,6 @@ public:
void send_message(const String &p_msg, const Array &p_data);
- static void call_toggle(void *p_user, bool p_enable, const Array &p_opts);
- static void call_add(void *p_user, const Array &p_data);
- static void call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
static Error call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured);
EngineDebugger() { singleton = this; }
diff --git a/core/debugger/engine_profiler.cpp b/core/debugger/engine_profiler.cpp
new file mode 100644
index 0000000000..c858b1febd
--- /dev/null
+++ b/core/debugger/engine_profiler.cpp
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* engine_profiler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "engine_profiler.h"
+
+#include "core/debugger/engine_debugger.h"
+
+void EngineProfiler::_bind_methods() {
+ GDVIRTUAL_BIND(_toggle, "enable", "options");
+ GDVIRTUAL_BIND(_add_frame, "data");
+ GDVIRTUAL_BIND(_tick, "frame_time", "idle_time", "physics_time", "physics_frame_time");
+}
+
+void EngineProfiler::toggle(bool p_enable, const Array &p_array) {
+ GDVIRTUAL_CALL(_toggle, p_enable, p_array);
+}
+
+void EngineProfiler::add(const Array &p_data) {
+ GDVIRTUAL_CALL(_add_frame, p_data);
+}
+
+void EngineProfiler::tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ GDVIRTUAL_CALL(_tick, p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+}
+
+Error EngineProfiler::bind(const String &p_name) {
+ ERR_FAIL_COND_V(is_bound(), ERR_ALREADY_IN_USE);
+ EngineDebugger::Profiler prof(
+ this,
+ [](void *p_user, bool p_enable, const Array &p_opts) {
+ ((EngineProfiler *)p_user)->toggle(p_enable, p_opts);
+ },
+ [](void *p_user, const Array &p_data) {
+ ((EngineProfiler *)p_user)->add(p_data);
+ },
+ [](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ ((EngineProfiler *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+ });
+ registration = p_name;
+ EngineDebugger::register_profiler(p_name, prof);
+ return OK;
+}
+
+Error EngineProfiler::unbind() {
+ ERR_FAIL_COND_V(!is_bound(), ERR_UNCONFIGURED);
+ EngineDebugger::unregister_profiler(registration);
+ registration.clear();
+ return OK;
+}
+
+EngineProfiler::~EngineProfiler() {
+ if (is_bound()) {
+ unbind();
+ }
+}
diff --git a/core/debugger/engine_profiler.h b/core/debugger/engine_profiler.h
new file mode 100644
index 0000000000..ade280a7bb
--- /dev/null
+++ b/core/debugger/engine_profiler.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* engine_profiler.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef ENGINE_PROFILER_H
+#define ENGINE_PROFILER_H
+
+#include "core/object/ref_counted.h"
+
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+
+class EngineProfiler : public RefCounted {
+ GDCLASS(EngineProfiler, RefCounted);
+
+private:
+ String registration;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void toggle(bool p_enable, const Array &p_opts);
+ virtual void add(const Array &p_data);
+ virtual void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
+
+ Error bind(const String &p_name);
+ Error unbind();
+ bool is_bound() const { return registration.length() > 0; }
+
+ GDVIRTUAL2(_toggle, bool, Array);
+ GDVIRTUAL1(_add_frame, Array);
+ GDVIRTUAL4(_tick, double, double, double, double);
+
+ EngineProfiler() {}
+ virtual ~EngineProfiler();
+};
+
+#endif // ENGINE_PROFILER_H
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 388368d181..a4b6a589f3 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -37,6 +37,7 @@
#include "core/crypto/aes_context.h"
#include "core/crypto/crypto.h"
#include "core/crypto/hashing_context.h"
+#include "core/debugger/engine_profiler.h"
#include "core/extension/native_extension.h"
#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
@@ -237,6 +238,8 @@ void register_core_types() {
GDREGISTER_VIRTUAL_CLASS(ResourceUID);
+ GDREGISTER_CLASS(EngineProfiler);
+
resource_uid = memnew(ResourceUID);
native_extension_manager = memnew(NativeExtensionManager);
diff --git a/doc/classes/EngineDebugger.xml b/doc/classes/EngineDebugger.xml
index 861053b1c9..0e1bf99afc 100644
--- a/doc/classes/EngineDebugger.xml
+++ b/doc/classes/EngineDebugger.xml
@@ -65,14 +65,9 @@
<method name="register_profiler">
<return type="void" />
<argument index="0" name="name" type="StringName" />
- <argument index="1" name="toggle" type="Callable" />
- <argument index="2" name="add" type="Callable" />
- <argument index="3" name="tick" type="Callable" />
+ <argument index="1" name="profiler" type="EngineProfiler" />
<description>
- Registers a profiler with the given [code]name[/code].
- [code]toggle[/code] callable is called when the profiler is enabled/disabled. It must take an argument array as an argument.
- [code]add[/code] callable is called when data is added to profiler using [method EngineDebugger.profiler_add_frame_data]. It must take a data array as argument.
- [code]tick[/code] callable is called at every active profiler iteration. It must take frame time, idle time, physics time, and physics idle time as arguments.
+ Registers a profiler with the given [code]name[/code]. See [EngineProfiler] for more informations.
</description>
</method>
<method name="send_message">
diff --git a/doc/classes/EngineProfiler.xml b/doc/classes/EngineProfiler.xml
new file mode 100644
index 0000000000..88780b1a41
--- /dev/null
+++ b/doc/classes/EngineProfiler.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EngineProfiler" inherits="RefCounted" version="4.0">
+ <brief_description>
+ Base class for creating custom profilers.
+ </brief_description>
+ <description>
+ This class can be used to implement custom profilers that are able to interact with the engine and editor debugger.
+ See [EngineDebugger] and [EditorDebuggerPlugin] for more informations.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_add_frame" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="data" type="Array" />
+ <description>
+ Called when data is added to profiler using [method EngineDebugger.profiler_add_frame_data].
+ </description>
+ </method>
+ <method name="_tick" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="frame_time" type="float" />
+ <argument index="1" name="idle_time" type="float" />
+ <argument index="2" name="physics_time" type="float" />
+ <argument index="3" name="physics_frame_time" type="float" />
+ <description>
+ Called once every engine iteration when the profiler is active with informations about the current frame.
+ </description>
+ </method>
+ <method name="_toggle" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="enable" type="bool" />
+ <argument index="1" name="options" type="Array" />
+ <description>
+ Called when the profiler is enabled/disabled, along with a set of [code]options[/code].
+ </description>
+ </method>
+ </methods>
+</class>