From d7d19ec29750c20dedca0b5233ea034589cbecf1 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 4 Sep 2024 13:10:31 -0400 Subject: [PATCH] Sculpt: Push multiple undo nodes at once for some operations For the draw face set brush, dynamic topology remesh, and "Show All", push all the affected nodes in one call. This helps to decrease overhead from multithreading and data access. --- .../sculpt_paint/brushes/draw_face_sets.cc | 26 ++++---- .../editors/sculpt_paint/paint_hide.cc | 62 +++++++++---------- source/blender/editors/sculpt_paint/sculpt.cc | 18 +++--- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc b/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc index caea8aa497c..a924cf00376 100644 --- a/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc +++ b/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc @@ -177,8 +177,9 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span corner_tris = mesh.corner_tri_faces(); - bke::SpanAttributeWriter attribute = face_set::ensure_face_sets_mesh(object); - MutableSpan face_sets = attribute.span; + undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet); + + bke::SpanAttributeWriter face_sets = face_set::ensure_face_sets_mesh(object); threading::EnumerableThreadSpecific all_tls; MutableSpan nodes = ss.pbvh->nodes(); @@ -188,8 +189,6 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, const Span face_indices = bke::pbvh::node_face_indices_calc_mesh( corner_tris, nodes[i], tls.face_indices); - undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); - calc_faces(depsgraph, object, brush, @@ -199,11 +198,11 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, nodes[i], face_indices, tls, - face_sets); + face_sets.span); }); }); - attribute.finish(); + face_sets.finish(); } struct GridLocalData { @@ -278,16 +277,15 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph, { SculptSession &ss = *object.sculpt; - bke::SpanAttributeWriter attribute = face_set::ensure_face_sets_mesh(object); - MutableSpan face_sets = attribute.span; + undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet); + + bke::SpanAttributeWriter face_sets = face_set::ensure_face_sets_mesh(object); threading::EnumerableThreadSpecific all_tls; MutableSpan nodes = ss.pbvh->nodes(); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); - calc_grids(depsgraph, object, brush, @@ -295,10 +293,10 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph, ss.cache->paint_face_set, nodes[i], tls, - face_sets); + face_sets.span); }); }); - attribute.finish(); + face_sets.finish(); } struct BMeshLocalData { Vector positions; @@ -409,6 +407,9 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph, const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; + + undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet); + const int cd_offset = face_set::ensure_face_sets_bmesh(object); threading::EnumerableThreadSpecific all_tls; @@ -416,7 +417,6 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph, threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); calc_bmesh( object, brush, ss.cache->bstrength, ss.cache->paint_face_set, nodes[i], tls, cd_offset); }); diff --git a/source/blender/editors/sculpt_paint/paint_hide.cc b/source/blender/editors/sculpt_paint/paint_hide.cc index 10b7d4a612d..fcb600bb67b 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.cc +++ b/source/blender/editors/sculpt_paint/paint_hide.cc @@ -128,20 +128,21 @@ void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask & MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); - if (const VArray attribute = *attributes.lookup(".hide_vert", - bke::AttrDomain::Point)) - { - const VArraySpan hide_vert(attribute); - node_mask.foreach_index(GrainSize(1), [&](const int i) { - const Span verts = bke::pbvh::node_unique_verts(nodes[i]); - if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) { - undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); - BKE_pbvh_node_mark_rebuild_draw(nodes[i]); - } - }); - } - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); + const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); + if (!hide_vert.is_empty()) { + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1), memory, [&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + return std::any_of( + verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; }); + }); + undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert); + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_mark_rebuild_draw(nodes[i]); }); + } + + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); attributes.remove(".hide_vert"); bke::mesh_hide_vert_flush(mesh); } @@ -152,25 +153,24 @@ void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_ MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - bool any_changed = false; - if (!grid_hidden.is_empty()) { - node_mask.foreach_index(GrainSize(1), [&](const int i) { - const Span grids = bke::pbvh::node_grid_indices(nodes[i]); - if (std::any_of(grids.begin(), grids.end(), [&](const int i) { - return bits::any_bit_set(grid_hidden[i]); - })) - { - any_changed = true; - undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); - BKE_pbvh_node_mark_rebuild_draw(nodes[i]); - } - }); - } - if (!any_changed) { - return; - } - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); + if (!grid_hidden.is_empty()) { + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1), memory, [&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); + return std::any_of(grids.begin(), grids.end(), [&](const int i) { + return bits::any_bit_set(grid_hidden[i]); + }); + }); + if (changed_nodes.is_empty()) { + return; + } + undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert); + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_mark_rebuild_draw(nodes[i]); }); + } + + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg); BKE_pbvh_sync_visibility_from_verts(object); multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED); diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 20164647777..660cd384ba8 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -3275,15 +3275,15 @@ static void dynamic_topology_update(const Depsgraph &depsgraph, } } - node_mask.foreach_index([&](const int i) { - undo::push_node(depsgraph, - ob, - &nodes[i], - brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK ? undo::Type::Mask : - undo::Type::Position); - BKE_pbvh_node_mark_update(nodes[i]); - - BKE_pbvh_node_mark_topology_update(nodes[i]); + if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK) { + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask); + } + else { + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position); + } + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); }); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); }); + node_mask.foreach_index(GrainSize(1), [&](const int i) { BKE_pbvh_bmesh_node_save_orig(ss.bm, ss.bm_log, &nodes[i], false); });