From bd51bb7623b0b2119642c8a8b252d539983ab5c4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 28 Dec 2023 16:36:11 -0500 Subject: [PATCH] Sculpt: Avoid expensive mask access in remaining cases In the last couple places, avoid retrieving the mask attribute per vertex. Use existing attribute data pointers instead. This also avoids function calls and branches for every vertex, since there is no PBVH type switch at the lowest level of the loop anymore. --- .../editors/sculpt_paint/paint_mask.cc | 23 +++---- source/blender/editors/sculpt_paint/sculpt.cc | 27 -------- .../editors/sculpt_paint/sculpt_expand.cc | 62 +++++++++++++++---- .../sculpt_paint/sculpt_filter_mask.cc | 2 +- .../editors/sculpt_paint/sculpt_intern.hh | 3 +- .../editors/sculpt_paint/sculpt_smooth.cc | 42 +++++++++---- 6 files changed, 89 insertions(+), 70 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 97e718513f1..b0334495bf6 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -372,14 +372,11 @@ static void fill_mask_bmesh(Object &object, const float value, const Span nodes) +static void fill_mask( + Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value) { PBVH &pbvh = *object.sculpt->pbvh; + Vector nodes = bke::pbvh::search_gather(&pbvh, {}); switch (BKE_pbvh_type(&pbvh)) { case PBVH_FACES: fill_mask_mesh(object, value, nodes); @@ -489,12 +486,9 @@ static void invert_mask_bmesh(Object &object, const Span nodes) }); } -static void invert_mask(Main &bmain, - const Scene &scene, - Depsgraph &depsgraph, - Object &object, - const Span nodes) +static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object) { + Vector nodes = bke::pbvh::search_gather(object.sculpt->pbvh, {}); switch (BKE_pbvh_type(object.sculpt->pbvh)) { case PBVH_FACES: invert_mask_mesh(object, nodes); @@ -521,16 +515,15 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) BKE_sculpt_update_object_for_edit(&depsgraph, &object, false); undo::push_begin(&object, op); - Vector nodes = bke::pbvh::search_gather(object.sculpt->pbvh, {}); switch (mode) { case PAINT_MASK_FLOOD_VALUE: - fill_mask(bmain, scene, depsgraph, object, value, nodes); + fill_mask(bmain, scene, depsgraph, object, value); break; case PAINT_MASK_FLOOD_VALUE_INVERSE: - fill_mask(bmain, scene, depsgraph, object, 1.0f - value, nodes); + fill_mask(bmain, scene, depsgraph, object, 1.0f - value); break; case PAINT_MASK_INVERT: - invert_mask(bmain, scene, depsgraph, object, nodes); + invert_mask(bmain, scene, depsgraph, object); break; } diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index c63e51420e9..3a251a18b42 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -303,33 +303,6 @@ float SCULPT_mask_get_at_grids_vert_index(const SubdivCCG &subdiv_ccg, return *CCG_elem_offset_mask(&key, elem, index_in_grid); } -float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex) -{ - using namespace blender; - switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: { - const Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh); - const bke::AttributeAccessor attributes = mesh->attributes(); - const VArray mask = *attributes.lookup_or_default( - ".sculpt_mask", bke::AttrDomain::Point, 0.0f); - return mask[vertex.i]; - } - case PBVH_BMESH: { - BMVert *v; - int cd_mask = CustomData_get_offset_named(&ss->bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); - - v = (BMVert *)vertex.i; - return cd_mask != -1 ? BM_ELEM_CD_GET_FLOAT(v, cd_mask) : 0.0f; - } - case PBVH_GRIDS: { - return SCULPT_mask_get_at_grids_vert_index( - *ss->subdiv_ccg, *BKE_pbvh_get_grid_key(ss->pbvh), vertex.i); - } - } - - return 0.0f; -} - PBVHVertRef SCULPT_active_vertex_get(SculptSession *ss) { if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) { diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index bfaebf283c7..7e821d01e03 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -2105,6 +2105,54 @@ static void sculpt_expand_undo_push(Object *ob, Cache *expand_cache) } } +static bool any_nonzero_mask(const Object &object) +{ + const SculptSession &ss = *object.sculpt; + switch (BKE_pbvh_type(ss.pbvh)) { + case PBVH_FACES: { + const Mesh &mesh = *static_cast(object.data); + const bke::AttributeAccessor attributes = mesh.attributes(); + const VArraySpan mask = *attributes.lookup(".sculpt_mask"); + if (mask.is_empty()) { + return false; + } + return std::any_of( + mask.begin(), mask.end(), [&](const float value) { return value > 0.0f; }); + } + case PBVH_GRIDS: { + const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; + const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); + if (!key.has_mask) { + return false; + } + return std::any_of(subdiv_ccg.grids.begin(), subdiv_ccg.grids.end(), [&](CCGElem *elem) { + for (const int i : IndexRange(key.grid_area)) { + if (*CCG_elem_offset_mask(&key, elem, i) > 0.0f) { + return true; + } + } + return false; + }); + } + case PBVH_BMESH: { + BMesh &bm = *ss.bm; + const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); + if (offset == -1) { + return false; + } + BMIter iter; + BMVert *vert; + BM_ITER_MESH (vert, &iter, &bm, BM_VERTS_OF_MESH) { + if (BM_ELEM_CD_GET_FLOAT(vert, offset) > 0.0f) { + return true; + } + } + return false; + } + } + return false; +} + static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -2134,19 +2182,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); if (RNA_boolean_get(op->ptr, "use_auto_mask")) { - int verts_num = SCULPT_vertex_count_get(ss); - bool ok = true; - - for (int i = 0; i < verts_num; i++) { - PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - - if (SCULPT_vertex_mask_get(ss, vertex) != 0.0f) { - ok = false; - break; - } - } - - if (ok) { + if (any_nonzero_mask(*ob)) { write_mask_data(ss, Array(SCULPT_vertex_count_get(ss), 1.0f)); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index 98fbb2a40c8..e756b2adad8 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -91,7 +91,7 @@ static void mask_filter_task(SculptSession *ss, switch (mode) { case MASK_FILTER_SMOOTH: case MASK_FILTER_SHARPEN: { - float val = smooth::neighbor_mask_average(ss, vd.vertex); + float val = smooth::neighbor_mask_average(ss, mask_write, vd.vertex); val -= mask; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index ec2f1e4fb5c..10e2ab6be52 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -877,7 +877,6 @@ void SCULPT_vertex_normal_get(const SculptSession *ss, PBVHVertRef vertex, float float SCULPT_mask_get_at_grids_vert_index(const SubdivCCG &subdiv_ccg, const CCGKey &key, int vert_index); -float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex); void SCULPT_vertex_color_get(const SculptSession *ss, PBVHVertRef vertex, float r_color[4]); void SCULPT_vertex_color_set(SculptSession *ss, PBVHVertRef vertex, const float color[4]); @@ -1522,7 +1521,7 @@ namespace blender::ed::sculpt_paint::smooth { void bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v); void neighbor_coords_average(SculptSession *ss, float result[3], PBVHVertRef vertex); -float neighbor_mask_average(SculptSession *ss, PBVHVertRef vertex); +float neighbor_mask_average(SculptSession *ss, SculptMaskWriteInfo write_info, PBVHVertRef vertex); void neighbor_color_average(SculptSession *ss, float result[4], PBVHVertRef vertex); /** diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index 448a87d2c55..5ac45dcebc9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -134,22 +134,40 @@ void neighbor_coords_average(SculptSession *ss, float result[3], PBVHVertRef ver } } -float neighbor_mask_average(SculptSession *ss, PBVHVertRef vertex) +float neighbor_mask_average(SculptSession *ss, + const SculptMaskWriteInfo mask_write, + PBVHVertRef vertex) { float avg = 0.0f; int total = 0; - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { - avg += SCULPT_vertex_mask_get(ss, ni.vertex); - total++; + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { + avg += mask_write.layer[ni.vertex.i]; + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + break; + case PBVH_GRIDS: + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { + avg += SCULPT_mask_get_at_grids_vert_index( + *ss->subdiv_ccg, *BKE_pbvh_get_grid_key(ss->pbvh), vertex.i); + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + break; + case PBVH_BMESH: + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { + BMVert *vert = reinterpret_cast(vertex.i); + avg += BM_ELEM_CD_GET_FLOAT(vert, mask_write.bm_offset); + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + break; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - - if (total > 0) { - return avg / total; - } - return SCULPT_vertex_mask_get(ss, vertex); + BLI_assert(total > 0); + return avg / total; } void neighbor_color_average(SculptSession *ss, float result[4], PBVHVertRef vertex) @@ -289,7 +307,7 @@ static void smooth_mask_node(Object *ob, vd.vertex, thread_id, &automask_data); - float val = neighbor_mask_average(ss, vd.vertex) - vd.mask; + float val = neighbor_mask_average(ss, mask_write, vd.vertex) - vd.mask; val *= fade * bstrength; float new_mask = vd.mask + val; CLAMP(new_mask, 0.0f, 1.0f);