diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 1a1e510b9e1..22782b675f5 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -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). */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9a886f494cf..93ef7fe5b73 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h index d34b6d724cb..d96c621f4b2 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.h +++ b/source/blender/depsgraph/intern/depsgraph_type.h @@ -36,6 +36,8 @@ #include #include #include +#include +#include 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; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index cae84c3e535..5e8516d744c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -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(type) < static_cast(other.type); + } + return false; + } + + ModifierData *modifier_data; + ModifierType type; +}; + +/* Storage for backed up runtime modifier data. */ +typedef map 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(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(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(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; } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 2719e324bda..99b9b4ce361 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -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 { diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 4a474dde585..acd4573ec44 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -204,4 +204,5 @@ ModifierTypeInfo modifierType_Armature = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 56567c79c6a..e45a46c54b9 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -777,4 +777,5 @@ ModifierTypeInfo modifierType_Array = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 6e1dd9ed45d..01f307c45de 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -239,4 +239,5 @@ ModifierTypeInfo modifierType_Bevel = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index a90ddde7946..250a6d73953 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -360,4 +360,5 @@ ModifierTypeInfo modifierType_Boolean = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index e46c9aca5ce..c8106605077 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -315,4 +315,5 @@ ModifierTypeInfo modifierType_Build = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index f408a22aadf..44ca565b807 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -496,4 +496,5 @@ ModifierTypeInfo modifierType_Cast = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 41f35faac1b..abbd32f70d3 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -263,4 +263,5 @@ ModifierTypeInfo modifierType_Cloth = { /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 3e1fa4954fa..87775cb5f3b 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -273,4 +273,5 @@ ModifierTypeInfo modifierType_Collision = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index cc6177b9bc8..2c9ace65024 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -765,4 +765,5 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index f3a5e280947..4f722626a9b 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -174,4 +174,5 @@ ModifierTypeInfo modifierType_Curve = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 3db33ca07c2..c06c190c7b8 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -240,4 +240,5 @@ ModifierTypeInfo modifierType_DataTransfer = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 0ca6111c41a..b621b168ccc 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -247,4 +247,5 @@ ModifierTypeInfo modifierType_Decimate = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 87b25982d81..e199b4b362e 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -428,4 +428,5 @@ ModifierTypeInfo modifierType_Displace = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index b84e46e145c..c4b1ebbb841 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -192,4 +192,5 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index a7b980494b3..b8dda4d9103 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -168,4 +168,5 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 3a0449a4e52..e7e76f58c93 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1106,4 +1106,5 @@ ModifierTypeInfo modifierType_Explode = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index d4bac71f677..0af576efda9 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -160,4 +160,5 @@ ModifierTypeInfo modifierType_Fluidsim = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index e911dbc4b5a..ae8b3e3bfa4 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -408,4 +408,5 @@ ModifierTypeInfo modifierType_Hook = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index db76b0fd0c2..26d1c65605b 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -793,4 +793,5 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index a6670f313ce..fe939cb9284 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -557,4 +557,5 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 46a9c4f0a47..17c5fefd562 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -149,4 +149,5 @@ ModifierTypeInfo modifierType_Lattice = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index 6d8317ffe77..90188cb21b3 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Mask = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 0ecd56372c7..2107d1fa1fa 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -316,4 +316,5 @@ ModifierTypeInfo modifierType_MeshCache = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index e59a6ae9add..82a33181e29 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -530,4 +530,5 @@ ModifierTypeInfo modifierType_MeshDeform = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index d17f343a1ec..05bc7d927dc 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -211,4 +211,5 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index c46445471df..420f9c746e5 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -454,4 +454,5 @@ ModifierTypeInfo modifierType_Mirror = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 97380a60322..03423795aa5 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -226,4 +226,5 @@ ModifierTypeInfo modifierType_Multires = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 781e52fc426..93343a227cd 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -68,4 +68,5 @@ ModifierTypeInfo modifierType_None = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index d838d203ed5..0bbf64d5d56 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -578,4 +578,5 @@ ModifierTypeInfo modifierType_NormalEdit = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 50ec32bd605..b14e6d64ab0 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -524,4 +524,5 @@ ModifierTypeInfo modifierType_Ocean = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index a9d8db493b8..8bec6b568f2 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -546,4 +546,5 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 08a19506694..d1939d36777 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -268,4 +268,5 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 2ff82d863df..bb92de7b2a4 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -237,4 +237,5 @@ ModifierTypeInfo modifierType_Remesh = { /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 837b4d3d532..f9bb6abc5a7 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1157,4 +1157,5 @@ ModifierTypeInfo modifierType_Screw = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 3530ca21d34..03bc11c65f9 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -143,4 +143,5 @@ ModifierTypeInfo modifierType_ShapeKey = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 7b33df5bf86..63d9b409d62 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -205,4 +205,5 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index cc36cfbf9eb..ccd01c37157 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -451,4 +451,5 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 7ba7882d0d0..9aad2a00fa1 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1961,4 +1961,5 @@ ModifierTypeInfo modifierType_Skin = { /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index 905e8a18e1b..8578cf32626 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -187,4 +187,5 @@ ModifierTypeInfo modifierType_Smoke = { /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 2b9339842fa..dde64cc675a 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -266,4 +266,5 @@ ModifierTypeInfo modifierType_Smooth = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 868b42bc241..074bc4c1d76 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -98,4 +98,5 @@ ModifierTypeInfo modifierType_Softbody = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index e449403eb70..d9b05b102a2 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -975,4 +975,5 @@ ModifierTypeInfo modifierType_Solidify = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 1899faa3583..c092b3f3621 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -24,6 +24,8 @@ #include +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "DNA_object_types.h" @@ -44,6 +46,11 @@ #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, }; diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index ee3c99bef85..114b327884b 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -217,4 +217,5 @@ ModifierTypeInfo modifierType_Surface = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 554545077fa..1b23769e75b 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1278,4 +1278,5 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 802bde21b5c..e39698e142e 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -148,4 +148,5 @@ ModifierTypeInfo modifierType_Triangulate = { /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 26c7ec7ed13..d8ed70ec328 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -345,4 +345,5 @@ ModifierTypeInfo modifierType_UVProject = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index d4f17b742f1..8ef17caa4ff 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -277,4 +277,5 @@ ModifierTypeInfo modifierType_UVWarp = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index adda5df61ea..51676b8cd4b 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Warp = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 80ac323c82f..4fe7e0fd4d6 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -379,4 +379,5 @@ ModifierTypeInfo modifierType_Wave = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 2cf15fa43a0..5f69e6e9e54 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -655,4 +655,5 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 32d058e5659..2383cfc8c91 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -301,4 +301,5 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 495d235b406..d0df42db3e6 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -414,4 +414,5 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 2e2e4fe963d..b9921be752f 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -586,4 +586,5 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 2f70ab16cf8..ab4763d0d47 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -137,4 +137,5 @@ ModifierTypeInfo modifierType_Wireframe = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, };