[Bf-blender-cvs] [f6fc863acd7] master: Sculpt: multithread GPU draw buffer filling for workbench

Brecht Van Lommel noreply at git.blender.org
Sun Sep 29 16:24:11 CEST 2019


Commit: f6fc863acd7c24874026202d4c2aec50c60b40d2
Author: Brecht Van Lommel
Date:   Fri Sep 27 22:42:57 2019 +0200
Branches: master
https://developer.blender.org/rBf6fc863acd7c24874026202d4c2aec50c60b40d2

Sculpt: multithread GPU draw buffer filling for workbench

This improves performance of some sculpt tools, particularly those that modify
many vertices like filter and mask tools, or use brushes with large radius.

For mask expand it can make updates up to 2x faster on heavy meshes, but for
most tools it's more on the order of 1-1.1x. There are bigger bottlenecks to
solve, like normal updates.

Ref T70295

Differential Revision: https://developer.blender.org/D5926

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/draw/intern/draw_manager_data.c
M	source/blender/gpu/GPU_buffers.h
M	source/blender/gpu/intern/gpu_buffers.c
M	source/blender/gpu/intern/gpu_init_exit.c
M	source/blender/gpu/intern/gpu_private.h

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 563546251bf..fa773ce78d9 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -173,6 +173,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
 /* Drawing */
 
 void BKE_pbvh_draw_cb(PBVH *bvh,
+                      bool show_vcol,
                       PBVHFrustumPlanes *frustum,
                       void (*draw_fn)(void *user_data, struct GPU_PBVH_Buffers *buffers),
                       void *user_data);
@@ -266,7 +267,6 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
 
 void BKE_pbvh_update_bounds(PBVH *bvh, int flags);
 void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
-void BKE_pbvh_update_draw_buffers(PBVH *bvh, bool show_vcol);
 void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
 void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface);
 void BKE_pbvh_grids_update(PBVH *bvh,
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index bfc513454b4..50ea4fb0b36 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -988,6 +988,7 @@ typedef struct PBVHUpdateData {
 
   float (*vnors)[3];
   int flag;
+  bool show_vcol;
 } PBVHUpdateData;
 
 static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
@@ -1148,71 +1149,105 @@ static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol)
   return update_flags;
 }
 
