[Bf-blender-cvs] [c876bccb57a] greasepencil-object: GPencil: Update-on-write using update cache

Falk David noreply at git.blender.org
Wed Feb 2 09:51:45 CET 2022


Commit: c876bccb57a5760a56f13774c1cdbc1d65f9bcf5
Author: Falk David
Date:   Wed Feb 2 09:51:16 2022 +0100
Branches: greasepencil-object
https://developer.blender.org/rBc876bccb57a5760a56f13774c1cdbc1d65f9bcf5

GPencil: Update-on-write using update cache

This implements the update cache described in T95401 and uses it for drawing strokes as well as sculpting (using the push brush).

**Note: Making use of the cache throughout grease pencil will have to be done incrementally in other patches. **

Demo on an Intel® Core™ i7-9700 CPU @ 3.00GHz with 8 cores:
{F12839817 width=100%}

Remaining issues:
 - [ ] Fix memory leaks

Design task: T95401
Co-authored-by: @yann-lty

Maniphest Tasks: T95401

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

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

M	release/scripts/startup/bl_ui/space_userpref.py
M	source/blender/blenkernel/BKE_gpencil.h
A	source/blender/blenkernel/BKE_gpencil_update_cache.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/gpencil.c
A	source/blender/blenkernel/intern/gpencil_update_cache.c
M	source/blender/blenlib/BLI_dlrbTree.h
M	source/blender/blenlib/BLI_listbase.h
M	source/blender/blenlib/intern/DLRB_tree.c
M	source/blender/blenlib/intern/listbase.c
M	source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
M	source/blender/editors/gpencil/gpencil_paint.c
M	source/blender/editors/gpencil/gpencil_sculpt_paint.c
M	source/blender/makesdna/DNA_gpencil_types.h
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesrna/intern/rna_userdef.c

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

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 0548486c786..d19e73d6982 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2321,6 +2321,7 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
                 ({"property": "use_geometry_nodes_legacy"}, "T91274"),
                 ({"property": "show_asset_debug_info"}, None),
                 ({"property": "use_asset_indexing"}, None),
+                ({"property": "use_gpencil_update_cache"}, "T95401"),
             ),
         )
 
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 885d0c2fd90..4aec1e684af 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -48,6 +48,7 @@ struct bGPDlayer;
 struct bGPDlayer_Mask;
 struct bGPDstroke;
 struct bGPdata;
+struct GPencilUpdateCache;
 
 #define GPENCIL_SIMPLIFY(scene) (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)
 #define GPENCIL_SIMPLIFY_ONPLAY(playing) \
@@ -175,10 +176,28 @@ struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src, b
 struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src,
                                               bool dup_frames,
                                               bool dup_strokes);
+
+/**
+ * Make a copy of a given gpencil data settings.
+ */
+void BKE_gpencil_data_copy_settings(const struct bGPdata *gpd_src, struct bGPdata *gpd_dst);
+
 /**
  * Make a copy of a given gpencil layer settings.
  */
 void BKE_gpencil_layer_copy_settings(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst);
+
+/**
+ * Make a copy of a given gpencil frame settings.
+ */
+void BKE_gpencil_frame_copy_settings(const struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
+
+/**
+ * Make a copy of a given gpencil stroke settings.
+ */
+void BKE_gpencil_stroke_copy_settings(const struct bGPDstroke *gpf_src,
+                                      struct bGPDstroke *gpf_dst);
+
 /**
  * Make a copy of strokes between gpencil frames.
  * \param gpf_src: Source grease pencil frame
@@ -675,6 +694,9 @@ extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
  */
 void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
                                                 const struct bGPDframe *gpf_eval);
+
+void BKE_gpencil_layer_original_pointers_update(const struct bGPDlayer *gpl_orig,
+                                                const struct bGPDlayer *gpl_eval);
 /**
  * Update pointers of eval data to original data to keep references.
  * \param ob_orig: Original grease pencil object
@@ -682,6 +704,14 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig
  */
 void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval);
 
