[Bf-blender-cvs] [1677ddb7eea] master: Sculpt: Avoid retrieving vertices attribute when flushing positions

Hans Goudey noreply at git.blender.org
Wed Nov 16 22:37:30 CET 2022


Commit: 1677ddb7eeaea3e2189e21a83a283baebc182577
Author: Hans Goudey
Date:   Wed Nov 16 14:54:20 2022 -0600
Branches: master
https://developer.blender.org/rB1677ddb7eeaea3e2189e21a83a283baebc182577

Sculpt: Avoid retrieving vertices attribute when flushing positions

Currently the positions are retrieved again for every vertex. This is
slow, and will get slower when positions are stored as a named
attribute. Saves around 0.5ms per stroke update when a modifier
is active in my test with a 1 million face mesh.

===================================================================

M	source/blender/editors/sculpt_paint/sculpt.cc

===================================================================

diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc
index b8ab3ba4917..9be59b9df01 100644
--- a/source/blender/editors/sculpt_paint/sculpt.cc
+++ b/source/blender/editors/sculpt_paint/sculpt.cc
@@ -18,6 +18,8 @@
 #include "BLI_gsqueue.h"
 #include "BLI_math.h"
 #include "BLI_task.h"
+#include "BLI_task.hh"
+#include "BLI_timeit.hh"
 #include "BLI_utildefines.h"
 
 #include "DNA_brush_types.h"
@@ -69,6 +71,8 @@
 
 #include "bmesh.h"
 
+using blender::MutableSpan;
+
 /* -------------------------------------------------------------------- */
 /** \name Sculpt PBVH Abstraction API
  *
@@ -3622,48 +3626,46 @@ static void do_brush_action(Sculpt *sd,
 }
 
 /* Flush displacement from deformed PBVH vertex to original mesh. */
-static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
+static void sculpt_flush_pbvhvert_deform(const SculptSession &ss,
+                                         const PBVHVertexIter &vd,
+                                         MutableSpan<MVert> verts)
 {
-  SculptSession *ss = ob->sculpt;
-  Mesh *me = static_cast<Mesh *>(ob->data);
   float disp[3], newco[3];
-  int index = vd->vert_indices[vd->i];
+  int index = vd.vert_indices[vd.i];
 
-  sub_v3_v3v3(disp, vd->co, ss->deform_cos[index]);
-  mul_m3_v3(ss->deform_imats[index], disp);
-  add_v3_v3v3(newco, disp, ss->orig_cos[index]);
+  sub_v3_v3v3(disp, vd.co, ss.deform_cos[index]);
+  mul_m3_v3(ss.deform_imats[index], disp);
+  add_v3_v3v3(newco, disp, ss.orig_cos[index]);
 
-  copy_v3_v3(ss->deform_cos[index], vd->co);
-  copy_v3_v3(ss->orig_cos[index], newco);
+  copy_v3_v3(ss.deform_cos[index], vd.co);
+  copy_v3_v3(ss.orig_cos[index], newco);
 
-  MVert *verts = BKE_mesh_verts_for_write(me);
-  if (!ss->shapekey_active) {
+  if (!ss.shapekey_active) {
     copy_v3_v3(verts[index].co, newco);
   }
 }
 
-static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
-                                           const int n,
-                                           const TaskParallelTLS *__restrict /*tls*/)
+static void sculpt_combine_proxies_node(Object &object,
+                                        Sculpt &sd,
+                                        const bool use_orco,
+                                        PBVHNode &node)
 {
-  SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
-  SculptSession *ss = data->ob->sculpt;
-  Sculpt *sd = data->sd;
-  Object *ob = data->ob;
-  const bool use_orco = data->use_proxies_orco;
+  SculptSession *ss = object.sculpt;
 
-  PBVHVertexIter vd;
-  PBVHProxyNode *proxies;
-  int proxy_count;
   float(*orco)[3] = nullptr;
-
   if (use_orco && !ss->bm) {
-    orco = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS)->co;
+    orco = SCULPT_undo_push_node(&object, &node, SCULPT_UNDO_COORDS)->co;
   }
 
-  BKE_pbvh_node_get_proxies(data->nodes[n], &proxies, &proxy_count);
+  int proxy_count;
+  PBVHProxyNode *proxies;
+  BKE_pbvh_node_get_proxies(&node, &proxies, &proxy_count);
 