-static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, bool show_vcol)
-{
-  /* can't be done in parallel with OpenGL */
-  for (int n = 0; n < totnode; n++) {
-    PBVHNode *node = nodes[n];
-
-    if (node->flag & PBVH_RebuildDrawBuffers) {
-      GPU_pbvh_buffers_free(node->draw_buffers);
-      switch (bvh->type) {
-        case PBVH_GRIDS:
-          node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden);
-          break;
-        case PBVH_FACES:
-          node->draw_buffers = GPU_pbvh_mesh_buffers_build(node->face_vert_indices,
-                                                           bvh->mpoly,
-                                                           bvh->mloop,
-                                                           bvh->looptri,
-                                                           bvh->verts,
-                                                           node->prim_indices,
-                                                           node->totprim);
-          break;
-        case PBVH_BMESH:
-          node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
-                                                            PBVH_DYNTOPO_SMOOTH_SHADING);
-          break;
-      }
-
-      node->flag &= ~PBVH_RebuildDrawBuffers;
-    }
+static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
+                                       const int n,
+                                       const TaskParallelTLS *__restrict UNUSED(tls))
+{
+  /* Create and update draw buffers. The functions called here must not
+   * do any OpenGL calls. Flags are not cleared immediately, that happens
+   * after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */
+  PBVHUpdateData *data = userdata;
+  PBVH *bvh = data->bvh;
+  PBVHNode *node = data->nodes[n];
 
-    if (node->flag & PBVH_UpdateDrawBuffers) {
-      const int update_flags = pbvh_get_buffers_update_flags(bvh, show_vcol);
-      switch (bvh->type) {
-        case PBVH_GRIDS:
-          GPU_pbvh_grid_buffers_update(node->draw_buffers,
-                                       bvh->grids,
-                                       bvh->grid_flag_mats,
-                                       node->prim_indices,
-                                       node->totprim,
-                                       &bvh->gridkey,
-                                       update_flags);
-          break;
-        case PBVH_FACES:
-          GPU_pbvh_mesh_buffers_update(node->draw_buffers,
-                                       bvh->verts,
-                                       node->vert_indices,
-                                       node->uniq_verts + node->face_verts,
-                                       CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
-                                       CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
-                                       node->face_vert_indices,
-                                       update_flags);
-          break;
-        case PBVH_BMESH:
-          GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
-                                        bvh->bm,
-                                        node->bm_faces,
-                                        node->bm_unique_verts,
-                                        node->bm_other_verts,
-                                        update_flags);
-          break;
+  if (node->flag & PBVH_RebuildDrawBuffers) {
+    switch (bvh->type) {
+      case PBVH_GRIDS:
+        node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden);
+        break;
+      case PBVH_FACES:
+        node->draw_buffers = GPU_pbvh_mesh_buffers_build(node->face_vert_indices,
+                                                         bvh->mpoly,
+                                                         bvh->mloop,
+                                                         bvh->looptri,
+                                                         bvh->verts,
+                                                         node->prim_indices,
+                                                         node->totprim);
+        break;
+      case PBVH_BMESH:
+        node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
+                                                          PBVH_DYNTOPO_SMOOTH_SHADING);
+        break;
+    }
+  }
+
+  if (node->flag & PBVH_UpdateDrawBuffers) {
+    const int update_flags = pbvh_get_buffers_update_flags(bvh, data->show_vcol);
+    switch (bvh->type) {
+      case PBVH_GRIDS:
+        GPU_pbvh_grid_buffers_update(node->draw_buffers,
+                                     bvh->grids,
+                                     bvh->grid_flag_mats,
+                                     node->prim_indices,
+                                     node->totprim,
+                                     &bvh->gridkey,
+                                     update_flags);
+        break;
+      case PBVH_FACES:
+        GPU_pbvh_mesh_buffers_update(node->draw_buffers,
+                                     bvh->verts,
+                                     node->vert_indices,
+                                     node->uniq_verts + node->face_verts,
+                                     CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
+                                     CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
+                                     node->face_vert_indices,
+                                     update_flags);
+        break;
+      case PBVH_BMESH:
+        GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
+                                      bvh->bm,
+                                      node->bm_faces,
+                                      node->bm_unique_verts,
+                                      node->bm_other_verts,
+                                      update_flags);
+        break;
+    }
+  }
+}
+
+static void pbvh_update_draw_buffers(
+    PBVH *bvh, PBVHNode **nodes, int totnode, bool show_vcol, int update_flag)
+{
+  if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(bvh->type, PBVH_GRIDS, PBVH_BMESH)) {
+    /* Free buffers uses OpenGL, so not in parallel. */
+    for (int n = 0; n < totnode; n++) {
+      PBVHNode *node = nodes[n];
+      if (node->flag & PBVH_RebuildDrawBuffers) {
+        GPU_pbvh_buffers_free(node->draw_buffers);
+        node->draw_buffers = NULL;
+      }
+      else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) {
+        if (bvh->type == PBVH_GRIDS) {
+          GPU_pbvh_grid_buffers_update_free(
+              node->draw_buffers, bvh->grid_flag_mats, node->prim_indices);
+        }
+        else if (bvh->type == PBVH_BMESH) {
+          GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers);
+        }
       }
-
-      node->flag &= ~PBVH_UpdateDrawBuffers;
     }
   }
+
+  /* Parallel creation and update of draw buffers. */
+  PBVHUpdateData data = {
+      .bvh = bvh,
+      .nodes = nodes,
+      .show_vcol = show_vcol,
+  };
+
+  TaskParallelSettings settings;
+  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+  BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
 }
 
 static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -1568,8 +1603,8 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
 
 /**
  * \note doing a full search on all vertices here seems expensive,
- * however this is important to avoid having to recalculate boundbox & sync the buffers to the GPU
- * (which is far more expensive!) See: T47232.
+ * however this is important to avoid having to recalculate boundbox & sync the buffers to the
+ * GPU (which is far more expensive!) See: T47232.
  */
 bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node)
 {
@@ -2216,20 +2251,6 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data)
   return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
 }
 
-typedef struct PBVHNodeDrawCallbackData {
-  void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers);
-  void *user_data;
-} PBVHNodeDrawCallbackData;
-
-static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
-{
-  PBVHNodeDrawCallbackData *data = data_v;
-
-  if (!(node->flag & PBVH_FullyHidden)) {
-    data->draw_fn(data->user_data, node->draw_buffers);
-  }
-}
-
 void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
 {
   /* Update normals */
@@ -2260,41 +2281,67 @@ void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
   }
 }
 
-void BKE_pbvh_update_draw_buffers(PBVH *bvh, bool show_vcol)
+/**
+ * PBVH drawing, upda

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list