[Bf-blender-cvs] [5196533f91f] greasepencil-refactor: GPencil: Refactor: Make sbuffer batches managment more robust

Clément Foucault noreply at git.blender.org
Thu Jan 9 16:00:18 CET 2020


Commit: 5196533f91f6b2e783a76c3f9ffafb4e05511b22
Author: Clément Foucault
Date:   Wed Jan 8 18:50:54 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB5196533f91f6b2e783a76c3f9ffafb4e05511b22

GPencil: Refactor: Make sbuffer batches managment more robust

This fix the slowdown issue caused by the triangulation of the stroke even
when fill wasn't needed. Now the fill buffer is only computed on demand.

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

M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/intern/draw_cache_impl_gpencil.c
M	source/blender/makesdna/DNA_gpencil_types.h

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 4978c46beab..ef02da6f5ef 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -207,12 +207,16 @@ void GPENCIL_cache_init(void *ved)
     pd->fill_batch = NULL;
     pd->do_fast_drawing = false;
 
-    Object *ob = draw_ctx->obact;
-    if (ob && ob->type == OB_GPENCIL) {
+    pd->obact = draw_ctx->obact;
+    if (pd->obact && pd->obact->type == OB_GPENCIL) {
       /* Check if active object has a temp stroke data. */
-      if (DRW_cache_gpencil_sbuffer_get(
-              ob, &pd->stroke_batch, &pd->fill_batch, &pd->sbuffer_stroke)) {
-        pd->sbuffer_gpd = (bGPdata *)ob->data;
+      bGPdata *gpd = (bGPdata *)pd->obact->data;
+      /* Current stroke data is stored in the original id. This is waiting refactor of the
+       * Depsgraph to support more granular update of the GPencil data. */
+      bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
+      if (gpd_orig->runtime.sbuffer_used > 0) {
+        pd->sbuffer_gpd = gpd;
+        pd->sbuffer_stroke = DRW_cache_gpencil_sbuffer_stroke_data_get(pd->obact);
         pd->sbuffer_layer = BKE_gpencil_layer_active_get(pd->sbuffer_gpd);
         pd->do_fast_drawing = false; /* TODO option */
       }
@@ -462,17 +466,19 @@ static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
     }
   }
 
+  bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW);
+
   if (show_fill) {
-    GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
-    geom = (iter->do_sbuffer_call == DRAW_NOW) ? iter->pd->fill_batch : geom;
+    GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_fill_get(iter->ob) :
+                                  DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
     int vfirst = gps->runtime.fill_start * 3;
     int vcount = gps->tot_triangles * 3;
     DRW_shgroup_call_range(iter->grp, iter->ob, geom, vfirst, vcount);
   }
 
   if (show_stroke) {
-    GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra);
-    geom = (iter->do_sbuffer_call == DRAW_NOW) ? iter->pd->stroke_batch : geom;
+    GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_stroke_get(iter->ob) :
+                                  DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra);
     /* Start one vert before to have gl_InstanceID > 0 (see shader). */
     int vfirst = gps->runtime.stroke_start - 1;
     /* Include "potential" cyclic vertex and start adj vertex (see shader). */
@@ -836,9 +842,9 @@ void GPENCIL_draw_scene(void *ved)
   pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
 
   /* Free temp stroke buffers. */
-  GPU_BATCH_DISCARD_SAFE(pd->stroke_batch);
-  GPU_BATCH_DISCARD_SAFE(pd->fill_batch);
-  MEM_SAFE_FREE(pd->sbuffer_stroke);
+  if (pd->sbuffer_gpd) {
+    DRW_cache_gpencil_sbuffer_clear(pd->obact);
+  }
 }
 
 static const DrawEngineDataSize GPENCIL_data_size = DRW_VIEWPORT_DATA_SIZE(GPENCIL_Data);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 3b83001f9be..0cb417fd467 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -296,6 +296,8 @@ typedef struct GPENCIL_PrivateData {
   /* Used for DoF Setup. */
   Object *camera;
 
+  /* Active object. */
+  Object *obact;
   /* Object being in draw mode. */
   struct bGPdata *sbuffer_gpd;
   /* Layer to append the temp stroke to. */
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 84a37fc98e3..9736233fc35 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -209,14 +209,14 @@ struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob);
 struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold);
 
 /* GPencil */
-
 struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
 struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_edit_lines_get(Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra);
-bool DRW_cache_gpencil_sbuffer_get(struct Object *ob,
-                                   struct GPUBatch **r_stroke_batch,
-                                   struct GPUBatch **r_fill_batch,
-                                   struct bGPDstroke **r_stroke);
+struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);
+void DRW_cache_gpencil_sbuffer_clear(struct Object *ob);
+
+struct bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(struct Object *ob);
 
 #endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index d1927f23328..b3ad1dc4f30 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -391,97 +391,153 @@ GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra)
   return cache->fill_batch;
 }
 
