50#define USE_ARRAY_STORE
68# define ARRAY_CHUNK_SIZE_IN_BYTES 65536
69# define ARRAY_CHUNK_NUM_MIN 256
71# define USE_ARRAY_STORE_THREAD
74#ifdef USE_ARRAY_STORE_THREAD
128#ifdef USE_ARRAY_STORE
141#ifdef USE_ARRAY_STORE
160# define ARRAY_STORE_INDEX_NUM (ARRAY_STORE_INDEX_MSEL + 1)
172# ifdef USE_ARRAY_STORE_THREAD
179 const size_t data_len,
188 *r_bcd_first =
nullptr;
194 for (
int layer_start = 0, layer_end; layer_start < cdata->
totlayer; layer_start = layer_end) {
212 layer_end = layer_start + 1;
213 while ((layer_end < cdata->totlayer) && (type == cdata->
layers[layer_end].
type)) {
222 const int layer_len = layer_end - layer_start;
225 if (bcd_reference_current && (bcd_reference_current->
type == type)) {
229 bcd_reference_current =
nullptr;
235 if (bcd_iter->
type == type) {
236 bcd_reference_current = bcd_iter;
239 bcd_iter = bcd_iter->
next;
246 bcd = MEM_new<BArrayCustomData>(__func__);
252 bcd_prev->next = bcd;
262 for (
int i = 0; i < layer_len; i++, layer++) {
265 if (layer_type_is_dynamic) {
268 if (layer->sharing_info) {
269 sharing_info = layer->sharing_info;
273 sharing_info = implicit_sharing::info_for_mem_free(layer->data);
279 if (bcd_reference_current && i < bcd_reference_current->states.size()) {
280 state_reference = std::get<BArrayState *>(bcd_reference_current->
states[i]);
284 bs, layer->data,
size_t(data_len) * stride, state_reference);
293 if (layer->sharing_info) {
294 layer->sharing_info->remove_user_and_delete_if_last();
295 layer->sharing_info =
nullptr;
296 layer->
data =
nullptr;
305 if (bcd_reference_current) {
306 bcd_reference_current = bcd_reference_current->
next;
312 *r_bcd_first = bcd_first;
322 const size_t data_len)
328 for (
int i = 0; i < bcd->
states.
size(); i++) {
330 if (std::holds_alternative<BArrayState *>(bcd->
states[i])) {
339 layer->data =
nullptr;
344 layer->data =
const_cast<void *
>(
state.data);
345 layer->sharing_info =
state.sharing_info;
346 layer->sharing_info->add_user();
361 for (
int i = 0; i < bcd->
states.
size(); i++) {
362 if (std::holds_alternative<BArrayState *>(bcd->
states[i])) {
369 state.sharing_info->remove_user_and_delete_if_last();
394 4096 < (mesh->verts_num + mesh->edges_num + mesh->corners_num + mesh->faces_num),
396 um_arraystore_cd_compact(&mesh->vert_data,
399 ARRAY_STORE_INDEX_VERT,
400 um_ref ? um_ref->store.vdata : nullptr,
404 um_arraystore_cd_compact(&mesh->edge_data,
407 ARRAY_STORE_INDEX_EDGE,
408 um_ref ? um_ref->store.edata : nullptr,
412 um_arraystore_cd_compact(&mesh->corner_data,
415 ARRAY_STORE_INDEX_LOOP,
416 um_ref ? um_ref->store.ldata : nullptr,
420 um_arraystore_cd_compact(&mesh->face_data,
423 ARRAY_STORE_INDEX_POLY,
424 um_ref ? um_ref->store.pdata : nullptr,
428 if (mesh->face_offset_indices) {
429 BLI_assert(create == (um->store.face_offset_indices == nullptr));
431 BArrayState *state_reference = um_ref ? um_ref->store.face_offset_indices : nullptr;
432 const size_t stride = sizeof(*mesh->face_offset_indices);
433 BArrayStore *bs = BLI_array_store_at_size_ensure(
434 &um_arraystore.bs_stride[ARRAY_STORE_INDEX_POLY_OFFSETS],
436 array_chunk_size_calc(stride));
437 um->store.face_offset_indices = BLI_array_store_state_add(bs,
438 mesh->face_offset_indices,
439 size_t(mesh->faces_num + 1) *
443 blender::implicit_sharing::free_shared_data(&mesh->face_offset_indices,
444 &mesh->runtime->face_offsets_sharing_info);
448 if (mesh->key && mesh->key->totkey) {
449 const size_t stride = mesh->key->elemsize;
457 MEM_mallocN(mesh->key->totkey *
sizeof(*um->store.keyblocks), __func__));
460 for (
int i = 0; i < mesh->key->totkey; i++, keyblock = keyblock->
next) {
462 BArrayState *state_reference = (um_ref && um_ref->mesh.key &&
463 (i < um_ref->mesh.key->totkey)) ?
464 um_ref->store.keyblocks[i] :
467 bs, keyblock->data,
size_t(keyblock->totelem) * stride, state_reference);
470 if (keyblock->data) {
472 keyblock->data =
nullptr;
478 if (mesh->mselect && mesh->totselect) {
479 BLI_assert(create == (um->store.mselect ==
nullptr));
481 BArrayState *state_reference = um_ref ? um_ref->store.mselect :
nullptr;
482 const size_t stride =
sizeof(*mesh->mselect);
488 bs, mesh->mselect,
size_t(mesh->totselect) * stride, state_reference);
493 mesh->mselect =
nullptr;
513 size_t size_expanded_prev = 0, size_compacted_prev = 0;
516 size_t size_expanded_prev_iter, size_compacted_prev_iter;
518 &
um_arraystore.bs_stride[bs_index], &size_expanded_prev_iter, &size_compacted_prev_iter);
519 size_expanded_prev += size_expanded_prev_iter;
520 size_compacted_prev += size_compacted_prev_iter;
536 size_t size_expanded = 0, size_compacted = 0;
539 size_t size_expanded_iter, size_compacted_iter;
541 &
um_arraystore.bs_stride[bs_index], &size_expanded_iter, &size_compacted_iter);
542 size_expanded += size_expanded_iter;
543 size_compacted += size_compacted_iter;
546 const double percent_total = size_expanded ?
547 ((
double(size_compacted) /
double(size_expanded)) * 100.0) :
550 size_t size_expanded_step = size_expanded - size_expanded_prev;
551 size_t size_compacted_step = size_compacted - size_compacted_prev;
552 const double percent_step = size_expanded_step ?
553 ((
double(size_compacted_step) /
double(size_expanded_step)) *
557 printf(
"overall memory use: %.8f%% of expanded size\n", percent_total);
558 printf(
"step memory use: %.8f%% of expanded size\n", percent_step);
563# ifdef USE_ARRAY_STORE_THREAD
595 const size_t stride = mesh->key->elemsize;
597 for (
int i = 0; i < mesh->key->totkey; i++, keyblock = keyblock->
next) {
607 const size_t stride =
sizeof(*mesh->face_offset_indices);
610 mesh->face_offset_indices =
static_cast<int *
>(
613 mesh->face_offset_indices);
614 BLI_assert((mesh->faces_num + 1) == (state_len / stride));
618 const size_t stride =
sizeof(*mesh->mselect);
621 mesh->mselect =
static_cast<MSelect *
>(
623 BLI_assert(mesh->totselect == (state_len / stride));
638 const size_t stride = mesh->key->elemsize;
641 for (
int i = 0; i < mesh->key->totkey; i++) {
650 const size_t stride =
sizeof(*mesh->face_offset_indices);
658 const size_t stride =
sizeof(*mesh->mselect);
672 printf(
"mesh undo store: freeing all data!\n");
677# ifdef USE_ARRAY_STORE_THREAD
707 for (
int i = 0; i < object_len; i++) {
708 const Mesh *mesh =
static_cast<const Mesh *
>(
object[i]->data);
711 int uuid_map_len = object_len;
717 while (um_iter && (uuid_map_len != 0)) {
719 if ((um_p =
static_cast<UndoMesh **
>(
729 if (uuid_map_len == object_len) {
731 um_references =
nullptr;
733 return um_references;
748#ifdef USE_ARRAY_STORE_THREAD
755 if (key !=
nullptr) {
779 params.calc_object_remap =
false;
780 params.update_shapekey_indices =
false;
781 params.cd_mask_extra = cd_mask_extra;
782 params.active_shapekey_to_mvert =
true;
788#ifdef USE_ARRAY_STORE
793# ifdef USE_ARRAY_STORE_THREAD
819#ifdef USE_ARRAY_STORE
820# ifdef USE_ARRAY_STORE_THREAD
849 convert_params.calc_vert_normal =
false;
850 convert_params.active_shapekey = um->
shapenr;
868#ifdef USE_ARRAY_STORE
877#ifdef USE_ARRAY_STORE
879# ifdef USE_ARRAY_STORE_THREAD
909 if (mesh->runtime->edit_mesh !=
nullptr) {
960#ifdef USE_ARRAY_STORE
964 for (
uint i = 0; i < objects.size(); i++) {
970 BMEditMesh *em = mesh->runtime->edit_mesh.get();
976#ifdef USE_ARRAY_STORE
982 if (um_references !=
nullptr) {
1009 if (mesh->runtime->edit_mesh ==
nullptr) {
1012 "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
1017 BMEditMesh *em = mesh->runtime->edit_mesh.get();
1064 ut->
name =
"Edit Mesh";
Scene * CTX_data_scene(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_sizeof(eCustomDataType type)
bool CustomData_layertype_is_dynamic(eCustomDataType type)
BMEditMesh * BKE_editmesh_create(BMesh *bm)
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
void BKE_key_free_data(Key *key)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
@ LIB_ID_COPY_NO_ANIMDATA
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
void BKE_mesh_free_data_for_undo(Mesh *mesh)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
@ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE
void(*)(void *user_data, UndoRefID *id_ref) UndoTypeForEachIDRefFn
Efficient in-memory storage of multiple similar arrays.
BArrayState * BLI_array_store_state_add(BArrayStore *bs, const void *data, size_t data_len, const BArrayState *state_reference)
void BLI_array_store_state_remove(BArrayStore *bs, BArrayState *state)
void * BLI_array_store_state_data_get_alloc(BArrayState *state, size_t *r_data_len)
void BLI_array_store_at_size_clear(struct BArrayStore_AtSize *bs_stride)
void BLI_array_store_at_size_calc_memory_usage(const struct BArrayStore_AtSize *bs_stride, size_t *r_size_expanded, size_t *r_size_compacted)
BArrayStore * BLI_array_store_at_size_get(struct BArrayStore_AtSize *bs_stride, int stride)
BArrayStore * BLI_array_store_at_size_ensure(struct BArrayStore_AtSize *bs_stride, int stride, int chunk_size)
Generic array manipulation API.
#define BLI_array_is_zeroed(arr, arr_len)
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int power_of_2_max_i(int n)
#define STRNCPY(dst, src)
void BLI_task_pool_work_and_wait(TaskPool *pool)
TaskPool * BLI_task_pool_create_background(void *userdata, eTaskPriority priority)
void BLI_task_pool_free(TaskPool *pool)
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
typedef double(DMatrix)[4][4]
#define CLOG_ERROR(clg_ref,...)
void DEG_id_tag_update(ID *id, unsigned int flags)
#define CD_MASK_SHAPE_KEYINDEX
Object is a sort of wrapper for general info.
void EDBM_mesh_free_data(BMEditMesh *em)
void ED_undo_object_set_active_or_warn(Scene *scene, ViewLayer *view_layer, Object *ob, const char *info, CLG_LogRef *log)
void ED_undo_object_editmode_restore_helper(Scene *scene, ViewLayer *view_layer, Object **object_array, uint object_array_len, uint object_array_stride)
blender::Vector< Object * > ED_undo_editmode_objects_from_view_layer(const Scene *scene, ViewLayer *view_layer)
void ED_undo_object_editmode_validate_scene_from_windows(wmWindowManager *wm, const Scene *scene_ref, Scene **scene_p, ViewLayer **view_layer_p)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
#define BMALLOC_TEMPLATE_FROM_ME(...)
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParams *params)
void reinitialize(const int64_t new_size)
static Object * editmesh_object_from_context(bContext *C)
static void um_arraystore_expand(UndoMesh *um)
static void um_arraystore_compact_cb(TaskPool *__restrict, void *taskdata)
static void um_arraystore_free(UndoMesh *um)
static void undomesh_free_data(UndoMesh *um)
static void um_arraystore_cd_free(BArrayCustomData *bcd, const int bs_index)
#define ARRAY_CHUNK_NUM_MIN
static bool mesh_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
#define ARRAY_CHUNK_SIZE_IN_BYTES
BArrayStore_AtSize bs_stride[ARRAY_STORE_INDEX_NUM]
void ED_mesh_undosys_type(UndoType *ut)
static struct @443 um_arraystore
static void um_arraystore_compact(UndoMesh *um, const UndoMesh *um_ref)
#define ARRAY_STORE_INDEX_NUM
static size_t array_chunk_size_calc(const size_t stride)
static void um_arraystore_expand_clear(UndoMesh *um)
static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em)
static void um_arraystore_cd_expand(const BArrayCustomData *bcd, CustomData *cdata, const size_t data_len)
static bool mesh_undosys_poll(bContext *C)
static void mesh_undosys_foreach_ID_ref(UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
@ ARRAY_STORE_INDEX_POLY_OFFSETS
@ ARRAY_STORE_INDEX_SHAPE
static void * undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, UndoMesh *um_ref)
static void mesh_undosys_step_free(UndoStep *us_p)
static void mesh_undosys_step_decode(bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir, bool)
static UndoMesh ** mesh_undostep_reference_elems_from_objects(Object **object, int object_len)
static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref)
static void um_arraystore_cd_compact(CustomData *cdata, const size_t data_len, const bool create, const int bs_index, const BArrayCustomData *bcd_reference, BArrayCustomData **r_bcd_first)
static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool create)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
const ImplicitSharingInfo * info_for_mem_free(void *data)
void parallel_invoke(Functions &&...functions)
blender::Array< std::variant< BArrayState *, blender::ImplicitSharingInfoAndData > > states
bool is_memfile_undo_flush_needed
UndoRefID_Object obedit_ref
MeshUndoStep_Elem * elems
UndoRefID_Scene scene_ref
MeshRuntimeHandle * runtime
BArrayState * face_offset_indices
struct UndoMesh::@444 store
void(* step_foreach_ID_ref)(UndoStep *us, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
void(* step_free)(UndoStep *us)
bool(* poll)(struct bContext *C)
void(* step_decode)(bContext *C, Main *bmain, UndoStep *us, eUndoStepDir dir, bool is_final)
bool(* step_encode)(bContext *C, Main *bmain, UndoStep *us)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)