From 76c322047e2f862f70cee05d56fc75c140e34d3d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 13 Sep 2024 22:25:27 -0400 Subject: [PATCH] Sculpt: Only re-upload mask attribute data Similar to the previous commits, previously all GPU buffers were recreated when only masks changed. Now only that masks are re-uploaded, using the same mechanism. Part of #118145. --- source/blender/blenkernel/BKE_pbvh_api.hh | 5 +- source/blender/blenkernel/intern/pbvh.cc | 12 ++- source/blender/draw/intern/draw_pbvh.cc | 8 ++ .../editors/sculpt_paint/brushes/mask.cc | 5 +- .../sculpt_paint/brushes/smooth_mask.cc | 12 +-- .../editors/sculpt_paint/paint_mask.cc | 102 ++++++++++++------ source/blender/editors/sculpt_paint/sculpt.cc | 11 +- .../editors/sculpt_paint/sculpt_expand.cc | 30 +++--- .../sculpt_paint/sculpt_filter_mask.cc | 92 +++++++++++----- .../editors/sculpt_paint/sculpt_mask_init.cc | 6 +- .../editors/sculpt_paint/sculpt_ops.cc | 4 +- .../editors/sculpt_paint/sculpt_undo.cc | 5 +- 12 files changed, 195 insertions(+), 97 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh_api.hh b/source/blender/blenkernel/BKE_pbvh_api.hh index b48e10a1ff8..95ff3ea6cbf 100644 --- a/source/blender/blenkernel/BKE_pbvh_api.hh +++ b/source/blender/blenkernel/BKE_pbvh_api.hh @@ -179,6 +179,7 @@ class DrawCache { virtual ~DrawCache() = default; virtual void tag_positions_changed(const IndexMask &node_mask) = 0; virtual void tag_face_sets_changed(const IndexMask &node_mask) = 0; + virtual void tag_masks_changed(const IndexMask &node_mask) = 0; virtual void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) = 0; }; @@ -240,6 +241,9 @@ class Tree { /** Tag nodes where face sets have changed, causing refresh of derived data. */ void tag_face_sets_changed(const IndexMask &node_mask); + /** Tag nodes where mask values have changed, causing refresh of derived data. */ + void tag_masks_changed(const IndexMask &node_mask); + /** * Tag nodes where generic attribute data has changed (not positions, masks, or face sets). */ @@ -406,7 +410,6 @@ bool bmesh_update_topology(BMesh &bm, /* Node Access */ void BKE_pbvh_node_mark_update(blender::bke::pbvh::Node &node); -void BKE_pbvh_node_mark_update_mask(blender::bke::pbvh::Node &node); void BKE_pbvh_node_mark_update_visibility(blender::bke::pbvh::Node &node); void BKE_pbvh_node_mark_rebuild_draw(blender::bke::pbvh::Node &node); void BKE_pbvh_node_mark_redraw(blender::bke::pbvh::Node &node); diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 50bb7cc847c..f9acf270918 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -571,6 +571,13 @@ void Tree::tag_face_sets_changed(const IndexMask &node_mask) } } +void Tree::tag_masks_changed(const IndexMask &node_mask) +{ + if (this->draw_data) { + this->draw_data->tag_masks_changed(node_mask); + } +} + void Tree::tag_attribute_changed(const IndexMask &node_mask, const StringRef attribute_name) { if (this->draw_data) { @@ -1512,11 +1519,6 @@ void BKE_pbvh_node_mark_update(blender::bke::pbvh::Node &node) node.flag_ |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw | PBVH_RebuildPixels; } -void BKE_pbvh_node_mark_update_mask(blender::bke::pbvh::Node &node) -{ - node.flag_ |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; -} - void BKE_pbvh_mark_rebuild_pixels(blender::bke::pbvh::Tree &pbvh) { std::visit( diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index cbe9b9eb90a..07ecf2f8293 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -141,6 +141,7 @@ class DrawCacheImpl : public DrawCache { void tag_all_attributes_dirty(const IndexMask &node_mask) override; void tag_positions_changed(const IndexMask &node_mask) override; void tag_face_sets_changed(const IndexMask &node_mask) override; + void tag_masks_changed(const IndexMask &node_mask) override; void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) override; Span ensure_tris_batches(const Object &object, @@ -212,6 +213,13 @@ void DrawCacheImpl::tag_face_sets_changed(const IndexMask &node_mask) } } +void DrawCacheImpl::tag_masks_changed(const IndexMask &node_mask) +{ + if (DrawCacheImpl::AttributeData *data = attribute_vbos_.lookup_ptr(CustomRequest::Mask)) { + data->tag_dirty(node_mask); + } +} + void DrawCacheImpl::tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) { for (const auto &[data_request, data] : attribute_vbos_.items()) { diff --git a/source/blender/editors/sculpt_paint/brushes/mask.cc b/source/blender/editors/sculpt_paint/brushes/mask.cc index cbbc608e6b5..af880d7ca3c 100644 --- a/source/blender/editors/sculpt_paint/brushes/mask.cc +++ b/source/blender/editors/sculpt_paint/brushes/mask.cc @@ -245,7 +245,6 @@ void do_mask_brush(const Depsgraph &depsgraph, tls, mask.span); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); mask.finish(); @@ -261,7 +260,6 @@ void do_mask_brush(const Depsgraph &depsgraph, node_mask.slice(range).foreach_index([&](const int i) { calc_grids(depsgraph, object, brush, bstrength, nodes[i], tls); bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); break; @@ -275,11 +273,12 @@ void do_mask_brush(const Depsgraph &depsgraph, node_mask.slice(range).foreach_index([&](const int i) { calc_bmesh(depsgraph, object, brush, bstrength, nodes[i], tls); bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); break; } } + pbvh.tag_masks_changed(node_mask); } + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc index 7a5a799ee0b..c8da6117088 100644 --- a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc +++ b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc @@ -172,10 +172,10 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph, tls, new_masks.as_span().slice(node_vert_offsets[pos]), mask.span); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); } bke::pbvh::update_mask_mesh(mesh, node_mask, pbvh); + pbvh.tag_masks_changed(node_mask); mask.finish(); } @@ -306,13 +306,12 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph, MutableSpan nodes = pbvh.nodes(); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - node_mask.slice(range).foreach_index([&](const int i) { - calc_grids(depsgraph, object, brush, strength, nodes[i], tls); - BKE_pbvh_node_mark_update_mask(nodes[i]); - }); + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, object, brush, strength, nodes[i], tls); }); }); } bke::pbvh::update_mask_grids(*ss.subdiv_ccg, node_mask, pbvh); + pbvh.tag_masks_changed(node_mask); break; } case bke::pbvh::Type::BMesh: { @@ -327,13 +326,14 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph, LocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { calc_bmesh(depsgraph, object, mask_offset, brush, strength, nodes[i], tls); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); } bke::pbvh::update_mask_bmesh(*ss.bm, node_mask, pbvh); + pbvh.tag_masks_changed(node_mask); break; } } } + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 8f5e318813f..6f32d9bd2d1 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -201,6 +201,8 @@ void update_mask_mesh(const Depsgraph &depsgraph, Vector mask; }; + Array node_changed(node_mask.min_array_size(), false); + threading::EnumerableThreadSpecific all_tls; threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); @@ -215,10 +217,13 @@ void update_mask_mesh(const Depsgraph &depsgraph, undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); scatter_data_mesh(tls.mask.as_span(), verts, mask.span); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); - BKE_pbvh_node_mark_redraw(nodes[i]); + node_changed[i] = true; }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); + mask.finish(); } @@ -350,21 +355,21 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph, return false; } - /* Store undo data for nodes with changed mask. */ - node_mask.foreach_index(GrainSize(1), [&](const int i) { - const Span verts = nodes[i].verts(); - if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) { - return; - } - undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); - BKE_pbvh_node_mark_redraw(nodes[i]); - }); + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1), memory, [&](const int i) { + const Span verts = nodes[i].verts(); + return std::any_of( + verts.begin(), verts.end(), [&](const int i) { return mask[i] != 0.0f; }); + }); + undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::Mask); attributes.remove(".sculpt_mask"); - node_mask.foreach_index([&](const int i) { + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_fully_masked_set(nodes[i], false); BKE_pbvh_node_fully_unmasked_set(nodes[i], true); }); + pbvh.tag_masks_changed(changed_nodes); return true; } @@ -388,6 +393,8 @@ static void fill_mask_mesh(const Depsgraph &depsgraph, bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span( ".sculpt_mask", bke::AttrDomain::Point); + Array node_changed(node_mask.min_array_size(), false); + threading::EnumerableThreadSpecific> all_index_data; threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &index_data = all_index_data.local(); @@ -398,12 +405,16 @@ static void fill_mask_mesh(const Depsgraph &depsgraph, } undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); mask.span.fill_indices(verts, value); - BKE_pbvh_node_mark_redraw(nodes[i]); + node_changed[i] = true; }); }); + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_bools(node_mask, node_changed, memory); + pbvh.tag_masks_changed(changed_nodes); + mask.finish(); - node_mask.foreach_index([&](const int i) { + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); }); @@ -433,8 +444,9 @@ static void fill_mask_grids(Main &bmain, const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; + Array node_changed(node_mask.min_array_size(), false); + MutableSpan masks = subdiv_ccg.masks; - bool any_changed = false; node_mask.foreach_index(GrainSize(1), [&](const int i) { const Span grid_indices = nodes[i].grids(); if (std::all_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) { @@ -459,14 +471,17 @@ static void fill_mask_grids(Main &bmain, bits::foreach_0_index(grid_hidden[grid], [&](const int i) { grid_masks[i] = value; }); } } - BKE_pbvh_node_mark_redraw(nodes[i]); - any_changed = true; + node_changed[i] = true; }); - if (any_changed) { - multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory); + if (node_changed.is_empty()) { + return; } - node_mask.foreach_index([&](const int i) { + pbvh.tag_masks_changed(changed_nodes); + multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); }); @@ -492,22 +507,31 @@ static void fill_mask_bmesh(const Depsgraph &depsgraph, return; } + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); + + Array node_changed(node_mask.min_array_size(), false); + node_mask.foreach_index(GrainSize(1), [&](const int i) { - bool redraw = false; - undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + bool changed = false; for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) { BM_ELEM_CD_SET_FLOAT(vert, offset, value); - redraw = true; + changed = true; } } } - if (redraw) { - BKE_pbvh_node_mark_redraw(nodes[i]); + if (changed) { + node_changed[i] = true; } }); - node_mask.foreach_index([&](const int i) { + IndexMaskMemory memory; + const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory); + if (node_changed.is_empty()) { + return; + } + pbvh.tag_masks_changed(changed_nodes); + changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); }); @@ -569,9 +593,9 @@ static void invert_mask_grids(Main &bmain, [&](const int i) { grid_masks[i] = 1.0f - grid_masks[i]; }); } } - BKE_pbvh_node_mark_update_mask(nodes[i]); bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); }); + pbvh.tag_masks_changed(node_mask); multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); } @@ -596,9 +620,9 @@ static void invert_mask_bmesh(const Depsgraph &depsgraph, BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset)); } } - BKE_pbvh_node_mark_update_mask(nodes[i]); bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); }); + pbvh.tag_masks_changed(node_mask); } static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object) @@ -747,6 +771,9 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa MutableSpan masks = subdiv_ccg.masks; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); + + Array node_changed(node_mask.min_array_size(), false); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; @@ -763,11 +790,16 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa mask = mask_gesture_get_new_value(mask, op.mode, op.value); } }); - bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + if (any_changed) { + bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); + node_changed[i] = true; + } } }); }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } case bke::pbvh::Type::BMesh: { @@ -775,6 +807,9 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa MutableSpan nodes = pbvh.nodes(); BMesh &bm = *gesture_data.ss->bm; const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); + + Array node_changed(node_mask.min_array_size(), false); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; @@ -789,10 +824,15 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa BM_ELEM_CD_SET_FLOAT(vert, offset, new_mask); } } - bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + if (any_changed) { + bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); + node_changed[i] = true; + } }); }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 35ccf8a1a1e..077f66d1a35 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -1212,6 +1212,8 @@ static void restore_mask_from_undo_step(Object &object) IndexMaskMemory memory; const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + Array node_changed(node_mask.min_array_size(), false); + switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { MutableSpan nodes = pbvh.nodes(); @@ -1226,7 +1228,7 @@ static void restore_mask_from_undo_step(Object &object) const Span verts = nodes[i].verts(); array_utils::scatter(*orig_data, verts, mask.span); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; } }); mask.finish(); @@ -1241,7 +1243,7 @@ static void restore_mask_from_undo_step(Object &object) if (const float *orig_mask = BM_log_find_original_vert_mask(ss.bm_log, vert)) { BM_ELEM_CD_SET_FLOAT(vert, offset, *orig_mask); bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; } } }); @@ -1269,12 +1271,13 @@ static void restore_mask_from_undo_step(Object &object) } } bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; } }); break; } } + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); } static void restore_color_from_undo_step(Object &object) @@ -1303,6 +1306,7 @@ static void restore_color_from_undo_step(Object &object) verts[i], (*orig_data)[i], color_attribute.span); + // TODO } } }); @@ -1466,6 +1470,7 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object) break; } } + // TODO pbvh.tag_positions_changed(node_mask); /* Update normals for potentially-changed positions. Theoretically this may be unnecessary if diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index e75cf1b76b6..79726e95369 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -1467,32 +1467,26 @@ static void write_mask_data(Object &object, const Span mask) bke::AttrDomain::Point, bke::AttributeInitVArray(VArray::ForSpan(mask))); bke::pbvh::update_mask_mesh(mesh, node_mask, pbvh); - MutableSpan nodes = pbvh.nodes(); - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); - BM_mesh_elem_table_ensure(&bm, BM_VERT); for (const int i : mask.index_range()) { BM_ELEM_CD_SET_FLOAT(BM_vert_at_index(&bm, i), offset, mask[i]); } bke::pbvh::update_mask_bmesh(bm, node_mask, pbvh); - MutableSpan nodes = pbvh.nodes(); - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; subdiv_ccg.masks.as_mutable_span().copy_from(mask); bke::pbvh::update_mask_grids(subdiv_ccg, node_mask, pbvh); - MutableSpan nodes = pbvh.nodes(); - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } } + pbvh.tag_masks_changed(node_mask); } /* Main function to restore the original state of the data to how it was before starting the expand @@ -1572,7 +1566,7 @@ static void calc_new_mask_mesh(const SculptSession &ss, mask::clamp_mask(mask); } -static void update_mask_grids(const SculptSession &ss, +static bool update_mask_grids(const SculptSession &ss, const BitSpan enabled_verts, bke::pbvh::GridsNode &node, SubdivCCG &subdiv_ccg) @@ -1618,12 +1612,12 @@ static void update_mask_grids(const SculptSession &ss, } } if (any_changed) { - BKE_pbvh_node_mark_update_mask(node); bke::pbvh::node_update_mask_grids(key, masks, node); } + return any_changed; } -static void update_mask_bmesh(SculptSession &ss, +static bool update_mask_bmesh(SculptSession &ss, const BitSpan enabled_verts, const int mask_offset, bke::pbvh::BMeshNode *node) @@ -1665,9 +1659,9 @@ static void update_mask_bmesh(SculptSession &ss, any_changed = true; } if (any_changed) { - BKE_pbvh_node_mark_update_mask(*node); bke::pbvh::node_update_mask_bmesh(mask_offset, *node); } + return any_changed; } /** @@ -1866,19 +1860,29 @@ static void update_for_vert(bContext *C, Object &ob, const std::optional ve break; } case bke::pbvh::Type::Grids: { + Array node_changed(node_mask.min_array_size(), false); + MutableSpan nodes = pbvh.nodes(); node_mask.foreach_index(GrainSize(1), [&](const int i) { - update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg); + node_changed[i] = update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg); }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } case bke::pbvh::Type::BMesh: { const int mask_offset = CustomData_get_offset_named( &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); MutableSpan nodes = pbvh.nodes(); + + Array node_changed(node_mask.min_array_size(), false); node_mask.foreach_index(GrainSize(1), [&](const int i) { - update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]); + node_changed[i] = update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]); }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index e56fb01aa32..acf8cda53df 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -117,6 +117,9 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph, bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); MutableSpan nodes = pbvh.nodes(); threading::EnumerableThreadSpecific> all_tls; + + Array node_changed(node_mask.min_array_size(), false); + node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) { Vector &tls = all_tls.local(); const Span verts = hide::node_visible_verts(nodes[i], hide_vert, tls); @@ -127,8 +130,11 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph, undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); scatter_data_mesh(new_node_mask, verts, mask); bke::pbvh::node_update_mask_mesh(mask, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); } static void smooth_mask_mesh(const OffsetIndices faces, @@ -219,7 +225,7 @@ static void shrink_mask_mesh(const OffsetIndices faces, } } -static void increase_contrast_mask_mesh(const Depsgraph &depsgraph, +static bool increase_contrast_mask_mesh(const Depsgraph &depsgraph, const Object &object, const Span hide_vert, bke::pbvh::MeshNode &node, @@ -235,16 +241,16 @@ static void increase_contrast_mask_mesh(const Depsgraph &depsgraph, mask_increase_contrast(node_mask, new_mask); if (node_mask == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_data_mesh(new_mask.as_span(), verts, mask); bke::pbvh::node_update_mask_mesh(mask, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } -static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph, +static bool decrease_contrast_mask_mesh(const Depsgraph &depsgraph, const Object &object, const Span hide_vert, bke::pbvh::MeshNode &node, @@ -260,13 +266,13 @@ static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph, mask_decrease_contrast(node_mask, new_mask); if (node_mask == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_data_mesh(new_mask.as_span(), verts, mask); bke::pbvh::node_update_mask_mesh(mask, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } BLI_NOINLINE static void copy_old_hidden_mask_grids(const SubdivCCG &subdiv_ccg, @@ -300,6 +306,8 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph, const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); MutableSpan masks = subdiv_ccg.masks; + Array node_changed(node_mask.min_array_size(), false); + node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) { const Span grids = nodes[i].grids(); const Span new_node_mask = new_mask.slice(node_verts[pos]); @@ -309,9 +317,12 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph, undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); scatter_data_grids(subdiv_ccg, new_node_mask, grids, masks); bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); + /* New mask values need propagation across grid boundaries. */ BKE_subdiv_ccg_average_grids(subdiv_ccg); } @@ -412,7 +423,7 @@ static void shrink_mask_grids(const SubdivCCG &subdiv_ccg, copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask); } -static void increase_contrast_mask_grids(const Depsgraph &depsgraph, +static bool increase_contrast_mask_grids(const Depsgraph &depsgraph, const Object &object, bke::pbvh::GridsNode &node, FilterLocalData &tls) @@ -435,16 +446,16 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph, copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask); if (node_mask.as_span() == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span()); bke::pbvh::node_update_mask_grids(key, subdiv_ccg.masks, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } -static void decrease_contrast_mask_grids(const Depsgraph &depsgraph, +static bool decrease_contrast_mask_grids(const Depsgraph &depsgraph, const Object &object, bke::pbvh::GridsNode &node, FilterLocalData &tls) @@ -467,13 +478,13 @@ static void decrease_contrast_mask_grids(const Depsgraph &depsgraph, copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask); if (node_mask.as_span() == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span()); bke::pbvh::node_update_mask_grids(key, subdiv_ccg.masks, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } BLI_NOINLINE static void copy_old_hidden_mask_bmesh(const int mask_offset, @@ -501,6 +512,8 @@ static void apply_new_mask_bmesh(const Depsgraph &depsgraph, MutableSpan nodes = pbvh.nodes(); BMesh &bm = *ss.bm; + Array node_changed(node_mask.min_array_size(), false); + node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) { const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span new_node_mask = new_mask.slice(node_verts[pos]); @@ -510,8 +523,11 @@ static void apply_new_mask_bmesh(const Depsgraph &depsgraph, undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); scatter_mask_bmesh(new_node_mask, bm, verts); bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); + node_changed[i] = true; }); + + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); } static void smooth_mask_bmesh(const int mask_offset, @@ -580,7 +596,7 @@ static void shrink_mask_bmesh(const int mask_offset, copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask); } -static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph, +static bool increase_contrast_mask_bmesh(const Depsgraph &depsgraph, Object &object, const int mask_offset, bke::pbvh::BMeshNode &node, @@ -602,16 +618,16 @@ static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph, copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask); if (node_mask.as_span() == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_mask_bmesh(new_mask.as_span(), bm, verts); bke::pbvh::node_update_mask_bmesh(mask_offset, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } -static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph, +static bool decrease_contrast_mask_bmesh(const Depsgraph &depsgraph, Object &object, const int mask_offset, bke::pbvh::BMeshNode &node, @@ -633,13 +649,13 @@ static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph, copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask); if (node_mask.as_span() == new_mask.as_span()) { - return; + return false; } undo::push_node(depsgraph, object, &node, undo::Type::Mask); scatter_mask_bmesh(new_mask.as_span(), bm, verts); bke::pbvh::node_update_mask_bmesh(mask_offset, node); - BKE_pbvh_node_mark_update_mask(node); + return true; } static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) @@ -762,21 +778,29 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) break; } case FilterType::ContrastIncrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - increase_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span); + node_changed[i] = increase_contrast_mask_mesh( + *depsgraph, ob, hide_vert, nodes[i], tls, mask.span); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } case FilterType::ContrastDecrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - decrease_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span); + node_changed[i] = decrease_contrast_mask_mesh( + *depsgraph, ob, hide_vert, nodes[i], tls, mask.span); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } } @@ -829,21 +853,27 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) break; } case FilterType::ContrastIncrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); + node_changed[i] = increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } case FilterType::ContrastDecrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); + node_changed[i] = decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } } @@ -901,21 +931,29 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) break; } case FilterType::ContrastIncrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls); + node_changed[i] = increase_contrast_mask_bmesh( + *depsgraph, ob, mask_offset, nodes[i], tls); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } case FilterType::ContrastDecrease: { + Array node_changed(node_mask.min_array_size(), false); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls); + node_changed[i] = decrease_contrast_mask_bmesh( + *depsgraph, ob, mask_offset, nodes[i], tls); }); }); + IndexMaskMemory memory; + pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory)); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc index ce253832e68..26c84923289 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc @@ -71,10 +71,10 @@ void write_mask_mesh(const Depsgraph &depsgraph, Vector &index_data = all_index_data.local(); node_mask.slice(range).foreach_index(GrainSize(1), [&](const int i) { write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data)); - BKE_pbvh_node_mark_redraw(nodes[i]); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); }); }); + pbvh.tag_masks_changed(node_mask); mask.finish(); } @@ -104,8 +104,8 @@ static void init_mask_grids( write_fn(grid_hidden, grid, masks.slice(bke::ccg::grid_range(key, grid))); } bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); + pbvh.tag_masks_changed(node_mask); BKE_subdiv_ccg_average_grids(subdiv_ccg); } @@ -256,8 +256,8 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) } } bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); + pbvh.tag_masks_changed(node_mask); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 9cbce71aa80..f65e4f8610d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -1179,7 +1179,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) LocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span); - BKE_pbvh_node_mark_update_mask(nodes[i]); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); }); }); @@ -1195,7 +1194,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) node_mask.slice(range).foreach_index([&](const int i) { bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); break; @@ -1209,7 +1207,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) node_mask.slice(range).foreach_index([&](const int i) { bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]); - BKE_pbvh_node_mark_update_mask(nodes[i]); }); }); break; @@ -1218,6 +1215,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) undo::push_end(ob); + pbvh.tag_masks_changed(node_mask); flush_update_done(C, ob, UpdateType::Mask); SCULPT_tag_update_overlays(C); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index 28da6016ad2..d821c8e8faa 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -735,8 +735,7 @@ static void bmesh_restore_generic(StepData &step_data, Object &object, SculptSes bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); IndexMaskMemory memory; const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); - MutableSpan nodes = pbvh.nodes(); - node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); + pbvh.tag_masks_changed(node_mask); } else { BKE_sculptsession_free_pbvh(object); @@ -1139,6 +1138,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) return indices_contain_true(modified_grids, nodes[i].grids()); }); bke::pbvh::update_mask_grids(*ss.subdiv_ccg, changed_nodes, pbvh); + pbvh.tag_masks_changed(changed_nodes); } else { MutableSpan nodes = pbvh.nodes(); @@ -1152,6 +1152,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) return indices_contain_true(modified_verts, nodes[i].all_verts()); }); bke::pbvh::update_mask_mesh(mesh, changed_nodes, pbvh); + pbvh.tag_masks_changed(changed_nodes); } break; }