Subdiv: Enable topology cache in edit mode
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 18 Mar 2019 14:56:16 +0000 (15:56 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 18 Mar 2019 16:11:43 +0000 (17:11 +0100)
The general idea of this change is to have a runtime data pointer
in the ModifierData, so it can be preserved through copy-on-write
updates by the dependency graph.

This is where subdivision surface modifier can store its topology
cache, so it is not getting trashed on every copy-on-write which
is happening when moving a vertex.

Similar mechanism should be used by multiresolution, dynamic paint
and some other modifiers which cache evaluated data.

This fixes T61746.

Thing to keep in mind, that there are more reports about slow
subdivision surface in the tracker, but that boils down to the
fact that those have a lot of extraordinary vertices, and hence
a lot slower to evaluated topology.
Other thing is, this speeds up oeprations which doesn't change
topology (i.e. moving vertices).

Reviewers: brecht

Reviewed By: brecht

Maniphest Tasks: T61746

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

60 files changed:
source/blender/blenkernel/BKE_modifier.h
source/blender/blenloader/intern/readfile.c
source/blender/depsgraph/intern/depsgraph_type.h
source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
source/blender/makesdna/DNA_modifier_types.h
source/blender/modifiers/intern/MOD_armature.c
source/blender/modifiers/intern/MOD_array.c
source/blender/modifiers/intern/MOD_bevel.c
source/blender/modifiers/intern/MOD_boolean.c
source/blender/modifiers/intern/MOD_build.c
source/blender/modifiers/intern/MOD_cast.c
source/blender/modifiers/intern/MOD_cloth.c
source/blender/modifiers/intern/MOD_collision.c
source/blender/modifiers/intern/MOD_correctivesmooth.c
source/blender/modifiers/intern/MOD_curve.c
source/blender/modifiers/intern/MOD_datatransfer.c
source/blender/modifiers/intern/MOD_decimate.c
source/blender/modifiers/intern/MOD_displace.c
source/blender/modifiers/intern/MOD_dynamicpaint.c
source/blender/modifiers/intern/MOD_edgesplit.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_fluidsim.c
source/blender/modifiers/intern/MOD_hook.c
source/blender/modifiers/intern/MOD_laplaciandeform.c
source/blender/modifiers/intern/MOD_laplaciansmooth.c
source/blender/modifiers/intern/MOD_lattice.c
source/blender/modifiers/intern/MOD_mask.c
source/blender/modifiers/intern/MOD_meshcache.c
source/blender/modifiers/intern/MOD_meshdeform.c
source/blender/modifiers/intern/MOD_meshsequencecache.c
source/blender/modifiers/intern/MOD_mirror.c
source/blender/modifiers/intern/MOD_multires.c
source/blender/modifiers/intern/MOD_none.c
source/blender/modifiers/intern/MOD_normal_edit.c
source/blender/modifiers/intern/MOD_ocean.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/modifiers/intern/MOD_particlesystem.c
source/blender/modifiers/intern/MOD_remesh.c
source/blender/modifiers/intern/MOD_screw.c
source/blender/modifiers/intern/MOD_shapekey.c
source/blender/modifiers/intern/MOD_shrinkwrap.c
source/blender/modifiers/intern/MOD_simpledeform.c
source/blender/modifiers/intern/MOD_skin.c
source/blender/modifiers/intern/MOD_smoke.c
source/blender/modifiers/intern/MOD_smooth.c
source/blender/modifiers/intern/MOD_softbody.c
source/blender/modifiers/intern/MOD_solidify.c
source/blender/modifiers/intern/MOD_subsurf.c
source/blender/modifiers/intern/MOD_surface.c
source/blender/modifiers/intern/MOD_surfacedeform.c
source/blender/modifiers/intern/MOD_triangulate.c
source/blender/modifiers/intern/MOD_uvproject.c
source/blender/modifiers/intern/MOD_uvwarp.c
source/blender/modifiers/intern/MOD_warp.c
source/blender/modifiers/intern/MOD_wave.c
source/blender/modifiers/intern/MOD_weighted_normal.c
source/blender/modifiers/intern/MOD_weightvgedit.c
source/blender/modifiers/intern/MOD_weightvgmix.c
source/blender/modifiers/intern/MOD_weightvgproximity.c
source/blender/modifiers/intern/MOD_wireframe.c

index 1a1e510b9e1c0a275652adf335b217cdfbfa891b..22782b675f5c511e70a23b7e469e95033f174d45 100644 (file)
@@ -233,6 +233,8 @@ typedef struct ModifierTypeInfo {
        /* Free internal modifier data variables, this function should
         * not free the md variable itself.
         *
+        * This function is responsible for freeing the runtime data as well.
+        *
         * This function is optional.
         */
        void (*freeData)(struct ModifierData *md);
@@ -301,6 +303,18 @@ typedef struct ModifierTypeInfo {
         */
        void (*foreachTexLink)(struct ModifierData *md, struct Object *ob,
                               TexWalkFunc walk, void *userData);
+
+       /* Free given runtime data.
+        *
+        * This data is coming from a modifier of the corresponding type, but actual
+        * modifier data is not known here.
+        *
+        * Notes:
+        *  - The data itself is to be de-allocated as well.
+        *  - This calback is allowed to receive NULL pointer as a data, so it's
+        *    more like "ensure the data is freed".
+        */
+       void (*freeRuntimeData)(void *runtime_data);
 } ModifierTypeInfo;
 
 /* Initialize modifier's global data (type info and some common global storages). */
index 9a886f494cf0efc0988cff7d9913985fe4eed0cb..93ef7fe5b73c1c3eba7a3c55fe29bc2079992d50 100644 (file)
@@ -5458,6 +5458,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
 
        for (md = lb->first; md; md = md->next) {
                md->error = NULL;
+               md->runtime = NULL;
 
                /* if modifiers disappear, or for upward compatibility */
                if (NULL == modifierType_getInfo(md->type))
@@ -5467,7 +5468,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        SubsurfModifierData *smd = (SubsurfModifierData *)md;
 
                        smd->emCache = smd->mCache = NULL;
-                       smd->subdiv = NULL;
                }
                else if (md->type == eModifierType_Armature) {
                        ArmatureModifierData *amd = (ArmatureModifierData *)md;
index d34b6d724cbe4b50133e0654712bb82d86cae88e..d96c621f4b2ccd8804d34252aa8a11d63607d3c5 100644 (file)
@@ -36,6 +36,8 @@
 #include <string>
 #include <vector>
 #include <algorithm>
+#include <map>
+#include <unordered_map>
 
 struct Depsgraph;
 
@@ -46,10 +48,14 @@ namespace DEG {
 /* Commonly used types. */
 using std::string;
 using std::vector;
+using std::map;
+using std::pair;
+using std::unordered_map;
 
 /* Commonly used functions. */
 using std::max;
 using std::to_string;
+using std::make_pair;
 
 /* Function bindings. */
 using std::function;
index cae84c3e535ff6b9311141e2ec07930fb36aae38..5e8516d744c31a56c826aa4a53445707d6d0558c 100644 (file)
@@ -83,6 +83,7 @@ extern "C" {
 #include "BKE_armature.h"
 #include "BKE_editmesh.h"
 #include "BKE_library_query.h"
+#include "BKE_modifier.h"
 #include "BKE_object.h"
 }
 
@@ -846,43 +847,119 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
                                                  create_placeholders);
 }
 
+namespace {
+
+/* Identifier used to match modifiers to backup/restore their runtime data.
+ * Identification is happening using original modifier data pointer and the
+ * modifier type.
+ * It is not enough to only pointer, since it's possible to have a situation
+ * when modifier is removed and a new one added, and due to memory allocation
+ * policy they might have same pointer.
+ * By adding type into matching we are at least ensuring that modifier will not
+ * try to interpret runtime data created by another modifier type. */
+class ModifierDataBackupID {
+public:
+       ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None)
+       {
+       }
+
+       ModifierDataBackupID(ModifierData *modifier_data, ModifierType type)
+               : modifier_data(modifier_data),
+                 type(type)
+       {
+       }
+
+       bool operator <(const ModifierDataBackupID& other) const {
+               if (modifier_data < other.modifier_data) {
+                       return true;
+               }
+               if (modifier_data == other.modifier_data) {
+                       return static_cast<int>(type) < static_cast<int>(other.type);
+               }
+               return false;
+       }
+
+       ModifierData *modifier_data;
+       ModifierType type;
+};
+
+/* Storage for backed up runtime modifier data. */
+typedef map<ModifierDataBackupID, void*> ModifierRuntimeDataBackup;
+
 struct ObjectRuntimeBackup {
+       ObjectRuntimeBackup()
+               : base_flag(0),
+                 base_local_view_bits(0)
+       {
+               /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
+               memset(&runtime, 0, sizeof(runtime));
+       }
+
+       /* Make a backup of object's evaluation runtime data, additionally
+        * make object to be safe for free without invalidating backed up
+        * pointers. */
+       void init_from_object(Object *object);
+       void backup_modifier_runtime_data(Object *object);
+
+       /* Restore all fields to the given object. */
+       void restore_to_object(Object *object);
+       /* NOTE: Will free all runtime data which has not been restored. */
+       void restore_modifier_runtime_data(Object *object);
+
        Object_Runtime runtime;
        short base_flag;
        unsigned short base_local_view_bits;
+       ModifierRuntimeDataBackup modifier_runtime_data;
 };
 
-/* Make a backup of object's evaluation runtime data, additionally
- * make object to be safe for free without invalidating backed up
- * pointers. */
-static void deg_backup_object_runtime(
-        Object *object,
-        ObjectRuntimeBackup *object_runtime_backup)
+void ObjectRuntimeBackup::init_from_object(Object *object)
 {
        /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
        Mesh *mesh_eval = object->runtime.mesh_eval;
-       object_runtime_backup->runtime = object->runtime;
+       runtime = object->runtime;
        BKE_object_runtime_reset(object);
-       /* Keep bbox (for now at least...). */
-       object->runtime.bb = object_runtime_backup->runtime.bb;
+       /* Keep bbox (for now at least). */
+       object->runtime.bb = runtime.bb;
        /* Object update will override actual object->data to an evaluated version.
         * Need to make sure we don't have data set to evaluated one before free
         * anything. */
        if (mesh_eval != NULL && object->data == mesh_eval) {
-               object->data = object_runtime_backup->runtime.mesh_orig;
+               object->data = runtime.mesh_orig;
        }
        /* Make a backup of base flags. */
-       object_runtime_backup->base_flag = object->base_flag;
-       object_runtime_backup->base_local_view_bits = object->base_local_view_bits;
+       base_flag = object->base_flag;
+       base_local_view_bits = object->base_local_view_bits;
+       /* Backup tuntime data of all modifiers. */
+       backup_modifier_runtime_data(object);
 }
 
-static void deg_restore_object_runtime(
-        Object *object,
-        const ObjectRuntimeBackup *object_runtime_backup)
+inline ModifierDataBackupID create_modifier_data_id(
+        const ModifierData* modifier_data)
+{
+       return ModifierDataBackupID(modifier_data->orig_modifier_data,
+                                   static_cast<ModifierType>(modifier_data->type));
+}
+
+void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
+{
+       LISTBASE_FOREACH(ModifierData *, modifier_data, &object->modifiers) {
+               if (modifier_data->runtime == NULL) {
+                       continue;
+               }
+               BLI_assert(modifier_data->orig_modifier_data != NULL);
+               ModifierDataBackupID modifier_data_id =
+                       create_modifier_data_id(modifier_data);
+               modifier_runtime_data.insert(
+                       make_pair(modifier_data_id, modifier_data->runtime));
+               modifier_data->runtime = NULL;
+       }
+}
+
+void ObjectRuntimeBackup::restore_to_object(Object *object)
 {
        Mesh *mesh_orig = object->runtime.mesh_orig;
        BoundBox *bb = object->runtime.bb;
-       object->runtime = object_runtime_backup->runtime;
+       object->runtime = runtime;
        object->runtime.mesh_orig = mesh_orig;
        object->runtime.bb = bb;
        if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
@@ -909,60 +986,108 @@ static void deg_restore_object_runtime(
                        mesh_eval->edit_mesh = mesh_orig->edit_mesh;
                }
        }
-       object->base_flag = object_runtime_backup->base_flag;
-       object->base_local_view_bits = object_runtime_backup->base_local_view_bits;
+       object->base_flag = base_flag;
+       object->base_local_view_bits = base_local_view_bits;
+       /* Restore modifier's runtime data.
+        * NOTE: Data of unused modifiers will be freed there. */
+       restore_modifier_runtime_data(object);
+}
+
+void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) {
+       LISTBASE_FOREACH(ModifierData *, modifier_data, &object->modifiers) {
+               BLI_assert(modifier_data->orig_modifier_data != NULL);
+               ModifierDataBackupID modifier_data_id =
+                       create_modifier_data_id(modifier_data);
+               ModifierRuntimeDataBackup::iterator runtime_data_iterator =
+                       modifier_runtime_data.find(modifier_data_id);
+               if (runtime_data_iterator != modifier_runtime_data.end()) {
+                       modifier_data->runtime = runtime_data_iterator->second;
+                       runtime_data_iterator->second = NULL;
+               }
+       }
+       for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) {
+               const ModifierDataBackupID modifier_data_id = value.first;
+               void *runtime = value.second;
+               if (value.second == NULL) {
+                       continue;
+               }
+               const ModifierTypeInfo *modifier_type_info =
+                       modifierType_getInfo(modifier_data_id.type);
+               BLI_assert(modifier_type_info != NULL);
+               modifier_type_info->freeRuntimeData(runtime);
+       }
+}
+
+class RuntimeBackup {
+public:
+       RuntimeBackup() : drawdata_ptr(NULL) {
+               drawdata_backup.first = drawdata_backup.last = NULL;
+       }
+
+       /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */
+       void init_from_id(ID *id);
+
+       /* Restore fields to the given ID. */
+       void restore_to_id(ID *id);
+
+       ObjectRuntimeBackup object_backup;
+       DrawDataList drawdata_backup;
+       DrawDataList *drawdata_ptr;
+};
+
+void RuntimeBackup::init_from_id(ID *id)
+{
+       if (!check_datablock_expanded(id)) {
+               return;
+       }
+       const ID_Type id_type = GS(id->name);
+       switch (id_type) {
+               case ID_OB:
+                       object_backup.init_from_object(reinterpret_cast<Object*>(id));
+                       break;
+               default:
+                       break;
+       }
+       /* Note that we never free GPU draw data from here since that's not
+        * safe for threading and draw data is likely to be re-used. */
+       drawdata_ptr = DRW_drawdatalist_from_id(id);
+       if (drawdata_ptr != NULL) {
+               drawdata_backup = *drawdata_ptr;
+               drawdata_ptr->first = drawdata_ptr->last = NULL;
+       }
+}
+
+void RuntimeBackup::restore_to_id(ID *id)
+{
+       const ID_Type id_type = GS(id->name);
+       switch (id_type) {
+               case ID_OB:
+                       object_backup.restore_to_object(reinterpret_cast<Object*>(id));
+                       break;
+               default:
+                       break;
+       }
+       if (drawdata_ptr != NULL) {
+               *drawdata_ptr = drawdata_backup;
+       }
 }
 
