DrawManager: Cycles+GPencil
authorJeroen Bakker <j.bakker@atmind.nl>
Tue, 28 May 2019 07:11:55 +0000 (09:11 +0200)
committerJeroen Bakker <j.bakker@atmind.nl>
Wed, 29 May 2019 12:48:59 +0000 (14:48 +0200)
Fix for GPencil and Cycles Render draw type. GPencil objects were only
shown when overlays were turned on. The cause of this is an
optimization we did to not populate any draw engine when an
external renderer was used with overlays turned off.

This will check if there is any visible GPencil object in the scene. if
so it will still perform the loop.

`DEG_id_type_any_exists` can check if any object of a certain type_id is in the
result. This check is also being used to check if there are any
visible grease pencil objects as a precheck in `DRW_render_check_grease_pencil`.

Reviewed By: brecht, fclem, antoniov

Maniphest Tasks: T65191

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

source/blender/depsgraph/DEG_depsgraph_query.h
source/blender/depsgraph/intern/depsgraph.cc
source/blender/depsgraph/intern/depsgraph.h
source/blender/depsgraph/intern/depsgraph_query.cc
source/blender/draw/intern/draw_manager.c
source/blender/render/intern/source/external_engine.c

index b9cbd75..48a62a6 100644 (file)
@@ -67,6 +67,9 @@ float DEG_get_ctime(const Depsgraph *graph);
 bool DEG_id_type_updated(const struct Depsgraph *depsgraph, short id_type);
 bool DEG_id_type_any_updated(const struct Depsgraph *depsgraph);
 
+/* Check if given ID type is present in the depsgraph */
+bool DEG_id_type_any_exists(const struct Depsgraph *depsgraph, short id_type);
+
 /* Get additional evaluation flags for the given ID. */
 uint32_t DEG_get_eval_flags_for_id(const struct Depsgraph *graph, struct ID *id);
 
index 5d96bfa..d8a9b41 100644 (file)
@@ -38,6 +38,7 @@
 extern "C" {
 #include "BKE_scene.h"
 #include "BKE_global.h"
+#include "BKE_idcode.h"
 }
 
 #include "DEG_depsgraph.h"
@@ -81,6 +82,7 @@ Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
   entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
   debug_flags = G.debug;
   memset(id_type_updated, 0, sizeof(id_type_updated));
+  memset(id_type_exist, 0, sizeof(id_type_exist));
   memset(physics_relations, 0, sizeof(physics_relations));
 }
 
@@ -130,6 +132,8 @@ IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint)
      * referencing to. */
     BLI_ghash_insert(id_hash, id, id_node);
     id_nodes.push_back(id_node);
+
+    id_type_exist[BKE_idcode_to_index(GS(id->name))] = 1;
   }
   return id_node;
 }
index 073ec99..f194a44 100644 (file)
@@ -152,6 +152,9 @@ struct Depsgraph {
   /* Indicates which ID types were updated. */
   char id_type_updated[MAX_LIBARRAY];
 
+  /* Indicates type of IDs present in the depsgraph. */
+  char id_type_exist[MAX_LIBARRAY];
+
   /* Quick-Access Temp Data ............. */
 
   /* Nodes which have been tagged as "directly modified". */
index 326d852..0345f29 100644 (file)
@@ -95,6 +95,12 @@ bool DEG_id_type_any_updated(const Depsgraph *graph)
   return false;
 }
 
+bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
+{
+  const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
+  return deg_graph->id_type_exist[BKE_idcode_to_index(id_type)] != 0;
+}
+
 uint32_t DEG_get_eval_flags_for_id(const Depsgraph *graph, ID *id)
 {
   if (graph == NULL) {
index 47d0e97..8897d14 100644 (file)
@@ -999,13 +999,10 @@ void DRW_cache_free_old_batches(Main *bmain)
 
       /* TODO(fclem): This is not optimal since it iter over all dupli instances.
        * In this case only the source object should be tagged. */
-      int iter_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
-                       DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI;
-
-      DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flags) {
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
         DRW_batch_cache_free_old(ob, ctime);
       }
-      DEG_OBJECT_ITER_END;
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
     }
   }
 }
@@ -1366,7 +1363,9 @@ static void drw_engines_enable_basic(void)
   use_drw_engine(DRW_engine_viewport_basic_type.draw_engine);
 }
 
-static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_type)
+static void drw_engines_enable(ViewLayer *view_layer,
+                               RenderEngineType *engine_type,
+                               bool gpencil_engine_needed)
 {
   Object *obact = OBACT(view_layer);
   const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
@@ -1377,7 +1376,9 @@ static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_t
 
   drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
   /* grease pencil */
-  use_drw_engine(&draw_engine_gpencil_type);
+  if (gpencil_engine_needed) {
+    use_drw_engine(&draw_engine_gpencil_type);
+  }
 
   if (DRW_state_draw_support()) {
     /* Draw paint modes first so that they are drawn below the wireframes. */
@@ -1414,6 +1415,16 @@ static void drw_engines_data_validate(void)
   GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array);
 }
 
