From cf9fcbf24ec1fbc101da01ae68298fc51aaeb5b8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 25 Aug 2023 18:18:35 +0200 Subject: [PATCH] Cleanup: Use C++ threading API in sculpt/paint code Remove the global `SculptThreadedTaskData` struct which contained the arguments to ALL multi-threaded sculpt functions. Use the C++ threading API instead of the old task API, moving the arguments previously stored in the shared struct to actual function arguments. Pull Request: https://projects.blender.org/blender/blender/pulls/111525 --- .../editors/sculpt_paint/paint_mask.cc | 27 +- .../editors/sculpt_paint/paint_vertex.cc | 2 +- .../editors/sculpt_paint/paint_weight.cc | 307 +++--- source/blender/editors/sculpt_paint/sculpt.cc | 616 +++++------ .../editors/sculpt_paint/sculpt_boundary.cc | 152 ++- .../sculpt_paint/sculpt_brush_types.cc | 997 +++++++----------- .../editors/sculpt_paint/sculpt_cloth.cc | 226 ++-- .../editors/sculpt_paint/sculpt_expand.cc | 39 +- .../editors/sculpt_paint/sculpt_face_set.cc | 63 +- .../sculpt_paint/sculpt_filter_color.cc | 47 +- .../sculpt_paint/sculpt_filter_mask.cc | 46 +- .../sculpt_paint/sculpt_filter_mesh.cc | 88 +- .../editors/sculpt_paint/sculpt_intern.hh | 122 --- .../sculpt_paint/sculpt_mask_expand.cc | 83 +- .../editors/sculpt_paint/sculpt_mask_init.cc | 29 +- .../sculpt_paint/sculpt_multiplane_scrape.cc | 126 +-- .../editors/sculpt_paint/sculpt_ops.cc | 138 +-- .../sculpt_paint/sculpt_paint_color.cc | 200 ++-- .../editors/sculpt_paint/sculpt_pose.cc | 141 ++- .../editors/sculpt_paint/sculpt_smooth.cc | 135 +-- .../editors/sculpt_paint/sculpt_transform.cc | 95 +- 21 files changed, 1519 insertions(+), 2160 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index f8e276d66a3..3baa1b347c0 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -103,23 +103,19 @@ struct MaskTaskData { float view_normal[3]; }; -static void mask_flood_fill_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void mask_flood_fill_task(MaskTaskData &data, const int i) { - MaskTaskData *data = static_cast(userdata); + PBVHNode *node = data.nodes[i]; - PBVHNode *node = data->nodes[i]; - - const PaintMaskFloodMode mode = data->mode; - const float value = data->value; + const PaintMaskFloodMode mode = data.mode; + const float value = data.value; bool redraw = false; PBVHVertexIter vi; - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_MASK); + SCULPT_undo_push_node(data.ob, node, SCULPT_UNDO_MASK); - BKE_pbvh_vertex_iter_begin (data->pbvh, node, vi, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (data.pbvh, node, vi, PBVH_ITER_UNIQUE) { float prevmask = *vi.mask; mask_flood_fill_set_elem(vi.mask, mode, value); if (prevmask != *vi.mask) { @@ -130,7 +126,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata, if (redraw) { BKE_pbvh_node_mark_update_mask(node); - if (data->multires) { + if (data.multires) { BKE_pbvh_node_mark_normals_update(node); } } @@ -138,6 +134,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata, static int mask_flood_fill_exec(bContext *C, wmOperator *op) { + using namespace blender; const Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -166,9 +163,11 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) data.mode = mode; data.value = value; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, mask_flood_fill_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mask_flood_fill_task(data, i); + } + }); if (multires) { multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index e0b94823d2a..de0cc3583a4 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -293,7 +293,7 @@ Vector pbvh_gather_generic(Object *ob, VPaint *wp, Sculpt *sd, Brush ss->pbvh, [&](PBVHNode &node) { return SCULPT_search_sphere(&node, &data); }); if (use_normal) { - SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, ss->cache->sculpt_normal_symm); + SCULPT_pbvh_calc_area_normal(brush, ob, nodes, ss->cache->sculpt_normal_symm); } else { zero_v3(ss->cache->sculpt_normal_symm); diff --git a/source/blender/editors/sculpt_paint/paint_weight.cc b/source/blender/editors/sculpt_paint/paint_weight.cc index fe8b843035c..6781ec43cae 100644 --- a/source/blender/editors/sculpt_paint/paint_weight.cc +++ b/source/blender/editors/sculpt_paint/paint_weight.cc @@ -1043,34 +1043,20 @@ static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintIn return weight; } -static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) -{ - SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - const MDeformVert *dv = &data->wpi->dvert[n]; - - data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi); -} - static void precompute_weight_values( - bContext *C, Object *ob, Brush *brush, WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me) + Object *ob, Brush *brush, WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me) { + using namespace blender; if (wpd->precomputed_weight_ready && !vwpaint::brush_use_accumulate_ex(brush, ob->mode)) { return; } - /* threaded loop over vertices */ - SculptThreadedTaskData data; - data.C = C; - data.ob = ob; - data.wpd = wpd; - data.wpi = wpi; - data.me = me; - - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - BLI_task_parallel_range(0, me->totvert, &data, do_wpaint_precompute_weight_cb_ex, &settings); + threading::parallel_for(IndexRange(me->totvert), 512, [&](const IndexRange range) { + for (const int i : range) { + const MDeformVert *dv = &wpi->dvert[i]; + wpd->precomputed_weight[i] = wpaint_get_active_weight(dv, wpi); + } + }); wpd->precomputed_weight_ready = true; } @@ -1079,40 +1065,42 @@ static void precompute_weight_values( /** \name Weight paint brushes. * \{ */ -static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_wpaint_brush_blur_task(const Scene *scene, + Object *ob, + const Brush *brush, + VPaint *vp, + WPaintData *wpd, + const WeightPaintInfo *wpi, + Mesh *me, + PBVHNode *node) { - SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); const bool has_grids = (pbvh_type == PBVH_GRIDS); const SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap; - const Brush *brush = data->brush; const StrokeCache *cache = ss->cache; - Scene *scene = CTX_data_scene(data->C); float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; vwpaint::get_brush_alpha_data( scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure); - const bool use_normal = vwpaint::use_normal(data->vp); - const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_normal = vwpaint::use_normal(vp); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( - ss, data->brush->falloff_shape); + ss, brush->falloff_shape); - const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::bke::AttributeAccessor attributes = me->attributes(); const blender::VArray select_vert = *attributes.lookup_or_default( ".select_vert", ATTR_DOMAIN_POINT, false); /* For each vertex */ PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -1134,7 +1122,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, total_hit_loops += face.size(); for (const int vert : ss->corner_verts.slice(face)) { - weight_final += data->wpd->precomputed_weight[vert]; + weight_final += wpd->precomputed_weight[vert]; } } @@ -1147,7 +1135,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; if (!vwpaint::test_brush_angle_falloff( - *brush, data->wpd->normal_angle_precalc, angle_cos, &brush_strength)) + *brush, wpd->normal_angle_precalc, angle_cos, &brush_strength)) { continue; } @@ -1166,23 +1154,25 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, weight_final /= total_hit_loops; /* Only paint visible verts */ - do_weight_paint_vertex(data->vp, data->ob, data->wpi, v_index, final_alpha, weight_final); + do_weight_paint_vertex(vp, ob, wpi, v_index, final_alpha, weight_final); } BKE_pbvh_vertex_iter_end; } -static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_wpaint_brush_smear_task(const Scene *scene, + Object *ob, + const Brush *brush, + VPaint *vp, + WPaintData *wpd, + const WeightPaintInfo *wpi, + Mesh *me, + PBVHNode *node) { - SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); const bool has_grids = (pbvh_type == PBVH_GRIDS); const SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap; - const Brush *brush = data->brush; - const Scene *scene = CTX_data_scene(data->C); const StrokeCache *cache = ss->cache; if (!cache->is_last_valid) { return; @@ -1191,9 +1181,9 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; vwpaint::get_brush_alpha_data( scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure); - const bool use_normal = vwpaint::use_normal(data->vp); - const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_normal = vwpaint::use_normal(vp); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; float brush_dir[3]; sub_v3_v3v3(brush_dir, cache->location, cache->last_location); @@ -1202,19 +1192,19 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, return; } - const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::bke::AttributeAccessor attributes = me->attributes(); const blender::VArray select_vert = *attributes.lookup_or_default( ".select_vert", ATTR_DOMAIN_POINT, false); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( - ss, data->brush->falloff_shape); + ss, brush->falloff_shape); /* For each vertex */ PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -1236,7 +1226,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; if (!vwpaint::test_brush_angle_falloff( - *brush, data->wpd->normal_angle_precalc, angle_cos, &brush_strength)) + *brush, wpd->normal_angle_precalc, angle_cos, &brush_strength)) { continue; } @@ -1266,7 +1256,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, if (stroke_dot > stroke_dot_max) { stroke_dot_max = stroke_dot; - weight_final = data->wpd->precomputed_weight[v_other_index]; + weight_final = wpd->precomputed_weight[v_other_index]; do_color = true; } } @@ -1281,48 +1271,50 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, continue; } - do_weight_paint_vertex( - data->vp, data->ob, data->wpi, v_index, final_alpha, float(weight_final)); + do_weight_paint_vertex(vp, ob, wpi, v_index, final_alpha, float(weight_final)); } } BKE_pbvh_vertex_iter_end; } -static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_wpaint_brush_draw_task(const Scene *scene, + Object *ob, + const Brush *brush, + VPaint *vp, + WPaintData *wpd, + const WeightPaintInfo *wpi, + Mesh *me, + const float strength, + PBVHNode *node) { - SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); const bool has_grids = (pbvh_type == PBVH_GRIDS); - const Scene *scene = CTX_data_scene(data->C); - const Brush *brush = data->brush; const StrokeCache *cache = ss->cache; /* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used, * however in this case we calculate a new weight each time. */ - const float paintweight = data->strength; + const float paintweight = strength; float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; vwpaint::get_brush_alpha_data( scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure); - const bool use_normal = vwpaint::use_normal(data->vp); - const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_normal = vwpaint::use_normal(vp); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( - ss, data->brush->falloff_shape); + ss, brush->falloff_shape); - const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::bke::AttributeAccessor attributes = me->attributes(); const blender::VArray select_vert = *attributes.lookup_or_default( ".select_vert", ATTR_DOMAIN_POINT, false); /* For each vertex */ PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -1342,7 +1334,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; if (!vwpaint::test_brush_angle_falloff( - *brush, data->wpd->normal_angle_precalc, angle_cos, &brush_strength)) + *brush, wpd->normal_angle_precalc, angle_cos, &brush_strength)) { continue; } @@ -1358,42 +1350,44 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, } } - do_weight_paint_vertex(data->vp, data->ob, data->wpi, v_index, final_alpha, paintweight); + do_weight_paint_vertex(vp, ob, wpi, v_index, final_alpha, paintweight); } BKE_pbvh_vertex_iter_end; } -static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static WPaintAverageAccum do_wpaint_brush_calc_average_weight(Object *ob, + const Mesh *me, + const Brush *brush, + const VPaint *vp, + WeightPaintInfo *wpi, + PBVHNode *node) { - SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); const bool has_grids = (pbvh_type == PBVH_GRIDS); - const bool use_normal = vwpaint::use_normal(data->vp); - const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_normal = vwpaint::use_normal(vp); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - WPaintAverageAccum *accum = (WPaintAverageAccum *)data->custom_data + n; - accum->len = 0; - accum->value = 0.0; + WPaintAverageAccum accum{}; + accum.len = 0; + accum.value = 0.0; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( - ss, data->brush->falloff_shape); + ss, brush->falloff_shape); - const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::bke::AttributeAccessor attributes = me->attributes(); const blender::VArray select_vert = *attributes.lookup_or_default( ".select_vert", ATTR_DOMAIN_POINT, false); /* For each vertex */ PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -1402,8 +1396,7 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata, const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; if (angle_cos <= 0.0f || - BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) <= 0.0f) - { + BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius) <= 0.0f) { continue; } @@ -1414,23 +1407,32 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata, continue; } - const MDeformVert *dv = &data->wpi->dvert[v_index]; - accum->len += 1; - accum->value += wpaint_get_active_weight(dv, data->wpi); + const MDeformVert *dv = &wpi->dvert[v_index]; + accum.len += 1; + accum.value += wpaint_get_active_weight(dv, wpi); } BKE_pbvh_vertex_iter_end; + + return accum; } -static void calculate_average_weight(SculptThreadedTaskData *data, Span nodes) +static float calculate_average_weight(Object *ob, + const Mesh *me, + const Brush *brush, + VPaint *vp, + WeightPaintInfo *wpi, + Span nodes) { WPaintAverageAccum *accum = (WPaintAverageAccum *)MEM_mallocN(sizeof(*accum) * nodes.size(), __func__); - data->custom_data = accum; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range( - 0, nodes.size(), data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + accum[i] = do_wpaint_brush_calc_average_weight(ob, me, brush, vp, wpi, nodes[i]); + } + }); + + float strength = 0.0f; uint accum_len = 0; double accum_weight = 0.0; @@ -1440,15 +1442,16 @@ static void calculate_average_weight(SculptThreadedTaskData *data, Spanstrength = float(accum_weight); + strength = float(accum_weight); } - MEM_SAFE_FREE(data->custom_data); /* 'accum' */ + MEM_SAFE_FREE(accum); + + return strength; } static void wpaint_paint_leaves(bContext *C, Object *ob, - Sculpt *sd, VPaint *vp, WPaintData *wpd, WeightPaintInfo *wpi, @@ -1458,40 +1461,70 @@ static void wpaint_paint_leaves(bContext *C, Scene *scene = CTX_data_scene(C); const Brush *brush = ob->sculpt->cache->brush; - /* threaded loop over nodes */ - SculptThreadedTaskData data = {nullptr}; - data.C = C; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.vp = vp; - data.wpd = wpd; - data.wpi = wpi; - data.me = me; - /* Use this so average can modify its weight without touching the brush. */ - data.strength = BKE_brush_weight_get(scene, brush); + float strength = BKE_brush_weight_get(scene, brush); + if (brush->weightpaint_tool == WPAINT_TOOL_AVERAGE) { + strength = calculate_average_weight(ob, me, brush, vp, wpi, nodes); + } - /* NOTE: current mirroring code cannot be run in parallel */ - TaskParallelSettings settings; - const bool use_threading = !ME_USING_MIRROR_X_VERTEX_GROUPS(me); - BKE_pbvh_parallel_range_settings(&settings, use_threading, nodes.size()); - - switch ((eBrushWeightPaintTool)brush->weightpaint_tool) { - case WPAINT_TOOL_AVERAGE: - calculate_average_weight(&data, nodes); - BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_draw_task_cb_ex, &settings); - break; - case WPAINT_TOOL_SMEAR: - BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_smear_task_cb_ex, &settings); - break; - case WPAINT_TOOL_BLUR: - BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_blur_task_cb_ex, &settings); - break; - case WPAINT_TOOL_DRAW: - BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_draw_task_cb_ex, &settings); - break; + if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) { + /* NOTE: current mirroring code cannot be run in parallel */ + switch ((eBrushWeightPaintTool)brush->weightpaint_tool) { + case WPAINT_TOOL_AVERAGE: { + for (const int i : nodes.index_range()) { + do_wpaint_brush_draw_task(scene, ob, brush, vp, wpd, wpi, me, strength, nodes[i]); + } + break; + } + case WPAINT_TOOL_SMEAR: + for (const int i : nodes.index_range()) { + do_wpaint_brush_smear_task(scene, ob, brush, vp, wpd, wpi, me, nodes[i]); + } + break; + case WPAINT_TOOL_BLUR: + for (const int i : nodes.index_range()) { + do_wpaint_brush_blur_task(scene, ob, brush, vp, wpd, wpi, me, nodes[i]); + } + break; + case WPAINT_TOOL_DRAW: + for (const int i : nodes.index_range()) { + do_wpaint_brush_draw_task(scene, ob, brush, vp, wpd, wpi, me, strength, nodes[i]); + } + break; + } + } + else { + switch ((eBrushWeightPaintTool)brush->weightpaint_tool) { + case WPAINT_TOOL_AVERAGE: { + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_wpaint_brush_draw_task(scene, ob, brush, vp, wpd, wpi, me, strength, nodes[i]); + } + }); + break; + } + case WPAINT_TOOL_SMEAR: + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_wpaint_brush_smear_task(scene, ob, brush, vp, wpd, wpi, me, nodes[i]); + } + }); + break; + case WPAINT_TOOL_BLUR: + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_wpaint_brush_blur_task(scene, ob, brush, vp, wpd, wpi, me, nodes[i]); + } + }); + break; + case WPAINT_TOOL_DRAW: + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_wpaint_brush_draw_task(scene, ob, brush, vp, wpd, wpi, me, strength, nodes[i]); + } + }); + break; + } } } /** \} */ @@ -1665,7 +1698,7 @@ static void wpaint_do_paint(bContext *C, Vector nodes = vwpaint::pbvh_gather_generic(ob, wp, sd, brush); - wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes); + wpaint_paint_leaves(C, ob, wp, wpd, wpi, me, nodes); } static void wpaint_do_radial_symmetry(bContext *C, @@ -1808,7 +1841,7 @@ static void wpaint_stroke_update_step(bContext *C, /* *** done setting up WeightPaintInfo *** */ if (wpd->precomputed_weight) { - precompute_weight_values(C, ob, brush, wpd, &wpi, mesh); + precompute_weight_values(ob, brush, wpd, &wpi, mesh); } wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi); diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 9b64a04c644..50a1247781c 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -1028,53 +1028,34 @@ bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], return is_in_symmetry_area; } -struct NearestVertexTLSData { +struct NearestVertexData { PBVHVertRef nearest_vertex; - float nearest_vertex_distance_squared; + float nearest_vertex_distance_sq; }; -static void do_nearest_vertex_get_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void nearest_vertex_get_node(PBVH *pbvh, + const float nearest_vertex_search_co[3], + const float max_distance_sq, + PBVHNode *node, + NearestVertexData *nvtd) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - NearestVertexTLSData *nvtd = static_cast(tls->userdata_chunk); PBVHVertexIter vd; - - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - float distance_squared = len_squared_v3v3(vd.co, data->nearest_vertex_search_co); - if (distance_squared < nvtd->nearest_vertex_distance_squared && - distance_squared < data->max_distance_squared) + BKE_pbvh_vertex_iter_begin (pbvh, node, vd, PBVH_ITER_UNIQUE) { + float distance_squared = len_squared_v3v3(vd.co, nearest_vertex_search_co); + if (distance_squared < nvtd->nearest_vertex_distance_sq && distance_squared < max_distance_sq) { nvtd->nearest_vertex = vd.vertex; - nvtd->nearest_vertex_distance_squared = distance_squared; + nvtd->nearest_vertex_distance_sq = distance_squared; } } BKE_pbvh_vertex_iter_end; } -static void nearest_vertex_get_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) -{ - NearestVertexTLSData *join = static_cast(chunk_join); - NearestVertexTLSData *nvtd = static_cast(chunk); - if (join->nearest_vertex.i == PBVH_REF_NONE) { - join->nearest_vertex = nvtd->nearest_vertex; - join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; - } - else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) { - join->nearest_vertex = nvtd->nearest_vertex; - join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; - } -} - PBVHVertRef SCULPT_nearest_vertex_get( Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original) { + using namespace blender; SculptSession *ss = ob->sculpt; - Vector nodes; SculptSearchSphereData data{}; data.sd = sd; @@ -1082,31 +1063,28 @@ PBVHVertRef SCULPT_nearest_vertex_get( data.original = use_original; data.center = co; - nodes = blender::bke::pbvh::search_gather( + Vector nodes = blender::bke::pbvh::search_gather( ss->pbvh, [&](PBVHNode &node) { return SCULPT_search_sphere(&node, &data); }); if (nodes.is_empty()) { return BKE_pbvh_make_vref(PBVH_REF_NONE); } - SculptThreadedTaskData task_data{}; - task_data.sd = sd; - task_data.ob = ob; - task_data.nodes = nodes; - task_data.max_distance_squared = max_distance * max_distance; + const float max_distance_sq = max_distance * max_distance; - copy_v3_v3(task_data.nearest_vertex_search_co, co); - NearestVertexTLSData nvtd; - nvtd.nearest_vertex.i = PBVH_REF_NONE; - nvtd.nearest_vertex_distance_squared = FLT_MAX; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - settings.func_reduce = nearest_vertex_get_reduce; - settings.userdata_chunk = &nvtd; - settings.userdata_chunk_size = sizeof(NearestVertexTLSData); - BLI_task_parallel_range(0, nodes.size(), &task_data, do_nearest_vertex_get_task_cb, &settings); - - return nvtd.nearest_vertex; + return threading::parallel_reduce( + nodes.index_range(), + 1, + NearestVertexData{PBVH_REF_NONE, FLT_MAX}, + [&](const IndexRange range, NearestVertexData nearest) { + for (const int i : range) { + nearest_vertex_get_node(ss->pbvh, co, max_distance_sq, nodes[i], &nearest); + } + return nearest; + }, + [](const NearestVertexData a, const NearestVertexData b) { + return a.nearest_vertex_distance_sq < b.nearest_vertex_distance_sq ? a : b; + }) + .nearest_vertex; } bool SCULPT_is_symmetry_iteration_valid(char i, char symm) @@ -1482,15 +1460,91 @@ bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *bru /** \name Sculpt Paint Mesh * \{ */ -static void paint_mesh_restore_co_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void paint_mesh_restore_node(Object *ob, const SculptUndoType type, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; + + SculptUndoNode *unode; + if (ss->bm) { + unode = SCULPT_undo_push_node(ob, node, type); + } + else { + unode = SCULPT_undo_get_node(node, type); + } + + if (!unode) { + return; + } + + switch (type) { + case SCULPT_UNDO_MASK: { + SculptOrigVertData orig_vert_data; + SCULPT_orig_vert_data_unode_init(&orig_vert_data, ob, unode); + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { + SCULPT_orig_vert_data_update(&orig_vert_data, &vd); + *vd.mask = orig_vert_data.mask; + } + BKE_pbvh_vertex_iter_end; + BKE_pbvh_node_mark_update_mask(node); + break; + } + case SCULPT_UNDO_COLOR: { + SculptOrigVertData orig_vert_data; + SCULPT_orig_vert_data_unode_init(&orig_vert_data, ob, unode); + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { + SCULPT_orig_vert_data_update(&orig_vert_data, &vd); + SCULPT_vertex_color_set(ss, vd.vertex, orig_vert_data.col); + } + BKE_pbvh_vertex_iter_end; + BKE_pbvh_node_mark_update_color(node); + break; + } + case SCULPT_UNDO_FACE_SETS: { + SculptOrigFaceData orig_face_data; + SCULPT_orig_face_data_unode_init(&orig_face_data, ob, unode); + PBVHFaceIter fd; + BKE_pbvh_face_iter_begin (ss->pbvh, node, fd) { + SCULPT_orig_face_data_update(&orig_face_data, &fd); + if (fd.face_set) { + *fd.face_set = orig_face_data.face_set; + } + } + BKE_pbvh_face_iter_end(fd); + BKE_pbvh_node_mark_update_face_sets(node); + break; + } + case SCULPT_UNDO_COORDS: { + SculptOrigVertData orig_vert_data; + SCULPT_orig_vert_data_unode_init(&orig_vert_data, ob, unode); + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { + SCULPT_orig_vert_data_update(&orig_vert_data, &vd); + copy_v3_v3(vd.co, orig_vert_data.co); + if (vd.is_mesh) { + BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); + } + } + BKE_pbvh_vertex_iter_end; + BKE_pbvh_node_mark_update(node); + break; + } + default: + break; + } +} + +static void paint_mesh_restore_co(Sculpt *sd, Object *ob) +{ + using namespace blender; + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + + Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); SculptUndoType type; - switch (data->brush->sculpt_tool) { + switch (brush->sculpt_tool) { case SCULPT_TOOL_MASK: type = SCULPT_UNDO_MASK; break; @@ -1506,99 +1560,22 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, break; } - SculptUndoNode *unode; if (ss->bm) { - unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type); + /* Disable multi-threading when dynamic-topology is enabled. Otherwise, + * new entries might be inserted by #SCULPT_undo_push_node() into the #GHash + * used internally by #BM_log_original_vert_co() by a different thread. See #33787. */ + for (const int i : nodes.index_range()) { + paint_mesh_restore_node(ob, type, nodes[i]); + } } else { - unode = SCULPT_undo_get_node(data->nodes[n], type); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + paint_mesh_restore_node(ob, type, nodes[i]); + } + }); } - if (!unode) { - return; - } - - switch (type) { - case SCULPT_UNDO_MASK: { - SculptOrigVertData orig_vert_data; - SCULPT_orig_vert_data_unode_init(&orig_vert_data, data->ob, unode); - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_vert_data, &vd); - *vd.mask = orig_vert_data.mask; - } - BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_update_mask(data->nodes[n]); - break; - } - case SCULPT_UNDO_COLOR: { - SculptOrigVertData orig_vert_data; - SCULPT_orig_vert_data_unode_init(&orig_vert_data, data->ob, unode); - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_vert_data, &vd); - SCULPT_vertex_color_set(ss, vd.vertex, orig_vert_data.col); - } - BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_update_color(data->nodes[n]); - break; - } - case SCULPT_UNDO_FACE_SETS: { - SculptOrigFaceData orig_face_data; - SCULPT_orig_face_data_unode_init(&orig_face_data, data->ob, unode); - PBVHFaceIter fd; - BKE_pbvh_face_iter_begin (ss->pbvh, data->nodes[n], fd) { - SCULPT_orig_face_data_update(&orig_face_data, &fd); - if (fd.face_set) { - *fd.face_set = orig_face_data.face_set; - } - } - BKE_pbvh_face_iter_end(fd); - BKE_pbvh_node_mark_update_face_sets(data->nodes[n]); - break; - } - case SCULPT_UNDO_COORDS: { - SculptOrigVertData orig_vert_data; - SCULPT_orig_vert_data_unode_init(&orig_vert_data, data->ob, unode); - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_vert_data, &vd); - copy_v3_v3(vd.co, orig_vert_data.co); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } - } - BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_update(data->nodes[n]); - break; - } - default: - break; - } -} - -static void paint_mesh_restore_co(Sculpt *sd, Object *ob) -{ - SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); - - Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); - - /** - * Disable multi-threading when dynamic-topology is enabled. Otherwise, - * new entries might be inserted by #SCULPT_undo_push_node() into the #GHash - * used internally by #BM_log_original_vert_co() by a different thread. See #33787. - */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, paint_mesh_restore_co_task_cb, &settings); - BKE_pbvh_node_color_buffer_free(ss->pbvh); } @@ -1990,7 +1967,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) * \note These are all _very_ similar, when changing one, check others. * \{ */ -struct AreaNormalCenterTLSData { +struct AreaNormalCenterData { /* 0 = towards view, 1 = flipped */ float area_cos[2][3]; float area_nos[2][3]; @@ -1998,15 +1975,16 @@ struct AreaNormalCenterTLSData { int count_co[2]; }; -static void calc_area_normal_and_center_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void calc_area_normal_and_center_task(Object *ob, + const Brush *brush, + const bool use_area_nos, + const bool use_area_cos, + const bool has_bm_orco, + PBVHNode *node, + AreaNormalCenterData *anctd, + bool &r_any_vertex_sampled) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - AreaNormalCenterTLSData *anctd = static_cast(tls->userdata_chunk); - const bool use_area_nos = data->use_area_nos; - const bool use_area_cos = data->use_area_cos; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptUndoNode *unode = nullptr; @@ -2015,40 +1993,40 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, bool normal_test_r, area_test_r; if (ss->cache && !ss->cache->accum) { - unode = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + unode = SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS); use_original = (unode->co || unode->bm_entry); } SculptBrushTest normal_test; SculptBrushTestFn sculpt_brush_normal_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &normal_test, data->brush->falloff_shape); + ss, &normal_test, brush->falloff_shape); /* Update the test radius to sample the normal using the normal radius of the brush. */ - if (data->brush->ob_mode == OB_MODE_SCULPT) { + if (brush->ob_mode == OB_MODE_SCULPT) { float test_radius = sqrtf(normal_test.radius_squared); - test_radius *= data->brush->normal_radius_factor; + test_radius *= brush->normal_radius_factor; normal_test.radius = test_radius; normal_test.radius_squared = test_radius * test_radius; } SculptBrushTest area_test; SculptBrushTestFn sculpt_brush_area_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &area_test, data->brush->falloff_shape); + ss, &area_test, brush->falloff_shape); - if (data->brush->ob_mode == OB_MODE_SCULPT) { + if (brush->ob_mode == OB_MODE_SCULPT) { float test_radius = sqrtf(area_test.radius_squared); /* Layer brush produces artifacts with normal and area radius */ /* Enable area radius control only on Scrape for now */ - if (ELEM(data->brush->sculpt_tool, SCULPT_TOOL_SCRAPE, SCULPT_TOOL_FILL) && - data->brush->area_radius_factor > 0.0f) + if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SCRAPE, SCULPT_TOOL_FILL) && + brush->area_radius_factor > 0.0f) { - test_radius *= data->brush->area_radius_factor; - if (ss->cache && data->brush->flag2 & BRUSH_AREA_RADIUS_PRESSURE) { + test_radius *= brush->area_radius_factor; + if (ss->cache && brush->flag2 & BRUSH_AREA_RADIUS_PRESSURE) { test_radius *= ss->cache->pressure; } } else { - test_radius *= data->brush->normal_radius_factor; + test_radius *= brush->normal_radius_factor; } area_test.radius = test_radius; area_test.radius_squared = test_radius * test_radius; @@ -2056,13 +2034,12 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, /* When the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius). */ - if (use_original && data->has_bm_orco) { + if (use_original && has_bm_orco) { float(*orco_coords)[3]; int(*orco_tris)[3]; int orco_tris_num; - BKE_pbvh_node_get_bm_orco_data( - data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords, nullptr); + BKE_pbvh_node_get_bm_orco_data(node, &orco_tris, &orco_tris_num, &orco_coords, nullptr); for (int i = 0; i < orco_tris_num; i++) { const float *co_tri[3] = { @@ -2112,7 +2089,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, } } else { - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { float co[3]; /* For bm_vert only. */ @@ -2145,7 +2122,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, float no[3]; int flip_index; - data->any_vertex_sampled = true; + r_any_vertex_sampled = true; if (use_original) { copy_v3_v3(no, no_s); @@ -2189,50 +2166,48 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, } } -static void calc_area_normal_and_center_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) +static AreaNormalCenterData calc_area_normal_and_center_reduce(const AreaNormalCenterData &a, + const AreaNormalCenterData &b) { - AreaNormalCenterTLSData *join = static_cast(chunk_join); - AreaNormalCenterTLSData *anctd = static_cast(chunk); + AreaNormalCenterData joined{}; /* For flatten center. */ - add_v3_v3(join->area_cos[0], anctd->area_cos[0]); - add_v3_v3(join->area_cos[1], anctd->area_cos[1]); + add_v3_v3v3(joined.area_cos[0], a.area_cos[0], b.area_cos[0]); + add_v3_v3v3(joined.area_cos[1], a.area_cos[1], b.area_cos[1]); /* For area normal. */ - add_v3_v3(join->area_nos[0], anctd->area_nos[0]); - add_v3_v3(join->area_nos[1], anctd->area_nos[1]); + add_v3_v3v3(joined.area_nos[0], a.area_nos[0], b.area_nos[0]); + add_v3_v3v3(joined.area_nos[1], a.area_nos[1], b.area_nos[1]); /* Weights. */ - add_v2_v2_int(join->count_no, anctd->count_no); - add_v2_v2_int(join->count_co, anctd->count_co); + add_v2_v2v2_int(joined.count_no, a.count_no, b.count_no); + add_v2_v2v2_int(joined.count_co, a.count_co, b.count_co); + + return joined; } void SCULPT_calc_area_center(Sculpt *sd, Object *ob, Span nodes, float r_area_co[3]) { + using namespace blender; const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush); int n; - /* Intentionally set 'sd' to nullptr since we share logic with vertex paint. */ - SculptThreadedTaskData data{}; - data.sd = nullptr; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.has_bm_orco = has_bm_orco; - data.use_area_cos = true; + bool any_vertex_sampled = false; - AreaNormalCenterTLSData anctd = {{{0}}}; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - settings.func_reduce = calc_area_normal_and_center_reduce; - settings.userdata_chunk = &anctd; - settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings); + const AreaNormalCenterData anctd = threading::parallel_reduce( + nodes.index_range(), + 1, + AreaNormalCenterData{}, + [&](const IndexRange range, AreaNormalCenterData anctd) { + for (const int i : range) { + calc_area_normal_and_center_task( + ob, brush, false, true, has_bm_orco, nodes[i], &anctd, any_vertex_sampled); + } + return anctd; + }, + calc_area_normal_and_center_reduce); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -2258,33 +2233,32 @@ void SCULPT_calc_area_center(Sculpt *sd, Object *ob, Span nodes, flo void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, Span nodes, float r_area_no[3]) { const Brush *brush = BKE_paint_brush(&sd->paint); - SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, r_area_no); + SCULPT_pbvh_calc_area_normal(brush, ob, nodes, r_area_no); } -bool SCULPT_pbvh_calc_area_normal( - const Brush *brush, Object *ob, Span nodes, bool use_threading, float r_area_no[3]) +bool SCULPT_pbvh_calc_area_normal(const Brush *brush, + Object *ob, + Span nodes, + float r_area_no[3]) { + using namespace blender; SculptSession *ss = ob->sculpt; const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush); - /* Intentionally set 'sd' to nullptr since this is used for vertex paint too. */ - SculptThreadedTaskData data{}; - data.sd = nullptr; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.has_bm_orco = has_bm_orco; - data.use_area_nos = true; - data.any_vertex_sampled = false; + bool any_vertex_sampled = false; - AreaNormalCenterTLSData anctd = {{{0}}}; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, use_threading, nodes.size()); - settings.func_reduce = calc_area_normal_and_center_reduce; - settings.userdata_chunk = &anctd; - settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings); + const AreaNormalCenterData anctd = threading::parallel_reduce( + nodes.index_range(), + 1, + AreaNormalCenterData{}, + [&](const IndexRange range, AreaNormalCenterData anctd) { + for (const int i : range) { + calc_area_normal_and_center_task( + ob, brush, true, false, has_bm_orco, nodes[i], &anctd, any_vertex_sampled); + } + return anctd; + }, + calc_area_normal_and_center_reduce); /* For area normal. */ for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) { @@ -2293,35 +2267,32 @@ bool SCULPT_pbvh_calc_area_normal( } } - return data.any_vertex_sampled; + return any_vertex_sampled; } void SCULPT_calc_area_normal_and_center( Sculpt *sd, Object *ob, Span nodes, float r_area_no[3], float r_area_co[3]) { + using namespace blender; const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush); int n; - /* Intentionally set 'sd' to nullptr since this is used for vertex paint too. */ - SculptThreadedTaskData data{}; - data.sd = nullptr; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.has_bm_orco = has_bm_orco; - data.use_area_cos = true; - data.use_area_nos = true; + bool any_vertex_sampled = false; - AreaNormalCenterTLSData anctd = {{{0}}}; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - settings.func_reduce = calc_area_normal_and_center_reduce; - settings.userdata_chunk = &anctd; - settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings); + const AreaNormalCenterData anctd = threading::parallel_reduce( + nodes.index_range(), + 1, + AreaNormalCenterData{}, + [&](const IndexRange range, AreaNormalCenterData anctd) { + for (const int i : range) { + calc_area_normal_and_center_task( + ob, brush, true, true, has_bm_orco, nodes[i], &anctd, any_vertex_sampled); + } + return anctd; + }, + calc_area_normal_and_center_reduce); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -3278,26 +3249,20 @@ float SCULPT_brush_plane_offset_get(Sculpt *sd, SculptSession *ss) /** \name Sculpt Gravity Brush * \{ */ -static void do_gravity_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_gravity_task(SculptSession *ss, + const Brush *brush, + const float *offset, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - float *offset = data->offset; - PBVHVertexIter vd; - float(*proxy)[3]; - - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -3323,6 +3288,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, static void do_gravity(Sculpt *sd, Object *ob, Span nodes, float bstrength) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -3335,17 +3301,11 @@ static void do_gravity(Sculpt *sd, Object *ob, Span nodes, float bst mul_v3_v3v3(offset, gravity_vector, ss->cache->scale); mul_v3_fl(offset, bstrength); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.offset = offset; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_gravity_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_gravity_task(ss, brush, offset, nodes[i]); + } + }); } /** \} */ @@ -3455,41 +3415,38 @@ static void sculpt_topology_update(Sculpt *sd, mul_m4_v3(ob->object_to_world, location); } -static void do_brush_action_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_brush_action_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; bool need_coords = ss->cache->supports_gravity; - if (data->brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { - BKE_pbvh_node_mark_update_face_sets(data->nodes[n]); + if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { + BKE_pbvh_node_mark_update_face_sets(node); /* Draw face sets in smooth mode moves the vertices. */ if (ss->cache->alt_smooth) { need_coords = true; } else { - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_FACE_SETS); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS); } } - else if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); - BKE_pbvh_node_mark_update_mask(data->nodes[n]); + else if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); + BKE_pbvh_node_mark_update_mask(node); } - else if (SCULPT_tool_is_paint(data->brush->sculpt_tool)) { - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR); - BKE_pbvh_node_mark_update_color(data->nodes[n]); + else if (SCULPT_tool_is_paint(brush->sculpt_tool)) { + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COLOR); + BKE_pbvh_node_mark_update_color(node); } else { need_coords = true; } if (need_coords) { - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); - BKE_pbvh_node_mark_update(data->nodes[n]); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS); + BKE_pbvh_node_mark_update(node); } } @@ -3499,6 +3456,7 @@ static void do_brush_action(Sculpt *sd, UnifiedPaintSettings *ups, PaintModeSettings *paint_mode_settings) { + using namespace blender; SculptSession *ss = ob->sculpt; Vector nodes, texnodes; @@ -3599,15 +3557,11 @@ static void do_brush_action(Sculpt *sd, float location[3]; if (!use_pixels) { - SculptThreadedTaskData task_data{}; - task_data.sd = sd; - task_data.ob = ob; - task_data.brush = brush; - task_data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &task_data, do_brush_action_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_brush_action_task(ob, brush, nodes[i]); + } + }); } if (sculpt_brush_needs_normal(ss, sd, brush)) { @@ -5194,7 +5148,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, } /* Calculate the sampled normal. */ - if (SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, sampled_normal)) { + if (SCULPT_pbvh_calc_area_normal(brush, ob, nodes, sampled_normal)) { copy_v3_v3(out->normal, sampled_normal); copy_v3_v3(ss->cursor_sampled_normal, sampled_normal); } @@ -6018,63 +5972,42 @@ static void sculpt_pose_fake_neighbors_free(SculptSession *ss) MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); } -struct NearestVertexFakeNeighborTLSData { +struct NearestVertexFakeNeighborData { PBVHVertRef nearest_vertex; - float nearest_vertex_distance_squared; + float nearest_vertex_distance_sq; int current_topology_id; }; -static void do_fake_neighbor_search_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_fake_neighbor_search_task(SculptSession *ss, + const float nearest_vertex_search_co[3], + const float max_distance_sq, + PBVHNode *node, + NearestVertexFakeNeighborData *nvtd) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - NearestVertexFakeNeighborTLSData *nvtd = static_cast( - tls->userdata_chunk); PBVHVertexIter vd; - - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { int vd_topology_id = SCULPT_vertex_island_get(ss, vd.vertex); if (vd_topology_id != nvtd->current_topology_id && ss->fake_neighbors.fake_neighbor_index[vd.index] == FAKE_NEIGHBOR_NONE) { - float distance_squared = len_squared_v3v3(vd.co, data->nearest_vertex_search_co); - if (distance_squared < nvtd->nearest_vertex_distance_squared && - distance_squared < data->max_distance_squared) - { + float distance_squared = len_squared_v3v3(vd.co, nearest_vertex_search_co); + if (distance_squared < nvtd->nearest_vertex_distance_sq && + distance_squared < max_distance_sq) { nvtd->nearest_vertex = vd.vertex; - nvtd->nearest_vertex_distance_squared = distance_squared; + nvtd->nearest_vertex_distance_sq = distance_squared; } } } BKE_pbvh_vertex_iter_end; } -static void fake_neighbor_search_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) -{ - NearestVertexFakeNeighborTLSData *join = static_cast( - chunk_join); - NearestVertexFakeNeighborTLSData *nvtd = static_cast(chunk); - if (join->nearest_vertex.i == PBVH_REF_NONE) { - join->nearest_vertex = nvtd->nearest_vertex; - join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; - } - else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) { - join->nearest_vertex = nvtd->nearest_vertex; - join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; - } -} - static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const PBVHVertRef vertex, float max_distance) { + using namespace blender; SculptSession *ss = ob->sculpt; - Vector nodes; SculptSearchSphereData data{}; data.ss = ss; @@ -6083,32 +6016,43 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd, data.original = false; data.center = SCULPT_vertex_co_get(ss, vertex); - nodes = blender::bke::pbvh::search_gather( + Vector nodes = blender::bke::pbvh::search_gather( ss->pbvh, [&](PBVHNode &node) { return SCULPT_search_sphere(&node, &data); }); - if (nodes.is_empty()) { return BKE_pbvh_make_vref(PBVH_REF_NONE); } - SculptThreadedTaskData task_data{}; - task_data.sd = sd; - task_data.ob = ob; - task_data.nodes = nodes; - task_data.max_distance_squared = max_distance * max_distance; + const float3 nearest_vertex_search_co = SCULPT_vertex_co_get(ss, vertex); + const float max_distance_sq = max_distance * max_distance; - copy_v3_v3(task_data.nearest_vertex_search_co, SCULPT_vertex_co_get(ss, vertex)); - - NearestVertexFakeNeighborTLSData nvtd; + NearestVertexFakeNeighborData nvtd; nvtd.nearest_vertex.i = -1; - nvtd.nearest_vertex_distance_squared = FLT_MAX; + nvtd.nearest_vertex_distance_sq = FLT_MAX; nvtd.current_topology_id = SCULPT_vertex_island_get(ss, vertex); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - settings.func_reduce = fake_neighbor_search_reduce; - settings.userdata_chunk = &nvtd; - settings.userdata_chunk_size = sizeof(NearestVertexFakeNeighborTLSData); - BLI_task_parallel_range(0, nodes.size(), &task_data, do_fake_neighbor_search_task_cb, &settings); + nvtd = threading::parallel_reduce( + nodes.index_range(), + 1, + nvtd, + [&](const IndexRange range, NearestVertexFakeNeighborData nvtd) { + for (const int i : range) { + do_fake_neighbor_search_task( + ss, nearest_vertex_search_co, max_distance_sq, nodes[i], &nvtd); + } + return nvtd; + }, + [](const NearestVertexFakeNeighborData &a, const NearestVertexFakeNeighborData &b) { + NearestVertexFakeNeighborData joined = a; + if (joined.nearest_vertex.i == PBVH_REF_NONE) { + joined.nearest_vertex = b.nearest_vertex; + joined.nearest_vertex_distance_sq = b.nearest_vertex_distance_sq; + } + else if (b.nearest_vertex_distance_sq < joined.nearest_vertex_distance_sq) { + joined.nearest_vertex = b.nearest_vertex; + joined.nearest_vertex_distance_sq = b.nearest_vertex_distance_sq; + } + return joined; + }); return nvtd.nearest_vertex; } diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.cc b/source/blender/editors/sculpt_paint/sculpt_boundary.cc index a3236b48063..d4d8f619208 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.cc +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.cc @@ -647,23 +647,18 @@ static float sculpt_boundary_displacement_from_grab_delta_get(SculptSession *ss, return dist_signed_to_plane_v3(pos, plane); } -/* Deformation tasks callbacks. */ -static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_bend_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symm_area = ss->cache->mirror_symmetry_pass; SculptBoundary *boundary = ss->cache->boundaries[symm_area]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); float angle_factor = disp / ss->cache->radius; @@ -673,10 +668,9 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, } const float angle = angle_factor * M_PI; AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -707,29 +701,24 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_slide_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symm_area = ss->cache->mirror_symmetry_pass; SculptBoundary *boundary = ss->cache->boundaries[symm_area]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -758,29 +747,24 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_inflate_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symm_area = ss->cache->mirror_symmetry_pass; SculptBoundary *boundary = ss->cache->boundaries[symm_area]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -809,27 +793,22 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_grab_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symm_area = ss->cache->mirror_symmetry_pass; SculptBoundary *boundary = ss->cache->boundaries[symm_area]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -857,25 +836,20 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_twist_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symm_area = ss->cache->mirror_symmetry_pass; SculptBoundary *boundary = ss->cache->boundaries[symm_area]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); float angle_factor = disp / ss->cache->radius; @@ -885,7 +859,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, } const float angle = angle_factor * M_PI; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -916,24 +890,20 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_boundary_brush_smooth_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; const int symmetry_pass = ss->cache->mirror_symmetry_pass; const SculptBoundary *boundary = ss->cache->boundaries[symmetry_pass]; - const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(data->ob); - const Brush *brush = data->brush; + const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); const float strength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -977,6 +947,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -1026,39 +997,48 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, Span nodes) return; } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - switch (brush->boundary_deform_type) { case BRUSH_BOUNDARY_DEFORM_BEND: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_bend_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_bend_task(ob, brush, nodes[i]); + } + }); break; case BRUSH_BOUNDARY_DEFORM_EXPAND: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_slide_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_slide_task(ob, brush, nodes[i]); + } + }); break; case BRUSH_BOUNDARY_DEFORM_INFLATE: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_inflate_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_inflate_task(ob, brush, nodes[i]); + } + }); break; case BRUSH_BOUNDARY_DEFORM_GRAB: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_grab_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_grab_task(ob, brush, nodes[i]); + } + }); break; case BRUSH_BOUNDARY_DEFORM_TWIST: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_twist_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_twist_task(ob, brush, nodes[i]); + } + }); break; case BRUSH_BOUNDARY_DEFORM_SMOOTH: - BLI_task_parallel_range( - 0, nodes.size(), &data, do_boundary_brush_smooth_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_boundary_brush_smooth_task(ob, brush, nodes[i]); + } + }); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc index f92cef9445f..0034d822739 100644 --- a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc +++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc @@ -14,6 +14,7 @@ #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" +#include "BLI_math_vector.hh" #include "BLI_span.hh" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -243,30 +244,23 @@ static void sculpt_project_v3_normal_align(SculptSession *ss, /** \name Sculpt Draw Brush * \{ */ -static void do_draw_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_draw_brush_task(Object *ob, const Brush *brush, const float *offset, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *offset = data->offset; - + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -314,6 +308,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float offset[3]; @@ -330,17 +325,11 @@ void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, Span nodes) * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.offset = offset; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_draw_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_draw_brush_task(ob, brush, offset, nodes[i]); + } + }); } /** \} */ @@ -349,34 +338,28 @@ void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, Span nodes) /** \name Sculpt Fill Brush * \{ */ -static void do_fill_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_fill_brush_task( + Object *ob, const Brush *brush, const float *area_no, const float *area_co, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *area_no = data->area_no; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -418,6 +401,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -441,46 +425,34 @@ void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, Span nodes) mul_v3_fl(temp, displace); add_v3_v3(area_co, temp); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no = area_no; - data.area_co = area_co; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_fill_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_fill_brush_task(ob, brush, area_no, area_co, nodes[i]); + } + }); } -static void do_scrape_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_scrape_brush_task( + Object *ob, const Brush *brush, const float *area_no, const float *area_co, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *area_no = data->area_no; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -522,6 +494,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -545,17 +518,11 @@ void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, Span nodes) mul_v3_fl(temp, displace); add_v3_v3(area_co, temp); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no = area_no; - data.area_co = area_co; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_scrape_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_scrape_brush_task(ob, brush, area_no, area_co, nodes[i]); + } + }); } /** \} */ @@ -564,27 +531,25 @@ void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, Span nodes) /** \name Sculpt Clay Thumb Brush * \{ */ -static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_clay_thumb_brush_task(Object *ob, + const Brush *brush, + float (*mat)[4], + const float *area_no_sp, + const float *area_co, + const float bstrength, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - float(*mat)[4] = data->mat; - const float *area_no_sp = data->area_no_sp; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; - const float bstrength = data->clay_strength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); float plane_tilt[4]; float normal_tilt[3]; @@ -599,10 +564,9 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, plane_from_point_normal_v3(plane_tilt, area_co, normal_tilt); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -655,6 +619,7 @@ float SCULPT_clay_thumb_get_stabilized_pressure(StrokeCache *cache) void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -723,19 +688,11 @@ void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, Span nodes) float clay_strength = ss->cache->bstrength * SCULPT_clay_thumb_get_stabilized_pressure(ss->cache); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no_sp = area_no_sp; - data.area_co = ss->cache->location; - data.mat = mat; - data.clay_strength = clay_strength; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_clay_thumb_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_clay_thumb_brush_task(ob, brush, mat, area_no_sp, area_co, clay_strength, nodes[i]); + } + }); } /** \} */ @@ -744,34 +701,28 @@ void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, Span nodes) /** \name Sculpt Flatten Brush * \{ */ -static void do_flatten_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_flatten_brush_task( + Object *ob, const Brush *brush, const float *area_no, const float *area_co, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *area_no = data->area_no; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -808,6 +759,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -830,17 +782,11 @@ void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, Span nodes) mul_v3_fl(temp, displace); add_v3_v3(area_co, temp); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no = area_no; - data.area_co = area_co; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_flatten_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_flatten_brush_task(ob, brush, area_no, area_co, nodes[i]); + } + }); } /** \} */ @@ -850,19 +796,17 @@ void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, Span nodes) * \{ */ struct ClaySampleData { - float plane_dist[2]; + blender::float2 plane_dist; }; -static void calc_clay_surface_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void calc_clay_surface_task_cb(Object *ob, + const Brush *brush, + const float *area_no, + const float *area_co, + PBVHNode *node, + ClaySampleData *csd) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - ClaySampleData *csd = static_cast(tls->userdata_chunk); - const float *area_no = data->area_no; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; float plane[4]; PBVHVertexIter vd; @@ -881,7 +825,7 @@ static void calc_clay_surface_task_cb(void *__restrict userdata, return; } - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -898,44 +842,28 @@ static void calc_clay_surface_task_cb(void *__restrict userdata, } } -static void calc_clay_surface_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) +static void do_clay_brush_task( + Object *ob, const Brush *brush, const float *area_no, const float *area_co, PBVHNode *node) { - ClaySampleData *join = static_cast(chunk_join); - ClaySampleData *csd = static_cast(chunk); - join->plane_dist[0] = MIN2(csd->plane_dist[0], join->plane_dist[0]); - join->plane_dist[1] = MIN2(csd->plane_dist[1], join->plane_dist[1]); -} - -static void do_clay_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) -{ - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *area_no = data->area_no; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = fabsf(ss->cache->bstrength); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -970,6 +898,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -986,24 +915,19 @@ void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, Span nodes) SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co); - SculptThreadedTaskData sample_data{}; - sample_data.sd = nullptr; - sample_data.ob = ob; - sample_data.brush = brush; - sample_data.nodes = nodes; - sample_data.area_no = area_no; - sample_data.area_co = ss->cache->location; - - ClaySampleData csd = {{0}}; - - TaskParallelSettings sample_settings; - BKE_pbvh_parallel_range_settings(&sample_settings, true, nodes.size()); - sample_settings.func_reduce = calc_clay_surface_reduce; - sample_settings.userdata_chunk = &csd; - sample_settings.userdata_chunk_size = sizeof(ClaySampleData); - - BLI_task_parallel_range( - 0, nodes.size(), &sample_data, calc_clay_surface_task_cb, &sample_settings); + ClaySampleData csd = threading::parallel_reduce( + nodes.index_range(), + 1, + ClaySampleData{}, + [&](const IndexRange range, ClaySampleData csd) { + for (const int i : range) { + calc_clay_surface_task_cb(ob, brush, area_no, area_co, nodes[i], &csd); + } + return csd; + }, + [](const ClaySampleData &a, const ClaySampleData &b) { + return ClaySampleData{math::min(a.plane_dist, b.plane_dist)}; + }); float d_offset = (csd.plane_dist[0] + csd.plane_dist[1]); d_offset = min_ff(radius, d_offset); @@ -1019,29 +943,21 @@ void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, Span nodes) copy_v3_v3(area_co, ss->cache->location); add_v3_v3(area_co, temp); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no = area_no; - data.area_co = area_co; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_clay_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_clay_brush_task(ob, brush, area_no, area_co, nodes[i]); + } + }); } -static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_clay_strips_brush_task(Object *ob, + const Brush *brush, + const float (*mat)[4], + const float *area_no_sp, + const float *area_co, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - float(*mat)[4] = data->mat; - const float *area_no_sp = data->area_no_sp; - const float *area_co = data->area_co; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptBrushTest test; @@ -1049,17 +965,16 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, const bool flip = (ss->cache->bstrength < 0.0f); const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SCULPT_brush_test_init(ss, &test); plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp); - const int thread_id = BLI_task_parallel_thread_id(tls); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness, brush->tip_scale_x)) { continue; } @@ -1102,6 +1017,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -1141,7 +1057,7 @@ void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, Span nodes) add_v3_v3(area_co, temp); /* Clay Strips uses a cube test with falloff in the XY axis (not in Z) and a plane to deform the - * vertices. When in Add mode, vertices that are below the plane and inside the cube are move + * vertices. When in Add mode, vertices that are below the plane and inside the cube are moved * towards the plane. In this situation, there may be cases where a vertex is outside the cube * but below the plane, so won't be deformed, causing artifacts. In order to prevent these * artifacts, this displaces the test cube space in relation to the plane in order to @@ -1174,29 +1090,20 @@ void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, Span nodes) invert_m4_m4(mat, tmat); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.area_no_sp = area_no_sp; - data.area_co = area_co; - data.mat = mat; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_clay_strips_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_clay_strips_brush_task(ob, brush, mat, area_no_sp, area_co, nodes[i]); + } + }); } -static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_snake_hook_brush_task(Object *ob, + const Brush *brush, + SculptProjectVector *spvc, + const float *grab_delta, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - SculptProjectVector *spvc = data->spvc; - const float *grab_delta = data->grab_delta; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; @@ -1209,21 +1116,20 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, const bool do_elastic = brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); KelvinletParams params; BKE_kelvinlet_init_params(¶ms, ss->cache->radius, bstrength, 1.0f, 0.4f); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!do_elastic && !sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -1306,6 +1212,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); const float bstrength = ss->cache->bstrength; @@ -1328,47 +1235,35 @@ void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, Span nodes) sculpt_project_v3_cache_init(&spvc, grab_delta); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.spvc = &spvc; - data.grab_delta = grab_delta; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_snake_hook_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_snake_hook_brush_task(ob, brush, &spvc, grab_delta, nodes[i]); + } + }); } -static void do_thumb_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_thumb_brush_task(Object *ob, const Brush *brush, const float *cono, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *cono = data->cono; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptOrigVertData orig_data; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { @@ -1398,6 +1293,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float grab_delta[3]; @@ -1408,46 +1304,35 @@ void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, Span nodes) cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta); cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.cono = cono; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_thumb_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_thumb_brush_task(ob, brush, cono, nodes[i]); + } + }); } -static void do_rotate_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_rotate_brush_task(Object *ob, const Brush *brush, const float angle, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float angle = data->angle; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptOrigVertData orig_data; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { @@ -1483,32 +1368,23 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); static const int flip[8] = {1, -1, -1, 1, -1, 1, 1, -1}; const float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass]; - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.angle = angle; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_rotate_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_rotate_brush_task(ob, brush, angle, nodes[i]); + } + }); } -static void do_layer_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_layer_brush_task(Object *ob, Sculpt *sd, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - Sculpt *sd = data->sd; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const bool use_persistent_base = !ss->bm && ss->attrs.persistent_co && brush->flag & BRUSH_PERSISTENT; @@ -1516,18 +1392,17 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; SculptOrigVertData orig_data; const float bstrength = ss->cache->bstrength; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { @@ -1606,6 +1481,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -1614,41 +1490,32 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, Span nodes) __func__); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_layer_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_layer_brush_task(ob, sd, brush, nodes[i]); + } + }); } -static void do_inflate_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_inflate_brush_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -1685,44 +1552,35 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_inflate_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_inflate_brush_task(ob, brush, nodes[i]); + } + }); } -static void do_nudge_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_nudge_brush_task(Object *ob, const Brush *brush, const float *cono, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *cono = data->cono; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -1750,6 +1608,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float grab_delta[3]; @@ -1760,16 +1619,11 @@ void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, Span nodes) cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta); cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.cono = cono; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_nudge_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_nudge_brush_task(ob, brush, cono, nodes[i]); + } + }); } /** \} */ @@ -1781,32 +1635,29 @@ void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, Span nodes) /** * Used for 'SCULPT_TOOL_CREASE' and 'SCULPT_TOOL_BLOB' */ -static void do_crease_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_crease_brush_task(Object *ob, + const Brush *brush, + SculptProjectVector *spvc, + const float flippedbstrength, + const float *offset, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - SculptProjectVector *spvc = data->spvc; - const float flippedbstrength = data->flippedbstrength; - const float *offset = data->offset; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -1850,6 +1701,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; const Scene *scene = ss->cache->vc->scene; Brush *brush = BKE_paint_brush(&sd->paint); @@ -1885,40 +1737,30 @@ void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, Span nodes) * point. Without this we get a 'flat' surface surrounding the pinch. */ sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.spvc = &spvc; - data.offset = offset; - data.flippedbstrength = flippedbstrength; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_crease_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_crease_brush_task(ob, brush, &spvc, flippedbstrength, offset, nodes[i]); + } + }); } -static void do_pinch_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_pinch_brush_task(Object *ob, + const Brush *brush, + const float (*stroke_xz)[3], + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - float(*stroke_xz)[3] = data->stroke_xz; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); float x_object_space[3]; float z_object_space[3]; @@ -1926,10 +1768,9 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, copy_v3_v3(z_object_space, stroke_xz[1]); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -1975,6 +1816,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -2008,48 +1850,40 @@ void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, Span nodes) normalize_v3_v3(stroke_xz[0], mat[0]); normalize_v3_v3(stroke_xz[1], mat[2]); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.stroke_xz = stroke_xz; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_pinch_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_pinch_brush_task(ob, brush, stroke_xz, nodes[i]); + } + }); } -static void do_grab_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_grab_brush_task(Object *ob, + const Brush *brush, + const float *grab_delta, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *grab_delta = data->grab_delta; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptOrigVertData orig_data; float(*proxy)[3]; const float bstrength = ss->cache->bstrength; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE; AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { @@ -2090,6 +1924,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float grab_delta[3]; @@ -2100,26 +1935,19 @@ void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, Span nodes) sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.grab_delta = grab_delta; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_grab_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_grab_brush_task(ob, brush, grab_delta, nodes[i]); + } + }); } -static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_elastic_deform_brush_task(Object *ob, + const Brush *brush, + const float *grab_delta, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *grab_delta = data->grab_delta; + SculptSession *ss = ob->sculpt; const float *location = ss->cache->location; PBVHVertexIter vd; @@ -2128,12 +1956,11 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, const float bstrength = ss->cache->bstrength; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; float dir; if (ss->cache->mouse[0] > ss->cache->initial_mouse[0]) { @@ -2155,7 +1982,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, BKE_kelvinlet_init_params( ¶ms, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); SCULPT_automasking_node_update(ss, &automask_data, &vd); @@ -2204,6 +2031,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float grab_delta[3]; @@ -2214,16 +2042,11 @@ void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, Span nod sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.grab_delta = grab_delta; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_elastic_deform_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_elastic_deform_brush_task(ob, brush, grab_delta, nodes[i]); + } + }); } /** \} */ @@ -2232,33 +2055,30 @@ void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, Span nod /** \name Sculpt Draw Sharp Brush * \{ */ -static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_draw_sharp_brush_task(Object *ob, + const Brush *brush, + const float *offset, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - const float *offset = data->offset; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptOrigVertData orig_data; float(*proxy)[3]; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -2288,6 +2108,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); float offset[3]; @@ -2304,17 +2125,11 @@ void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, Span nodes) * initialize before threads so they can do curve mapping. */ BKE_curvemapping_init(brush->curve); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.offset = offset; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_draw_sharp_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_draw_sharp_brush_task(ob, brush, offset, nodes[i]); + } + }); } /** \} */ @@ -2323,32 +2138,27 @@ void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, Span nodes) /** \name Sculpt Topology Brush * \{ */ -static void do_topology_slide_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_topology_slide_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptOrigVertData orig_data; float(*proxy)[3]; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -2488,32 +2298,27 @@ void SCULPT_relax_vertex(SculptSession *ss, add_v3_v3v3(r_final_pos, vd->co, final_disp); } -static void do_topology_relax_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_topology_relax_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); - BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n]); + BKE_pbvh_node_add_proxy(ss->pbvh, node); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -2541,6 +2346,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -2550,22 +2356,24 @@ void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, Span nodes) BKE_curvemapping_init(brush->curve); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); if (ss->cache->alt_smooth) { SCULPT_boundary_info_ensure(ob); for (int i = 0; i < 4; i++) { - BLI_task_parallel_range(0, nodes.size(), &data, do_topology_relax_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_topology_relax_task(ob, brush, nodes[i]); + } + }); } } else { - BLI_task_parallel_range(0, nodes.size(), &data, do_topology_slide_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_topology_slide_task(ob, brush, nodes[i]); + } + }); } } @@ -2575,28 +2383,23 @@ void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, Span nodes) /** \name Sculpt Multires Displacement Eraser Brush * \{ */ -static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_displacement_eraser_brush_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f); - float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -2628,20 +2431,15 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); BKE_curvemapping_init(brush->curve); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range( - 0, nodes.size(), &data, do_displacement_eraser_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_displacement_eraser_brush_task(ob, brush, nodes[i]); + } + }); } /** \} */ @@ -2650,26 +2448,21 @@ void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, Span(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -2745,14 +2538,10 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_displacement_smear_store_prev_disp_task_cb_ex( - void *__restrict userdata, const int n, const TaskParallelTLS *__restrict /*tls*/) +static void do_displacement_smear_store_prev_disp_task(SculptSession *ss, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { sub_v3_v3v3(ss->cache->prev_displacement[vd.index], SCULPT_vertex_co_get(ss, vd.vertex), ss->cache->limit_surface_co[vd.index]); @@ -2762,6 +2551,7 @@ static void do_displacement_smear_store_prev_disp_task_cb_ex( void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; @@ -2782,19 +2572,17 @@ void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, Span ss->cache->limit_surface_co[i]); } } - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range( - 0, nodes.size(), &data, do_displacement_smear_store_prev_disp_task_cb_ex, &settings); - BLI_task_parallel_range( - 0, nodes.size(), &data, do_displacement_smear_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_displacement_smear_store_prev_disp_task(ss, nodes[i]); + } + }); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_displacement_smear_brush_task(ob, brush, nodes[i]); + } + }); } /** \} */ @@ -2803,14 +2591,10 @@ void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, Span /** \name Sculpt Topology Rake (Shared Utility) * \{ */ -static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_topology_rake_bmesh_task( + Object *ob, Sculpt *sd, const Brush *brush, const float strength, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - Sculpt *sd = data->sd; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; float direction[3]; copy_v3_v3(direction, ss->cache->grab_delta_symmetry); @@ -2826,19 +2610,18 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, return; } - const float bstrength = clamp_f(data->strength, 0.0f, 1.0f); + const float bstrength = clamp_f(strength, 0.0f, 1.0f); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -2876,6 +2659,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, void SCULPT_bmesh_topology_rake(Sculpt *sd, Object *ob, Span nodes, float bstrength) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); const float strength = clamp_f(bstrength, 0.0f, 1.0f); @@ -2887,18 +2671,11 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd, Object *ob, Span nodes, const float factor = iterations * strength / count; for (iteration = 0; iteration <= count; iteration++) { - - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.strength = factor; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - - BLI_task_parallel_range(0, nodes.size(), &data, do_topology_rake_bmesh_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_topology_rake_bmesh_task(ob, sd, brush, factor, nodes[i]); + } + }); } } @@ -2908,27 +2685,22 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd, Object *ob, Span nodes, /** \name Sculpt Mask Brush * \{ */ -static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_mask_brush_draw_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -2958,18 +2730,13 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, Span nodes) { - Brush *brush = BKE_paint_brush(&sd->paint); - - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_mask_brush_draw_task_cb_ex, &settings); + using namespace blender; + const Brush *brush = BKE_paint_brush(&sd->paint); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_mask_brush_draw_task(ob, brush, nodes[i]); + } + }); } void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, Span nodes) diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 1dc1fbc9945..8b3d5f3e8da 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -291,17 +291,17 @@ static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_ cloth_brush_reallocate_constraints(cloth_sim); } -static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_cloth_brush_build_constraints_task(Object *ob, + const Brush *brush, + SculptClothSimulation *cloth_sim, + float *cloth_sim_initial_location, + float cloth_sim_radius, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - PBVHNode *node = data->nodes[n]; + SculptSession *ss = ob->sculpt; - const int node_index = POINTER_AS_INT(BLI_ghash_lookup(data->cloth_sim->node_state_index, node)); - if (data->cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_UNINITIALIZED) { + const int node_index = POINTER_AS_INT(BLI_ghash_lookup(cloth_sim->node_state_index, node)); + if (cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_UNINITIALIZED) { /* The simulation already contains constraints for this node. */ return; } @@ -330,11 +330,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat /* Only limit the constraint creation to a radius when the simulation is local. */ const float cloth_sim_radius_squared = brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL ? - data->cloth_sim_radius * data->cloth_sim_radius : + cloth_sim_radius * cloth_sim_radius : FLT_MAX; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - const float len_squared = len_squared_v3v3(vd.co, data->cloth_sim_initial_location); + const float len_squared = len_squared_v3v3(vd.co, cloth_sim_initial_location); if (len_squared < cloth_sim_radius_squared) { SculptVertexNeighborIter ni; @@ -348,8 +348,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - if (data->cloth_sim->softbody_strength > 0.0f) { - cloth_brush_add_softbody_constraint(data->cloth_sim, node_index, vd.index, 1.0f); + if (cloth_sim->softbody_strength > 0.0f) { + cloth_brush_add_softbody_constraint(cloth_sim, node_index, vd.index, 1.0f); } /* As we don't know the order of the neighbor vertices, we create all possible combinations @@ -360,14 +360,10 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat for (int c_i = 0; c_i < tot_indices; c_i++) { for (int c_j = 0; c_j < tot_indices; c_j++) { if (c_i != c_j && !cloth_brush_sim_has_length_constraint( - data->cloth_sim, build_indices[c_i], build_indices[c_j])) + cloth_sim, build_indices[c_i], build_indices[c_j])) { - cloth_brush_add_length_constraint(ss, - data->cloth_sim, - node_index, - build_indices[c_i], - build_indices[c_j], - use_persistent); + cloth_brush_add_length_constraint( + ss, cloth_sim, node_index, build_indices[c_i], build_indices[c_j], use_persistent); } } } @@ -381,7 +377,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat /* With plane falloff the strength of the constraints is set when applying the * deformation forces. */ cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_GRAB_STRENGTH); + cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_GRAB_STRENGTH); } else if (len_squared < radius_squared) { /* With radial falloff deformation constraints are created with different strengths and @@ -389,22 +385,22 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat const float fade = BKE_brush_curve_strength( brush, sqrtf(len_squared), ss->cache->radius); cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); + cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); } } else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) { /* Cloth Snake Hook creates deformation constraint with fixed strength because the strength * is controlled per iteration using cloth_sim->deformation_strength. */ cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_SNAKEHOOK_STRENGTH); + cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_SNAKEHOOK_STRENGTH); } } - else if (data->cloth_sim->deformation_pos) { + else if (cloth_sim->deformation_pos) { /* Any other tool that target the cloth simulation handle the falloff in * their own code when modifying the deformation coordinates of the simulation, so * deformation constraints are created with a fixed strength for all vertices. */ cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_TARGET_STRENGTH); + cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_TARGET_STRENGTH); } if (pin_simulation_boundary) { @@ -414,7 +410,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(void *__restrict userdat if (sim_falloff < 1.0f) { /* Create constraints with more strength the closer the vertex is to the simulation * boundary. */ - cloth_brush_add_pin_constraint(data->cloth_sim, node_index, vd.index, 1.0f - sim_falloff); + cloth_brush_add_pin_constraint(cloth_sim, node_index, vd.index, 1.0f - sim_falloff); } } } @@ -429,17 +425,17 @@ static void cloth_brush_apply_force_to_vertex(SculptSession * /*ss*/, madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass); } -static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_cloth_brush_apply_forces_task(Object *ob, + const Sculpt *sd, + const Brush *brush, + const float *offset, + const float *grab_delta, + float (*imat)[4], + float *area_co, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; - const float *offset = data->offset; - const float *grab_delta = data->grab_delta; - float(*imat)[4] = data->mat; const bool use_falloff_plane = brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE; @@ -449,8 +445,8 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); /* For Pinch Perpendicular Deform Type. */ float x_object_space[3]; @@ -465,20 +461,20 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float plane_normal[3]; if (use_falloff_plane) { normalize_v3_v3(plane_normal, grab_delta); - plane_from_point_normal_v3(deform_plane, data->area_co, plane_normal); + plane_from_point_normal_v3(deform_plane, area_co, plane_normal); } /* Gravity */ float gravity[3] = {0.0f}; if (ss->cache->supports_gravity) { - madd_v3_v3fl(gravity, ss->cache->gravity_direction, -data->sd->gravity_factor); + madd_v3_v3fl(gravity, ss->cache->gravity_direction, -sd->gravity_factor); } AutomaskingNodeData automask_data; SCULPT_automasking_node_begin( - data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, data->nodes[n]); + ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); float force[3]; @@ -722,30 +718,27 @@ static void cloth_brush_solve_collision(Object *object, } } -static void do_cloth_brush_solve_simulation_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_cloth_brush_solve_simulation_task(Object *ob, + const Brush *brush, + SculptClothSimulation *cloth_sim, + const float time_step, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; - PBVHNode *node = data->nodes[n]; PBVHVertexIter vd; - SculptClothSimulation *cloth_sim = data->cloth_sim; - const float time_step = data->cloth_time_step; - const int node_index = POINTER_AS_INT(BLI_ghash_lookup(data->cloth_sim->node_state_index, node)); - if (data->cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_ACTIVE) { + const int node_index = POINTER_AS_INT(BLI_ghash_lookup(cloth_sim->node_state_index, node)); + if (cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_ACTIVE) { return; } AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss); AutomaskingNodeData automask_data; SCULPT_automasking_node_begin( - data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, data->nodes[n]); + ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); float sim_location[3]; @@ -775,7 +768,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(void *__restrict userdata madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); if (cloth_sim->collider_list != nullptr) { - cloth_brush_solve_collision(data->ob, cloth_sim, i); + cloth_brush_solve_collision(ob, cloth_sim, i); } copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); @@ -908,32 +901,24 @@ void SCULPT_cloth_brush_do_simulation_step(Sculpt *sd, SculptClothSimulation *cloth_sim, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); /* Update the constraints. */ cloth_brush_satisfy_constraints(ss, brush, cloth_sim); - /* Solve the simulation and write the final step to the mesh. */ - SculptThreadedTaskData solve_simulation_data{}; - solve_simulation_data.sd = sd; - solve_simulation_data.ob = ob; - solve_simulation_data.brush = brush; - solve_simulation_data.nodes = nodes; - solve_simulation_data.cloth_time_step = CLOTH_SIMULATION_TIME_STEP; - solve_simulation_data.cloth_sim = cloth_sim; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, - nodes.size(), - &solve_simulation_data, - do_cloth_brush_solve_simulation_task_cb_ex, - &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_cloth_brush_solve_simulation_task( + ob, brush, cloth_sim, CLOTH_SIMULATION_TIME_STEP, nodes[i]); + } + }); } static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -941,26 +926,14 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Spancurve); /* Initialize the grab delta. */ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry); normalize_v3(grab_delta); - apply_forces_data.grab_delta = grab_delta; - if (is_zero_v3(ss->cache->grab_delta_symmetry)) { return; } @@ -971,8 +944,6 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Spancache->sculpt_normal_symm, ss->cache->radius); mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, 2.0f); - - apply_forces_data.offset = offset; } if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR || @@ -991,10 +962,6 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Spancache->mirror_symmetry_pass == 0) { copy_m4_m4(ss->cache->stroke_local_mat, mat); @@ -1010,10 +977,11 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Spanpaint); /* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of * storing the constraints per node. */ /* Currently all constrains are added to the same global array which can't be accessed from * different threads. */ - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, false, nodes.size()); cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints"); - SculptThreadedTaskData build_constraints_data{}; - build_constraints_data.sd = sd; - build_constraints_data.ob = ob; - build_constraints_data.brush = brush; - build_constraints_data.nodes = nodes; - build_constraints_data.cloth_sim = cloth_sim; - build_constraints_data.cloth_sim_initial_location = initial_location; - build_constraints_data.cloth_sim_radius = radius; - - BLI_task_parallel_range(0, - nodes.size(), - &build_constraints_data, - do_cloth_brush_build_constraints_task_cb_ex, - &settings); + for (const int i : nodes.index_range()) { + do_cloth_brush_build_constraints_task( + ob, brush, cloth_sim, initial_location, radius, nodes[i]); + } BLI_edgeset_free(cloth_sim->created_length_constraints); } @@ -1399,18 +1356,16 @@ static void cloth_filter_apply_forces_to_vertices(const int v_index, cloth_brush_apply_force_to_vertex(nullptr, filter_cache->cloth_sim, final_force, v_index); } -static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void cloth_filter_apply_forces_task(Object *ob, + Sculpt *sd, + const eSculptClothFilterType filter_type, + const float filter_strength, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - Sculpt *sd = data->sd; - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim; - const eSculptClothFilterType filter_type = eSculptClothFilterType(data->filter_type); const bool is_deformation_filter = cloth_filter_is_deformation_filter(filter_type); float sculpt_gravity[3] = {0.0f}; @@ -1420,10 +1375,10 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, else { sculpt_gravity[2] = -1.0f; } - mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength); + mul_v3_fl(sculpt_gravity, sd->gravity_factor * filter_strength); AutomaskingNodeData automask_data; SCULPT_automasking_node_begin( - data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, node); + ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, node); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { @@ -1447,30 +1402,30 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, if (ss->filter_cache->orientation == SCULPT_FILTER_ORIENTATION_VIEW) { /* When using the view orientation apply gravity in the -Y axis, this way objects will * fall down instead of backwards. */ - force[1] = -data->filter_strength * fade; + force[1] = -filter_strength * fade; } else { - force[2] = -data->filter_strength * fade; + force[2] = -filter_strength * fade; } SCULPT_filter_to_object_space(force, ss->filter_cache); break; case CLOTH_FILTER_INFLATE: { float normal[3]; SCULPT_vertex_normal_get(ss, vd.vertex, normal); - mul_v3_v3fl(force, normal, fade * data->filter_strength); + mul_v3_v3fl(force, normal, fade * filter_strength); } break; case CLOTH_FILTER_EXPAND: - cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f; + cloth_sim->length_constraint_tweak[vd.index] += fade * filter_strength * 0.01f; zero_v3(force); break; case CLOTH_FILTER_PINCH: sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co); normalize_v3(force); - mul_v3_fl(force, fade * data->filter_strength); + mul_v3_fl(force, fade * filter_strength); break; case CLOTH_FILTER_SCALE: unit_m3(transform); - scale_m3_fl(transform, 1.0f + (fade * data->filter_strength)); + scale_m3_fl(transform, 1.0f + (fade * filter_strength)); copy_v3_v3(temp, cloth_sim->init_pos[vd.index]); mul_m3_v3(transform, temp); sub_v3_v3v3(disp, temp, cloth_sim->init_pos[vd.index]); @@ -1493,6 +1448,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) { + using namespace blender; Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); SculptSession *ss = ob->sculpt; @@ -1526,17 +1482,15 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, vertex)); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.filter_type = filter_type; - data.filter_strength = filter_strength; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, cloth_filter_apply_forces_task_cb, &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + cloth_filter_apply_forces_task(ob, + sd, + eSculptClothFilterType(filter_type), + filter_strength, + ss->filter_cache->nodes[i]); + } + }); /* Activate all nodes. */ SCULPT_cloth_sim_activate_nodes(ss->filter_cache->cloth_sim, ss->filter_cache->nodes); diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index 547f1a74537..995d8b796a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -1262,13 +1262,8 @@ static void sculpt_expand_cancel(bContext *C, wmOperator * /*op*/) /** * Callback to update mask data per PBVH node. */ -static void sculpt_expand_mask_update_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_expand_mask_update_task(SculptSession *ss, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; ExpandCache *expand_cache = ss->expand_cache; bool any_changed = false; @@ -1342,13 +1337,8 @@ static void sculpt_expand_face_sets_update(SculptSession *ss, ExpandCache *expan /** * Callback to update vertex colors per PBVH node. */ -static void sculpt_expand_colors_update_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_expand_colors_update_task(SculptSession *ss, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; ExpandCache *expand_cache = ss->expand_cache; bool any_changed = false; @@ -1476,8 +1466,8 @@ static void sculpt_expand_face_sets_restore(SculptSession *ss, ExpandCache *expa static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const PBVHVertRef vertex) { + using namespace blender; SculptSession *ss = ob->sculpt; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; ExpandCache *expand_cache = ss->expand_cache; int vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, vertex); @@ -1501,26 +1491,23 @@ static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const PBVHV sculpt_expand_face_sets_restore(ss, expand_cache); } - /* Update the mesh sculpt data. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = expand_cache->nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->nodes.size()); - switch (expand_cache->target) { case SCULPT_EXPAND_TARGET_MASK: - BLI_task_parallel_range( - 0, expand_cache->nodes.size(), &data, sculpt_expand_mask_update_task_cb, &settings); + threading::parallel_for(expand_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_expand_mask_update_task(ss, expand_cache->nodes[i]); + } + }); break; case SCULPT_EXPAND_TARGET_FACE_SETS: sculpt_expand_face_sets_update(ss, expand_cache); break; case SCULPT_EXPAND_TARGET_COLORS: - BLI_task_parallel_range( - 0, expand_cache->nodes.size(), &data, sculpt_expand_colors_update_task_cb, &settings); + threading::parallel_for(expand_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_expand_colors_update_task(ss, expand_cache->nodes[i]); + } + }); break; } diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 8fe55b13a48..8cd027a1562 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -113,32 +113,27 @@ int ED_sculpt_face_sets_active_update_and_get(bContext *C, Object *ob, const flo /* Draw Face Sets Brush. */ -static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_draw_face_sets_brush_task(Object *ob, const Brush *brush, PBVHNode *node) { using namespace blender; - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); const Span positions( reinterpret_cast(SCULPT_mesh_deformed_positions_get(ss)), SCULPT_vertex_count_get(ss)); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); bool changed = false; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { @@ -196,37 +191,35 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; if (changed) { - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_FACE_SETS); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS); } } -static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_relax_face_sets_brush_task(Object *ob, + const Brush *brush, + const int iteration, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0); /* This operations needs a strength tweak as the relax deformation is too weak by default. */ - if (relax_face_sets && data->iteration < 2) { + if (relax_face_sets && iteration < 2) { bstrength *= 1.5f; } - const int thread_id = BLI_task_parallel_thread_id(tls); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); if (!sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -257,6 +250,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -268,25 +262,24 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, Span nod BKE_curvemapping_init(brush->curve); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); if (ss->cache->alt_smooth) { SCULPT_boundary_info_ensure(ob); for (int i = 0; i < 4; i++) { - data.iteration = i; - BLI_task_parallel_range( - 0, nodes.size(), &data, do_relax_face_sets_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_relax_face_sets_brush_task(ob, brush, i, nodes[i]); + } + }); } } else { - BLI_task_parallel_range(0, nodes.size(), &data, do_draw_face_sets_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_draw_face_sets_brush_task(ob, brush, nodes[i]); + } + }); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc index 67775d225dc..d0f6178f489 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc @@ -72,24 +72,22 @@ static EnumPropertyItem prop_color_filter_types[] = { {0, nullptr, 0, nullptr, nullptr}, }; -static void color_filter_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void color_filter_task(Object *ob, + const int mode, + const float filter_strength, + const float *filter_fill_color, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - - const int mode = data->filter_type; + SculptSession *ss = ob->sculpt; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COLOR); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->filter_cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->filter_cache->automasking, &automask_data, node); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); SCULPT_automasking_node_update(ss, &automask_data, &vd); @@ -98,7 +96,7 @@ static void color_filter_task_cb(void *__restrict userdata, float brightness, contrast, gain, delta, offset; float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; - fade *= data->filter_strength; + fade *= filter_strength; fade *= SCULPT_automasking_factor_get( ss->filter_cache->automasking, ss, vd.vertex, &automask_data); if (fade == 0.0f) { @@ -111,7 +109,7 @@ static void color_filter_task_cb(void *__restrict userdata, switch (mode) { case COLOR_FILTER_FILL: { float fill_color_rgba[4]; - copy_v3_v3(fill_color_rgba, data->filter_fill_color); + copy_v3_v3(fill_color_rgba, filter_fill_color); fill_color_rgba[3] = 1.0f; fade = clamp_f(fade, 0.0f, 1.0f); mul_v4_fl(fill_color_rgba, fade); @@ -223,7 +221,7 @@ static void color_filter_task_cb(void *__restrict userdata, SCULPT_vertex_color_set(ss, vd.vertex, final_color); } BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_update_color(data->nodes[n]); + BKE_pbvh_node_mark_update_color(node); } static void sculpt_color_presmooth_init(SculptSession *ss) @@ -269,7 +267,7 @@ static void sculpt_color_presmooth_init(SculptSession *ss) static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object *ob) { - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + using namespace blender; SculptSession *ss = ob->sculpt; const int mode = RNA_enum_get(op->ptr, "type"); @@ -283,20 +281,11 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object *ob) sculpt_color_presmooth_init(ss); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.filter_type = mode; - data.filter_strength = filter_strength; - data.filter_fill_color = fill_color; - - TaskParallelSettings settings; - BLI_parallel_range_settings_defaults(&settings); - - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, color_filter_task_cb, &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + color_filter_task(ob, mode, filter_strength, fill_color, ss->filter_cache->nodes[i]); + } + }); SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR); } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index aeef16ff2c7..89bc134f0a9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -60,16 +60,10 @@ static EnumPropertyItem prop_mask_filter_types[] = { {0, nullptr, 0, nullptr, nullptr}, }; -static void mask_filter_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void mask_filter_task(SculptSession *ss, const int mode, float *prev_mask, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; bool update = false; - const int mode = data->filter_type; float contrast = 0.0f; PBVHVertexIter vd; @@ -110,7 +104,7 @@ static void mask_filter_task_cb(void *__restrict userdata, case MASK_FILTER_GROW: max = 0.0f; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { - float vmask_f = data->prev_mask[ni.index]; + float vmask_f = prev_mask[ni.index]; if (vmask_f > max) { max = vmask_f; } @@ -121,7 +115,7 @@ static void mask_filter_task_cb(void *__restrict userdata, case MASK_FILTER_SHRINK: min = 1.0f; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { - float vmask_f = data->prev_mask[ni.index]; + float vmask_f = prev_mask[ni.index]; if (vmask_f < min) { min = vmask_f; } @@ -158,10 +152,10 @@ static void mask_filter_task_cb(void *__restrict userdata, static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); const Scene *scene = CTX_data_scene(C); - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; int filter_type = RNA_enum_get(op->ptr, "filter_type"); MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); @@ -203,16 +197,11 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) } } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = nodes; - data.filter_type = filter_type; - data.prev_mask = prev_mask; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, mask_filter_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mask_filter_task(ss, filter_type, prev_mask, nodes[i]); + } + }); if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { MEM_freeN(prev_mask); @@ -226,21 +215,18 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void SCULPT_mask_filter_smooth_apply(Sculpt *sd, +void SCULPT_mask_filter_smooth_apply(Sculpt * /*sd*/, Object *ob, Span nodes, const int smooth_iterations) { - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = nodes; - data.filter_type = MASK_FILTER_SMOOTH; - + using namespace blender; for (int i = 0; i < smooth_iterations; i++) { - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, mask_filter_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mask_filter_task(ob->sculpt, MASK_FILTER_SMOOTH, nullptr, nodes[i]); + } + }); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index bcff08e6d81..127358fe687 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -98,16 +98,6 @@ void SCULPT_filter_zero_disabled_axis_components(float r_v[3], FilterCache *filt SCULPT_filter_to_object_space(r_v, filter_cache); } -static void filter_cache_init_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) -{ - SculptThreadedTaskData *data = static_cast(userdata); - PBVHNode *node = data->nodes[i]; - - SCULPT_undo_push_node(data->ob, node, SculptUndoType(data->filter_undo_type)); -} - void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, @@ -116,6 +106,7 @@ void SCULPT_filter_cache_init(bContext *C, float area_normal_radius, float start_strength) { + using namespace blender; SculptSession *ss = ob->sculpt; PBVH *pbvh = ob->sculpt->pbvh; @@ -147,16 +138,9 @@ void SCULPT_filter_cache_init(bContext *C, BKE_pbvh_update_normals(ss->pbvh, nullptr); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.filter_undo_type = undo_type; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, filter_cache_init_task_cb, &settings); + for (const int i : ss->filter_cache->nodes.index_range()) { + SCULPT_undo_push_node(ob, ss->filter_cache->nodes[i], SculptUndoType(undo_type)); + } /* Setup orientation matrices. */ copy_m4_m4(ss->filter_cache->obmat, ob->object_to_world); @@ -207,7 +191,7 @@ void SCULPT_filter_cache_init(bContext *C, pbvh, [&](PBVHNode &node) { return SCULPT_search_sphere(&node, &search_data2); }); if (BKE_paint_brush(&sd->paint) && - SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, ss->filter_cache->initial_normal)) + SCULPT_pbvh_calc_area_normal(brush, ob, nodes, ss->filter_cache->initial_normal)) { copy_v3_v3(ss->last_normal, ss->filter_cache->initial_normal); } @@ -363,18 +347,15 @@ static bool sculpt_mesh_filter_is_continuous(eSculptMeshFilterType type) MESH_FILTER_RELAX_FACE_SETS); } -static void mesh_filter_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void mesh_filter_task(Object *ob, + const eSculptMeshFilterType filter_type, + const float filter_strength, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; - - const eSculptMeshFilterType filter_type = eSculptMeshFilterType(data->filter_type); + SculptSession *ss = ob->sculpt; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); /* When using the relax face sets meshes filter, * each 3 iterations, do a whole mesh relax to smooth the contents of the Face Set. */ @@ -382,7 +363,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, * boundaries. */ const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin(data->ob, ss, ss->filter_cache->automasking, &automask_data, node); + SCULPT_automasking_node_begin(ob, ss, ss->filter_cache->automasking, &automask_data, node); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { @@ -392,7 +373,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, float orig_co[3], val[3], avg[3], disp[3], disp2[3], transform[3][3], final_pos[3]; float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; - fade *= data->filter_strength; + fade *= filter_strength; fade *= SCULPT_automasking_factor_get( ss->filter_cache->automasking, ss, vd.vertex, &automask_data); @@ -674,25 +655,22 @@ static void mesh_filter_sharpen_init(SculptSession *ss, } } -static void mesh_filter_surface_smooth_displace_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void mesh_filter_surface_smooth_displace_task(Object *ob, + const float filter_strength, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->filter_cache->automasking, &automask_data, data->nodes[i]); + SCULPT_automasking_node_begin(ob, ss, ss->filter_cache->automasking, &automask_data, node); BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; - fade *= data->filter_strength; + fade *= filter_strength; fade *= SCULPT_automasking_factor_get( ss->filter_cache->automasking, ss, vd.vertex, &automask_data); if (fade == 0.0f) { @@ -759,6 +737,7 @@ static void sculpt_mesh_update_status_bar(bContext *C, wmOperator *op) static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -767,24 +746,19 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op) SCULPT_vertex_random_access_ensure(ss); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.filter_type = filter_type; - data.filter_strength = filter_strength; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, mesh_filter_task_cb, &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mesh_filter_task( + ob, eSculptMeshFilterType(filter_type), filter_strength, ss->filter_cache->nodes[i]); + } + }); if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { - BLI_task_parallel_range(0, - ss->filter_cache->nodes.size(), - &data, - mesh_filter_surface_smooth_displace_task_cb, - &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mesh_filter_surface_smooth_displace_task(ob, filter_strength, ss->filter_cache->nodes[i]); + } + }); } ss->filter_cache->iteration_count++; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 07e52a56c8d..c1843899663 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -242,127 +242,6 @@ struct SculptRakeData { float angle; }; -/** - * Generic thread data. The size of this struct has gotten a little out of hand; - * normally we would split it up, but it might be better to see if we can't eliminate it - * altogether after moving to C++ (where we'll be able to use lambdas). - */ -struct SculptThreadedTaskData { - bContext *C; - Sculpt *sd; - Object *ob; - const Brush *brush; - Span nodes; - - VPaint *vp; - WPaintData *wpd; - WeightPaintInfo *wpi; - unsigned int *lcol; - Mesh *me; - /* For passing generic params. */ - void *custom_data; - - /* Data specific to some callbacks. */ - - /* NOTE: even if only one or two of those are used at a time, - * keeping them separated, names help figuring out - * what it is, and memory overhead is ridiculous anyway. */ - float flippedbstrength; - float angle; - float strength; - bool smooth_mask; - bool has_bm_orco; - - SculptProjectVector *spvc; - float *offset; - float *grab_delta; - float *cono; - float *area_no; - float *area_no_sp; - float *area_co; - float (*mat)[4]; - float (*vertCos)[3]; - - /* When true, the displacement stored in the proxies will be applied to the original coordinates - * instead of to the current coordinates. */ - bool use_proxies_orco; - - /* X and Z vectors aligned to the stroke direction for operations where perpendicular vectors to - * the stroke direction are needed. */ - float (*stroke_xz)[3]; - - int filter_type; - float filter_strength; - float *filter_fill_color; - - bool use_area_cos; - bool use_area_nos; - - /* 0=towards view, 1=flipped */ - float (*area_cos)[3]; - float (*area_nos)[3]; - int *count_no; - int *count_co; - - bool any_vertex_sampled; - - float *wet_mix_sampled_color; - - float *prev_mask; - - float *pose_factor; - float *pose_initial_co; - int pose_chain_segment; - - float multiplane_scrape_angle; - float multiplane_scrape_planes[2][4]; - - float max_distance_squared; - float nearest_vertex_search_co[3]; - - /* Stabilized strength for the Clay Thumb brush. */ - float clay_strength; - - int mask_expand_update_it; - bool mask_expand_invert_mask; - bool mask_expand_use_normals; - bool mask_expand_keep_prev_mask; - bool mask_expand_create_face_set; - - float transform_mats[8][4][4]; - float elastic_transform_mat[4][4]; - float elastic_transform_pivot[3]; - float elastic_transform_pivot_init[3]; - float elastic_transform_radius; - - /* Boundary brush */ - float boundary_deform_strength; - - float cloth_time_step; - SculptClothSimulation *cloth_sim; - float *cloth_sim_initial_location; - float cloth_sim_radius; - - /* Mask By Color Tool */ - - float mask_by_color_threshold; - bool mask_by_color_invert; - bool mask_by_color_preserve_mask; - - /* Index of the vertex that is going to be used as a reference for the colors. */ - PBVHVertRef mask_by_color_vertex; - float *mask_by_color_floodfill; - - int face_set; - int filter_undo_type; - - int mask_init_mode; - int mask_init_seed; - - ThreadMutex mutex; - int iteration; -}; - /*************** Brush testing declarations ****************/ struct SculptBrushTest { float radius_squared; @@ -1595,7 +1474,6 @@ void SCULPT_relax_vertex(SculptSession *ss, bool SCULPT_pbvh_calc_area_normal(const Brush *brush, Object *ob, Span nodes, - bool use_threading, float r_area_no[3]); /** diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc b/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc index 7479c777c10..6ef7a43f96d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc @@ -74,15 +74,16 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op) ED_workspace_status_text(C, nullptr); } -static void sculpt_expand_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_expand_task(Object *ob, + const int update_it, + const bool mask_expand_use_normals, + const bool mask_expand_create_face_set, + const bool mask_expand_keep_prev_mask, + const bool mask_expand_invert_mask, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; - int update_it = data->mask_expand_update_it; PBVHVertRef active_vertex = SCULPT_active_vertex_get(ss); int active_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, active_vertex); @@ -92,7 +93,7 @@ static void sculpt_expand_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_ALL) { int vi = vd.index; float final_mask = *vd.mask; - if (data->mask_expand_use_normals) { + if (mask_expand_use_normals) { if (ss->filter_cache->normal_factor[active_vertex_i] < ss->filter_cache->normal_factor[vd.index]) { final_mask = 1.0f; @@ -111,7 +112,7 @@ static void sculpt_expand_task_cb(void *__restrict userdata, } } - if (data->mask_expand_create_face_set) { + if (mask_expand_create_face_set) { if (final_mask == 1.0f) { SCULPT_vertex_face_set_set(ss, vd.vertex, ss->filter_cache->new_face_set); face_sets_changed = true; @@ -120,11 +121,11 @@ static void sculpt_expand_task_cb(void *__restrict userdata, } else { - if (data->mask_expand_keep_prev_mask) { + if (mask_expand_keep_prev_mask) { final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask); } - if (data->mask_expand_invert_mask) { + if (mask_expand_invert_mask) { final_mask = 1.0f - final_mask; } @@ -137,12 +138,13 @@ static void sculpt_expand_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_end; if (face_sets_changed) { - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_FACE_SETS); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS); } } static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event) { + using namespace blender; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -261,20 +263,24 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * ss->face_sets[i] = ss->filter_cache->prev_face_set[i]; } } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.mask_expand_update_it = mask_expand_update_it; - data.mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"); - data.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"); - data.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); - data.mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, sculpt_expand_task_cb, &settings); + const bool use_normals = RNA_boolean_get(op->ptr, "use_normals"); + const bool invert_mask = RNA_boolean_get(op->ptr, "invert"); + const bool keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); + const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); + + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_expand_task(ob, + mask_expand_update_it, + use_normals, + create_face_set, + keep_prev_mask, + invert_mask, + ss->filter_cache->nodes[i]); + } + }); + ss->filter_cache->mask_update_current_it = mask_expand_update_it; } @@ -330,6 +336,7 @@ static bool mask_expand_floodfill_cb( static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + using namespace blender; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -438,20 +445,20 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent MEM_SAFE_FREE(ss->filter_cache->edge_factor); } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.mask_expand_update_it = 0; - data.mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"); - data.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"); - data.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); - data.mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); + const bool invert_mask = RNA_boolean_get(op->ptr, "invert"); + const bool keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, sculpt_expand_task_cb, &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_expand_task(ob, + 0, + use_normals, + create_face_set, + keep_prev_mask, + invert_mask, + ss->filter_cache->nodes[i]); + } + }); const char *status_str = TIP_( "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: " diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc index a8991fa35ec..595f03ad017 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc @@ -73,17 +73,11 @@ static EnumPropertyItem prop_sculpt_mask_init_mode_types[] = { {0, nullptr, 0, nullptr, nullptr}, }; -static void mask_init_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void mask_init_task(Object *ob, const int mode, const int seed, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; - const int mode = data->mask_init_mode; - const int seed = data->mask_init_seed; - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_MASK); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { switch (mode) { case SCULPT_MASK_INIT_RANDOM_PER_VERTEX: @@ -100,11 +94,12 @@ static void mask_init_task_cb(void *__restrict userdata, } } BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_update_mask(data->nodes[i]); + BKE_pbvh_node_mark_update_mask(node); } static int sculpt_mask_init_exec(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -129,15 +124,13 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) SCULPT_topology_islands_ensure(ob); } - SculptThreadedTaskData data{}; - data.ob = ob; - data.nodes = nodes; - data.mask_init_mode = mode; - data.mask_init_seed = PIL_check_seconds_timer(); + const int mask_init_seed = PIL_check_seconds_timer(); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, mask_init_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + mask_init_task(ob, mode, mask_init_seed, nodes[i]); + } + }); multires_stitch_grids(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc index 8e45ff981b4..42136bae2e2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc @@ -35,23 +35,20 @@ struct MultiplaneScrapeSampleData { int area_count[2]; }; -static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void calc_multiplane_scrape_surface_task(Object *ob, + const Brush *brush, + const float (*mat)[4], + PBVHNode *node, + MultiplaneScrapeSampleData *mssd) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - MultiplaneScrapeSampleData *mssd = static_cast( - tls->userdata_chunk); - float(*mat)[4] = data->mat; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + const int thread_id = BLI_task_parallel_thread_id(nullptr); /* Apply the brush normal radius to the test before sampling. */ float test_radius = sqrtf(test.radius_squared); @@ -59,10 +56,9 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, test.radius_squared = test_radius * test_radius; AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -101,51 +97,30 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, } } -static void calc_multiplane_scrape_surface_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) +static void do_multiplane_scrape_brush_task(Object *ob, + const Brush *brush, + const float (*mat)[4], + const float (*scrape_planes)[4], + const float angle, + PBVHNode *node) { - MultiplaneScrapeSampleData *join = static_cast(chunk_join); - MultiplaneScrapeSampleData *mssd = static_cast(chunk); - - add_v3_v3(join->area_cos[0], mssd->area_cos[0]); - add_v3_v3(join->area_cos[1], mssd->area_cos[1]); - - add_v3_v3(join->area_nos[0], mssd->area_nos[0]); - add_v3_v3(join->area_nos[1], mssd->area_nos[1]); - - join->area_count[0] += mssd->area_count[0]; - join->area_count[1] += mssd->area_count[1]; -} - -static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) -{ - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; - float(*mat)[4] = data->mat; - float(*scrape_planes)[4] = data->multiplane_scrape_planes; - - float angle = data->multiplane_scrape_angle; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; float(*proxy)[3]; const float bstrength = fabsf(ss->cache->bstrength); - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -215,6 +190,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -278,23 +254,29 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span if (brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) { /* Sample the individual normal and area center of the two areas at both sides of the cursor. */ - SculptThreadedTaskData sample_data{}; - sample_data.sd = nullptr; - sample_data.ob = ob; - sample_data.brush = brush; - sample_data.nodes = nodes; - sample_data.mat = mat; + const MultiplaneScrapeSampleData mssd = threading::parallel_reduce( + nodes.index_range(), + 1, + MultiplaneScrapeSampleData{}, + [&](const IndexRange range, MultiplaneScrapeSampleData mssd) { + for (const int i : range) { + calc_multiplane_scrape_surface_task(ob, brush, mat, nodes[i], &mssd); + } + return mssd; + }, + [](const MultiplaneScrapeSampleData &a, const MultiplaneScrapeSampleData &b) { + MultiplaneScrapeSampleData joined = a; - MultiplaneScrapeSampleData mssd = {{{0}}}; + add_v3_v3v3(joined.area_cos[0], a.area_cos[0], b.area_cos[0]); + add_v3_v3v3(joined.area_cos[1], a.area_cos[1], b.area_cos[1]); - TaskParallelSettings sample_settings; - BKE_pbvh_parallel_range_settings(&sample_settings, true, nodes.size()); - sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce; - sample_settings.userdata_chunk = &mssd; - sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData); + add_v3_v3v3(joined.area_nos[0], a.area_nos[0], b.area_nos[0]); + add_v3_v3v3(joined.area_nos[1], a.area_nos[1], b.area_nos[1]); - BLI_task_parallel_range( - 0, nodes.size(), &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings); + joined.area_count[0] = a.area_count[0] + b.area_count[0]; + joined.area_count[1] = a.area_count[1] + b.area_count[1]; + return joined; + }); float sampled_plane_normals[2][3]; float sampled_plane_co[2][3]; @@ -348,14 +330,6 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span } } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.mat = mat; - data.multiplane_scrape_angle = ss->cache->multiplane_scrape_angle; - /* Calculate the final left and right scrape planes. */ float plane_no[3]; float plane_no_rot[3]; @@ -363,24 +337,28 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span float mat_inv[4][4]; invert_m4_m4(mat_inv, mat); + float multiplane_scrape_planes[2][4]; + mul_v3_mat3_m4v3(plane_no, mat, area_no); rotate_v3_v3v3fl( plane_no_rot, plane_no, y_axis, DEG2RADF(-ss->cache->multiplane_scrape_angle * 0.5f)); mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot); normalize_v3(plane_no); - plane_from_point_normal_v3(data.multiplane_scrape_planes[1], area_co, plane_no); + plane_from_point_normal_v3(multiplane_scrape_planes[1], area_co, plane_no); mul_v3_mat3_m4v3(plane_no, mat, area_no); rotate_v3_v3v3fl( plane_no_rot, plane_no, y_axis, DEG2RADF(ss->cache->multiplane_scrape_angle * 0.5f)); mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot); normalize_v3(plane_no); - plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no); + plane_from_point_normal_v3(multiplane_scrape_planes[0], area_co, plane_no); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range( - 0, nodes.size(), &data, do_multiplane_scrape_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_multiplane_scrape_brush_task( + ob, brush, mat, multiplane_scrape_planes, ss->cache->multiplane_scrape_angle, nodes[i]); + } + }); } void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 679fa432f4c..fd9d07500e7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -730,23 +730,21 @@ struct MaskByColorContiguousFloodFillData { float initial_color[3]; }; -static void do_mask_by_color_contiguous_update_nodes_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_mask_by_color_contiguous_update_node(Object *ob, + const float *mask_by_color_floodfill, + const bool invert, + const bool preserve_mask, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); bool update_node = false; - const bool invert = data->mask_by_color_invert; - const bool preserve_mask = data->mask_by_color_preserve_mask; - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { const float current_mask = *vd.mask; - const float new_mask = data->mask_by_color_floodfill[vd.index]; + const float new_mask = mask_by_color_floodfill[vd.index]; *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); if (current_mask == *vd.mask) { continue; @@ -755,11 +753,11 @@ static void do_mask_by_color_contiguous_update_nodes_cb(void *__restrict userdat } BKE_pbvh_vertex_iter_end; if (update_node) { - BKE_pbvh_node_mark_update_mask(data->nodes[n]); + BKE_pbvh_node_mark_update_mask(node); } } -static bool sculpt_mask_by_color_contiguous_floodfill_cb( +static bool sculpt_mask_by_color_contiguous_floodfill( SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) { int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); @@ -790,6 +788,7 @@ static void sculpt_mask_by_color_contiguous(Object *object, const bool invert, const bool preserve_mask) { + using namespace blender; SculptSession *ss = object->sculpt; const int totvert = SCULPT_vertex_count_get(ss); @@ -815,47 +814,38 @@ static void sculpt_mask_by_color_contiguous(Object *object, copy_v3_v3(ffd.initial_color, color); - SCULPT_floodfill_execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill_cb, &ffd); + SCULPT_floodfill_execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill, &ffd); SCULPT_floodfill_free(&flood); Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); - SculptThreadedTaskData data{}; - data.ob = object; - data.nodes = nodes; - data.mask_by_color_floodfill = new_mask; - data.mask_by_color_vertex = vertex; - data.mask_by_color_threshold = threshold; - data.mask_by_color_invert = invert; - data.mask_by_color_preserve_mask = preserve_mask; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range( - 0, nodes.size(), &data, do_mask_by_color_contiguous_update_nodes_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_mask_by_color_contiguous_update_node(object, new_mask, invert, preserve_mask, nodes[i]); + } + }); MEM_freeN(new_mask); } -static void do_mask_by_color_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_mask_by_color_task(Object *ob, + const float threshold, + const bool invert, + const bool preserve_mask, + const PBVHVertRef mask_by_color_vertex, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; - SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); bool update_node = false; - const float threshold = data->mask_by_color_threshold; - const bool invert = data->mask_by_color_invert; - const bool preserve_mask = data->mask_by_color_preserve_mask; float active_color[4]; - SCULPT_vertex_color_get(ss, data->mask_by_color_vertex, active_color); + SCULPT_vertex_color_get(ss, mask_by_color_vertex, active_color); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { float col[4]; SCULPT_vertex_color_get(ss, vd.vertex, col); @@ -870,7 +860,7 @@ static void do_mask_by_color_task_cb(void *__restrict userdata, } BKE_pbvh_vertex_iter_end; if (update_node) { - BKE_pbvh_node_mark_update_mask(data->nodes[n]); + BKE_pbvh_node_mark_update_mask(node); } } @@ -880,21 +870,16 @@ static void sculpt_mask_by_color_full_mesh(Object *object, const bool invert, const bool preserve_mask) { + using namespace blender; SculptSession *ss = object->sculpt; Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); - SculptThreadedTaskData data{}; - data.ob = object; - data.nodes = nodes; - data.mask_by_color_vertex = vertex; - data.mask_by_color_threshold = threshold; - data.mask_by_color_invert = invert; - data.mask_by_color_preserve_mask = preserve_mask; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_mask_by_color_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_mask_by_color_task(object, threshold, invert, preserve_mask, vertex, nodes[i]); + } + }); } static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -1004,36 +989,24 @@ enum CavityBakeSettingsSource { AUTOMASK_SETTINGS_BRUSH }; -struct AutomaskBakeTaskData { - SculptSession *ss; - AutomaskingCache *automasking; - Span nodes; - CavityBakeMixMode mode; - float factor; - Object *ob; -}; - -static void sculpt_bake_cavity_exec_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_bake_cavity_exec_task(Object *ob, + AutomaskingCache *automasking, + const CavityBakeMixMode mode, + const float factor, + PBVHNode *node) { - AutomaskBakeTaskData *tdata = static_cast(userdata); - SculptSession *ss = tdata->ss; - PBVHNode *node = tdata->nodes[n]; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; - const CavityBakeMixMode mode = tdata->mode; - const float factor = tdata->factor; - SCULPT_undo_push_node(tdata->ob, node, SCULPT_UNDO_MASK); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin(tdata->ob, ss, tdata->automasking, &automask_data, node); + SCULPT_automasking_node_begin(ob, ss, automasking, &automask_data, node); BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_automasking_node_update(ss, &automask_data, &vd); - float automask = SCULPT_automasking_factor_get( - tdata->automasking, ss, vd.vertex, &automask_data); + float automask = SCULPT_automasking_factor_get(automasking, ss, vd.vertex, &automask_data); float mask; switch (mode) { @@ -1068,6 +1041,7 @@ static void sculpt_bake_cavity_exec_task_cb(void *__restrict userdata, static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) { + using namespace blender; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -1087,10 +1061,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); - AutomaskBakeTaskData tdata; - - /* Set up automasking settings. - */ + /* Set up automasking settings. */ Sculpt sd2 = *sd; CavityBakeSettingsSource src = (CavityBakeSettingsSource)RNA_enum_get(op->ptr, @@ -1150,18 +1121,15 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) SCULPT_stroke_id_next(ob); - tdata.ob = ob; - tdata.mode = mode; - tdata.factor = factor; - tdata.ss = ss; - tdata.nodes = nodes; - tdata.automasking = SCULPT_automasking_cache_init(&sd2, &brush2, ob); + AutomaskingCache *automasking = SCULPT_automasking_cache_init(&sd2, &brush2, ob); - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &tdata, sculpt_bake_cavity_exec_task_cb, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_bake_cavity_exec_task(ob, automasking, mode, factor, nodes[i]); + } + }); - SCULPT_automasking_cache_free(tdata.automasking); + SCULPT_automasking_cache_free(automasking); BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask); SCULPT_undo_push_end(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.cc b/source/blender/editors/sculpt_paint/sculpt_paint_color.cc index 10b88bfc73e..32bdfccec32 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.cc @@ -35,27 +35,22 @@ using blender::Vector; -static void do_color_smooth_task_cb_exec(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_color_smooth_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -84,27 +79,27 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_paint_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_paint_brush_task(Object *ob, + const Brush *brush, + const float (*mat)[4], + float *wet_mix_sampled_color, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = fabsf(ss->cache->bstrength); PBVHVertexIter vd; PBVHColorBufferNode *color_buffer; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COLOR); - color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]); + color_buffer = BKE_pbvh_node_color_buffer_get(node); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); float brush_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; @@ -115,8 +110,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, IMB_colormanagement_srgb_to_scene_linear_v3(brush_color, brush_color); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); if (brush->flag & BRUSH_USE_GRADIENT) { switch (brush->gradient_stroke_mode) { @@ -136,14 +130,14 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, } } - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); bool affect_vertex = false; float distance_to_stroke_location = 0.0f; if (brush->tip_roundness < 1.0f) { affect_vertex = SCULPT_brush_test_cube( - &test, vd.co, data->mat, brush->tip_roundness, brush->tip_scale_x); + &test, vd.co, mat, brush->tip_roundness, brush->tip_scale_x); distance_to_stroke_location = ss->cache->radius * test.dist; } else { @@ -185,7 +179,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, float buffer_color[4]; mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); - mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(wet_mix_color, wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); /* Interpolate with the wet_mix color for wet paint mixing. */ blend_color_interpolate_float( @@ -207,28 +201,26 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -struct SampleWetPaintTLSData { +struct SampleWetPaintData { int tot_samples; float color[4]; }; -static void do_sample_wet_paint_task_cb(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_sample_wet_paint_task(SculptSession *ss, + const Brush *brush, + PBVHNode *node, + SampleWetPaintData *swptd) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - SampleWetPaintTLSData *swptd = static_cast(tls->userdata_chunk); PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); - test.radius *= data->brush->wet_paint_radius_factor; + test.radius *= brush->wet_paint_radius_factor; test.radius_squared = test.radius * test.radius; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -242,23 +234,13 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void sample_wet_paint_reduce(const void *__restrict /*userdata*/, - void *__restrict chunk_join, - void *__restrict chunk) -{ - SampleWetPaintTLSData *join = static_cast(chunk_join); - SampleWetPaintTLSData *swptd = static_cast(chunk); - - join->tot_samples += swptd->tot_samples; - add_v4_v4(join->color, swptd->color); -} - void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings, Sculpt *sd, Object *ob, Span nodes, Span texnodes) { + using namespace blender; if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) { SCULPT_do_paint_brush_image(paint_mode_settings, sd, ob, texnodes); return; @@ -294,16 +276,11 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings, /* Smooth colors mode. */ if (ss->cache->alt_smooth) { - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.mat = mat; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_color_smooth_task_cb_exec, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_color_smooth_task(ob, brush, nodes[i]); + } + }); return; } @@ -312,23 +289,22 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings, /* Wet paint color sampling. */ float wet_color[4] = {0.0f}; if (ss->cache->paint_brush.wet_mix > 0.0f) { - SculptThreadedTaskData task_data{}; - task_data.sd = sd; - task_data.ob = ob; - task_data.nodes = nodes; - task_data.brush = brush; - - SampleWetPaintTLSData swptd; - swptd.tot_samples = 0; - zero_v4(swptd.color); - - TaskParallelSettings settings_sample; - BKE_pbvh_parallel_range_settings(&settings_sample, true, nodes.size()); - settings_sample.func_reduce = sample_wet_paint_reduce; - settings_sample.userdata_chunk = &swptd; - settings_sample.userdata_chunk_size = sizeof(SampleWetPaintTLSData); - BLI_task_parallel_range( - 0, nodes.size(), &task_data, do_sample_wet_paint_task_cb, &settings_sample); + const SampleWetPaintData swptd = threading::parallel_reduce( + nodes.index_range(), + 1, + SampleWetPaintData{}, + [&](const IndexRange range, SampleWetPaintData swptd) { + for (const int i : range) { + do_sample_wet_paint_task(ss, brush, nodes[i], &swptd); + } + return swptd; + }, + [](const SampleWetPaintData &a, const SampleWetPaintData &b) { + SampleWetPaintData joined{}; + joined.tot_samples = a.tot_samples + b.tot_samples; + add_v4_v4v4(joined.color, a.color, b.color); + return joined; + }); if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) { copy_v4_v4(wet_color, swptd.color); @@ -347,35 +323,24 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings, } } - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.wet_mix_sampled_color = wet_color; - data.mat = mat; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_paint_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_paint_brush_task(ob, brush, mat, wet_color, nodes[i]); + } + }); } -static void do_smear_brush_task_cb_exec(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_smear_brush_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; PBVHVertexIter vd; SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); float brush_delta[3]; @@ -387,10 +352,9 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, } AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -514,22 +478,20 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_smear_store_prev_colors_task(SculptSession *ss, + PBVHNode *node, + float (*prev_colors)[4]) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_vertex_color_get(ss, vd.vertex, ss->cache->prev_colors[vd.index]); + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { + SCULPT_vertex_color_get(ss, vd.vertex, prev_colors[vd.index]); } BKE_pbvh_vertex_iter_end; } void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; @@ -550,23 +512,25 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, Span nodes) BKE_curvemapping_init(brush->curve); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - /* Smooth colors mode. */ if (ss->cache->alt_smooth) { - BLI_task_parallel_range(0, nodes.size(), &data, do_color_smooth_task_cb_exec, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_color_smooth_task(ob, brush, nodes[i]); + } + }); } else { /* Smear mode. */ - BLI_task_parallel_range( - 0, nodes.size(), &data, do_smear_store_prev_colors_task_cb_exec, &settings); - BLI_task_parallel_range(0, nodes.size(), &data, do_smear_brush_task_cb_exec, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_smear_store_prev_colors_task(ss, nodes[i], ss->cache->prev_colors); + } + }); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_smear_brush_task(ob, brush, nodes[i]); + } + }); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index 5a8d2a3a690..fc4d2a8d18e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -137,27 +137,22 @@ static void pose_solve_scale_chain(SculptPoseIKChain *ik_chain, const float scal } } -static void do_pose_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void do_pose_brush_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; + SculptSession *ss = ob->sculpt; SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain; SculptPoseIKChainSegment *segments = ik_chain->segments; - const Brush *brush = data->brush; PBVHVertexIter vd; float disp[3], new_co[3]; float final_pos[3]; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); SCULPT_automasking_node_update(ss, &automask_data, &vd); @@ -203,35 +198,36 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -struct PoseGrowFactorTLSData { +struct PoseGrowFactorData { float pos_avg[3]; int pos_count; }; -static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void pose_brush_grow_factor_task(Object *ob, + const float pose_initial_co[3], + const float *prev_mask, + float *pose_factor, + PBVHNode *node, + PoseGrowFactorData *gftd) { - SculptThreadedTaskData *data = static_cast(userdata); - PoseGrowFactorTLSData *gftd = static_cast(tls->userdata_chunk); - SculptSession *ss = data->ob->sculpt; - const char symm = SCULPT_mesh_symmetry_xyz_get(data->ob); + SculptSession *ss = ob->sculpt; + const char symm = SCULPT_mesh_symmetry_xyz_get(ob); PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SculptVertexNeighborIter ni; float max = 0.0f; /* Grow the factor. */ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { - float vmask_f = data->prev_mask[ni.index]; + float vmask_f = prev_mask[ni.index]; max = MAX2(vmask_f, max); } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); /* Keep the count of the vertices that where added to the factors in this grow iteration. */ - if (max > data->prev_mask[vd.index]) { - data->pose_factor[vd.index] = max; - if (SCULPT_check_vertex_pivot_symmetry(vd.co, data->pose_initial_co, symm)) { + if (max > prev_mask[vd.index]) { + pose_factor[vd.index] = max; + if (SCULPT_check_vertex_pivot_symmetry(vd.co, pose_initial_co, symm)) { add_v3_v3(gftd->pos_avg, vd.co); gftd->pos_count++; } @@ -245,16 +241,15 @@ static void pose_brush_grow_factor_reduce(const void *__restrict /*userdata*/, void *__restrict chunk_join, void *__restrict chunk) { - PoseGrowFactorTLSData *join = static_cast(chunk_join); - PoseGrowFactorTLSData *gftd = static_cast(chunk); + PoseGrowFactorData *join = static_cast(chunk_join); + PoseGrowFactorData *gftd = static_cast(chunk); add_v3_v3(join->pos_avg, gftd->pos_avg); join->pos_count += gftd->pos_count; } /* Grow the factor until its boundary is near to the offset pose origin or outside the target * distance. */ -static void sculpt_pose_grow_pose_factor(Sculpt *sd, - Object *ob, +static void sculpt_pose_grow_pose_factor(Object *ob, SculptSession *ss, float pose_origin[3], float pose_target[3], @@ -262,35 +257,40 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, float *r_pose_origin, float *pose_factor) { + using namespace blender; PBVH *pbvh = ob->sculpt->pbvh; Vector nodes = blender::bke::pbvh::search_gather(pbvh, {}); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = nodes; - data.pose_factor = pose_factor; - - data.pose_initial_co = pose_target; - TaskParallelSettings settings; - PoseGrowFactorTLSData gftd; + PoseGrowFactorData gftd; gftd.pos_count = 0; zero_v3(gftd.pos_avg); - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - settings.func_reduce = pose_brush_grow_factor_reduce; - settings.userdata_chunk = &gftd; - settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData); bool grow_next_iteration = true; float prev_len = FLT_MAX; - data.prev_mask = static_cast( + float *prev_mask = static_cast( MEM_malloc_arrayN(SCULPT_vertex_count_get(ss), sizeof(float), __func__)); while (grow_next_iteration) { zero_v3(gftd.pos_avg); gftd.pos_count = 0; - memcpy(data.prev_mask, pose_factor, SCULPT_vertex_count_get(ss) * sizeof(float)); - BLI_task_parallel_range(0, nodes.size(), &data, pose_brush_grow_factor_task_cb_ex, &settings); + memcpy(prev_mask, pose_factor, SCULPT_vertex_count_get(ss) * sizeof(float)); + + gftd = threading::parallel_reduce( + nodes.index_range(), + 1, + gftd, + [&](const IndexRange range, PoseGrowFactorData gftd) { + for (const int i : range) { + pose_brush_grow_factor_task(ob, pose_target, prev_mask, pose_factor, nodes[i], &gftd); + } + return gftd; + }, + [](const PoseGrowFactorData &a, const PoseGrowFactorData &b) { + PoseGrowFactorData joined; + add_v3_v3v3(joined.pos_avg, a.pos_avg, b.pos_avg); + joined.pos_count = a.pos_count + b.pos_count; + return joined; + }); if (gftd.pos_count != 0) { mul_v3_fl(gftd.pos_avg, 1.0f / float(gftd.pos_count)); @@ -305,7 +305,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, } else { grow_next_iteration = false; - memcpy(pose_factor, data.prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float)); + memcpy(pose_factor, prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float)); } } else { @@ -321,7 +321,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, if (r_pose_origin) { copy_v3_v3(r_pose_origin, gftd.pos_avg); } - memcpy(pose_factor, data.prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float)); + memcpy(pose_factor, prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float)); } } } @@ -332,7 +332,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, grow_next_iteration = false; } } - MEM_freeN(data.prev_mask); + MEM_freeN(prev_mask); } static bool sculpt_pose_brush_is_vertex_inside_brush_radius(const float vertex[3], @@ -574,29 +574,25 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd, */ if (pose_offset != 0.0f && r_pose_factor) { sculpt_pose_grow_pose_factor( - sd, ob, ss, fdata.pose_origin, fdata.pose_origin, 0, nullptr, r_pose_factor); + ob, ss, fdata.pose_origin, fdata.pose_origin, 0, nullptr, r_pose_factor); } } -static void pose_brush_init_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict /*tls*/) +static void pose_brush_init_task(SculptSession *ss, float *pose_factor, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SculptVertexNeighborIter ni; float avg = 0.0f; int total = 0; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { - avg += data->pose_factor[ni.index]; + avg += pose_factor[ni.index]; total++; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { - data->pose_factor[vd.index] = avg / total; + pose_factor[vd.index] = avg / total; } } BKE_pbvh_vertex_iter_end; @@ -705,8 +701,7 @@ static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd, for (int i = 1; i < ik_chain->tot_segments; i++) { /* Grow the factors to get the new segment origin. */ - sculpt_pose_grow_pose_factor(sd, - ob, + sculpt_pose_grow_pose_factor(ob, ss, nullptr, next_chain_segment_target, @@ -979,27 +974,24 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br) { + using namespace blender; PBVH *pbvh = ob->sculpt->pbvh; Vector nodes = blender::bke::pbvh::search_gather(pbvh, {}); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = br; - data.nodes = nodes; - /* Init the IK chain that is going to be used to deform the vertices. */ ss->cache->pose_ik_chain = SCULPT_pose_ik_chain_init( sd, ob, ss, br, ss->cache->true_location, ss->cache->radius); /* Smooth the weights of each segment for cleaner deformation. */ for (int ik = 0; ik < ss->cache->pose_ik_chain->tot_segments; ik++) { - data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights; + float *pose_factor = ss->cache->pose_ik_chain->segments[ik].weights; for (int i = 0; i < br->pose_smooth_iterations; i++) { - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, pose_brush_init_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + pose_brush_init_task(ss, pose_factor, nodes[i]); + } + }); } } } @@ -1129,6 +1121,7 @@ static void sculpt_pose_align_pivot_local_space(float r_mat[4][4], void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); @@ -1212,15 +1205,11 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, Span nodes) } } - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_pose_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_pose_brush_task(ob, brush, nodes[i]); + } + }); } void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain) diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index 446520a6c89..40074ef50a8 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -177,14 +177,12 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], PBVHVertR } } -static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict tls) +static void do_enhance_details_brush_task(Object *ob, + Sculpt *sd, + const Brush *brush, + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - Sculpt *sd = data->sd; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; @@ -193,14 +191,13 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -231,6 +228,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, static void SCULPT_enhance_details_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -251,27 +249,21 @@ static void SCULPT_enhance_details_brush(Sculpt *sd, Object *ob, Span(userdata); - SculptSession *ss = data->ob->sculpt; - Sculpt *sd = data->sd; - const Brush *brush = data->brush; - const bool smooth_mask = data->smooth_mask; - float bstrength = data->strength; + SculptSession *ss = ob->sculpt; PBVHVertexIter vd; @@ -279,14 +271,13 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); + ss, &test, brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -327,6 +318,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, void SCULPT_smooth( Sculpt *sd, Object *ob, Span nodes, float bstrength, const bool smooth_mask) { + using namespace blender; SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -345,18 +337,11 @@ void SCULPT_smooth( for (iteration = 0; iteration <= count; iteration++) { const float strength = (iteration != count) ? 1.0f : last; - - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - data.smooth_mask = smooth_mask; - data.strength = strength; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); - BLI_task_parallel_range(0, nodes.size(), &data, do_smooth_brush_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_smooth_brush_task(ob, sd, brush, smooth_mask, strength, nodes[i]); + } + }); } } @@ -430,12 +415,9 @@ void SCULPT_surface_smooth_displace_step(SculptSession *ss, } } -static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( - void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) +static void do_surface_smooth_brush_laplacian_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; float alpha = brush->surface_smooth_shape_preservation; @@ -444,15 +426,14 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; @@ -482,12 +463,9 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( BKE_pbvh_vertex_iter_end; } -static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( - void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) +static void do_surface_smooth_brush_displace_task(Object *ob, const Brush *brush, PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - const Brush *brush = data->brush; + SculptSession *ss = ob->sculpt; const float bstrength = ss->cache->bstrength; const float beta = brush->surface_smooth_current_vertex; @@ -495,13 +473,12 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &test, data->brush->falloff_shape); - const int thread_id = BLI_task_parallel_thread_id(tls); + ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(nullptr); AutomaskingNodeData automask_data; - SCULPT_automasking_node_begin( - data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); + SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, node); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; } @@ -526,21 +503,21 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, Span nodes) { + using namespace blender; Brush *brush = BKE_paint_brush(&sd->paint); - /* Threaded loop over nodes. */ - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.brush = brush; - data.nodes = nodes; - TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, nodes.size()); for (int i = 0; i < brush->surface_smooth_iterations; i++) { - BLI_task_parallel_range( - 0, nodes.size(), &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings); - BLI_task_parallel_range( - 0, nodes.size(), &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_surface_smooth_brush_laplacian_task(ob, brush, nodes[i]); + } + }); + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + do_surface_smooth_brush_displace_task(ob, brush, nodes[i]); + } + }); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.cc b/source/blender/editors/sculpt_paint/sculpt_transform.cc index 4bf3bed078c..4bae752602b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.cc +++ b/source/blender/editors/sculpt_paint/sculpt_transform.cc @@ -137,21 +137,16 @@ static void sculpt_transform_matrices_init(SculptSession *ss, } } -static void sculpt_transform_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_transform_task(Object *ob, const float transform_mats[8][4][4], PBVHNode *node) { - - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); PBVHVertexIter vd; - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); float *start_co; @@ -170,7 +165,7 @@ static void sculpt_transform_task_cb(void *__restrict userdata, } copy_v3_v3(transformed_co, start_co); - mul_m4_v3(data->transform_mats[int(symm_area)], transformed_co); + mul_m4_v3(transform_mats[int(symm_area)], transformed_co); sub_v3_v3v3(disp, transformed_co, start_co); mul_v3_fl(disp, 1.0f - fade); add_v3_v3v3(vd.co, start_co, disp); @@ -184,40 +179,38 @@ static void sculpt_transform_task_cb(void *__restrict userdata, BKE_pbvh_node_mark_update(node); } -static void sculpt_transform_all_vertices(Sculpt *sd, Object *ob) +static void sculpt_transform_all_vertices(Object *ob) { + using namespace blender; SculptSession *ss = ob->sculpt; const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - + float transform_mats[8][4][4]; sculpt_transform_matrices_init( - ss, symm, ss->filter_cache->transform_displacement_mode, data.transform_mats); + ss, symm, ss->filter_cache->transform_displacement_mode, transform_mats); /* Regular transform applies all symmetry passes at once as it is split by symmetry areas * (each vertex can only be transformed once by the transform matrix of its area). */ - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, sculpt_transform_task_cb, &settings); + threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_transform_task(ob, transform_mats, ss->filter_cache->nodes[i]); + } + }); } -static void sculpt_elastic_transform_task_cb(void *__restrict userdata, - const int i, - const TaskParallelTLS *__restrict /*tls*/) +static void sculpt_elastic_transform_task(Object *ob, + const float transform_radius, + const float elastic_transform_mat[4][4], + const float elastic_transform_pivot[3], + PBVHNode *node) { - SculptThreadedTaskData *data = static_cast(userdata); - SculptSession *ss = data->ob->sculpt; - PBVHNode *node = data->nodes[i]; + SculptSession *ss = ob->sculpt; - float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[i])->co; + float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, node)->co; SculptOrigVertData orig_data; - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS); + SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS); KelvinletParams params; /* TODO(pablodp606): These parameters can be exposed if needed as transform strength and volume @@ -226,10 +219,9 @@ static void sculpt_elastic_transform_task_cb(void *__restrict userdata, const float force = 1.0f; const float shear_modulus = 1.0f; const float poisson_ratio = 0.4f; - BKE_kelvinlet_init_params( - ¶ms, data->elastic_transform_radius, force, shear_modulus, poisson_ratio); + BKE_kelvinlet_init_params(¶ms, transform_radius, force, shear_modulus, poisson_ratio); - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS); + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { @@ -239,11 +231,11 @@ static void sculpt_elastic_transform_task_cb(void *__restrict userdata, copy_v3_v3(orig_co, orig_data.co); copy_v3_v3(transformed_co, vd.co); - mul_m4_v3(data->elastic_transform_mat, transformed_co); + mul_m4_v3(elastic_transform_mat, transformed_co); sub_v3_v3v3(disp, transformed_co, vd.co); float final_disp[3]; - BKE_kelvinlet_grab_triscale(final_disp, ¶ms, vd.co, data->elastic_transform_pivot, disp); + BKE_kelvinlet_grab_triscale(final_disp, ¶ms, vd.co, elastic_transform_pivot, disp); mul_v3_fl(final_disp, 20.0f * (1.0f - fade)); copy_v3_v3(proxy[vd.i], final_disp); @@ -259,20 +251,16 @@ static void sculpt_elastic_transform_task_cb(void *__restrict userdata, static void sculpt_transform_radius_elastic(Sculpt *sd, Object *ob, const float transform_radius) { + using namespace blender; SculptSession *ss = ob->sculpt; BLI_assert(ss->filter_cache->transform_displacement_mode == SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL); const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); - SculptThreadedTaskData data{}; - data.sd = sd; - data.ob = ob; - data.nodes = ss->filter_cache->nodes; - data.elastic_transform_radius = transform_radius; - + float transform_mats[8][4][4]; sculpt_transform_matrices_init( - ss, symm, ss->filter_cache->transform_displacement_mode, data.transform_mats); + ss, symm, ss->filter_cache->transform_displacement_mode, transform_mats); TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size()); @@ -281,13 +269,24 @@ static void sculpt_transform_radius_elastic(Sculpt *sd, Object *ob, const float * displacement proxies as all vertices are modified by all symmetry passes. */ for (ePaintSymmetryFlags symmpass = PAINT_SYMM_NONE; symmpass <= symm; symmpass++) { if (SCULPT_is_symmetry_iteration_valid(symmpass, symm)) { - flip_v3_v3(data.elastic_transform_pivot, ss->pivot_pos, symmpass); - flip_v3_v3(data.elastic_transform_pivot_init, ss->init_pivot_pos, symmpass); + float elastic_transform_pivot[3]; + flip_v3_v3(elastic_transform_pivot, ss->pivot_pos, symmpass); + float elastic_transform_pivot_init[3]; + flip_v3_v3(elastic_transform_pivot_init, ss->init_pivot_pos, symmpass); - const int symm_area = SCULPT_get_vertex_symm_area(data.elastic_transform_pivot); - copy_m4_m4(data.elastic_transform_mat, data.transform_mats[symm_area]); - BLI_task_parallel_range( - 0, ss->filter_cache->nodes.size(), &data, sculpt_elastic_transform_task_cb, &settings); + const int symm_area = SCULPT_get_vertex_symm_area(elastic_transform_pivot); + float elastic_transform_mat[4][4]; + copy_m4_m4(elastic_transform_mat, transform_mats[symm_area]); + threading::parallel_for( + ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + sculpt_elastic_transform_task(ob, + transform_radius, + elastic_transform_mat, + elastic_transform_pivot, + ss->filter_cache->nodes[i]); + } + }); } } SCULPT_combine_transform_proxies(sd, ob); @@ -304,7 +303,7 @@ void ED_sculpt_update_modal_transform(bContext *C, Object *ob) switch (sd->transform_mode) { case SCULPT_TRANSFORM_MODE_ALL_VERTICES: { - sculpt_transform_all_vertices(sd, ob); + sculpt_transform_all_vertices(ob); break; } case SCULPT_TRANSFORM_MODE_RADIUS_ELASTIC: {