+}  // namespace
+
 ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
                                        const IDNode *id_node)
 {
        const ID *id_orig = id_node->id_orig;
-       const ID_Type id_type = GS(id_orig->name);
        ID *id_cow = id_node->id_cow;
        /* Similar to expansion, no need to do anything here. */
        if (!deg_copy_on_write_is_needed(id_orig)) {
                return id_cow;
        }
-       /* For the rest if datablock types we use simple logic:
-        * - Free previously expanded data, if any.
-        * - Perform full datablock copy.
-        *
-        * Note that we never free GPU draw data from here since that's not
-        * safe for threading and draw data is likely to be re-used. */
-       /* TODO(sergey): Either move this to an utility function or redesign
-        * Copy-on-Write components in a way that only needed parts are being
-        * copied over. */
-       /* TODO(sergey): Wrap GPU draw data backup and object runtime backup to a
-        * generic backup structure. */
-       DrawDataList drawdata_backup;
-       DrawDataList *drawdata_ptr = NULL;
-       ObjectRuntimeBackup object_runtime_backup = {{{0}}};
-       if (check_datablock_expanded(id_cow)) {
-               switch (id_type) {
-                       case ID_OB:
-                       {
-                               Object *ob = (Object *)id_cow;
-                               deg_backup_object_runtime(ob, &object_runtime_backup);
-                               break;
-                       }
-                       default:
-                               break;
-               }
-               drawdata_ptr = DRW_drawdatalist_from_id(id_cow);
-               if (drawdata_ptr != NULL) {
-                       drawdata_backup = *drawdata_ptr;
-                       drawdata_ptr->first = drawdata_ptr->last = NULL;
-               }
-       }
+       RuntimeBackup backup;
+       backup.init_from_id(id_cow);
        deg_free_copy_on_write_datablock(id_cow);
        deg_expand_copy_on_write_datablock(depsgraph, id_node);
-       /* Restore DrawData. */
-       if (drawdata_ptr != NULL) {
-               *drawdata_ptr = drawdata_backup;
-       }
-       if (id_type == ID_OB) {
-               deg_restore_object_runtime((Object *)id_cow, &object_runtime_backup);
-       }
+       backup.restore_to_id(id_cow);
        return id_cow;
 }
 