+/* Fast check to see if gpencil drawing engine is needed.
+ * For slow exact check use `DRW_render_check_grease_pencil` */
+static bool drw_gpencil_engine_needed(Depsgraph *depsgraph, View3D *v3d)
+{
+  const bool exclude_gpencil_rendering = v3d ? (v3d->object_type_exclude_viewport &
+                                                (1 << OB_GPENCIL)) != 0 :
+                                               false;
+  return (!exclude_gpencil_rendering) || DEG_id_type_any_exists(depsgraph, ID_GD);
+}
+
 /* -------------------------------------------------------------------- */
 /** \name View Update
  * \{ */
@@ -1428,6 +1439,8 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
   Scene *scene = update_ctx->scene;
   ViewLayer *view_layer = update_ctx->view_layer;
 
+  const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
+
   /* Separate update for each stereo view. */
   for (int view = 0; view < 2; view++) {
     GPUViewport *viewport = WM_draw_region_get_viewport(ar, view);
@@ -1456,7 +1469,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
         .object_mode = OB_MODE_OBJECT,
     };
 
-    drw_engines_enable(view_layer, engine_type);
+    drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
 
     for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
       DrawEngineType *draw_engine = link->data;
@@ -1541,8 +1554,17 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
   drw_context_state_init();
   drw_viewport_var_init();
 
+  const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
+  /* Check if scene needs to perform the populate loop */
+  const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
+  const bool draw_type_render = v3d->shading.type == OB_RENDER;
+  const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
+  const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
+  const bool do_populate_loop = internal_engine || overlays_on || !draw_type_render ||
+                                gpencil_engine_needed;
+
   /* Get list of enabled engines */
-  drw_engines_enable(view_layer, engine_type);
+  drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
 
   drw_engines_data_validate();
 
@@ -1565,15 +1587,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
     drw_engines_world_update(scene);
 
     /* Only iterate over objects for internal engines or when overlays are enabled */
-    const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
-    const bool draw_type_render = v3d->shading.type == OB_RENDER;
-    const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
-    if (internal_engine || overlays_on || !draw_type_render) {
-      const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
-      const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
-                            DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
-                            DEG_ITER_OBJECT_FLAG_DUPLI;
-      DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
+    if (do_populate_loop) {
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
         if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
           continue;
         }
@@ -1585,7 +1600,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
         drw_duplidata_load(DST.dupli_source);
         drw_engines_cache_populate(ob);
       }
-      DEG_OBJECT_ITER_END;
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
     }
 
     drw_duplidata_free();
@@ -1778,6 +1793,10 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
 /* Helper to check if exit object type to render. */
 bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
 {
+  if (!drw_gpencil_engine_needed(depsgraph, NULL)) {
+    return false;
+  }
+
   DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
     if (ob->type == OB_GPENCIL) {
       if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
@@ -2025,10 +2044,7 @@ void DRW_render_object_iter(
   const int object_type_exclude_viewport = draw_ctx->v3d ?
                                                draw_ctx->v3d->object_type_exclude_viewport :
                                                0;
-  const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
-                        DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
-                        DEG_ITER_OBJECT_FLAG_DUPLI;
-  DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
+  DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
     if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
       DST.dupli_parent = data_.dupli_parent;
       DST.dupli_source = data_.dupli_object_current;
@@ -2044,7 +2060,7 @@ void DRW_render_object_iter(
       }
     }
   }
-  DEG_OBJECT_ITER_END;
+  DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
 
   drw_duplidata_free();
 }
@@ -2282,13 +2298,10 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
       FOREACH_OBJECT_IN_MODE_END;
     }
     else {
-      const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
-                            DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
-                            DEG_ITER_OBJECT_FLAG_DUPLI;
       const int object_type_exclude_select = (v3d->object_type_exclude_viewport |
                                               v3d->object_type_exclude_select);
       bool filter_exclude = false;
-      DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
         if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
           continue;
         }
@@ -2318,7 +2331,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
           drw_engines_cache_populate(ob);
         }
       }
-      DEG_OBJECT_ITER_END;
+      DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
     }
 
     drw_duplidata_free();
@@ -2400,10 +2413,7 @@ static void drw_draw_depth_loop_imp(void)
 
     View3D *v3d = DST.draw_ctx.v3d;
     const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
-    const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
-                          DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
-                          DEG_ITER_OBJECT_FLAG_DUPLI;
-    DEG_OBJECT_ITER_BEGIN (DST.draw_ctx.depsgraph, ob, iter_flag) {
+    DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) {
       if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
         continue;
       }
@@ -2417,7 +2427,7 @@ static void drw_draw_depth_loop_imp(void)
       drw_duplidata_load(DST.dupli_source);
       drw_engines_cache_populate(ob);
     }
-    DEG_OBJECT_ITER_END;
+    DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
 
     drw_duplidata_free();
     drw_engines_cache_finish();
index a5bf5ad..a41f7bb 100644 (file)
@@ -867,8 +867,6 @@ void RE_engine_free_blender_memory(RenderEngine *engine)
   /* Weak way to save memory, but not crash grease pencil.
    *
    * TODO(sergey): Find better solution for this.
-   * TODO(sergey): Try to find solution which does not involve looping over
-   * all the objects.
    */
   if (DRW_render_check_grease_pencil(engine->depsgraph)) {
     return;