-/* Return true if there is anything to draw. */
-bool DRW_cache_gpencil_sbuffer_get(Object *ob,
-                                   GPUBatch **r_stroke_batch,
-                                   GPUBatch **r_fill_batch,
-                                   bGPDstroke **r_stroke)
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Sbuffer stroke batches.
+ * \{ */
+
+bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
 {
   bGPdata *gpd = (bGPdata *)ob->data;
   /* Current stroke data is stored in the original id. This is waiting refactor of the
-   * Depsgraph to support more granular update of the GPencil data.  */
-  bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
-  tGPspoint *tpoints = gpd_orig->runtime.sbuffer;
-  int vert_len = gpd_orig->runtime.sbuffer_used;
+   * Depsgraph to support more granular update of the GPencil data. */
+  gpd = (bGPdata *)DEG_get_original_id(&gpd->id);
 
-  if (vert_len <= 0) {
-    *r_stroke_batch = NULL;
-    *r_fill_batch = NULL;
-    return false;
+  /* Convert the sbuffer to a bGPDstroke. */
+  if (gpd->runtime.sbuffer_gps == NULL) {
+    bGPDstroke *gps = MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer");
+    gps->totpoints = gpd->runtime.sbuffer_used;
+    gps->mat_nr = gpd->runtime.matid - 1;
+    gps->flag = gpd->runtime.sbuffer_sflag;
+    gps->thickness = gpd->runtime.brush_size;
+    gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2);
+    gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND;
+    gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */
+
+    gpd->runtime.sbuffer_gps = gps;
   }
+  return gpd->runtime.sbuffer_gps;
+}
 
-  const DRWContextState *draw_ctx = DRW_context_state_get();
-  Scene *scene = draw_ctx->scene;
-  ARegion *ar = draw_ctx->ar;
+/* gpd is original ID. */
+static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill)
+{
+  tGPspoint *tpoints = gpd->runtime.sbuffer;
+  bGPDstroke *gps = gpd->runtime.sbuffer_gps;
+  int vert_len = gpd->runtime.sbuffer_used;
 
-  /* Get origin to reproject points. */
-  float origin[3];
-  bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
-  ToolSettings *ts = scene->toolsettings;
-  ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin);
+  /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */
+  BLI_assert(gps != NULL);
 
-  /* Convert the sbuffer to a bGPDstroke. */
-  bGPDstroke *gps = *r_stroke = MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer");
-  gps->totpoints = vert_len;
-  gps->mat_nr = gpd_orig->runtime.matid - 1;
-  gps->flag = gpd_orig->runtime.sbuffer_sflag;
-  gps->thickness = gpd_orig->runtime.brush_size;
-  gps->tot_triangles = max_ii(0, vert_len - 2);
-  gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND;
-  gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */
-  gps->points = MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
-
-  for (int i = 0; i < vert_len; i++) {
-    ED_gpencil_tpoint_to_point(ar, origin, &tpoints[i], &gps->points[i]);
-    mul_m4_v3(ob->imat, &gps->points[i].x);
-  }
+  if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) {
+    gps->points = MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
 
-  /* Create VBO. */
-  GPUVertFormat *format = gpencil_stroke_format();
-  GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format);
-  /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */
-  GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2);
-  gpStrokeVert *verts = (gpStrokeVert *)vbo->data;
-  /* Create IBO. */
-  GPUIndexBufBuilder ibo_builder;
-  GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len);
+    const DRWContextState *draw_ctx = DRW_context_state_get();
+    Scene *scene = draw_ctx->scene;
+    ARegion *ar = draw_ctx->ar;
+    Object *ob = draw_ctx->obact;
 
-  /* Fill buffers with data. */
-  gpencil_buffer_add_stroke(verts, gps);
+    BLI_assert(ob && (ob->type == OB_GPENCIL));
+
+    /* Get origin to reproject points. */
+    float origin[3];
+    bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+    ToolSettings *ts = scene->toolsettings;
+    ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin);
 
-  if (gps->tot_triangles > 0) {
-    float(*tpoints2d)[2] = MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__);
-    /* Triangulate in 2D. */
     for (int i = 0; i < vert_len; i++) {
-      copy_v2_v2(tpoints2d[i], &tpoints[i].x);
+      ED_gpencil_tpoint_to_point(ar, origin, &tpoints[i], &gps->points[i]);
+      mul_m4_v3(ob->imat, &gps->points[i].x);
     }
-    /* Compute directly inside the IBO d

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list