53#define USE_ARRAY_STORE
71# define ARRAY_CHUNK_SIZE_IN_BYTES 65536
72# define ARRAY_CHUNK_NUM_MIN 256
74# define USE_ARRAY_STORE_THREAD
98# define USE_ARRAY_STORE_RLE
101#ifdef USE_ARRAY_STORE_THREAD
112#ifdef USE_ARRAY_STORE
129# ifdef USE_ARRAY_STORE_RLE
168#ifdef USE_ARRAY_STORE
181#ifdef USE_ARRAY_STORE
200# define ARRAY_STORE_INDEX_NUM (ARRAY_STORE_INDEX_MSEL + 1)
212# ifdef USE_ARRAY_STORE_THREAD
219 const size_t data_len,
228 *r_bcd_first =
nullptr;
234 for (
int layer_start = 0, layer_end; layer_start < cdata->
totlayer; layer_start = layer_end) {
252 layer_end = layer_start + 1;
253 while ((layer_end < cdata->totlayer) && (type == cdata->
layers[layer_end].
type)) {
262 const int layer_len = layer_end - layer_start;
265 if (bcd_reference_current && (bcd_reference_current->
type == type)) {
269 bcd_reference_current =
nullptr;
275 if (bcd_iter->
type == type) {
276 bcd_reference_current = bcd_iter;
279 bcd_iter = bcd_iter->
next;
286 bcd = MEM_new<BArrayCustomData>(__func__);
292 bcd_prev->next = bcd;
302 for (
int i = 0;
i < layer_len;
i++, layer++) {
305 if (layer_type_is_dynamic) {
320 state_reference = std::get<BArrayState *>(bcd_reference_current->
states[
i]);
323 void *data_final = layer->
data;
324 size_t data_final_size = size_t(data_len) * stride;
326# ifdef USE_ARRAY_STORE_RLE
328 uint8_t *data_enc =
nullptr;
331 size_t data_enc_extra_size =
sizeof(size_t);
337 memcpy(data_enc, &data_final_size, data_enc_extra_size);
338 data_final = data_enc;
339 data_final_size = data_enc_extra_size + data_enc_len;
347# ifdef USE_ARRAY_STORE_RLE
363 layer->
data =
nullptr;
372 if (bcd_reference_current) {
373 bcd_reference_current = bcd_reference_current->
next;
379 *r_bcd_first = bcd_first;
389 const size_t data_len)
397 if (std::holds_alternative<BArrayState *>(bcd->
states[
i])) {
403# ifdef USE_ARRAY_STORE_RLE
407 size_t data_enc_extra_size =
sizeof(size_t);
408 const uint8_t *data_enc =
reinterpret_cast<uint8_t *
>(
data);
410 memcpy(&data_dec_len, data_enc,
sizeof(
size_t));
413 state_len - data_enc_extra_size,
417 data =
static_cast<void *
>(data_dec);
419 state_len = data_dec_len;
429 layer->
data =
nullptr;
434 layer->
data =
const_cast<void *
>(
state.data);
452 if (std::holds_alternative<BArrayState *>(bcd->
states[
i])) {
459 state.sharing_info->remove_user_and_delete_if_last();
486 um_arraystore_cd_compact(&mesh->vert_data,
489 ARRAY_STORE_INDEX_VERT,
490 um_ref ? um_ref->store.vdata : nullptr,
494 um_arraystore_cd_compact(&mesh->edge_data,
497 ARRAY_STORE_INDEX_EDGE,
498 um_ref ? um_ref->store.edata : nullptr,
502 um_arraystore_cd_compact(&mesh->corner_data,
505 ARRAY_STORE_INDEX_LOOP,
506 um_ref ? um_ref->store.ldata : nullptr,
510 um_arraystore_cd_compact(&mesh->face_data,
513 ARRAY_STORE_INDEX_POLY,
514 um_ref ? um_ref->store.pdata : nullptr,
518 if (mesh->face_offset_indices) {
519 BLI_assert(create == (um->store.face_offset_indices == nullptr));
521 BArrayState *state_reference = um_ref ? um_ref->store.face_offset_indices : nullptr;
522 const size_t stride = sizeof(*mesh->face_offset_indices);
523 BArrayStore *bs = BLI_array_store_at_size_ensure(
524 &um_arraystore.bs_stride[ARRAY_STORE_INDEX_POLY_OFFSETS],
526 array_chunk_size_calc(stride));
527 um->store.face_offset_indices = BLI_array_store_state_add(bs,
528 mesh->face_offset_indices,
529 size_t(mesh->faces_num + 1) *
533 blender::implicit_sharing::free_shared_data(&mesh->face_offset_indices,
534 &mesh->runtime->face_offsets_sharing_info);
538 if (mesh->key && mesh->key->totkey) {
539 const size_t stride = mesh->key->elemsize;
547 MEM_mallocN(mesh->key->totkey *
sizeof(*um->store.keyblocks), __func__));
550 for (
int i = 0;
i < mesh->key->totkey;
i++, keyblock = keyblock->
next) {
552 BArrayState *state_reference = (um_ref && um_ref->mesh->key &&
553 (
i < um_ref->mesh->key->totkey)) ?
554 um_ref->store.keyblocks[
i] :
557 bs, keyblock->data,
size_t(keyblock->totelem) * stride, state_reference);
560 if (keyblock->data) {
562 keyblock->data =
nullptr;
568 if (mesh->mselect && mesh->totselect) {
569 BLI_assert(create == (um->store.mselect ==
nullptr));
571 BArrayState *state_reference = um_ref ? um_ref->store.mselect :
nullptr;
572 const size_t stride =
sizeof(*mesh->mselect);
578 bs, mesh->mselect,
size_t(mesh->totselect) * stride, state_reference);
583 mesh->mselect =
nullptr;
603 size_t size_expanded_prev = 0, size_compacted_prev = 0;
606 size_t size_expanded_prev_iter, size_compacted_prev_iter;
608 &
um_arraystore.bs_stride[bs_index], &size_expanded_prev_iter, &size_compacted_prev_iter);
609 size_expanded_prev += size_expanded_prev_iter;
610 size_compacted_prev += size_compacted_prev_iter;
626 size_t size_expanded = 0, size_compacted = 0;
629 size_t size_expanded_iter, size_compacted_iter;
631 &
um_arraystore.bs_stride[bs_index], &size_expanded_iter, &size_compacted_iter);
632 size_expanded += size_expanded_iter;
633 size_compacted += size_compacted_iter;
636 const double percent_total = size_expanded ?
637 ((double(size_compacted) / double(size_expanded)) * 100.0) :
640 size_t size_expanded_step = size_expanded - size_expanded_prev;
641 size_t size_compacted_step = size_compacted - size_compacted_prev;
642 const double percent_step = size_expanded_step ?
643 ((double(size_compacted_step) / double(size_expanded_step)) *
647 printf(
"overall memory use: %.8f%% of expanded size\n", percent_total);
648 printf(
"step memory use: %.8f%% of expanded size\n", percent_step);
653# ifdef USE_ARRAY_STORE_THREAD
708 const size_t stride =
sizeof(*mesh->
mselect);
748 const size_t stride =
sizeof(*mesh->
mselect);
762 printf(
"mesh undo store: freeing all data!\n");
767# ifdef USE_ARRAY_STORE_THREAD
796 for (
int i = 0;
i < object_len;
i++) {
797 const Mesh *mesh =
static_cast<const Mesh *
>(
object[
i]->data);
800 int uuid_map_len = object_len;
806 while (um_iter && (uuid_map_len != 0)) {
818 if (uuid_map_len == object_len) {
820 um_references =
nullptr;
822 return um_references;
843 const int vertex_group_active_index,
847#ifdef USE_ARRAY_STORE_THREAD
857 if (key !=
nullptr) {
872 params.calc_object_remap =
false;
873 params.update_shapekey_indices =
false;
874 params.cd_mask_extra = cd_mask_extra;
875 params.active_shapekey_to_mvert =
true;
883#ifdef USE_ARRAY_STORE
888# ifdef USE_ARRAY_STORE_THREAD
920 int *vertex_group_active_index)
925#ifdef USE_ARRAY_STORE
926# ifdef USE_ARRAY_STORE_THREAD
975#ifdef USE_ARRAY_STORE
984#ifdef USE_ARRAY_STORE
986# ifdef USE_ARRAY_STORE_THREAD
1002 mesh->
key =
nullptr;
1017 if (mesh->
runtime->edit_mesh !=
nullptr) {
1065 UndoMesh **um_references =
nullptr;
1067#ifdef USE_ARRAY_STORE
1083 um_references ? um_references[
i] :
nullptr);
1089#ifdef USE_ARRAY_STORE
1095 if (um_references !=
nullptr) {
1122 if (mesh->
runtime->edit_mesh ==
nullptr) {
1125 "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
1184 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_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_COPY_NO_ANIMDATA
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
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(const BArrayState *state, size_t *r_data_len)
void BLI_array_store_rle_decode(const uint8_t *data_enc, const size_t data_enc_len, void *data_dec_v, const size_t data_dec_len)
uint8_t * BLI_array_store_rle_encode(const uint8_t *data_dec, size_t data_dec_len, size_t data_enc_extra_size, size_t *r_data_enc_len)
struct BArrayStore * BLI_array_store_at_size_ensure(struct BArrayStore_AtSize *bs_stride, int stride, int chunk_size)
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)
struct BArrayStore * BLI_array_store_at_size_get(struct BArrayStore_AtSize *bs_stride, int stride)
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)
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE int power_of_2_max_i(int n)
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(...)
#define CLOG_ERROR(clg_ref,...)
void DEG_id_tag_update(ID *id, unsigned int flags)
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.
BMesh const char void * data
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)
BArrayStore_AtSize bs_stride
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 * undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, const ListBase *vertex_group_names, const int vertex_group_active_index, UndoMesh *um_ref)
static void undomesh_to_editmesh(UndoMesh *um, BMEditMesh *em, ListBase *vertex_group_names, int *vertex_group_active_index)
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
void ED_mesh_undosys_type(UndoType *ut)
static void um_arraystore_compact(UndoMesh *um, const UndoMesh *um_ref)
static struct @060174143312344215311261256220167117024134050205 um_arraystore
#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 um_arraystore_cd_expand(const BArrayCustomData *bcd, CustomData *cdata, const size_t data_len)
@ ARRAY_STORE_INDEX_POLY_OFFSETS
@ ARRAY_STORE_INDEX_SHAPE
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)
static bool um_customdata_layer_use_rle(const BArrayCustomData *bcd)
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)
#define CD_MASK_SHAPE_KEYINDEX
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
Mesh * mesh_new_no_attributes(int verts_num, int edges_num, int faces_num, int corners_num)
const ImplicitSharingInfo * info_for_mem_free(void *data)
void parallel_invoke(Functions &&...functions)
blender::Array< std::variant< BArrayState *, blender::ImplicitSharingInfoAndData > > states
const ImplicitSharingInfoHandle * sharing_info
bool is_memfile_undo_flush_needed
UndoRefID_Object obedit_ref
MeshUndoStep_Elem * elems
UndoRefID_Scene scene_ref
MeshRuntimeHandle * runtime
ListBase vertex_group_names
int * face_offset_indices
int vertex_group_active_index
struct ToolSettings * toolsettings
BArrayState * face_offset_indices
struct UndoMesh::@241132136031332173343267200163210323165327054204 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)