From 0385e4df3cc30e5ccae1ff3c2abcf718a7d7b794 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 26 Oct 2022 19:27:12 +0200 Subject: Fix slow continuous depsgraph updates in sculpt paint mode in some cases Updates for cursor could cause the paint data to be continuously refreshed, which is pretty cheap by itself, but not when it starts tagging the depsgraph. The paint slot refresh code ideally should not be doing depsgraph tags at all, but checking if there were changes at least avoids continuous updates. --- source/blender/blenkernel/intern/material.c | 63 ++++++++++++++++------------- 1 file changed, 35 insertions(+), 28 deletions(-) (limited to 'source/blender/blenkernel/intern/material.c') diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 6c6d2298dbd..51e27f173c8 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1512,58 +1512,65 @@ static ePaintSlotFilter material_paint_slot_filter(const struct Object *ob) void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Object *ob) { - int count = 0; - if (!ma) { return; } const ePaintSlotFilter slot_filter = material_paint_slot_filter(ob); - /* COW needed when adding texture slot on an object with no materials. */ - DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE); + const TexPaintSlot *prev_texpaintslot = ma->texpaintslot; + const int prev_paint_active_slot = ma->paint_active_slot; + const int prev_paint_clone_slot = ma->paint_clone_slot; + const int prev_tot_slots = ma->tot_slots; - if (ma->texpaintslot) { - MEM_freeN(ma->texpaintslot); - ma->tot_slots = 0; - ma->texpaintslot = NULL; - } + ma->texpaintslot = NULL; + ma->tot_slots = 0; if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) { ma->paint_active_slot = 0; ma->paint_clone_slot = 0; - return; } - - if (!(ma->nodetree)) { + else if (!(ma->nodetree)) { ma->paint_active_slot = 0; ma->paint_clone_slot = 0; - return; } + else { + int count = count_texture_nodes_recursive(ma->nodetree, slot_filter); - count = count_texture_nodes_recursive(ma->nodetree, slot_filter); - - if (count == 0) { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + } + else { + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); - ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree); - bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree); + fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter); - fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter); + ma->tot_slots = count; - ma->tot_slots = count; + if (ma->paint_active_slot >= count) { + ma->paint_active_slot = count - 1; + } - if (ma->paint_active_slot >= count) { - ma->paint_active_slot = count - 1; + if (ma->paint_clone_slot >= count) { + ma->paint_clone_slot = count - 1; + } + } } - if (ma->paint_clone_slot >= count) { - ma->paint_clone_slot = count - 1; + /* COW needed when adding texture slot on an object with no materials. + * But do it only when slots actually change to avoid continuous depsgrap updates. */ + if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot || + ma->paint_clone_slot != prev_paint_clone_slot || + (ma->texpaintslot && prev_texpaintslot && + memcmp(ma->texpaintslot, prev_texpaintslot, sizeof(*ma->texpaintslot) * ma->tot_slots) != + 0)) { + DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE); } + + MEM_SAFE_FREE(prev_texpaintslot); } void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) -- cgit v1.2.3 From afc091c3c4bc86d4bb6165cbcdc9f17129d743e8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Nov 2022 12:24:06 +1100 Subject: Cleanup: spelling in comments --- source/blender/blenkernel/intern/material.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel/intern/material.c') diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 51e27f173c8..59530a6d6a6 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1450,7 +1450,7 @@ static bool fill_texpaint_slots_cb(bNode *node, void *userdata) NodeTexImage *storage = (NodeTexImage *)node->storage; slot->interp = storage->interpolation; slot->image_user = &storage->iuser; - /* for new renderer, we need to traverse the treeback in search of a UV node */ + /* For new renderer, we need to traverse the tree back in search of a UV node. */ bNode *uvnode = nodetree_uv_node_recursive(node); if (uvnode) { @@ -1561,7 +1561,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Ob } /* COW needed when adding texture slot on an object with no materials. - * But do it only when slots actually change to avoid continuous depsgrap updates. */ + * But do it only when slots actually change to avoid continuous depsgraph updates. */ if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot || ma->paint_clone_slot != prev_paint_clone_slot || (ma->texpaintslot && prev_texpaintslot && -- cgit v1.2.3