When writing .blend files, Blender traditionally wrote raw runtime-pointers into the file. Since these pointers are different whenever Blender is restarted or the file is loaded again, the written .blend file will be very different every time. The file always changing is a problem with tools that use change-detection on .blend files such as: * Change detection during undo in Blender. When a serialized data-block is the same in two consecutive undo steps, it's known that the data didn't change and the data-block does not have to be reloaded and can potentially skip depsgraph evaluation. Also see #141262. * BAT: https://projects.blender.org/studio/flamenco/issues/104437 * Generally using .blend files in version control. The diffs can be smaller when pointers aren't changing all the time and have a lower memory footprint. This PR makes pointers in .blend files across multiples saves much more consistent, improving the situation for the cases above. Although there is still other data that changes on almost every save currently; that needs to be addressed separately. The basic design for pointer stability in blend files stable pointers, described in #127706, is fairly straight forward. This patch implements a slightly modified variant of that design. When reading .blend files, Blender already does not care if the stored pointer values are actual pointer values, or just some arbitrary identifiers. Therefore, we mainly just have to change the write-file code. This also implies that this change is fully forward and backward compatible. The main non-obvious aspect of this patch is how to actually do the remapping of runtime pointers to stable identifiers. In theory, having a single integer that increments for every newly detected pointer works. But in practice that leads to many changes in the .blend file because one pointer is added or removed somewhere, all subsequent pointers will be different too. So some kind of scoping is required to make sure that one small change does not affect everything else. This PR starts a new scope pointer identifier scope whenever a new ID data-block starts. At first I thought it would be good to have separate maps for id-local and global pointers. However, that's tricky currently, because at write-time, we don't always have enough information to know if a specific pointer is local or global. I worked on #146136 to improve the situation but the problem is bigger than that since we also have various void pointers in DNA structs. Fortunately, the solution implemented now also works fine with a single global map. Implicit sharing in undo steps also had to be changed slightly to work with the stable address identifiers instead of raw pointers. There's also new code to find all pointers in DNA structs in the first place. This is done once when writing starts. Then whenever a struct is written, a copy is made, all pointers are replaced and the modified struct is written to the .blend file. There is an optimization for the case when a struct does not contain any pointers because then the copy can be skipped. For checking the diff between two saved .blend files, I recommend enabling `GENERATE_DEBUG_BLEND_FILE` and then diffing the text version of the .blend files. Co-authored-by: Hans Goudey <hans@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/127729
144 lines
3.1 KiB
CMake
144 lines
3.1 KiB
CMake
# SPDX-FileCopyrightText: 2006 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
set(INC
|
|
PUBLIC .
|
|
../editors/include
|
|
../makesrna
|
|
|
|
# RNA_prototypes.hh
|
|
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
|
)
|
|
|
|
set(INC_SYS
|
|
${ZSTD_INCLUDE_DIRS}
|
|
)
|
|
|
|
set(SRC
|
|
${CMAKE_SOURCE_DIR}/release/datafiles/userdef/userdef_default_theme.c
|
|
intern/blend_validate.cc
|
|
intern/readblenentry.cc
|
|
intern/readfile.cc
|
|
intern/readfile_tempload.cc
|
|
intern/undofile.cc
|
|
intern/versioning_250.cc
|
|
intern/versioning_260.cc
|
|
intern/versioning_270.cc
|
|
intern/versioning_280.cc
|
|
intern/versioning_290.cc
|
|
intern/versioning_300.cc
|
|
intern/versioning_400.cc
|
|
intern/versioning_410.cc
|
|
intern/versioning_420.cc
|
|
intern/versioning_430.cc
|
|
intern/versioning_440.cc
|
|
intern/versioning_450.cc
|
|
intern/versioning_500.cc
|
|
intern/versioning_common.cc
|
|
intern/versioning_defaults.cc
|
|
intern/versioning_dna.cc
|
|
intern/versioning_legacy.cc
|
|
intern/versioning_userdef.cc
|
|
intern/writefile.cc
|
|
|
|
BLO_blend_validate.hh
|
|
BLO_read_write.hh
|
|
BLO_readfile.hh
|
|
BLO_undofile.hh
|
|
BLO_userdef_default.h
|
|
BLO_writefile.hh
|
|
intern/readfile.hh
|
|
intern/versioning_common.hh
|
|
)
|
|
|
|
set(LIB
|
|
PRIVATE bf::animrig
|
|
PRIVATE bf::asset_system
|
|
PRIVATE bf::blenkernel
|
|
PRIVATE bf::blenlib
|
|
PUBLIC bf::blenloader_core
|
|
PRIVATE bf::blentranslation
|
|
PRIVATE bf::bmesh
|
|
PRIVATE bf::depsgraph
|
|
PRIVATE bf::dna
|
|
PRIVATE bf::draw
|
|
PRIVATE bf::gpu
|
|
PRIVATE bf::imbuf
|
|
PRIVATE bf::imbuf::movie
|
|
PRIVATE bf::intern::clog
|
|
PRIVATE bf::intern::guardedalloc
|
|
PRIVATE bf::extern::fmtlib
|
|
PRIVATE bf::intern::memutil
|
|
PRIVATE bf::nodes
|
|
PRIVATE bf::render
|
|
PRIVATE bf::sequencer
|
|
PRIVATE bf::windowmanager
|
|
PRIVATE bf::extern::xxhash
|
|
)
|
|
|
|
if(WITH_BUILDINFO)
|
|
add_definitions(-DWITH_BUILDINFO)
|
|
endif()
|
|
|
|
if(WITH_CODEC_FFMPEG)
|
|
add_definitions(-DWITH_FFMPEG)
|
|
endif()
|
|
|
|
if(WITH_ALEMBIC)
|
|
list(APPEND INC
|
|
../io/alembic
|
|
)
|
|
add_definitions(-DWITH_ALEMBIC)
|
|
endif()
|
|
|
|
if(WIN32)
|
|
add_definitions(-DNOMINMAX)
|
|
endif()
|
|
|
|
blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|
add_library(bf::blenloader ALIAS bf_blenloader)
|
|
|
|
# RNA_prototypes.hh
|
|
add_dependencies(bf_blenloader bf_rna)
|
|
|
|
if(WITH_GTESTS)
|
|
# Utility functions for test also used by other tests.
|
|
set(TEST_UTIL_SRC
|
|
tests/blendfile_loading_base_test.cc
|
|
tests/blendfile_loading_base_test.h
|
|
)
|
|
set(TEST_UTIL_INC
|
|
${INC}
|
|
../../../tests/gtests
|
|
../../../intern/ghost
|
|
)
|
|
set(TEST_UTIL_INC_SYS
|
|
${INC_SYS}
|
|
${GFLAGS_INCLUDE_DIRS}
|
|
${GLOG_INCLUDE_DIRS}
|
|
${CMAKE_SOURCE_DIR}/extern/gtest/include
|
|
)
|
|
set(TEST_UTIL_LIB
|
|
${LIB}
|
|
PRIVATE bf::blenfont
|
|
bf_blenloader
|
|
)
|
|
blender_add_lib(bf_blenloader_test_util "${TEST_UTIL_SRC}" "${TEST_UTIL_INC}" "${TEST_UTIL_INC_SYS}" "${TEST_UTIL_LIB}")
|
|
|
|
# Actual `blenloader` tests.
|
|
set(TEST_SRC
|
|
tests/blendfile_load_test.cc
|
|
)
|
|
set(TEST_LIB
|
|
${LIB}
|
|
bf_blenloader
|
|
bf_blenloader_test_util
|
|
)
|
|
blender_add_test_suite_lib(blenloader "${TEST_SRC}" "${INC}" "${INC_SYS}" "${TEST_LIB}")
|
|
endif()
|
|
|
|
if(WITH_EXPERIMENTAL_FEATURES)
|
|
add_definitions(-DWITH_EXPERIMENTAL_FEATURES)
|
|
endif()
|