index 2719e324bda671315de4163a635c335aca1c60f2..99b9b4ce3618fd19646a43d9ff4f380f17dda197 100644 (file)
@@ -116,7 +116,7 @@ typedef struct ModifierData {
 
        /* Pointer to a ModifierData in the original domain. */
        struct ModifierData *orig_modifier_data;
-       void *_pad2;
+       void *runtime;
 } ModifierData;
 
 typedef enum {
@@ -170,8 +170,6 @@ typedef struct SubsurfModifierData {
 
        /* TODO(sergey): Get rid of those with the old CCG subdivision code. */
        void *emCache, *mCache;
-       /* Cached subdivision surface descriptor, with topology and settings. */
-       struct Subdiv *subdiv;
 } SubsurfModifierData;
 
 typedef struct LatticeModifierData {
index 4a474dde5854dd73cfad72b195cc2d994f3478fd..acd4573ec44f22f0da038abe4fedd7bbea55d410 100644 (file)
@@ -204,4 +204,5 @@ ModifierTypeInfo modifierType_Armature = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 56567c79c6aa05efb1829efec33b967dd6c43b8d..e45a46c54b9a1c61d57062635346412c13c36376 100644 (file)
@@ -777,4 +777,5 @@ ModifierTypeInfo modifierType_Array = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 6e1dd9ed45d9b7d751ee5b3e91b9956a2f87a8b7..01f307c45de17efd6b8600c04ab5c008b4b52c81 100644 (file)
@@ -239,4 +239,5 @@ ModifierTypeInfo modifierType_Bevel = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index a90ddde7946c9e8a20a24a00a068ac22b424ef6b..250a6d7395340e1851bb420e5534d2aff7b772f6 100644 (file)
@@ -360,4 +360,5 @@ ModifierTypeInfo modifierType_Boolean = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index e46c9aca5ce07ae82ff88ec225342b109ac085d4..c8106605077a1aba89d0d3d9cdf072556800cf24 100644 (file)
@@ -315,4 +315,5 @@ ModifierTypeInfo modifierType_Build = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index f408a22aadf16ecf9c66d23742b426ec8d33ade2..44ca565b8075f8ccf07997ea9034c03217b735e6 100644 (file)
@@ -496,4 +496,5 @@ ModifierTypeInfo modifierType_Cast = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 41f35faac1b536dbfa4dde55ecbefe63608b6e71..abbd32f70d328232d4e1511c13913d9aa45b6086 100644 (file)
@@ -263,4 +263,5 @@ ModifierTypeInfo modifierType_Cloth = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 3e1fa4954fa6685e51765eef7fcf33f82382ff4a..87775cb5f3b39783bbf02c5dfa118bcb709db0a3 100644 (file)
@@ -273,4 +273,5 @@ ModifierTypeInfo modifierType_Collision = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index cc6177b9bc8ce1c226d6bd503f04e56fc464c210..2c9ace6502487767707c1565f077f7a5dcb264d7 100644 (file)
@@ -765,4 +765,5 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index f3a5e280947f57086581196d5ff758111da2b7ed..4f722626a9b23afcd59c9e37ef5187a72f1ccc11 100644 (file)
@@ -174,4 +174,5 @@ ModifierTypeInfo modifierType_Curve = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 3db33ca07c29db71fbd401fecbd9b196f9d60870..c06c190c7b8165a879afe9b1442df4ae592aa0a9 100644 (file)
@@ -240,4 +240,5 @@ ModifierTypeInfo modifierType_DataTransfer = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 0ca6111c41ad9fe7054d1782abcbe4ae588bcb70..b621b168ccc35153fc4c95e44bfec559f68b8e99 100644 (file)
@@ -247,4 +247,5 @@ ModifierTypeInfo modifierType_Decimate = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 87b25982d816f481c83e3d0eaa760959456d412d..e199b4b362eb9d3e07cc5b091dffd4ff98eea681 100644 (file)
@@ -428,4 +428,5 @@ ModifierTypeInfo modifierType_Displace = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index b84e46e145c082612c0af674f5159493e6dee549..c4b1ebbb8417f20eb38473e35adbf168d8db9817 100644 (file)
@@ -192,4 +192,5 @@ ModifierTypeInfo modifierType_DynamicPaint = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index a7b980494b35901f9d3ff4efcd2c722710c4cce4..b8dda4d9103009c761458335ed010849e78aa306 100644 (file)
@@ -168,4 +168,5 @@ ModifierTypeInfo modifierType_EdgeSplit = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 3a0449a4e523f1b0c184f93bef867fc8bf3afac4..e7e76f58c9329cbebe87cee48edcdd66c2150ca4 100644 (file)
@@ -1106,4 +1106,5 @@ ModifierTypeInfo modifierType_Explode = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index d4bac71f677ca10f82c573de9ab3cd4eb3c02d87..0af576efda9fbb34471c27e6ad56cc030bbda9a9 100644 (file)
@@ -160,4 +160,5 @@ ModifierTypeInfo modifierType_Fluidsim = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index e911dbc4b5abab2eb0c845679a449b26a8eb7dea..ae8b3e3bfa4b7a3c1d93776a14d9f4bf48c1c769 100644 (file)
@@ -408,4 +408,5 @@ ModifierTypeInfo modifierType_Hook = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index db76b0fd0c24052928040bb3632b4ede4f7db290..26d1c65605b46ef2469af897977d81229d3a4342 100644 (file)
@@ -793,4 +793,5 @@ ModifierTypeInfo modifierType_LaplacianDeform = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index a6670f313ce5be1f00f91a01367de06cc5817e0c..fe939cb9284089950bf22d96a81c98ee22163980 100644 (file)
@@ -557,4 +557,5 @@ ModifierTypeInfo modifierType_LaplacianSmooth = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 46a9c4f0a476b1b280be283c58b863c02c6e4626..17c5fefd56231ca2db7f29cc07867aa46e640234 100644 (file)
@@ -149,4 +149,5 @@ ModifierTypeInfo modifierType_Lattice = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 6d8317ffe77e8bc38745b9144dc6d93f749e32a3..90188cb21b301467980834835abaa05d05c9aa02 100644 (file)
@@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Mask = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 0ecd56372c76d4eabb41d9ae6441a124309a0cee..2107d1fa1fac2ca787bfaba5472dfd8c486b0758 100644 (file)
@@ -316,4 +316,5 @@ ModifierTypeInfo modifierType_MeshCache = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index e59a6ae9add9c4e9b8194140370db459ba0cd394..82a33181e29fd07238f9a7cdc39cfb941ca8409c 100644 (file)
@@ -530,4 +530,5 @@ ModifierTypeInfo modifierType_MeshDeform = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index d17f343a1ec925d94c0d4acb95fb73be876bf1d7..05bc7d927dced41c6b486672456151508936bf18 100644 (file)
@@ -211,4 +211,5 @@ ModifierTypeInfo modifierType_MeshSequenceCache = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index c46445471dfe15b3b9bcb5f5a60374f1dcd86f58..420f9c746e5507f155851593f1636e4ff517d9d7 100644 (file)
@@ -454,4 +454,5 @@ ModifierTypeInfo modifierType_Mirror = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 97380a603226875780110d6bc7c6a2e37f45ed21..03423795aa545f203cb3fcec4b68bd711d9992e8 100644 (file)
@@ -226,4 +226,5 @@ ModifierTypeInfo modifierType_Multires = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 781e52fc42659849c1962b71ec8a18e9a0482fb9..93343a227cd9c2d3c9f108442ecf07338df41b6c 100644 (file)
@@ -68,4 +68,5 @@ ModifierTypeInfo modifierType_None = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index d838d203ed572e3a503c24bdf5bc217112295175..0bbf64d5d56b5c699e1cb51308cbed9401e11e89 100644 (file)
@@ -578,4 +578,5 @@ ModifierTypeInfo modifierType_NormalEdit = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 50ec32bd605e46b16d59a91afdc8636a493d2ca4..b14e6d64ab06499c34caf07b8066b4ce7b7836e9 100644 (file)
@@ -524,4 +524,5 @@ ModifierTypeInfo modifierType_Ocean = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index a9d8db493b832d1094094326b73d64c9d7dfe670..8bec6b568f24a6283323fb68a0fd70f1250d2137 100644 (file)
@@ -546,4 +546,5 @@ ModifierTypeInfo modifierType_ParticleInstance = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 08a195066943d60adb22af0f8c09578e4442745d..d1939d367778e3de46bf01bda928187c75036fc2 100644 (file)
@@ -268,4 +268,5 @@ ModifierTypeInfo modifierType_ParticleSystem = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 2ff82d863dff3aca8e1e364bd778f84ecac22102..bb92de7b2a48d3c8bd15bf5ef816b6b52ea34858 100644 (file)
@@ -237,4 +237,5 @@ ModifierTypeInfo modifierType_Remesh = {
        /* dependsOnNormals */  NULL,
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
+       /* freeRuntimeData */   NULL,
 };
index 837b4d3d532c784f12ef0581bcd75e023748e2ba..f9bb6abc5a7fcd252807ce20890516642d7a9f94 100644 (file)
@@ -1157,4 +1157,5 @@ ModifierTypeInfo modifierType_Screw = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 3530ca21d342605755fc34eddc1f6a05e9dd807f..03bc11c65f9443160aa1bcf2c2bd3edb209f25bf 100644 (file)
@@ -143,4 +143,5 @@ ModifierTypeInfo modifierType_ShapeKey = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 7b33df5bf860e95526b06c8a76cb5acc19123c16..63d9b409d62b144ac3a230f0f618ac6bc59f2648 100644 (file)
@@ -205,4 +205,5 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index cc36cfbf9eb36f97de2bb72084e7c86f8a8842d4..ccd01c37157fc08f09357e62aba2bae2570227ff 100644 (file)
@@ -451,4 +451,5 @@ ModifierTypeInfo modifierType_SimpleDeform = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 7ba7882d0d0984f859e1c587c4b0a5c92f58be03..9aad2a00fa1e5b0a6c7d5f0ab49155749e931b60 100644 (file)
@@ -1961,4 +1961,5 @@ ModifierTypeInfo modifierType_Skin = {
        /* dependsOnNormals */  NULL,
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
+       /* freeRuntimeData */   NULL,
 };
index 905e8a18e1b9bd84ba6c85c2c50516052f57fdcf..8578cf326261d4e6da67b1be619c4757553249b7 100644 (file)
@@ -187,4 +187,5 @@ ModifierTypeInfo modifierType_Smoke = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 2b9339842fa758f15fdc30158d4548ec57c69a44..dde64cc675a188c3b71f52eef2d3da0d779e594f 100644 (file)
@@ -266,4 +266,5 @@ ModifierTypeInfo modifierType_Smooth = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 868b42bc241fdd3801c1c23b072df0334f583ba1..074bc4c1d764baa8a267b0d9772314a7349338b2 100644 (file)
@@ -98,4 +98,5 @@ ModifierTypeInfo modifierType_Softbody = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index e449403eb70d424e70f935e92c4a44c64961f550..d9b05b102a265eb06e6f6c566cac4b637d7773f7 100644 (file)
@@ -975,4 +975,5 @@ ModifierTypeInfo modifierType_Solidify = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 1899faa3583069395c3ab2b9cf32b0448e7e4d1f..c092b3f36217c69730bec134454551562dc1ca62 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <stddef.h>
 
+#include "MEM_guardedalloc.h"
+
 #include "BLI_utildefines.h"
 
 #include "DNA_object_types.h"
 
 #include "intern/CCGSubSurf.h"
 
+typedef struct SubsurfRuntimeData {
+       /* Cached subdivision surface descriptor, with topology and settings. */
+       struct Subdiv *subdiv;
+} SubsurfRuntimeData;
+
 static void initData(ModifierData *md)
 {
        SubsurfModifierData *smd = (SubsurfModifierData *) md;
@@ -64,7 +71,18 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
        modifier_copyData_generic(md, target, flag);
 
        tsmd->emCache = tsmd->mCache = NULL;
-       tsmd->subdiv = NULL;
+}
+
+static void freeRuntimeData(void *runtime_data_v)
+{
+       if (runtime_data_v == NULL) {
+               return;
+       }
+       SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)runtime_data_v;
+       if (runtime_data->subdiv != NULL) {
+               BKE_subdiv_free(runtime_data->subdiv);
+       }
+       MEM_freeN(runtime_data);
 }
 
 static void freeData(ModifierData *md)
@@ -79,9 +97,7 @@ static void freeData(ModifierData *md)
                ccgSubSurf_free(smd->emCache);
                smd->emCache = NULL;
        }
