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
167#ifdef USE_ARRAY_STORE
180#ifdef USE_ARRAY_STORE
199# define ARRAY_STORE_INDEX_NUM (ARRAY_STORE_INDEX_MSEL + 1)
211# ifdef USE_ARRAY_STORE_THREAD
218 const size_t data_len,
227 *r_bcd_first =
nullptr;
233 for (
int layer_start = 0, layer_end; layer_start < cdata->
totlayer; layer_start = layer_end) {
251 layer_end = layer_start + 1;
252 while ((layer_end < cdata->totlayer) && (type == cdata->
layers[layer_end].
type)) {
261 const int layer_len = layer_end - layer_start;
264 if (bcd_reference_current && (bcd_reference_current->
type == type)) {
268 bcd_reference_current =
nullptr;
274 if (bcd_iter->
type == type) {
275 bcd_reference_current = bcd_iter;
278 bcd_iter = bcd_iter->
next;
285 bcd = MEM_new<BArrayCustomData>(__func__);
291 bcd_prev->next = bcd;
301 for (
int i = 0;
i < layer_len;
i++, layer++) {
304 if (layer_type_is_dynamic) {
313 state_reference = std::get<BArrayState *>(bcd_reference_current->
states[
i]);
316 void *data_final = layer->
data;
317 size_t data_final_size = size_t(data_len) * stride;
319# ifdef USE_ARRAY_STORE_RLE
321 uint8_t *data_enc =
nullptr;
324 size_t data_enc_extra_size =
sizeof(size_t);
330 memcpy(data_enc, &data_final_size, data_enc_extra_size);
331 data_final = data_enc;
332 data_final_size = data_enc_extra_size + data_enc_len;
340# ifdef USE_ARRAY_STORE_RLE
355 layer->
data =
nullptr;
360 if (bcd_reference_current) {
361 bcd_reference_current = bcd_reference_current->
next;
367 *r_bcd_first = bcd_first;
377 const size_t data_len)
385 if (std::holds_alternative<BArrayState *>(bcd->
states[
i])) {
391# ifdef USE_ARRAY_STORE_RLE
395 size_t data_enc_extra_size =
sizeof(size_t);
396 const uint8_t *data_enc =
reinterpret_cast<uint8_t *
>(
data);
398 memcpy(&data_dec_len, data_enc,
sizeof(
size_t));
401 state_len - data_enc_extra_size,
405 data =
static_cast<void *
>(data_dec);
407 state_len = data_dec_len;
417 layer->
data =
nullptr;
422 layer->
data =
const_cast<void *
>(
state.data);
440 if (std::holds_alternative<BArrayState *>(bcd->
states[
i])) {
447 state.sharing_info->remove_user_and_delete_if_last();
474 um_arraystore_cd_compact(&mesh->vert_data,
477 ARRAY_STORE_INDEX_VERT,
478 um_ref ? um_ref->store.vdata : nullptr,
482 um_arraystore_cd_compact(&mesh->edge_data,
485 ARRAY_STORE_INDEX_EDGE,
486 um_ref ? um_ref->store.edata : nullptr,
490 um_arraystore_cd_compact(&mesh->corner_data,
493 ARRAY_STORE_INDEX_LOOP,
494 um_ref ? um_ref->store.ldata : nullptr,
498 um_arraystore_cd_compact(&mesh->face_data,
501 ARRAY_STORE_INDEX_POLY,
502 um_ref ? um_ref->store.pdata : nullptr,
506 if (mesh->face_offset_indices) {
507 BLI_assert(create == (um->store.face_offset_indices == nullptr));
509 const BArrayState *state_reference = um_ref ? um_ref->store.face_offset_indices :
511 const size_t stride = sizeof(*mesh->face_offset_indices);
512 BArrayStore *bs = BLI_array_store_at_size_ensure(
513 &um_arraystore.bs_stride[ARRAY_STORE_INDEX_POLY_OFFSETS],
515 array_chunk_size_calc(stride));
516 um->store.face_offset_indices = BLI_array_store_state_add(bs,
517 mesh->face_offset_indices,
518 size_t(mesh->faces_num + 1) *
522 blender::implicit_sharing::free_shared_data(&mesh->face_offset_indices,
523 &mesh->runtime->face_offsets_sharing_info);
527 if (mesh->key && mesh->key->totkey) {
528 const size_t stride = mesh->key->elemsize;
536 MEM_mallocN(mesh->key->totkey *
sizeof(*um->store.keyblocks), __func__));
539 for (
int i = 0;
i < mesh->key->totkey;
i++, keyblock = keyblock->
next) {
541 const BArrayState *state_reference = (um_ref && um_ref->mesh->key &&
542 (
i < um_ref->mesh->key->totkey)) ?
543 um_ref->store.keyblocks[
i] :
546 bs, keyblock->data,
size_t(keyblock->totelem) * stride, state_reference);
549 if (keyblock->data) {
551 keyblock->data =
nullptr;
557 if (mesh->mselect && mesh->totselect) {
558 BLI_assert(create == (um->store.mselect ==
nullptr));
560 const BArrayState *state_reference = um_ref ? um_ref->store.mselect :
nullptr;
561 const size_t stride =
sizeof(*mesh->mselect);
567 bs, mesh->mselect,
size_t(mesh->totselect) * stride, state_reference);
572 mesh->mselect =
nullptr;
592 size_t size_expanded_prev = 0, size_compacted_prev = 0;
595 size_t size_expanded_prev_iter, size_compacted_prev_iter;
597 &
um_arraystore.bs_stride[bs_index], &size_expanded_prev_iter, &size_compacted_prev_iter);
598 size_expanded_prev += size_expanded_prev_iter;
599 size_compacted_prev += size_compacted_prev_iter;
615 size_t size_expanded = 0, size_compacted = 0;
618 size_t size_expanded_iter, size_compacted_iter;
620 &
um_arraystore.bs_stride[bs_index], &size_expanded_iter, &size_compacted_iter);
621 size_expanded += size_expanded_iter;
622 size_compacted += size_compacted_iter;
625 const double percent_total = size_expanded ?
626 ((double(size_compacted) / double(size_expanded)) * 100.0) :
629 size_t size_expanded_step = size_expanded - size_expanded_prev;
630 size_t size_compacted_step = size_compacted - size_compacted_prev;
631 const double percent_step = size_expanded_step ?
632 ((double(size_compacted_step) / double(size_expanded_step)) *
636 printf(
"overall memory use: %.8f%% of expanded size\n", percent_total);
637 printf(
"step memory use: %.8f%% of expanded size\n", percent_step);
642# ifdef USE_ARRAY_STORE_THREAD
697 const size_t stride =
sizeof(*mesh->
mselect);
737 const size_t stride =
sizeof(*mesh->
mselect);
751 printf(
"mesh undo store: freeing all data!\n");
756# ifdef USE_ARRAY_STORE_THREAD
785 for (
int i = 0;
i < object_len;
i++) {
786 const Mesh *mesh =
static_cast<const Mesh *
>(
object[
i]->data);
789 int uuid_map_len = object_len;
795 while (um_iter && (uuid_map_len != 0)) {
807 if (uuid_map_len == object_len) {
809 um_references =
nullptr;
811 return um_references;
832 const int vertex_group_active_index,
836#ifdef USE_ARRAY_STORE_THREAD
846 if (key !=
nullptr) {
861 bool check_flush =
true;
863 bool check_contiguous = (cd_loop_uv_offset != -1);
866 em->
bm, cd_loop_uv_offset,
true, check_flush, check_contiguous, &info);
867 if (is_valid ==
false) {
868 fprintf(stderr,
"ERROR: UV sync check failed!\n");
878 params.calc_object_remap =
false;
879 params.update_shapekey_indices =
false;
880 params.cd_mask_extra = cd_mask_extra;
881 params.active_shapekey_to_mvert =
true;
889#ifdef USE_ARRAY_STORE
894# ifdef USE_ARRAY_STORE_THREAD
926 int *vertex_group_active_index)
931#ifdef USE_ARRAY_STORE
932# ifdef USE_ARRAY_STORE_THREAD
981#ifdef USE_ARRAY_STORE
990#ifdef USE_ARRAY_STORE
992# ifdef USE_ARRAY_STORE_THREAD
1008 mesh->
key =
nullptr;
1023 if (mesh->
runtime->edit_mesh !=
nullptr) {
1084 UndoMesh **um_references =
nullptr;
1086#ifdef USE_ARRAY_STORE
1110 um_references ? um_references[
i] :
nullptr);
1115#ifdef USE_ARRAY_STORE
1121 if (um_references !=
nullptr) {
1148 if (mesh->
runtime->edit_mesh ==
nullptr) {
1151 "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
1222 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)
int CustomData_get_offset(const CustomData *data, 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)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
@ LIB_ID_COPY_NO_ANIMDATA
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)
#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.
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)
bool BM_mesh_is_valid(BMesh *bm)
bool BM_mesh_uvselect_is_valid(BMesh *bm, const int cd_loop_uv_offset, const bool check_sync, const bool check_flush, const bool check_contiguous, UVSelectValidateInfo *info_p)
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)
@ ARRAY_STORE_INDEX_POLY_OFFSETS
@ ARRAY_STORE_INDEX_SHAPE
#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)
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 struct @337111344364020116106255322323117072035066202234 um_arraystore
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_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
bool uv_select_sync_valid
const ImplicitSharingInfoHandle * sharing_info
bool is_memfile_undo_flush_needed
UndoRefID_Object obedit_ref
MeshUndoStep_Elem * elems
UndoRefID_Scene scene_ref
MeshUndoStep_SceneData scene_data
MeshRuntimeHandle * runtime
ListBase vertex_group_names
int * face_offset_indices
int vertex_group_active_index
struct ToolSettings * toolsettings
BArrayState * face_offset_indices
struct UndoMesh::@125065304153060141020032116057354024373376324373 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)