[Bf-blender-cvs] [8dfe5b236e9] blender-v3.3-release: Fix slow continuous depsgraph updates in sculpt paint mode in some cases

Brecht Van Lommel noreply at git.blender.org
Mon Nov 28 17:05:24 CET 2022


Commit: 8dfe5b236e9fc057a372050985c4931a55bbb167
Author: Brecht Van Lommel
Date:   Wed Oct 26 19:27:12 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rB8dfe5b236e9fc057a372050985c4931a55bbb167

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.

===================================================================

M	source/blender/blenkernel/intern/material.c

===================================================================

diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index df2c48aaac5..c0d57cc20e6 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1496,58 +1496,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)



More information about the Bf-blender-cvs mailing list