[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