[Debugger] New extensible EngineProfiler class.
Uses GDExtension, replaces old Callable system for profilers, and is also used internally.
This commit is contained in:
parent
79a4d782a5
commit
789e648f4d
|
@ -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);
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue