[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