-       if (smd->subdiv != NULL) {
-               BKE_subdiv_free(smd->subdiv);
-       }
+       freeRuntimeData(smd->modifier.runtime);
 }
 
 static bool isDisabled(const Scene *scene, ModifierData *md, bool useRenderParams)
@@ -121,9 +137,11 @@ static Subdiv *subdiv_descriptor_ensure(SubsurfModifierData *smd,
                                         const SubdivSettings *subdiv_settings,
                                         const Mesh *mesh)
 {
+       SubsurfRuntimeData *runtime_data =
+               (SubsurfRuntimeData *)smd->modifier.runtime;
        Subdiv *subdiv = BKE_subdiv_update_from_mesh(
-               smd->subdiv, subdiv_settings, mesh);
-       smd->subdiv = subdiv;
+               runtime_data->subdiv, subdiv_settings, mesh);
+       runtime_data->subdiv = subdiv;
        return subdiv;
 }
 
@@ -181,6 +199,17 @@ static Mesh *subdiv_as_ccg(SubsurfModifierData *smd,
        return result;
 }
 
+static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd)
+{
+       SubsurfRuntimeData *runtime_data =
+               (SubsurfRuntimeData *)smd->modifier.runtime;
+       if (runtime_data == NULL) {
+               runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
+               smd->modifier.runtime = runtime_data;
+       }
+       return runtime_data;
+}
+
 /* Modifier itself. */
 
 static Mesh *applyModifier(ModifierData *md,
@@ -195,6 +224,7 @@ static Mesh *applyModifier(ModifierData *md,
                return result;
        }
        BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh);
