summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2022-02-06 01:55:58 +0100
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2022-02-06 17:33:45 +0100
commit789e648f4d5cf629240e8bcc7042322088a79949 (patch)
treefac912c4d2ffbaf61c9cd093f13aeac6aeb0a577 /core
parent79a4d782a5ef0801fb65ee8c8a488942044c8e10 (diff)
[Debugger] New extensible EngineProfiler class.
Uses GDExtension, replaces old Callable system for profilers, and is also used internally.
Diffstat (limited to 'core')
-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
5 files changed, 163 insertions, 77 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);