From 6c3ac28eb37f6aedcc73df06146fffe0057b79fd Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 14 Nov 2024 16:04:33 +0100 Subject: [PATCH] Nodes: Slightly improve editor drawing performance with large node trees Avoid retrieving context data for every single node which can be expensive when there are thousands of nodes. In the "Mouse House" test file I observed a 13% improvement in drawing timings. Pull Request: https://projects.blender.org/blender/blender/pulls/130239 --- .../blender/editors/include/UI_interface_c.hh | 16 ++++- source/blender/editors/interface/interface.cc | 44 ++++++++---- .../regions/interface_region_popup.cc | 11 ++- .../blender/editors/space_node/node_draw.cc | 71 +++++++++++++++++-- 4 files changed, 119 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index 42f51dffad5..95fac0d3ffd 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -877,7 +877,21 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss); -void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2]); +uiBlock *UI_block_begin(const bContext *C, + Scene *scene, + wmWindow *window, + ARegion *region, + std::string name, + eUIEmbossType emboss); +void UI_block_end_ex(const bContext *C, + Main *bmain, + wmWindow *window, + Scene *scene, + ARegion *region, + Depsgraph *depsgraph, + uiBlock *block, + const int xy[2] = nullptr, + int r_xy[2] = nullptr); void UI_block_end(const bContext *C, uiBlock *block); /** * Uses local copy of style, to scale things down, and allow widgets to change stuff. diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 882a6696cca..bfb47793e5a 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -1919,13 +1919,16 @@ bool ui_but_context_poll_operator(bContext *C, wmOperatorType *ot, const uiBut * return ui_but_context_poll_operator_ex(C, but, ¶ms); } -void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2]) +void UI_block_end_ex(const bContext *C, + Main *bmain, + wmWindow *window, + Scene *scene, + ARegion *region, + Depsgraph *depsgraph, + uiBlock *block, + const int xy[2], + int r_xy[2]) { - wmWindow *window = CTX_wm_window(C); - Scene *scene = CTX_data_scene(C); - ARegion *region = CTX_wm_region(C); - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - BLI_assert(block->active); /* Extend button data. This needs to be done before the block updating. */ @@ -1958,7 +1961,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( depsgraph, (scene) ? scene->r.cfra : 0.0f); ui_but_anim_flag(but, &anim_eval_context); - ui_but_override_flag(CTX_data_main(C), but); + ui_but_override_flag(bmain, but); if (UI_but_is_decorator(but)) { ui_but_anim_decorate_update_from_flag((uiButDecorator *)but); } @@ -1972,7 +1975,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x if (block->layouts.first) { UI_block_layout_resolve(block, nullptr, nullptr); } - ui_block_align_calc(block, CTX_wm_region(C)); + ui_block_align_calc(block, region); if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT) && (block->flag & UI_BLOCK_NO_ACCELERATOR_KEYS) == 0) { @@ -2029,7 +2032,15 @@ void UI_block_end(const bContext *C, uiBlock *block) { wmWindow *window = CTX_wm_window(C); - UI_block_end_ex(C, block, window->eventstate->xy, nullptr); + UI_block_end_ex(C, + CTX_data_main(C), + window, + CTX_data_scene(C), + CTX_wm_region(C), + CTX_data_depsgraph_pointer(C), + block, + window->eventstate->xy, + nullptr); } /* ************** BLOCK DRAWING FUNCTION ************* */ @@ -3786,11 +3797,13 @@ void UI_block_region_set(uiBlock *block, ARegion *region) block->oldblock = oldblock; } -uiBlock *UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss) +uiBlock *UI_block_begin(const bContext *C, + Scene *scene, + wmWindow *window, + ARegion *region, + std::string name, + eUIEmbossType emboss) { - wmWindow *window = CTX_wm_window(C); - Scene *scene = CTX_data_scene(C); - uiBlock *block = MEM_new(__func__); block->active = true; block->emboss = emboss; @@ -3831,6 +3844,11 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, std::string name, eU return block; } +uiBlock *UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss) +{ + return UI_block_begin(C, CTX_data_scene(C), CTX_wm_window(C), region, std::move(name), emboss); +} + void ui_block_add_dynamic_listener(uiBlock *block, void (*listener_func)(const wmRegionListenerParams *params)) { diff --git a/source/blender/editors/interface/regions/interface_region_popup.cc b/source/blender/editors/interface/regions/interface_region_popup.cc index 1feeb090a1a..943311dc4b1 100644 --- a/source/blender/editors/interface/regions/interface_region_popup.cc +++ b/source/blender/editors/interface/regions/interface_region_popup.cc @@ -706,8 +706,15 @@ uiBlock *ui_popup_block_refresh(bContext *C, block->oldblock = nullptr; if (!block->endblock) { - UI_block_end_ex( - C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy); + UI_block_end_ex(C, + CTX_data_main(C), + window, + CTX_data_scene(C), + region, + CTX_data_depsgraph_pointer(C), + block, + handle->popup_create_vars.event_xy, + handle->popup_create_vars.event_xy); } /* if this is being created from a button */ diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 43c60abad78..800dfaa5f3e 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -111,6 +111,12 @@ using blender::nodes::NodeExtraInfoRow; * This is passed to many functions which draw the node editor. */ struct TreeDrawContext { + Main *bmain; + wmWindow *window; + Scene *scene; + ARegion *region; + Depsgraph *depsgraph; + /** * Whether a viewer node is active in geometry nodes can not be determined by a flag on the node * alone. That's because if the node group with the viewer is used multiple times, it's only @@ -339,7 +345,11 @@ Array tree_draw_order_calc_nodes_reversed(bNodeTree &ntree) static Array node_uiblocks_init(const bContext &C, const Span nodes) { Array blocks(nodes.size()); + /* Add node uiBlocks in drawing order - prevents events going to overlapping nodes. */ + Scene *scene = CTX_data_scene(&C); + wmWindow *window = CTX_wm_window(&C); + ARegion *region = CTX_wm_region(&C); for (const int i : nodes.index_range()) { const bNode &node = *nodes[i]; std::string block_name = "node_" + std::string(node.name); @@ -3486,7 +3496,13 @@ static void node_draw_basis(const bContext &C, rect_with_preview.ymax += NODE_WIDTH(node); } if (BLI_rctf_isect(&rect_with_preview, &v2d.cur, nullptr) == false) { - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); return; } @@ -3826,7 +3842,13 @@ static void node_draw_basis(const bContext &C, node_draw_panels(ntree, node, block); } - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); UI_block_draw(&C, &block); } @@ -4011,7 +4033,13 @@ static void node_draw_hidden(const bContext &C, node_draw_sockets(v2d, C, ntree, node, block, true, false); - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); UI_block_draw(&C, &block); } @@ -4337,7 +4365,13 @@ static void frame_node_draw_overlay(const bContext &C, { /* Skip if out of view. */ if (BLI_rctf_isect(&node.runtime->totr, ®ion.v2d.cur, nullptr) == false) { - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); return; } @@ -4346,7 +4380,13 @@ static void frame_node_draw_overlay(const bContext &C, node_draw_extra_info_panel(C, tree_draw_ctx, snode, node, nullptr, block); - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); UI_block_draw(&C, &block); } @@ -4516,7 +4556,13 @@ static void reroute_node_draw(const bContext &C, if (rct.xmax < region.v2d.cur.xmin || rct.xmin > region.v2d.cur.xmax || rct.ymax < region.v2d.cur.ymin || node.runtime->totr.ymin > region.v2d.cur.ymax) { - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); return; } @@ -4526,7 +4572,13 @@ static void reroute_node_draw(const bContext &C, * if node itself is selected, since we don't display the node body separately. */ node_draw_sockets(region.v2d, C, ntree, node, block, false, node.flag & SELECT); - UI_block_end(&C, &block); + UI_block_end_ex(&C, + tree_draw_ctx.bmain, + tree_draw_ctx.window, + tree_draw_ctx.scene, + tree_draw_ctx.region, + tree_draw_ctx.depsgraph, + &block); UI_block_draw(&C, &block); } @@ -4936,6 +4988,11 @@ static void draw_nodetree(const bContext &C, Array blocks = node_uiblocks_init(C, nodes); TreeDrawContext tree_draw_ctx; + tree_draw_ctx.bmain = CTX_data_main(&C); + tree_draw_ctx.window = CTX_wm_window(&C); + tree_draw_ctx.scene = CTX_data_scene(&C); + tree_draw_ctx.region = CTX_wm_region(&C); + tree_draw_ctx.depsgraph = CTX_data_depsgraph_pointer(&C); BLI_SCOPED_DEFER([&]() { ntree.runtime->sockets_on_active_gizmo_paths.clear(); }); if (ntree.type == NTREE_GEOMETRY) {