[Bf-blender-cvs] [628925a5c67] sculpt-dev: Sculpt-dev: fix thread contention in weighted smooth * Cached face areas are now updated in a double buffered fashion; all threads read from one side of the buffer while the other is written to by the threads that own a given face; the buffers are swapped on each iteration of a tool that uses face areas. * Fixes smooth flickering.
Joseph Eagar
noreply at git.blender.org
Sun Nov 28 11:25:03 CET 2021
Commit: 628925a5c679fd371b42a1b3aeba907c0fb01a99
Author: Joseph Eagar
Date: Sun Nov 28 02:23:06 2021 -0800
Branches: sculpt-dev
https://developer.blender.org/rB628925a5c679fd371b42a1b3aeba907c0fb01a99
Sculpt-dev: fix thread contention
in weighted smooth
* Cached face areas are now updated
in a double buffered fashion;
all threads read from one side of
the buffer while the other is written
to by the threads that own a given
face; the buffers are swapped on
each iteration of a tool that uses
face areas.
* Fixes smooth flickering.
===================================================================
M source/blender/blenkernel/intern/paint.c
M source/blender/blenkernel/intern/pbvh.c
M source/blender/blenkernel/intern/pbvh_bmesh.c
M source/blender/blenkernel/intern/pbvh_intern.h
M source/blender/editors/sculpt_paint/sculpt_face_set.c
M source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
M source/blender/editors/sculpt_paint/sculpt_smooth.c
===================================================================
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9b28a12c57a..03ff3a6d833 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -2449,7 +2449,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, me->totvert);
MEM_SAFE_FREE(ss->face_areas);
- ss->face_areas = MEM_calloc_arrayN(me->totpoly, sizeof(float), "ss->face_areas");
+ ss->face_areas = MEM_calloc_arrayN(me->totpoly, sizeof(float) * 2, "ss->face_areas");
BKE_pbvh_build_mesh(pbvh,
me,
@@ -2496,7 +2496,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
int totgridfaces = base_mesh->totpoly * (key.grid_size - 1) * (key.grid_size - 1);
MEM_SAFE_FREE(ss->face_areas);
- ss->face_areas = MEM_calloc_arrayN(totgridfaces, sizeof(float), "ss->face_areas");
+ ss->face_areas = MEM_calloc_arrayN(totgridfaces, sizeof(float) * 2, "ss->face_areas");
BKE_pbvh_build_grids(pbvh,
subdiv_ccg->grids,
@@ -2944,7 +2944,7 @@ void BKE_sculptsession_bmesh_add_layers(Object *ob)
BMCustomLayerReq flayers[] = {
{CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
- {CD_PROP_FLOAT, dyntopop_faces_areas_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
+ {CD_PROP_FLOAT2, dyntopop_faces_areas_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
};
BM_data_layers_ensure(ss->bm, &ss->bm->pdata, flayers, 2);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 83557ba41de..518f065e8b6 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -4248,8 +4248,17 @@ void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node)
node->flag |= PBVH_UpdateTriAreas;
}
+/* must be called outside of threads */
+void BKE_pbvh_face_areas_begin(PBVH *pbvh)
+{
+ pbvh->face_area_i ^= 1;
+}
+
void BKE_pbvh_update_all_tri_areas(PBVH *pbvh)
{
+ /* swap read/write face area buffers */
+ pbvh->face_area_i ^= 1;
+
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
if (node->flag & PBVH_Leaf) {
@@ -4279,6 +4288,8 @@ void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
BKE_pbvh_bmesh_check_tris(pbvh, node);
}
+ const int cur_i = pbvh->face_area_i ^ 1;
+
switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES: {
for (int i = 0; i < node->totprim; i++) {
@@ -4289,7 +4300,7 @@ void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
continue;
}
- pbvh->face_areas[lt->poly] = 0.0f;
+ pbvh->face_areas[lt->poly * 2 + cur_i] = 0.0f;
}
for (int i = 0; i < node->totprim; i++) {
@@ -4304,7 +4315,14 @@ void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
MVert *mv2 = pbvh->verts + pbvh->mloop[lt->tri[1]].v;
MVert *mv3 = pbvh->verts + pbvh->mloop[lt->tri[2]].v;
- pbvh->face_areas[lt->poly] += area_tri_v3(mv1->co, mv2->co, mv3->co);
+ float area = area_tri_v3(mv1->co, mv2->co, mv3->co);
+
+ pbvh->face_areas[lt->poly * 2 + cur_i] += area;
+
+ /* sanity check on read side of read write buffer */
+ if (pbvh->face_areas[lt->poly * 2 + (cur_i ^ 1)] == 0.0f) {
+ pbvh->face_areas[lt->poly * 2 + (cur_i ^ 1)] = pbvh->face_areas[lt->poly * 2 + cur_i];
+ }
}
break;
}
@@ -4313,7 +4331,8 @@ void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
const int cd_face_area = pbvh->cd_face_area;
TGSET_ITER (f, node->bm_faces) {
- BM_ELEM_CD_SET_FLOAT(f, cd_face_area, 0.0f);
+ float *areabuf = BM_ELEM_CD_GET_VOID_P(f, cd_face_area);
+ areabuf[cur_i] = 0.0f;
}
TGSET_ITER_END;
@@ -4325,10 +4344,12 @@ void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
BMVert *v3 = (BMVert *)(node->tribuf->verts[tri->v[2]].i);
BMFace *f = (BMFace *)tri->f.i;
+ float *areabuf = BM_ELEM_CD_GET_VOID_P(f, cd_face_area);
+
float area = area_tri_v3(v1->co, v2->co, v3->co);
float farea = BM_ELEM_CD_GET_FLOAT(f, cd_face_area);
- BM_ELEM_CD_SET_FLOAT(f, cd_face_area, farea + area);
+ areabuf[cur_i] = farea + area;
}
break;
}
@@ -4439,6 +4460,8 @@ void BKE_pbvh_set_vemap(PBVH *pbvh, MeshElemMap *vemap)
void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_areas, int valence)
{
+ const int cur_i = pbvh->face_area_i;
+
switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES: {
int *edges = BLI_array_alloca(edges, 16);
@@ -4470,10 +4493,10 @@ void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_are
}
}
for (int i = 0; i < len; i++) {
- r_areas[i] = pbvh->face_areas[polys[i * 2]];
+ r_areas[i] = pbvh->face_areas[polys[i * 2] * 2 + cur_i];
if (polys[i * 2 + 1] != -1) {
- r_areas[i] += pbvh->face_areas[polys[i * 2 + 1]];
+ r_areas[i] += pbvh->face_areas[polys[i * 2 + 1] * 2 + cur_i];
r_areas[i] *= 0.5f;
}
}
@@ -4507,8 +4530,11 @@ void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_are
w = 0.0f;
}
else {
- w += BM_ELEM_CD_GET_FLOAT(e->l->f, cd_face_area) * 0.5f;
- w += BM_ELEM_CD_GET_FLOAT(e->l->radial_next->f, cd_face_area) * 0.5f;
+ float *a1 = BM_ELEM_CD_GET_VOID_P(e->l->f, cd_face_area);
+ float *a2 = BM_ELEM_CD_GET_VOID_P(e->l->radial_next->f, cd_face_area);
+
+ w += a1[cur_i] * 0.5f;
+ w += a2[cur_i] * 0.5f;
}
if (j >= valence) {
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index a6a0d8acf45..d6127f8b430 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -45,6 +45,7 @@ Topology rake:
#include "BLI_array.h"
#include "BLI_buffer.h"
#include "BLI_ghash.h"
+#include "BLI_hash.h"
#include "BLI_heap_simple.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
@@ -2463,6 +2464,31 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
}
pbvh_print_mem_size(pbvh);
+
+ /* update face areas */
+ const int cd_face_area = pbvh->cd_face_area;
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *node = pbvh->nodes + i;
+
+ if (!(node->flag & PBVH_Leaf)) {
+ continue;
+ }
+
+ BKE_pbvh_bmesh_check_tris(pbvh, node);
+
+ node->flag |= PBVH_UpdateTriAreas;
+ BKE_pbvh_check_tri_areas(pbvh, node);
+
+ int area_src_i = pbvh->face_area_i ^ 1;
+ int area_dst_i = pbvh->face_area_i;
+
+ /* make sure read side of double buffer is set too */
+ TGSET_ITER (f, node->bm_faces) {
+ float *areabuf = BM_ELEM_CD_GET_VOID_P(f, cd_face_area);
+ areabuf[area_dst_i] = areabuf[area_src_i];
+ }
+ TGSET_ITER_END;
+ }
}
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log)
@@ -2808,7 +2834,8 @@ static uintptr_t tri_loopkey(BMLoop *l, int mat_nr, int cd_fset, int cd_uvs[], i
key ^= (uintptr_t)l->v;
if (cd_fset >= 0) {
- key ^= BM_ELEM_CD_GET_INT(l->f, cd_fset);
+ // key ^= (uintptr_t)BLI_hash_int(BM_ELEM_CD_GET_INT(l->f, cd_fset));
+ key ^= (uintptr_t)BM_ELEM_CD_GET_INT(l->f, cd_fset);
}
for (int i = 0; i < totuv; i++) {
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index a361257a9b0..cf566efa75e 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -172,7 +172,8 @@ struct PBVH {
int face_sets_color_seed;
int face_sets_color_default;
int *face_sets;
- float *face_areas;
+ float *face_areas; /* float2 vector, double buffered to avoid thread contention */
+ int face_area_i;
/* Grid Data */
CCGKey gridkey;
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 3a636a9f1c8..b5b6e2e7180 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -412,6 +412,8 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
ss->cache->automasking->settings.flags &= ~BRUSH_AUTOMASKING_FACE_SETS;
}
+ bool modified = false;
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
MeshElemMap *vert_map = &ss->pmap[vd.index];
@@ -501,6 +503,7 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (ok) {
ss->face_sets[vert_map->indices[j]] = new_fset;
+ modified = true;
}
}
}
@@ -590,6 +593,7 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (ok) {
BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, new_fset);
+ modified = true;
}
}
}
@@ -621,12 +625,17 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (!use_fset_strength || fade > test_limit) {
SCULPT_vertex_face_set_set(ss, vd.vertex, new_fset);
+ modified = true;
}
}
}
}
BKE_pbvh_vertex_iter_end;
+ if (modified) {
+ BKE_pbvh_node_mark_update_triangulation(data->nodes[n]);
+ }
+
// restore automasking flag
if (set_active_faceset) {
ss->cache->automasking->settings.flags |= automasking_fset_flag;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index c8c3965a85e..47c4e2a2dbe 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -781,6 +781,10 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap,
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list