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. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs