[Bf-blender-cvs] [47a14ef4adc] sculpt-dev: sculpt-dev: Fix draw cache bug

Joseph Eagar noreply at git.blender.org
Tue Jun 14 18:55:34 CEST 2022


Commit: 47a14ef4adc53705aee722bb406c3f854791005f
Author: Joseph Eagar
Date:   Tue Jun 14 09:52:34 2022 -0700
Branches: sculpt-dev
https://developer.blender.org/rB47a14ef4adc53705aee722bb406c3f854791005f

sculpt-dev: Fix draw cache bug

Fix the pbvh draw optimization that only sends
active attributes to the GPU. The solution here
is the original sculpt-dev one (somehow this
ended up being removed but not replaced in the
pbvh-eevee patch).

It works by checking every viewport in every
window and if it finds eevee or workbench
in material mode it sets a flag in the pbvh
to forcibly upload all attributes.

Another approach is to simply rewrite pbvh
draw properly inside the draw manager to
begin with.

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

M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_draw.c

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

diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 632458019fb..3ed45fde5a4 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -870,7 +870,9 @@ void BKE_pbvh_free(PBVH *pbvh)
 
 void BKE_pbvh_need_full_render_set(PBVH *pbvh, bool state)
 {
-  GPU_pbvh_need_full_render_set(pbvh->vbo_id, state);
+  if (pbvh->vbo_id) {
+    GPU_pbvh_need_full_render_set(pbvh->vbo_id, state);
+  }
 }
 
 static void pbvh_iter_begin(PBVHIter *iter,
@@ -1657,7 +1659,7 @@ void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node)
   }
 }
 
