More fixes for sculpt vertex color undo. Moved one of the undo pushes

outside a thread, since dyntopo undo is not thread safe.
This commit is contained in:
Joseph Eagar 2020-10-31 11:06:15 -07:00
parent 093e29f3c2
commit 1014b6f455
5 changed files with 82 additions and 18 deletions

View File

@ -624,6 +624,8 @@ struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node);
#define DYNTOPO_CD_INTERP
#ifdef __cplusplus

View File

@ -3153,6 +3153,10 @@ void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
pbvh->respect_hide = respect_hide;
}
int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node) {
return (int)(node - pbvh->nodes);
}
void BKE_pbvh_get_nodes(PBVH *pbvh, int flag, PBVHNode ***r_array, int *r_totnode)
{
BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), r_array, r_totnode);

View File

@ -5770,15 +5770,10 @@ static void do_brush_action_task_cb(void *__restrict userdata,
BKE_pbvh_node_mark_update_mask(data->nodes[n]);
}
else if (ELEM(data->brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
// make sure we have at least one undo_color node
if (!ss->bm || SCULPT_stroke_is_first_brush_step(ss->cache)) {
if (!ss->bm) { // this is thread safe for faces and grids pbvh?
SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
}
if (ss->bm) {
BKE_pbvh_update_origcolor_bmesh(ss->pbvh, data->nodes[n]);
}
BKE_pbvh_node_mark_update_color(data->nodes[n]);
}
else {
@ -5889,6 +5884,15 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
.nodes = nodes,
};
// dyntopo can't push undo nodes inside a thread
if (ss->bm) {
for (int i = 0; i < totnode; i++) {
//SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COLOR);
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
BKE_pbvh_update_origcolor_bmesh(ss->pbvh, nodes[i]);
}
}
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
@ -7710,6 +7714,8 @@ bool all_nodes_callback(PBVHNode *node, void *data)
return true;
}
void sculpt_undo_print_nodes(void *active);
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
{
/* After we are done drawing the stroke, check if we need to do a more
@ -7762,12 +7768,12 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
#if 0
if (update_flags & SCULPT_UPDATE_COLOR) {
PBVHNode **nodes;
int totnode = 0;
//BKE_pbvh_get_nodes(ss->pbvh, PBVH_UpdateColor, &nodes, &totnode);
// BKE_pbvh_get_nodes(ss->pbvh, PBVH_UpdateColor, &nodes, &totnode);
BKE_pbvh_search_gather(ss->pbvh, all_nodes_callback, NULL, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
@ -7778,6 +7784,9 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
MEM_freeN(nodes);
}
}
#endif
sculpt_undo_print_nodes(NULL);
}
if (update_flags & SCULPT_UPDATE_COLOR) {
@ -7959,7 +7968,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SCULPT_undo_push_end();
if (brush->sculpt_tool == SCULPT_TOOL_PAINT || brush->sculpt_tool == SCULPT_TOOL_SMEAR) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS|SCULPT_UPDATE_COLOR);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS | SCULPT_UPDATE_COLOR);
}
else if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);

View File

@ -636,6 +636,9 @@ typedef struct SculptUndoNode {
/* Sculpt Face Sets */
int *face_sets;
bool *nodemap;
int nodemap_size;
size_t undo_size;
} SculptUndoNode;
@ -1159,3 +1162,6 @@ void SCULPT_OT_set_detail_size(struct wmOperatorType *ot);
/* Dyntopo. */
void SCULPT_OT_dynamic_topology_toggle(struct wmOperatorType *ot);
bool SCULPT_ensure_dyntopo_node_undo(struct Object *ob,
struct PBVHNode *node,
SculptUndoType type);

View File

@ -116,7 +116,7 @@ typedef struct UndoSculpt {
} UndoSculpt;
static UndoSculpt *sculpt_undo_get_nodes(void);
static void sculpt_undo_print_nodes(void *active);
void sculpt_undo_print_nodes(void *active);
static void update_cb(PBVHNode *node, void *rebuild)
{
@ -599,7 +599,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
{
if (ss->bm_log) {
BM_log_set_cd_offsets(
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
}
switch (unode->type) {
@ -846,6 +846,9 @@ static void sculpt_undo_free_list(ListBase *lb)
if (unode->co) {
MEM_freeN(unode->co);
}
if (unode->nodemap) {
MEM_freeN(unode->nodemap);
}
if (unode->no) {
MEM_freeN(unode->no);
}
@ -1240,7 +1243,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
{
void *dummy;
BKE_pbvh_bmesh_update_origvert(ss->pbvh, vd.bm_vert, &dummy, &dummy, &dummy);
//BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset, false);
// BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset, false);
}
BKE_pbvh_vertex_iter_end;
break;
@ -1284,12 +1287,49 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
}
if (new_node) {
// sculpt_undo_print_nodes(NULL);
sculpt_undo_print_nodes(NULL);
}
return unode;
}
bool SCULPT_ensure_dyntopo_node_undo(Object *ob, PBVHNode *node, SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode = usculpt->nodes.first;
if (!unode || unode->type != type) {
sculpt_undo_bmesh_push(ob, node, type);
SCULPT_ensure_dyntopo_node_undo(ob, node, type);
return true;
}
int n = BKE_pbvh_get_node_index(ss->pbvh, node);
if (unode->nodemap_size <= n) {
int newsize = (n + 1) * 2;
if (!unode->nodemap) {
unode->nodemap = MEM_callocN(sizeof(*unode->nodemap) * newsize, "unode->nodemap");
}
else {
unode->nodemap = MEM_recallocN(unode->nodemap, sizeof(*unode->nodemap) * newsize);
}
unode->nodemap_size = newsize;
}
if (unode->nodemap[n]) {
return false;
}
unode->nodemap[n] = 1;
sculpt_undo_bmesh_push(ob, node, type);
return true;
}
SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
@ -1469,7 +1509,7 @@ static void sculpt_undosys_step_decode_undo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = false;
// sculpt_undo_print_nodes(us);
sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
@ -1480,7 +1520,7 @@ static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = true;
// sculpt_undo_print_nodes(us);
sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_undo(struct bContext *C,
@ -1737,8 +1777,9 @@ static char *undo_type_to_str(int type)
static int nodeidgen = 1;
static void sculpt_undo_print_nodes(void *active)
void sculpt_undo_print_nodes(void *active)
{
#if 0
UndoStack *ustack = ED_undo_stack_get();
UndoStep *us = ustack->steps.first;
if (active == NULL) {
@ -1771,12 +1812,14 @@ static void sculpt_undo_print_nodes(void *active)
UndoSculpt *usculpt = sculpt_undosys_step_get_nodes(us);
for (node = usculpt->nodes.first; node; node = node->next) {
printf(" %s:%s {applied=%d bm_entry=%p}\n",
printf(" %s:%s {applied=%d bm_entry=%p node=%p}\n",
undo_type_to_str(node->type),
node->idname,
node->applied,
node->bm_entry);
node->bm_entry,
node->node);
}
}
}
#endif
}