+/**
+ * Update pointers of eval data to original data to keep references.
+ * \param gpd_orig: Original grease pencil data
+ * \param gpd_eval: Evaluated grease pencil data
+ */
+void BKE_gpencil_data_update_orig_pointers(const struct bGPdata *gpd_orig,
+                                           const struct bGPdata *gpd_eval);
+
 /**
  * Get parent matrix, including layer parenting.
  * \param depsgraph: Depsgraph
@@ -711,6 +741,10 @@ int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char
 
 void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd);
 
+bool BKE_gpencil_check_copy_on_write_needed(struct bGPdata *gpd);
+
+void BKE_gpencil_update_on_write(struct bGPdata *gpd_orig, struct bGPdata *gpd_eval);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/BKE_gpencil_update_cache.h b/source/blender/blenkernel/BKE_gpencil_update_cache.h
new file mode 100644
index 00000000000..7ee1542c28d
--- /dev/null
+++ b/source/blender/blenkernel/BKE_gpencil_update_cache.h
@@ -0,0 +1,150 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_sys_types.h" /* for bool */
+
+struct DLRBT_Tree;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
+struct bGPDstroke;
+struct GPencilUpdateCache;
+
+/* GPencilUpdateCache.flag */
+typedef enum eGPUpdateCacheNodeFlag {
+  /* Node is a placeholder (e.g. when only an index is needed). */
+  GP_UPDATE_NODE_NO_COPY = -1,
+  /* Copy the element as well as all of its content. */
+  GP_UPDATE_NODE_FULL_COPY = 0,
+  /* Copy only element, not the content. */
+  GP_UPDATE_NODE_STRUCT_COPY = 1,
+} eGPUpdateCacheNodeFlag;
+
+/**
+ *  Cache for what needs to be updated after bGPdata was modified.
+ *
+ *  Every node holds information about one element that was changed:
+ *    - the index of where that element is in the linked-list
+ *    - the pointer to the original element in bGPdata
+ *  Additionally, nodes also hold other nodes that are one "level" below them.
+ *  E.g. a node that represents a change on a bGPDframe could contain a set of
+ *  nodes that represent a change on bGPDstrokes.
+ *  These nodes are stored in a red-black tree so that they are sorted by their
+ *  index to make sure they can be processed in the correct order.
+ */
+typedef struct GPencilUpdateCache {
+  /* Mapping from index to a GPencilUpdateCache struct. */
+  struct DLRBT_Tree *children;
+  /* eGPUpdateCacheNodeFlag */
+  int flag;
+  /* Index of the element in the linked-list. */
+  int index;
+  /* Pointer to one of bGPdata, bGPDLayer, bGPDFrame, bGPDStroke. */
+  void *data;
+} GPencilUpdateCache;
+
+/* Node structure in the DLRBT_Tree for GPencilUpdateCache mapping. */
+typedef struct GPencilUpdateCacheNode {
+  /* DLRB tree capabilities. */
+  struct GPencilUpdateCacheNode *next, *prev;
+  struct GPencilUpdateCacheNode *left, *right;
+  struct GPencilUpdateCacheNode *parent;
+  char tree_col;
+
+  char _pad[7];
+  /* Content of DLRB tree node. */
+  GPencilUpdateCache *cache;
+} GPencilUpdateCacheNode;
+
+/**
+ * Callback that is called in BKE_gpencil_traverse_update_cache at each level.
+ * \param cache: The cache at this level.
+ * \param user_data: Pointer to the user_data passed to BKE_gpencil_traverse_update_cache.
+ */
+typedef bool (*GPencilUpdateCacheIter_Cb)(GPencilUpdateCache *cache, void *user_data);
+
+typedef struct GPencilUpdateCacheTraverseSettings {
+  /* Callbacks for the update cache traversal. Callback with index 0 is for layers, 1 for frames
+   * and 2 for strokes. */
+  GPencilUpdateCacheIter_Cb update_cache_cb[3];
+} GPencilUpdateCacheTraverseSettings;
+
+/**
+ * Allocates a new GPencilUpdateCache and populates it.
+ * \param data: A data pointer to populate the initial cache with.
+ * \param full_copy: If true, will mark this update cache as a full copy
+ * (GP_UPDATE_NODE_FULL_COPY). If false, it will be marked as a struct copy
+ * (GP_UPDATE_NODE_STRUCT_COPY).
+ */
+GPencilUpdateCache *BKE_gpencil_create_update_cache(void *data, bool full_copy);
+
+/**
+ * Traverses an update cache and executes callbacks at each level.
+ * \param cache: The update cache to traverse.
+ * \param ts: The traversal settings. This stores the callbacks that are called at each level.
+ * \param user_data: Custom data passed to each callback.
+ */
+void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache,
+                                       GPencilUpdateCacheTraverseSettings *ts,
+                                       void *user_data);
+
+/**
+ * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) and all of its containing data to
+ * be updated in the next update-on-write operation.
+ *
+ * The function assumes that when a parameter is NULL all of the following parameters are NULL too.
+ * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
+ */
+void BKE_gpencil_tag_full_update(struct bGPdata *gpd,
+                                 struct bGPDlayer *gpl,
+                                 struct bGPDframe *gpf,
+                                 struct bGPDstroke *gps);
+
+/**
+ * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) to be updated in the next
+ * update-on-write operation. This function will not update any of the containing data, only the
+ * struct itself.
+ *
+ * The function assumes that when a parameter is NULL all of the following parameters are NULL too.
+ * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
+ */
+void BKE_gpencil_tag_struct_update(struct bGPdata *gpd,
+                                   struct bGPDlayer *gpl,
+                                   struct bGPDframe *gpf,
+                                   struct bGPDstroke *gps);
+
+/**
+ * Frees the GPencilUpdateCache on the gpd->runtime. This will not free the data that the cache
+ * node might point to. It assumes that the cache does not own the data.
+ */
+void BKE_gpencil_free_update_cache(struct bGPdata *gpd);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 05902e94552..a6c1ac48875 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -156,6 +156,7 @@ set(SRC
   intern/gpencil_curve.c
   intern/gpenci

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list