+       SubsurfRuntimeData *runtime_data = subsurf_ensure_runtime(smd);
        Subdiv *subdiv = subdiv_descriptor_ensure(smd, &subdiv_settings, mesh);
        if (subdiv == NULL) {
                /* Happens on bad topology, but also on empty input mesh. */
@@ -209,7 +239,7 @@ static Mesh *applyModifier(ModifierData *md,
                result = subdiv_as_ccg(smd, ctx, mesh, subdiv);
        }
        // BKE_subdiv_stats_print(&subdiv->stats);
-       if (subdiv != smd->subdiv) {
+       if (subdiv != runtime_data->subdiv) {
                BKE_subdiv_free(subdiv);
        }
        return result;
@@ -250,4 +280,5 @@ ModifierTypeInfo modifierType_Subsurf = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   freeRuntimeData,
 };
index ee3c99bef85183d22df68db0762daeea81065e9d..114b327884b0b0863cc258fc2abf6b65443860ec 100644 (file)
@@ -217,4 +217,5 @@ ModifierTypeInfo modifierType_Surface = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 554545077fabb321e31a47016154248945c5ae85..1b23769e75b5ce9d2e79ec4fbeb870f19bc50d45 100644 (file)
@@ -1278,4 +1278,5 @@ ModifierTypeInfo modifierType_SurfaceDeform = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 802bde21b5c82b513e48e20e71db2fecfddd7b25..e39698e142ec62f3d4920f8390717819c50e99d2 100644 (file)
@@ -148,4 +148,5 @@ ModifierTypeInfo modifierType_Triangulate = {
        /* dependsOnNormals */  NULL,
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
+       /* freeRuntimeData */   NULL,
 };
index 26c7ec7ed13df695d3ada6628053ea4c3a29f406..d8ed70ec3282238c05e7e2d461d592617c066f2c 100644 (file)
@@ -345,4 +345,5 @@ ModifierTypeInfo modifierType_UVProject = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index d4f17b742f12ce07f0d6fb907cfb54d2f5af5bd5..8ef17caa4ff6bdba251bad37274917855c36dfbe 100644 (file)
@@ -277,4 +277,5 @@ ModifierTypeInfo modifierType_UVWarp = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index adda5df61ea68dc452e2415a3402da73b194d315..51676b8cd4b87e47467b1c6bb2c106234efd6f8a 100644 (file)
@@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Warp = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index 80ac323c82f41c920132ea7b49f54ae1f5ac14b7..4fe7e0fd4d66f675eaf2cf85e3c2e859b1c2c286 100644 (file)
@@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Wave = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index 2cf15fa43a007a98009d34f9ec29f3d8c68589fb..5f69e6e9e54fdc62dd2494417e3416a1cbfa7914 100644 (file)
@@ -655,4 +655,5 @@ ModifierTypeInfo modifierType_WeightedNormal = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };
index 32d058e56598a55dc5811994c591e87580de1738..2383cfc8c918d33e95a63cbfdcf6310b8b5d324b 100644 (file)
@@ -301,4 +301,5 @@ ModifierTypeInfo modifierType_WeightVGEdit = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index 495d235b40685e731d321e75017d795ce191fbfc..d0df42db3e63253854a296176ce9b9734398ac56 100644 (file)
@@ -414,4 +414,5 @@ ModifierTypeInfo modifierType_WeightVGMix = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index 2e2e4fe963d3755f86886e6d023703cf48b046cb..b9921be752fbd2f716c9b3c27f3ad8124034851b 100644 (file)
@@ -586,4 +586,5 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
        /* foreachTexLink */    foreachTexLink,
+       /* freeRuntimeData */   NULL,
 };
index 2f70ab16cf894acfafce48118aab89a400cdf538..ab4763d0d470295934042f27c5c8d559e053e2e4 100644 (file)
@@ -137,4 +137,5 @@ ModifierTypeInfo modifierType_Wireframe = {
        /* foreachObjectLink */ NULL,
        /* foreachIDLink */     NULL,
        /* foreachTexLink */    NULL,
+       /* freeRuntimeData */   NULL,
 };