-  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+  Mesh &mesh = *static_cast<Mesh *>(object.data);
+  MutableSpan<MVert> verts = mesh.verts_for_write();
+
+  PBVHVertexIter vd;
+  BKE_pbvh_vertex_iter_begin (ss->pbvh, &node, vd, PBVH_ITER_UNIQUE) {
     float val[3];
 
     if (use_orco) {
@@ -3682,23 +3684,22 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
       add_v3_v3(val, proxies[p].co[vd.i]);
     }
 
-    SCULPT_clip(sd, ss, vd.co, val);
+    SCULPT_clip(&sd, ss, vd.co, val);
 
     if (ss->deform_modifiers_active) {
-      sculpt_flush_pbvhvert_deform(ob, &vd);
+      sculpt_flush_pbvhvert_deform(*ss, vd, verts);
     }
   }
   BKE_pbvh_vertex_iter_end;
 
-  BKE_pbvh_node_free_proxies(data->nodes[n]);
+  BKE_pbvh_node_free_proxies(&node);
 }
 
 static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 {
+  using namespace blender;
   SculptSession *ss = ob->sculpt;
   Brush *brush = BKE_paint_brush(&sd->paint);
-  PBVHNode **nodes;
-  int totnode;
 
   if (!ss->cache->supports_gravity && sculpt_tool_is_proxy_used(brush->sculpt_tool)) {
     /* First line is tools that don't support proxies. */
@@ -3714,37 +3715,33 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
                              SCULPT_TOOL_BOUNDARY,
                              SCULPT_TOOL_POSE);
 
+  int totnode;
+  PBVHNode **nodes;
   BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
 
-  SculptThreadedTaskData data{};
-  data.sd = sd;
-  data.ob = ob;
-  data.brush = brush;
-  data.nodes = nodes;
-  data.use_proxies_orco = use_orco;
+  threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
+    for (const int i : range) {
+      sculpt_combine_proxies_node(*ob, *sd, use_orco, *nodes[i]);
+    }
+  });
 
-  TaskParallelSettings settings;
-  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-  BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
   MEM_SAFE_FREE(nodes);
 }
 
 void SCULPT_combine_transform_proxies(Sculpt *sd, Object *ob)
 {
+  using namespace blender;
   SculptSession *ss = ob->sculpt;
-  PBVHNode **nodes;
-  int totnode;
 
+  int totnode;
+  PBVHNode **nodes;
   BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
-  SculptThreadedTaskData data{};
-  data.sd = sd;
-  data.ob = ob;
-  data.nodes = nodes;
-  data.use_proxies_orco = false;
 
-  TaskParallelSettings settings;
-  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-  BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
+  threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
+    for (const int i : range) {
+      sculpt_combine_proxies_node(*ob, *sd, false, *nodes[i]);
+    }
+  });
 
   MEM_SAFE_FREE(nodes);
 }
@@ -3777,34 +3774,10 @@ static void sculpt_update_keyblock(Object *ob)
   }
 }
 
-static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata,
-                                               const int n,
-                                               const TaskParallelTLS *__restrict /*tls*/)
-{
-  SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
-  SculptSession *ss = data->ob->sculpt;
-  Object *ob = data->ob;
-  float(*vertCos)[3] = data->vertCos;
-
-  PBVHVertexIter vd;
-
-  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
-    sculpt_flush_pbvhvert_deform(ob, &vd);
-
-    if (!vertCos) {
-      continue;
-    }
-
-    int index = vd.vert_indices[vd.i];
-    copy_v3_v3(vertCos[index], ss->orig_cos[index]);
-  }
-  BKE_pbvh_vertex_iter_end;
-}
-
-void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
+void SCULPT_flush_stroke_deform(Sculpt * /*sd*/, Object *ob, bool is_proxy_used)
 {
+  using namespace blender;
   SculptSession *ss = ob->sculpt;
-  Brush *brush = BKE_paint_brush(&sd->paint);
 
   if (is_proxy_used && ss->deform_modifiers_active) {
     /* This brushes aren't using proxies, so sculpt_combine_proxies() wouldn't propagate needed
@@ -3826,16 +3799,24 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
 
     BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
 
-    SculptThreadedTaskData data{};
-    data.sd = sd;
-    data.ob = ob;
-    data.brush = brush;
-    data.nodes = nodes;
-    data.vertCos = vertCos;
+    MutableSpan<MVert> verts = me->verts_for_write();
 
-    TaskParallelSettings settings;
-    BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-    BLI_task_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings);
+    threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
+      for (const int i : range) {
+        PBVHVertexIter vd;
+        BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[i], vd, PBVH_ITER_UNIQUE) {
+          sculpt_flush_pbvhvert_deform(*ss, vd, verts);
+
+          if (!vertCos) {
+            continue;
+          }
+
+          int index = vd.vert_indices[vd.i];
+          copy_v3_v3(vertCos[index], ss->orig_cos[index]);
+        }
+        BKE_pbvh_vertex_iter_end;
+      }
+    });
 
     if (vertCos) {
       SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos);



More information about the Bf-blender-cvs mailing list