Debug CanvasItem redraw
I wanted to add this tool for years and always forget. This command line option: ``` $ godot.exe -e --debug-canvas-item-redraw ``` Allows to see when a canvas item is redrawn. This helps find out if something in the UI is refreshing in a way it should not. Examples as such: * Signals causing more of the UI to redraw. * Container resizing causes more UI elements to redraw. * Something using a timer is redrawing all time time, which can go unnoticed. To my surprise, the editor UI is redrawing very efficiently. There is some weird stuff with the scene tabs, redrawing when the inspector changes but most things for the most part are fine.
This commit is contained in:
parent
713bfaf5ea
commit
407b16ab00
|
@ -414,6 +414,12 @@
|
|||
<member name="compression/formats/zstd/window_log_size" type="int" setter="" getter="" default="27">
|
||||
Largest size limit (in power of 2) allowed when compressing using long-distance matching with Zstandard. Higher values can result in better compression, but will require more memory when compressing and decompressing.
|
||||
</member>
|
||||
<member name="debug/canvas_items/debug_redraw_color" type="Color" setter="" getter="" default="Color(1, 0.2, 0.2, 0.5)">
|
||||
If canvas item redraw debugging is active, this color will be flashed on canvas items when they redraw.
|
||||
</member>
|
||||
<member name="debug/canvas_items/debug_redraw_time" type="float" setter="" getter="" default="1.0">
|
||||
If canvas item redraw debugging is active, this will be the time the flash will last each time they redraw.
|
||||
</member>
|
||||
<member name="debug/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], logs all output to files.
|
||||
</member>
|
||||
|
|
|
@ -367,6 +367,12 @@ public:
|
|||
|
||||
void set_time(double p_time);
|
||||
|
||||
virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) override {
|
||||
if (p_enabled) {
|
||||
WARN_PRINT_ONCE("Debug CanvasItem Redraw is not available yet when using the GL Compatibility backend.");
|
||||
}
|
||||
}
|
||||
|
||||
static RasterizerCanvasGLES3 *get_singleton();
|
||||
RasterizerCanvasGLES3();
|
||||
~RasterizerCanvasGLES3();
|
||||
|
|
|
@ -110,6 +110,8 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
|
|||
bool debug_paths = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_paths", false);
|
||||
bool debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
|
||||
bool debug_avoidance = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_avoidance", false);
|
||||
bool debug_canvas_redraw = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_canvas_redraw", false);
|
||||
|
||||
if (debug_collisions) {
|
||||
args.push_back("--debug-collisions");
|
||||
}
|
||||
|
@ -126,6 +128,10 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
|
|||
args.push_back("--debug-avoidance");
|
||||
}
|
||||
|
||||
if (debug_canvas_redraw) {
|
||||
args.push_back("--debug-canvas-item-redraw");
|
||||
}
|
||||
|
||||
if (p_write_movie != "") {
|
||||
args.push_back("--write-movie");
|
||||
args.push_back(p_write_movie);
|
||||
|
|
|
@ -79,6 +79,10 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
|
|||
debug_menu->set_item_tooltip(-1,
|
||||
TTR("When this option is enabled, avoidance objects shapes, radius and velocities will be visible in the running project."));
|
||||
debug_menu->add_separator();
|
||||
debug_menu->add_check_shortcut(ED_SHORTCUT("editor/visible_canvas_redraw", TTR("Debug CanvasItem Redraws")), RUN_DEBUG_CANVAS_REDRAW);
|
||||
debug_menu->set_item_tooltip(-1,
|
||||
TTR("When this option is enabled, redraw requests of 2D objects will become visible (as a short flash) in the running project.\nThis is useful to troubleshoot low processor mode."));
|
||||
debug_menu->add_separator();
|
||||
debug_menu->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG);
|
||||
debug_menu->set_item_tooltip(-1,
|
||||
TTR("When this option is enabled, any changes made to the scene in the editor will be replicated in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
|
||||
|
@ -174,6 +178,12 @@ void DebuggerEditorPlugin::_menu_option(int p_option) {
|
|||
debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEBUG_AVOIDANCE), !ischecked);
|
||||
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_avoidance", !ischecked);
|
||||
|
||||
} break;
|
||||
case RUN_DEBUG_CANVAS_REDRAW: {
|
||||
bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_DEBUG_CANVAS_REDRAW));
|
||||
debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEBUG_CANVAS_REDRAW), !ischecked);
|
||||
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_canvas_redraw", !ischecked);
|
||||
|
||||
} break;
|
||||
case RUN_RELOAD_SCRIPTS: {
|
||||
bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_RELOAD_SCRIPTS));
|
||||
|
@ -213,6 +223,7 @@ void DebuggerEditorPlugin::_update_debug_options() {
|
|||
bool check_debug_paths = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_paths", false);
|
||||
bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
|
||||
bool check_debug_avoidance = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_avoidance", false);
|
||||
bool check_debug_canvas_redraw = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_canvas_redraw", false);
|
||||
bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true);
|
||||
bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true);
|
||||
bool check_server_keep_open = EditorSettings::get_singleton()->get_project_metadata("debug_options", "server_keep_open", false);
|
||||
|
@ -236,6 +247,9 @@ void DebuggerEditorPlugin::_update_debug_options() {
|
|||
if (check_debug_avoidance) {
|
||||
_menu_option(RUN_DEBUG_AVOIDANCE);
|
||||
}
|
||||
if (check_debug_canvas_redraw) {
|
||||
_menu_option(RUN_DEBUG_CANVAS_REDRAW);
|
||||
}
|
||||
if (check_live_debug) {
|
||||
_menu_option(RUN_LIVE_DEBUG);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ private:
|
|||
RUN_DEBUG_PATHS,
|
||||
RUN_DEBUG_NAVIGATION,
|
||||
RUN_DEBUG_AVOIDANCE,
|
||||
RUN_DEBUG_CANVAS_REDRAW,
|
||||
RUN_DEPLOY_REMOTE_DEBUG,
|
||||
RUN_RELOAD_SCRIPTS,
|
||||
SERVER_KEEP_OPEN,
|
||||
|
|
|
@ -209,6 +209,7 @@ static bool debug_collisions = false;
|
|||
static bool debug_paths = false;
|
||||
static bool debug_navigation = false;
|
||||
static bool debug_avoidance = false;
|
||||
static bool debug_canvas_item_redraw = false;
|
||||
#endif
|
||||
static int max_fps = -1;
|
||||
static int frame_delay = 0;
|
||||
|
@ -471,6 +472,7 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
|
||||
OS::get_singleton()->print(" --debug-avoidance Show navigation avoidance debug visuals when running the scene.\n");
|
||||
OS::get_singleton()->print(" --debug-stringnames Print all StringName allocations to stdout when the engine quits.\n");
|
||||
OS::get_singleton()->print(" --debug-canvas-item-redraw Display a rectangle each time a canvas item requests a redraw (useful to troubleshoot low processor mode).\n");
|
||||
#endif
|
||||
OS::get_singleton()->print(" --max-fps <fps> Set a maximum number of frames per second rendered (can be used to limit power usage). A value of 0 results in unlimited framerate.\n");
|
||||
OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds). Do not use as a FPS limiter; use --max-fps instead.\n");
|
||||
|
@ -1414,6 +1416,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
debug_navigation = true;
|
||||
} else if (I->get() == "--debug-avoidance") {
|
||||
debug_avoidance = true;
|
||||
} else if (I->get() == "--debug-canvas-item-redraw") {
|
||||
debug_canvas_item_redraw = true;
|
||||
} else if (I->get() == "--debug-stringnames") {
|
||||
StringName::set_debug_stringnames(true);
|
||||
#endif
|
||||
|
@ -3050,6 +3054,9 @@ bool Main::start() {
|
|||
NavigationServer3D::get_singleton()->set_active(true);
|
||||
NavigationServer3D::get_singleton()->set_debug_enabled(true);
|
||||
}
|
||||
if (debug_canvas_item_redraw) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_debug_redraw(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (single_threaded_scene) {
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
bool free(RID p_rid) override { return true; }
|
||||
void update() override {}
|
||||
|
||||
virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) override {}
|
||||
|
||||
RasterizerCanvasDummy() {}
|
||||
~RasterizerCanvasDummy() {}
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "renderer_canvas_cull.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "renderer_viewport.h"
|
||||
#include "rendering_server_default.h"
|
||||
|
@ -1557,6 +1558,11 @@ void RendererCanvasCull::canvas_item_clear(RID p_item) {
|
|||
ERR_FAIL_COND(!canvas_item);
|
||||
|
||||
canvas_item->clear();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_redraw) {
|
||||
canvas_item->debug_redraw_time = debug_redraw_time;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) {
|
||||
|
@ -1612,6 +1618,11 @@ void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_
|
|||
}
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_set_debug_redraw(bool p_enabled) {
|
||||
debug_redraw = p_enabled;
|
||||
RSG::canvas_render->set_debug_redraw(p_enabled, debug_redraw_time, debug_redraw_color);
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_COND(!canvas_item);
|
||||
|
@ -2155,6 +2166,9 @@ RendererCanvasCull::RendererCanvasCull() {
|
|||
z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
|
||||
|
||||
disable_scale = false;
|
||||
|
||||
debug_redraw_time = GLOBAL_DEF("debug/canvas_items/debug_redraw_time", 1.0);
|
||||
debug_redraw_color = GLOBAL_DEF("debug/canvas_items/debug_redraw_color", Color(1.0, 0.2, 0.2, 0.5));
|
||||
}
|
||||
|
||||
RendererCanvasCull::~RendererCanvasCull() {
|
||||
|
|
|
@ -174,6 +174,10 @@ public:
|
|||
bool sdf_used = false;
|
||||
bool snapping_2d_transforms_to_pixel = false;
|
||||
|
||||
bool debug_redraw = false;
|
||||
double debug_redraw_time = 0;
|
||||
Color debug_redraw_color;
|
||||
|
||||
PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator;
|
||||
SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list;
|
||||
|
||||
|
@ -260,6 +264,8 @@ public:
|
|||
|
||||
void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
|
||||
|
||||
void canvas_item_set_debug_redraw(bool p_enabled);
|
||||
|
||||
RID canvas_light_allocate();
|
||||
void canvas_light_initialize(RID p_rid);
|
||||
|
||||
|
|
|
@ -358,6 +358,9 @@ public:
|
|||
Command *last_command = nullptr;
|
||||
Vector<CommandBlock> blocks;
|
||||
uint32_t current_block;
|
||||
#ifdef DEBUG_ENABLED
|
||||
mutable double debug_redraw_time = 0;
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T *alloc_command() {
|
||||
|
@ -517,6 +520,8 @@ public:
|
|||
virtual bool free(RID p_rid) = 0;
|
||||
virtual void update() = 0;
|
||||
|
||||
virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) = 0;
|
||||
|
||||
RendererCanvasRender() { singleton = this; }
|
||||
virtual ~RendererCanvasRender() {}
|
||||
};
|
||||
|
|
|
@ -957,7 +957,48 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
|
||||
c = c->next;
|
||||
}
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (debug_redraw && p_item->debug_redraw_time > 0.0) {
|
||||
Color dc = debug_redraw_color;
|
||||
dc.a *= p_item->debug_redraw_time / debug_redraw_time;
|
||||
|
||||
RID pipeline = pipeline_variants->variants[PIPELINE_LIGHT_MODE_DISABLED][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
|
||||
|
||||
//bind textures
|
||||
|
||||
_bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size);
|
||||
|
||||
Rect2 src_rect;
|
||||
Rect2 dst_rect;
|
||||
|
||||
dst_rect = Rect2(Vector2(), p_item->rect.size);
|
||||
src_rect = Rect2(0, 0, 1, 1);
|
||||
|
||||
push_constant.modulation[0] = dc.r;
|
||||
push_constant.modulation[1] = dc.g;
|
||||
push_constant.modulation[2] = dc.b;
|
||||
push_constant.modulation[3] = dc.a;
|
||||
|
||||
push_constant.src_rect[0] = src_rect.position.x;
|
||||
push_constant.src_rect[1] = src_rect.position.y;
|
||||
push_constant.src_rect[2] = src_rect.size.width;
|
||||
push_constant.src_rect[3] = src_rect.size.height;
|
||||
|
||||
push_constant.dst_rect[0] = dst_rect.position.x;
|
||||
push_constant.dst_rect[1] = dst_rect.position.y;
|
||||
push_constant.dst_rect[2] = dst_rect.size.width;
|
||||
push_constant.dst_rect[3] = dst_rect.size.height;
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
|
||||
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
|
||||
RD::get_singleton()->draw_list_draw(p_draw_list, true);
|
||||
|
||||
p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time();
|
||||
|
||||
RenderingServerDefault::redraw_request();
|
||||
}
|
||||
#endif
|
||||
if (current_clip && reclip) {
|
||||
//will make it re-enable clipping if needed afterwards
|
||||
current_clip = nullptr;
|
||||
|
@ -2741,6 +2782,12 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
|
|||
}
|
||||
}
|
||||
|
||||
void RendererCanvasRenderRD::set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) {
|
||||
debug_redraw = p_enabled;
|
||||
debug_redraw_time = p_time;
|
||||
debug_redraw_color = p_color;
|
||||
}
|
||||
|
||||
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
//canvas state
|
||||
|
|
|
@ -418,6 +418,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
|
||||
RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer);
|
||||
|
||||
bool debug_redraw = false;
|
||||
Color debug_redraw_color;
|
||||
double debug_redraw_time = 1.0;
|
||||
|
||||
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead.
|
||||
void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used);
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false);
|
||||
|
@ -450,6 +454,8 @@ public:
|
|||
|
||||
virtual void set_shadow_texture_size(int p_size);
|
||||
|
||||
void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color);
|
||||
|
||||
void set_time(double p_time);
|
||||
void update();
|
||||
bool free(RID p_rid);
|
||||
|
|
|
@ -891,6 +891,8 @@ public:
|
|||
|
||||
FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
|
||||
|
||||
FUNC1(canvas_item_set_debug_redraw, bool)
|
||||
|
||||
FUNCRIDSPLIT(canvas_light)
|
||||
|
||||
FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
|
||||
|
|
|
@ -1393,6 +1393,8 @@ public:
|
|||
|
||||
virtual void canvas_item_set_canvas_group_mode(RID p_item, CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false) = 0;
|
||||
|
||||
virtual void canvas_item_set_debug_redraw(bool p_enabled) = 0;
|
||||
|
||||
/* CANVAS LIGHT */
|
||||
virtual RID canvas_light_create() = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue