[Bf-blender-cvs] [99c0ee0558c] sculpt-dev: Sculpt: cloth brush constraint solver is now multi-threaded

Joseph Eagar noreply at git.blender.org
Thu Sep 23 12:41:24 CEST 2021


Commit: 99c0ee0558cb498d0cfc782f457539deeee848a8
Author: Joseph Eagar
Date:   Thu Sep 23 03:40:11 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB99c0ee0558cb498d0cfc782f457539deeee848a8

Sculpt: cloth brush constraint solver is now multi-threaded

* Used a simple method of assigning constraints
  to threads.
* Constraints that couldn't be assigned are solved
  in the main thread.

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/paint_cursor.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_cloth.c
M	source/blender/editors/sculpt_paint/sculpt_dyntopo.c
M	source/blender/editors/sculpt_paint/sculpt_expand.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index b07e8e8be15..994993e9d39 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -319,10 +319,16 @@ typedef struct SculptClothLengthConstraint {
   /* Index in #SculptClothSimulation.node_state of the node from where this constraint was created.
    * This constraints will only be used by the solver if the state is active. */
   int node;
+  int thread_nr;
 
   eSculptClothConstraintType type;
 } SculptClothLengthConstraint;
 
+typedef struct SculptClothTaskData {
+  SculptClothLengthConstraint **length_constraints;
+  int tot_length_constraints;
+} SculptClothTaskData;
+
 typedef struct SculptClothSimulation {
   SculptClothLengthConstraint *length_constraints;
   int tot_length_constraints;
@@ -330,6 +336,13 @@ typedef struct SculptClothSimulation {
   int capacity_length_constraints;
   float *length_constraint_tweak;
 
+  SculptClothTaskData *constraint_tasks;
+
+  /* final task always run in main thread, after all the others
+   * have completed
+   */
+  int tot_constraint_tasks;
+
   /* Position anchors for deformation brushes. These positions are modified by the brush and the
    * final positions of the simulated vertices are updated with constraints that use these points
    * as targets. */
@@ -606,6 +619,7 @@ typedef struct SculptSession {
   int cd_vert_node_offset;
   int cd_face_node_offset;
   int cd_vcol_offset;
+  int cd_vert_mask_offset;
   int cd_faceset_offset;
   int cd_face_areas;
 
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index e9185b23750..15666a3886d 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1676,7 +1676,7 @@ static void paint_cursor_preview_boundary_data_update(PaintCursorContext *pconte
     SCULPT_boundary_data_free(ss->boundary_preview);
   }
 
-  ss->boundary_preview = SCULPT_boundary_data_init(
+  ss->boundary_preview = SCULPT_boundary_data_init(pcontext->sd,
       pcontext->vc.obact, pcontext->brush, ss->active_vertex_index, pcontext->radius);
 }
 
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index db55f29a036..e1222dceea4 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -645,7 +645,7 @@ float SCULPT_vertex_mask_get(SculptSession *ss, SculptVertRef index)
       return ss->vmask[index.i];
     case PBVH_BMESH:
       v = (BMVert *)index.i;
-      mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
+      mask = BM_ELEM_CD_GET_VOID_P(v, ss->cd_vert_mask_offset);
       return *mask;
     case PBVH_GRIDS: {
       const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index f31dd7176a5..63654840ab8 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -29,6 +29,7 @@
 #include "BLI_gsqueue.h"
 #include "BLI_hash.h"
 #include "BLI_math.h"
+#include "BLI_rand.h"
 #include "BLI_task.h"
 #include "BLI_utildefines.h"
 
@@ -116,8 +117,7 @@ static void cloth_brush_simulation_location_get(SculptSession *ss,
     return;
   }
 
-  if (SCULPT_get_int(ss, cloth_simulation_area_type, NULL, brush) ==
-      BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
+  if (ss->cache->cloth_sim->simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
     copy_v3_v3(r_location, ss->cache->initial_location);
     return;
   }
@@ -910,106 +910,246 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
   cloth_sim->node_state[node_index] = SCULPT_CLOTH_NODE_INACTIVE;
 }
 
-static void cloth_brush_satisfy_constraints(SculptSession *ss,
-                                            Brush *brush,
-                                            SculptClothSimulation *cloth_sim)
+static void cloth_free_tasks(SculptClothSimulation *cloth_sim)
 {
+  for (int i = 0; i < cloth_sim->tot_constraint_tasks; i++) {
+    MEM_SAFE_FREE(cloth_sim->constraint_tasks[i].length_constraints);
+  }
 
-  AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
+  MEM_SAFE_FREE(cloth_sim->constraint_tasks);
+  cloth_sim->constraint_tasks = NULL;
+  cloth_sim->tot_constraint_tasks = 0;
+}
 
-  for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) {
-    for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
-      const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
+static void cloth_sort_constraints_for_tasks(SculptSession *ss,
+                                             Brush *brush,
+                                             SculptClothSimulation *cloth_sim,
+                                             int totthread)
+{
+  SculptClothTaskData *tasks = MEM_calloc_arrayN(
+      totthread + 1, sizeof(SculptClothTaskData), "SculptClothTaskData");
 
-      if (cloth_sim->node_state[constraint->node] != SCULPT_CLOTH_NODE_ACTIVE) {
-        /* Skip all constraints that were created for inactive nodes. */
-        continue;
-      }
+  int *vthreads = MEM_calloc_arrayN(ss->totvert, sizeof(*vthreads), "cloth vthreads");
 
-      const int v1 = constraint->elem_index_a;
-      const int v2 = constraint->elem_index_b;
+  SculptClothLengthConstraint *cons = cloth_sim->length_constraints, *con;
+  int totcon = cloth_sim->tot_length_constraints;
 
-      const SculptVertRef v1ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v1);
-      const SculptVertRef v2ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v2);
+  RNG *rng = BLI_rng_new(BLI_thread_rand(0));
 
-      float v1_to_v2[3];
-      sub_v3_v3v3(v1_to_v2, constraint->elem_position_b, constraint->elem_position_a);
-      const float current_distance = len_v3(v1_to_v2);
-      float correction_vector[3];
-      float correction_vector_half[3];
+  bool not_dynamic = cloth_sim->simulation_area_type != BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC;
 
-      const float constraint_distance = constraint->length +
-                                        (cloth_sim->length_constraint_tweak[v1] * 0.5f) +
-                                        (cloth_sim->length_constraint_tweak[v2] * 0.5f);
+  con = cons;
+  for (int i = 0; i < totcon; i++, con++) {
+    int task1 = vthreads[con->elem_index_a];
+    int task2 = vthreads[con->elem_index_a];
 
-      if (current_distance > 0.0f) {
-        mul_v3_v3fl(correction_vector,
-                    v1_to_v2,
-                    CLOTH_SOLVER_DISPLACEMENT_FACTOR *
-                        (1.0f - (constraint_distance / current_distance)));
-      }
-      else {
-        mul_v3_v3fl(correction_vector, v1_to_v2, CLOTH_SOLVER_DISPLACEMENT_FACTOR);
-      }
+    int tasknr;
+    if (!task1 && !task2) {
+      tasknr = BLI_rng_get_int(rng) % totthread;
 
-      mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f);
-
-      const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1ref)) *
-                            SCULPT_automasking_factor_get(automasking, ss, v1ref);
-      const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2ref)) *
-                            SCULPT_automasking_factor_get(automasking, ss, v2ref);
-
-      float sim_location[3];
-      cloth_brush_simulation_location_get(ss, brush, sim_location);
-
-      const float sim_factor_v1 = ss->cache ?
-                                      cloth_brush_simulation_falloff_get(cloth_sim,
-                                                                         brush,
-                                                                         ss->cache->radius,
-                                                                         sim_location,
-                                                                         cloth_sim->init_pos[v1]) :
-                                      1.0f;
-      const float sim_factor_v2 = ss->cache ?
-                                      cloth_brush_simulation_falloff_get(cloth_sim,
-                                                                         brush,
-                                                                         ss->cache->radius,
-                                                                         sim_location,
-                                                                         cloth_sim->init_pos[v2]) :
-                                      1.0f;
-
-      float deformation_strength = 1.0f;
-      if (constraint->type == SCULPT_CLOTH_CONSTRAINT_DEFORMATION) {
-        deformation_strength = (cloth_sim->deformation_strength[v1] +
-                                cloth_sim->deformation_strength[v2]) *
-                               0.5f;
-      }
+      vthreads[con->elem_index_a] = tasknr + 1;
+      vthreads[con->elem_index_b] = tasknr + 1;
+    }
+    else if (task1 == task2) {
+      tasknr = task1 - 1;
+    }
+    else {
+      tasks[totthread].tot_length_constraints++;
+      con->thread_nr = -1;
+      continue;
+    }
 
-      if (constraint->type == SCULPT_CLOTH_CONSTRAINT_SOFTBODY) {
-        const float softbody_plasticity = brush ? brush->cloth_constraint_softbody_strength : 0.0f;
-        madd_v3_v3fl(cloth_sim->pos[v1],
-                     correction_vector_half,
-                     1.0f * mask_v1 * sim_factor_v1 * constraint->strength * softbody_plasticity);
-        madd_v3_v3fl(cloth_sim->softbody_pos[v1],
-                     correction_vector_half,
-                     -1.0f * mask_v1 * sim_factor_v1 * constraint->strength *
-                         (1.0f - softbody_plasticity));
-      }
-      else {
-        madd_v3_v3fl(cloth_sim->pos[v1],
-                     correction_vector_half,
-                     1.0f * mask_v1 * sim_factor_v1 * constraint->strength * deformation_strength);
-        if (v1 != v2) {
-          madd_v3_v3fl(cloth_sim->pos[v2],
-                       correction_vector_half,
-                       -1.0f * mask_v2 * sim_factor_v2 * constraint->strength *
-                           deformat

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list