diff options
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 12 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_undo.c | 22 |
3 files changed, 35 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 51650d161ea..57fdafaf8d9 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -421,6 +421,7 @@ int CustomData_sizeof(int type); /* get the name of a layer type */ const char *CustomData_layertype_name(int type); bool CustomData_layertype_is_singleton(int type); +bool CustomData_layertype_is_dynamic(int type); int CustomData_layertype_layers_max(const int type); /* make sure the name of layer at index is unique */ diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 37e9c810123..782b4fc200e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -4273,6 +4273,18 @@ bool CustomData_layertype_is_singleton(int type) } /** + * Has dynamically allocated members. + * This is useful to know if operations such as #memcmp are + * valid when comparing data from two layers. + */ +bool CustomData_layertype_is_dynamic(int type) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + return (typeInfo->free != NULL); +} + +/** * \return Maximum number of layers of given \a type, -1 means 'no limit'. */ int CustomData_layertype_layers_max(const int type) diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index d7f7cfa2888..dd51d63961c 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -153,6 +153,23 @@ static void um_arraystore_cd_compact(struct CustomData *cdata, for (int layer_start = 0, layer_end; layer_start < cdata->totlayer; layer_start = layer_end) { const CustomDataType type = cdata->layers[layer_start].type; + /* Perform a full copy on dynamic layers. + * + * Unfortunately we can't compare dynamic layer types as they contain allocated pointers, + * which burns CPU cycles looking for duplicate data that doesn't exist. + * The array data isn't comparable once copied from the mesh, + * this bottlenecks on high poly meshes, see T84114. + * + * Notes: + * + * - Ideally the data would be expanded into a format that could be de-duplicated effectively, + * this would require a flat representation of each dynamic custom-data layer. + * + * - The data in the layer could be kept as-is to save on the extra copy, + * it would complicate logic in this function. + */ + const bool layer_type_is_dynamic = CustomData_layertype_is_dynamic(type); + layer_end = layer_start + 1; while ((layer_end < cdata->totlayer) && (type == cdata->layers[layer_end].type)) { layer_end++; @@ -209,6 +226,11 @@ static void um_arraystore_cd_compact(struct CustomData *cdata, i < bcd_reference_current->states_len) ? bcd_reference_current->states[i] : NULL; + /* See comment on `layer_type_is_dynamic` above. */ + if (layer_type_is_dynamic) { + state_reference = NULL; + } + bcd->states[i] = BLI_array_store_state_add( bs, layer->data, (size_t)data_len * stride, state_reference); } |