Tune up a few hot loops revealed by profiling.
This commit is contained in:
@@ -125,8 +125,9 @@ class UnifiedPaintPanel:
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
typeprop = "float_value"
|
||||
|
||||
if ch.type == "FLOAT":
|
||||
typeprop = "float_value" if "spacing" in ch.idname else "factor_value"
|
||||
if ch.type == "INT":
|
||||
typeprop = "int_value"
|
||||
elif ch.type == "BOOL":
|
||||
@@ -139,7 +140,7 @@ class UnifiedPaintPanel:
|
||||
typeprop = "color3_value"
|
||||
elif ch.type == "VEC4":
|
||||
typeprop = "color4_value"
|
||||
|
||||
|
||||
if text is None:
|
||||
s = prop_name.lower().replace("_", " ").split(" ");
|
||||
text = ''
|
||||
@@ -191,14 +192,14 @@ class UnifiedPaintPanel:
|
||||
#if unified_name and not header:
|
||||
# # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
# row.prop(ups, unified_name, text="", icon='BRUSHES_ALL')
|
||||
if not header and ch.type != "BOOL":
|
||||
if not header: # and ch.type != "BOOL":
|
||||
if ch.type == "BITMASK" and not toolsettings_only and ch == finalch:
|
||||
row.prop(ch, "inherit_if_unset", text="Combine With Defaults")
|
||||
|
||||
if not toolsettings_only:
|
||||
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
if ch.type == "BITMASK" or ch.type == "BOOL":
|
||||
return
|
||||
|
||||
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
|
||||
@@ -806,7 +807,16 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
box.prop(brush, "ignore_falloff_for_topology_rake")
|
||||
|
||||
if context.sculpt_object.use_dynamic_topology_sculpting:
|
||||
layout.prop(brush.dyntopo, "disabled", text="Disable Dyntopo")
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"dyntopo_disabled",
|
||||
#text="Weight By Face Area",
|
||||
slider=True,
|
||||
header=True
|
||||
)
|
||||
#layout.prop(brush.dyntopo, "disabled", text="Disable Dyntopo")
|
||||
|
||||
# normal_weight
|
||||
if capabilities.has_normal_weight:
|
||||
@@ -1018,7 +1028,16 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
col = layout.column()
|
||||
col.prop(brush, "boundary_smooth_factor")
|
||||
|
||||
col.prop(brush, "use_weighted_smooth")
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"use_weighted_smooth",
|
||||
#text="Weight By Face Area",
|
||||
slider=True,
|
||||
)
|
||||
|
||||
#col.prop(brush, "use_weighted_smooth")
|
||||
col.prop(brush, "preserve_faceset_boundary")
|
||||
if brush.preserve_faceset_boundary:
|
||||
col.prop(brush, "autosmooth_fset_slide")
|
||||
|
||||
@@ -1628,6 +1628,7 @@ typedef struct EdgeQueueThreadData {
|
||||
int totedge;
|
||||
int size;
|
||||
bool is_collapse;
|
||||
int seed;
|
||||
} EdgeQueueThreadData;
|
||||
|
||||
static void edge_thread_data_insert(EdgeQueueThreadData *tdata, BMEdge *e)
|
||||
@@ -1962,6 +1963,16 @@ static void long_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata,
|
||||
|
||||
static int _long_edge_queue_task_cb_seed = 0;
|
||||
|
||||
BLI_INLINE int dyntopo_thread_rand(int seed)
|
||||
{
|
||||
// glibc
|
||||
const uint32_t multiplier = 1103515245;
|
||||
const uint32_t addend = 12345;
|
||||
const uint32_t mask = (1 << 31) - 1;
|
||||
|
||||
return (seed * multiplier + addend) & mask;
|
||||
}
|
||||
|
||||
static void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
@@ -1973,18 +1984,43 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
BMVert **val34 = NULL;
|
||||
BLI_array_declare(val34);
|
||||
|
||||
BMFace *f;
|
||||
int seed = tdata->seed + n;
|
||||
|
||||
BMFace *f, **faces = NULL;
|
||||
BLI_array_declare(faces);
|
||||
const int cd_dyn_vert = tdata->pbvh->cd_dyn_vert;
|
||||
|
||||
#if 1
|
||||
# if 0
|
||||
// try to be nice to branch predictor
|
||||
int off = (seed = dyntopo_thread_rand(seed));
|
||||
int stepi = off & 65535;
|
||||
# endif
|
||||
/*
|
||||
we care more about convergence to accurate results
|
||||
then accuracy in any individual runs. profiling
|
||||
has shown this loop overwhelms the L3 cache,
|
||||
so randomly skip bits of it.
|
||||
*/
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
# if 0
|
||||
if ((stepi++) & 3) {
|
||||
continue;
|
||||
}
|
||||
# else
|
||||
if ((seed = dyntopo_thread_rand(seed)) & 3) {
|
||||
continue;
|
||||
}
|
||||
# endif
|
||||
do {
|
||||
l->e->head.hflag &= ~BM_ELEM_TAG;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
#endif
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
#ifdef USE_EDGEQUEUE_FRONTFACE
|
||||
@@ -2014,7 +2050,9 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
|
||||
// try to improve convergence by applying a small amount of smoothing to topology,
|
||||
// but tangentially to surface.
|
||||
if (BLI_rng_get_float(rng) > 0.5) {
|
||||
int randval = (seed = dyntopo_thread_rand(seed)) & 255;
|
||||
|
||||
if (randval > 127) {
|
||||
surface_smooth_v_safe(tdata->pbvh, l_iter->v, eq_ctx->surface_smooth_fac);
|
||||
}
|
||||
|
||||
@@ -2040,6 +2078,7 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
TGSET_ITER_END
|
||||
|
||||
BLI_rng_free(rng);
|
||||
BLI_array_free(faces);
|
||||
|
||||
tdata->val34_verts = val34;
|
||||
tdata->val34_verts_tot = BLI_array_len(val34);
|
||||
@@ -2055,15 +2094,23 @@ static void short_edge_queue_task_cb(void *__restrict userdata,
|
||||
|
||||
BMFace *f;
|
||||
|
||||
int seed = tdata->seed + n;
|
||||
|
||||
// see comment in similar loop in long_edge_queue_task_cb
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
#if 0
|
||||
if ((stepi++) & 3) {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if ((seed = dyntopo_thread_rand(seed)) & 3) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
if (!l->e) {
|
||||
printf("bmesh error! %s\n", __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
l->e->head.hflag &= ~BM_ELEM_TAG;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
@@ -2562,30 +2609,41 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
|
||||
EdgeQueueThreadData *tdata = NULL;
|
||||
BLI_array_declare(tdata);
|
||||
|
||||
int totleaf = 0;
|
||||
|
||||
for (int n = 0; n < pbvh->totnode; n++) {
|
||||
PBVHNode *node = &pbvh->nodes[n];
|
||||
|
||||
/* Check leaf nodes marked for topology update */
|
||||
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
|
||||
!(node->flag & PBVH_FullyHidden)) {
|
||||
EdgeQueueThreadData td;
|
||||
|
||||
memset(&td, 0, sizeof(td));
|
||||
|
||||
td.pbvh = pbvh;
|
||||
td.node = node;
|
||||
td.eq_ctx = eq_ctx;
|
||||
|
||||
BLI_array_append(tdata, td);
|
||||
/* Check each face */
|
||||
/*
|
||||
BMFace *f;
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
long_edge_queue_face_add(eq_ctx, f);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
*/
|
||||
if (node->flag & PBVH_Leaf) {
|
||||
totleaf++;
|
||||
}
|
||||
|
||||
/* Check leaf nodes marked for topology update */
|
||||
bool ok = ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
|
||||
!(node->flag & PBVH_FullyHidden));
|
||||
|
||||
if (!ok) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EdgeQueueThreadData td;
|
||||
|
||||
memset(&td, 0, sizeof(td));
|
||||
|
||||
td.seed = BLI_thread_rand(0);
|
||||
td.pbvh = pbvh;
|
||||
td.node = node;
|
||||
td.eq_ctx = eq_ctx;
|
||||
|
||||
BLI_array_append(tdata, td);
|
||||
/* Check each face */
|
||||
/*
|
||||
BMFace *f;
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
long_edge_queue_face_add(eq_ctx, f);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
*/
|
||||
}
|
||||
|
||||
int count = BLI_array_len(tdata);
|
||||
@@ -2953,9 +3011,11 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
|
||||
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
|
||||
!(node->flag & PBVH_FullyHidden)) {
|
||||
memset(&td, 0, sizeof(td));
|
||||
|
||||
td.pbvh = pbvh;
|
||||
td.node = node;
|
||||
td.eq_ctx = eq_ctx;
|
||||
td.seed = BLI_thread_rand(0);
|
||||
|
||||
BLI_array_append(tdata, td);
|
||||
}
|
||||
|
||||
@@ -1158,22 +1158,35 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, SculptVertRef index, int face
|
||||
return false;
|
||||
}
|
||||
case PBVH_BMESH: {
|
||||
BMIter iter;
|
||||
BMLoop *l;
|
||||
BMEdge *e;
|
||||
BMVert *v = (BMVert *)index.i;
|
||||
|
||||
if (ss->cd_faceset_offset == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
|
||||
BMFace *f = l->f;
|
||||
e = v->e;
|
||||
|
||||
if (abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset)) == abs(face_set)) {
|
||||
return true;
|
||||
}
|
||||
if (UNLIKELY(!e)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
BMLoop *l = e->l;
|
||||
|
||||
if (UNLIKELY(!l)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
BMFace *f = l->f;
|
||||
|
||||
if (abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset)) == abs(face_set)) {
|
||||
return true;
|
||||
}
|
||||
} while ((l = l->radial_next) != e->l);
|
||||
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
|
||||
|
||||
return false;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
@@ -9321,7 +9334,8 @@ ATTR_NO_OPT static void SCULPT_run_command_list(
|
||||
break;
|
||||
case SCULPT_TOOL_DYNTOPO:
|
||||
if (has_dyntopo) {
|
||||
do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
|
||||
sculpt_topology_update(sd, ob, brush, ups);
|
||||
// do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
||||
}
|
||||
|
||||
if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
|
||||
if (!SCULPT_vertex_has_unique_face_set(ss, vert)) {
|
||||
if (SCULPT_vertex_is_boundary(ss, vert, SCULPT_BOUNDARY_FACE_SET)) {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user