-static void pbvh_check_draw_layout(PBVH *pbvh, bool full_render)
+ATTR_NO_OPT static void pbvh_check_draw_layout(PBVH *pbvh, bool full_render)
 {
   const CustomData *vdata;
   const CustomData *ldata;
@@ -1687,6 +1689,8 @@ static void pbvh_check_draw_layout(PBVH *pbvh, bool full_render)
 
   /* rebuild all draw buffers if attribute layout changed */
   if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, !full_render)) {
+    printf("%s: draw update\n", __func__);
+
     /* attribute layout changed; force rebuild */
     for (int i = 0; i < pbvh->totnode; i++) {
       PBVHNode *node = pbvh->nodes + i;
@@ -1701,29 +1705,10 @@ static void pbvh_check_draw_layout(PBVH *pbvh, bool full_render)
 static void pbvh_update_draw_buffers(
     PBVH *pbvh, Mesh *me, PBVHNode **nodes, int totnode, int update_flag)
 {
-  const CustomData *vdata;
-
   if (!pbvh->vbo_id) {
     pbvh->vbo_id = GPU_pbvh_make_format();
   }
 
-  switch (pbvh->type) {
-    case PBVH_BMESH:
-      if (!pbvh->bm) {
-        /* BMesh hasn't been created yet */
-        return;
-      }
-
-      vdata = &pbvh->bm->vdata;
-      break;
-    case PBVH_FACES:
-      vdata = pbvh->vdata;
-      break;
-    case PBVH_GRIDS:
-      vdata = NULL;
-      break;
-  }
-
   if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
     /* Free buffers uses OpenGL, so not in parallel. */
     for (int n = 0; n < totnode; n++) {
@@ -3265,6 +3250,10 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
   int totnode;
   int update_flag = 0;
 
+  if (pbvh->vbo_id) {
+    full_render |= GPU_pbvh_need_full_render_get(pbvh->vbo_id);
+  }
+
   pbvh->draw_cache_invalid = false;
 
   /* Search for nodes that need updates. */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ac06ababfd4..3ba41a79841 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -36,6 +36,7 @@ struct ImBuf;
 struct ImageFormatData;
 struct Main;
 struct MenuType;
+struct PBVH;
 struct PointerRNA;
 struct PropertyRNA;
 struct ScrArea;
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index e27a6aaefbc..a6e544ebe57 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -27,10 +27,10 @@
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
-#include "BKE_pbvh.h"
-#include "BKE_paint.h"
 
 #include "GHOST_C-api.h"
 
@@ -1194,16 +1194,24 @@ void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(region))
   }
 }
 
-static void pbvh_full_render_update(PBVH *pbvh, bContext *C, Main *bmain, wmWindowManager *wm)
+static void wm_pbvh_full_render_update(bContext *C)
 {
+  Main *bmain = CTX_data_main(C);
+  wmWindowManager *wm = CTX_wm_manager(C);
 
-  /*We can save GPU bandwidth for PBVH drawing if we know for sure that no
-    viewport has EEVEE running in it.  As in no viewport in any windows.
+  /*
+   * We can save GPU bandwidth for PBVH drawing if we know for sure that no
+   * viewport has EEVEE running in it.  As in no viewport in any windows.
+   *
+   * This saves us from having to upload every possible attribute eevee
+   * might need.
+   *
+   * This is because PBVH only supplies one set of drawing buffers
+   * to the draw manager.  Creating more buffers for specific drawengines
+   * is simply not feasible for performance reasons.
+   */
 
-    This is because PBVH only supplies one set of drawing buffers
-    to the draw manager.  Creating more buffers for specific drawengines
-    is simply not feasible for performance reasons.
-    */
+  bool need_full_render = false;
 
   LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
     GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
@@ -1214,7 +1222,12 @@ static void pbvh_full_render_update(PBVH *pbvh, bContext *C, Main *bmain, wmWind
 
     CTX_wm_window_set(C, win);
 
-    BKE_pbvh_need_full_render_set(pbvh, false);
+    Object *ob = CTX_data_active_object(C);
+    if (!ob || !(ob->mode & OB_MODE_SCULPT) || !ob->sculpt || !ob->sculpt->pbvh) {
+      continue;
+    }
+
+    BKE_pbvh_need_full_render_set(ob->sculpt->pbvh, false);
 
     if (wm_draw_update_test_window(bmain, C, win)) {
       bScreen *screen = WM_window_get_active_screen(win);
@@ -1226,13 +1239,31 @@ static void pbvh_full_render_update(PBVH *pbvh, bContext *C, Main *bmain, wmWind
         }
 
         CTX_wm_area_set(C, area);
+
         View3D *v3d = CTX_wm_view3d(C);
-        if (v3d->shading.type >= OB_MATERIAL) {
-          BKE_pbvh_need_full_render_set(pbvh, true);
-        }
+
+        need_full_render |= v3d->shading.type >= OB_MATERIAL;
+        need_full_render |= v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR;
       }
     }
   }
+
+  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
+    GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
+
+    if (state == GHOST_kWindowStateMinimized) {
+      continue;
+    }
+
+    CTX_wm_window_set(C, win);
+
+    Object *ob = CTX_data_active_object(C);
+    if (!ob || !(ob->mode & OB_MODE_SCULPT) || !ob->sculpt || !ob->sculpt->pbvh) {
+      continue;
+    }
+
+    BKE_pbvh_need_full_render_set(ob->sculpt->pbvh, need_full_render);
+  }
 }
 
 void wm_draw_update(bContext *C)
@@ -1247,11 +1278,6 @@ void wm_draw_update(bContext *C)
 
   BKE_image_free_unused_gpu_textures();
 
-  Object *ob = CTX_data_active_object(C);
-  if (ob && (ob->mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->pbvh) {
-    pbvh_full_render_update(ob->sculpt->pbvh, C, bmain, wm);
-  }
-
   LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
 #ifdef WIN32
     GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
@@ -1267,6 +1293,8 @@ void wm_draw_update(bContext *C)
 
     CTX_wm_window_set(C, win);
 
+    wm_pbvh_full_render_update(C);
+
     if (wm_draw_update_test_window(bmain, C, win)) {
       bScreen *screen = WM_window_get_active_screen(win);



More information about the Bf-blender-cvs mailing list