Merge branch 'refactor-mesh-position-generic' into refactor-mesh-corners-generic

This commit is contained in:
Hans Goudey 2023-01-09 14:42:02 -05:00
commit 39f498f350
564 changed files with 17487 additions and 6387 deletions

View File

@ -118,14 +118,18 @@ enable_testing()
if(CMAKE_COMPILER_IS_GNUCC)
if("${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "11.0.0")
message(FATAL_ERROR "The minimum supported version of GCC is 11.0.0")
message(FATAL_ERROR "The minimum supported version of GCC is 11.0.0, found ${CMAKE_C_COMPILER_VERSION}")
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
if(CMAKE_COMPILER_IS_GNUCC AND ("${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "8.0"))
message(FATAL_ERROR "The minimum supported version of CLANG is 8.0")
message(FATAL_ERROR "The minimum supported version of CLANG is 8.0, found ${CMAKE_C_COMPILER_VERSION}")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
if(MSVC_VERSION VERSION_LESS "1928")
# MSVC_VERSION is an internal version number, it doesn't map to something
# the end user would recognize as a version. Because of this, for MSVC we do
# not show the found number. When using our make.bat the actual VS version
# will be displayed on the console before starting the build, anyway.
message(FATAL_ERROR "The minimum supported version of MSVC is 2019 (16.9.16)")
endif()
endif()

View File

@ -22,6 +22,14 @@ elseif(UNIX AND NOT APPLE)
)
endif()
# Boolean crashes with Arm assembly, see T103423.
if(BLENDER_PLATFORM_ARM)
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL file://${PACKAGE_DIR}/${GMP_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -39,15 +39,15 @@ with-all,with-opencollada,with-jack,with-pulseaudio,with-embree,with-oidn,with-n
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,ver-level-zero:\
force-all,force-python,force-boost,force-tbb,\
force-ocio,force-imath,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\
force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-materialx,force-usd,\
force-xr-openxr,force-level-zero,force-openpgl,\
build-all,build-python,build-boost,build-tbb,\
build-ocio,build-imath,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\
build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-materialx,build-usd,\
build-xr-openxr,build-level-zero,build-openpgl,\
skip-python,skip-boost,skip-tbb,\
skip-ocio,skip-imath,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd,\
skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-materialx,skip-usd,\
skip-xr-openxr,skip-level-zero,skip-openpgl \
-- "$@" \
)
@ -223,6 +223,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--build-ffmpeg
Force the build of FFMpeg.
--build-materialx
Force the build of MaterialX.
--build-usd
Force the build of Universal Scene Description.
@ -296,6 +299,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-ffmpeg
Force the rebuild of FFMpeg.
--force-materialx
Force the rebuild of MaterialX.
--force-usd
Force the rebuild of Universal Scene Description.
@ -362,6 +368,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--skip-ffmpeg
Unconditionally skip FFMpeg installation/building.
--skip-materialx
Unconditionally skip MaterialX installation/building.
--skip-usd
Unconditionally skip Universal Scene Description installation/building.
@ -402,6 +411,7 @@ PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT
PYTHON_FORCE_BUILD=false
PYTHON_FORCE_REBUILD=false
PYTHON_SKIP=false
_with_built_python=false
# Additional Python modules.
PYTHON_IDNA_VERSION="3.3"
@ -466,7 +476,9 @@ BOOST_VERSION="1.80.0"
BOOST_VERSION_SHORT="1.80"
BOOST_VERSION_MIN="1.49"
BOOST_VERSION_MEX="2.0"
BOOST_FORCE_BUILD=false
# XXX Boost currently has an issue with python/tbb, see rB019b930 for details and patch used to fix it.
# So for now it has to be built, system packages are not usable. :(
BOOST_FORCE_BUILD=true
BOOST_FORCE_REBUILD=false
BOOST_SKIP=false
@ -560,6 +572,14 @@ ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
ALEMBIC_SKIP=false
MATERIALX_VERSION="1.38.6"
MATERIALX_VERSION_SHORT="1.38"
MATERIALX_VERSION_MIN="1.38"
MATERIALX_VERSION_MEX="1.40"
MATERIALX_FORCE_BUILD=false
MATERIALX_FORCE_REBUILD=false
MATERIALX_SKIP=false
USD_VERSION="22.11"
USD_VERSION_SHORT="22.11"
USD_VERSION_MIN="20.05"
@ -896,6 +916,9 @@ while true; do
--build-alembic)
ALEMBIC_FORCE_BUILD=true; shift; continue
;;
--build-materialx)
MATERIALX_FORCE_BUILD=true; shift; continue
;;
--build-usd)
USD_FORCE_BUILD=true; shift; continue
;;
@ -925,6 +948,7 @@ while true; do
OIDN_FORCE_REBUILD=true
FFMPEG_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
MATERIALX_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
XR_OPENXR_FORCE_REBUILD=true
LEVEL_ZERO_FORCE_REBUILD=true
@ -980,6 +1004,9 @@ while true; do
--force-alembic)
ALEMBIC_FORCE_REBUILD=true; shift; continue
;;
--force-materialx)
MATERIALX_FORCE_REBUILD=true; shift; continue
;;
--force-usd)
USD_FORCE_REBUILD=true; shift; continue
;;
@ -1043,6 +1070,9 @@ while true; do
--skip-usd)
USD_SKIP=true; shift; continue
;;
--skip-materialx)
MATERIALX_SKIP=true; shift; continue
;;
--skip-xr-openxr)
XR_OPENXR_SKIP=true; shift; continue
;;
@ -1108,7 +1138,9 @@ PYTHON_SOURCE=( "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHO
_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
BOOST_SOURCE=( "https://boostorg.jfrog.io/artifactory/main/release/$BOOST_VERSION/source/boost_$_boost_version_nodots.tar.bz2" )
BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options --with-serialization --with-atomic"
BOOST_BUILD_MODULES="--with-filesystem --with-locale --with-thread --with-regex --with-system --with-date_time --with-wave --with-atomic --with-serialization --with-program_options --with-iostreams --with-python"
# Used by debian distros.
BOOST_DEB_PACKAGE_MODULES=( "libboost-filesystem" "libboost-locale" "libboost-thread" "libboost-regex" "libboost-system" "libboost-date-time" "libboost-wave" "libboost-atomic" "libboost-serialization" "libboost-program-options" "libboost-iostreams" "libboost-python" "libboost-numpy" )
TBB_SOURCE=( "https://github.com/oneapi-src/oneTBB/archive/$TBB_VERSION$TBB_VERSION_UPDATE.tar.gz" )
TBB_SOURCE_CMAKE=( "https://raw.githubusercontent.com/wjakob/tbb/master/CMakeLists.txt" )
@ -1165,6 +1197,8 @@ ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.
# ALEMBIC_SOURCE_REPO_UID="e6c90d4faa32c4550adeaaf3f556dad4b73a92bb"
# ALEMBIC_SOURCE_REPO_BRANCH="master"
MATERIALX_SOURCE=( "https://github.com/AcademySoftwareFoundation/MaterialX/archive/refs/tags/v${MATERIALX_VERSION}.tar.gz" )
USD_SOURCE=( "https://github.com/PixarAnimationStudios/USD/archive/v${USD_VERSION}.tar.gz" )
OPENCOLLADA_USE_REPO=false
@ -1217,8 +1251,10 @@ Those libraries should be available as packages in all recent distributions (opt
* libjpeg, libpng, libtiff, [openjpeg2], [libopenal].
* libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed).
* libwayland-client0, libdecor, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland)
* libsqlite3, libzstd, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp, flex.
* libsdl2, libepoxy, libpugixml, libpotrace, [libgmp], fontconfig, [libharu/libhpdf].\""
* libsqlite3, libzstd, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp, flex, pybind11.
* libsdl2, libepoxy, libpugixml, libpotrace, [libgmp], fontconfig, [libharu/libhpdf].
* [libvulkan/vulkan-loader].
* [libfribidi], [libharfbuzz].\""
DEPS_SPECIFIC_INFO="\"BUILDABLE DEPENDENCIES:
@ -1479,9 +1515,17 @@ _init_python() {
_update_deps_python() {
if [ "$1" = true ]; then
BOOST_FORCE_BUILD=true
OCIO_FORCE_BUILD=true
OIIO_FORCE_BUILD=true
OPENVDB_FORCE_BUILD=true
USD_FORCE_BUILD=true
fi
if [ "$2" = true ]; then
BOOST_FORCE_REBUILD=true
OCIO_FORCE_REBUILD=true
OIIO_FORCE_REBUILD=true
OPENVDB_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
fi
}
@ -1567,6 +1611,9 @@ compile_Python() {
PRINT ""
$_python -m pip install $module --no-binary :all:
done
_with_built_python=true
_with_built_python_execpath="$INST/python-$PYTHON_VERSION_SHORT/bin/python3"
}
# ----------------------------------------------------------------------------
@ -1585,12 +1632,14 @@ _update_deps_boost() {
OSL_FORCE_BUILD=true
OPENVDB_FORCE_BUILD=true
ALEMBIC_FORCE_BUILD=true
USD_FORCE_BUILD=true
fi
if [ "$2" = true ]; then
OIIO_FORCE_REBUILD=true
OSL_FORCE_REBUILD=true
OPENVDB_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
fi
}
@ -1610,7 +1659,7 @@ compile_Boost() {
fi
# To be changed each time we make edits that would modify the compiled result!
boost_magic=14
boost_magic=15
_init_boost
@ -1636,11 +1685,13 @@ compile_Boost() {
mkdir -p $SRC
download BOOST_SOURCE[@] $_src.tar.bz2
tar -C $SRC --transform "s,\w*,boost-$BOOST_VERSION,x" -xf $_src.tar.bz2
patch -d $_src -p1 < $SCRIPT_DIR/patches/boost.diff
fi
cd $_src
if [ ! -f $_src/b2 ]; then
if [ -d $INST/python-$PYTHON_VERSION_INSTALLED ]; then
if [ -d $_with_built_python ]; then
./bootstrap.sh --with-python-root="$INST/python-$PYTHON_VERSION_INSTALLED"
else
./bootstrap.sh
@ -1835,7 +1886,7 @@ compile_OCIO() {
fi
# To be changed each time we make edits that would modify the compiled result!
ocio_magic=3
ocio_magic=5
_init_ocio
# Force having own builds for the dependencies.
@ -1890,9 +1941,13 @@ compile_OCIO() {
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D OCIO_BUILD_APPS=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_PYTHON=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_PYTHON=ON"
cmake_d="$cmake_d -D OCIO_BUILD_GPU_TESTS=OFF"
if [ "$_with_built_python" = true ]; then
cmake_d="$cmake_d -D Python_EXECUTABLE=$_with_built_python_execpath"
fi
if [ $(uname -m) == "aarch64" ]; then
cmake_d="$cmake_d -D OCIO_USE_SSE=OFF"
fi
@ -2082,11 +2137,13 @@ _update_deps_openexr() {
OIIO_FORCE_BUILD=true
OPENVDB_FORCE_BUILD=true
ALEMBIC_FORCE_BUILD=true
USD_FORCE_BUILD=true
fi
if [ "$2" = true ]; then
OIIO_FORCE_REBUILD=true
OPENVDB_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
fi
}
@ -2215,9 +2272,11 @@ _init_oiio() {
_update_deps_oiio() {
if [ "$1" = true ]; then
OSL_FORCE_BUILD=true
USD_FORCE_BUILD=true
fi
if [ "$2" = true ]; then
OSL_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
fi
}
@ -2237,7 +2296,7 @@ compile_OIIO() {
fi
# To be changed each time we make edits that would modify the compiled result!
oiio_magic=19
oiio_magic=20
_init_oiio
# Force having own builds for the dependencies.
@ -2291,6 +2350,7 @@ compile_OIIO() {
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
cmake_d="$cmake_d -D LINKSTATIC=OFF"
cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON"
if [ $(uname -m) != "aarch64" ]; then
cmake_d="$cmake_d -D USE_SIMD=sse2"
@ -2306,21 +2366,37 @@ compile_OIIO() {
cmake_d="$cmake_d -D OpenEXR_ROOT=$INST/openexr"
fi
# ptex is only needed when nicholas bishop is ready
cmake_d="$cmake_d -D USE_PTEX=OFF"
cmake_d="$cmake_d -D USE_PYTHON=ON"
if [ "$_with_built_python" = true ]; then
cmake_d="$cmake_d -D Python_EXECUTABLE=$_with_built_python_execpath"
fi
# Optional tests and cmd tools
cmake_d="$cmake_d -D USE_QT=OFF"
cmake_d="$cmake_d -D USE_PYTHON=OFF"
cmake_d="$cmake_d -D USE_QT5=OFF"
cmake_d="$cmake_d -D USE_OPENGL=OFF"
cmake_d="$cmake_d -D USE_TBB=OFF"
cmake_d="$cmake_d -D USE_BZIP2=OFF"
cmake_d="$cmake_d -D USE_FREETYPE=OFF"
cmake_d="$cmake_d -D USE_OPENCOLORIO=OFF"
cmake_d="$cmake_d -D USE_WEBP=ON"
cmake_d="$cmake_d -D USE_OPENJPEG=ON"
cmake_d="$cmake_d -D USE_FFMPEG=OFF"
cmake_d="$cmake_d -D USE_OPENCV=OFF"
cmake_d="$cmake_d -D USE_OPENVDB=OFF"
cmake_d="$cmake_d -D USE_NUKE=OFF"
cmake_d="$cmake_d -D USE_DCMTK=OFF"
cmake_d="$cmake_d -D USE_LIBHEIF=OFF"
cmake_d="$cmake_d -D USE_GIF=OFF"
cmake_d="$cmake_d -D USE_LIBRAW=OFF"
cmake_d="$cmake_d -D USE_LIBSQUISH=OFF"
cmake_d="$cmake_d -D BUILD_TESTING=OFF"
cmake_d="$cmake_d -D OIIO_BUILD_TESTS=OFF"
cmake_d="$cmake_d -D OIIO_BUILD_TOOLS=ON"
cmake_d="$cmake_d -D TXT2MAN="
#cmake_d="$cmake_d -D CMAKE_EXPORT_COMPILE_COMMANDS=ON"
#cmake_d="$cmake_d -D CMAKE_VERBOSE_MAKEFILE=ON"
if [ -d $INST/boost ]; then
cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON -D Boost_NO_BOOST_CMAKE=ON"
@ -2878,7 +2954,12 @@ _init_openvdb() {
}
_update_deps_openvdb() {
:
if [ "$1" = true ]; then
USD_FORCE_BUILD=true
fi
if [ "$2" = true ]; then
USD_FORCE_REBUILD=true
fi
}
clean_OPENVDB() {
@ -2900,7 +2981,7 @@ compile_OPENVDB() {
PRINT ""
# To be changed each time we make edits that would modify the compiled result!
openvdb_magic=4
openvdb_magic=5
_init_openvdb
# Force having own builds for the dependencies.
@ -2949,12 +3030,18 @@ compile_OPENVDB() {
cmake_d="-D CMAKE_BUILD_TYPE=Release"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D USE_STATIC_DEPENDENCIES=OFF"
cmake_d="$cmake_d -D OPENVDB_CORE_SHARED=ON"
cmake_d="$cmake_d -D OPENVDB_CORE_STATIC=OFF"
cmake_d="$cmake_d -D OPENVDB_BUILD_BINARIES=OFF"
if [ "$WITH_NANOVDB" = true ]; then
cmake_d="$cmake_d -D USE_NANOVDB=ON"
cmake_d="$cmake_d -D OPENVDB_BUILD_NANOVDB=ON"
cmake_d="$cmake_d -D NANOVDB_BUILD_TOOLS=OFF"
else
cmake_d="$cmake_d -D USE_NANOVDB=OFF"
cmake_d="$cmake_d -D OPENVDB_BUILD_NANOVDB=OFF"
cmake_d="$cmake_d -D NANOVDB_BUILD_TOOLS=OFF"
fi
if [ -d $INST/boost ]; then
@ -2982,6 +3069,13 @@ compile_OPENVDB() {
cmake_d="$cmake_d -D Blosc_ROOT=$INST/blosc"
fi
cmake_d="$cmake_d -D OPENVDB_BUILD_PYTHON_MODULE=ON"
cmake_d="$cmake_d -D OPENVDB_PYTHON_WRAP_ALL_GRID_TYPES=ON"
cmake_d="$cmake_d -D USE_NUMPY=ON"
if [ "$_with_built_python" = true ]; then
cmake_d="$cmake_d -D Python_EXECUTABLE=$_with_built_python_execpath"
fi
cmake $cmake_d ..
make -j$THREADS install
@ -3119,6 +3213,103 @@ compile_ALEMBIC() {
run_ldconfig "alembic"
}
#### Build materialX ####
_init_materialx() {
_src=$SRC/MaterialX-$MATERIALX_VERSION
_git=false
_inst=$INST/materialx-$MATERIALX_VERSION_SHORT
_inst_shortcut=$INST/materialx
}
_update_deps_materialx() {
:
}
clean_MATERIALX() {
_init_materialx
if [ -d $_inst ]; then
# Force rebuilding the dependencies if needed.
_update_deps_materialx false true
fi
_clean
}
compile_MATERIALX() {
if [ "$NO_BUILD" = true ]; then
WARNING "--no-build enabled, MaterialX will not be compiled!"
return
fi
# To be changed each time we make edits that would modify the compiled result!
materialx_magic=1
_init_materialx
# Force having own builds for the dependencies.
_update_deps_materialx true false
# Clean install if needed!
magic_compile_check materialx-$MATERIALX_VERSION $materialx_magic
if [ $? -eq 1 -o "$MATERIALX_FORCE_REBUILD" = true ]; then
clean_MATERIALX
fi
if [ ! -d $_inst ]; then
INFO "Building MaterialX-$MATERIALX_VERSION"
# Force rebuilding the dependencies.
_update_deps_materialx true true
prepare_inst
if [ ! -d $_src ]; then
mkdir -p $SRC
download MATERIALX_SOURCE[@] "$_src.tar.gz"
INFO "Unpacking MaterialX-$MATERIALX_VERSION"
tar -C $SRC -xf $_src.tar.gz
patch -d $_src -p1 < $SCRIPT_DIR/patches/materialx.diff
fi
cd $_src
cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -DMATERIALX_BUILD_SHARED_LIBS=ON"
cmake_d="$cmake_d -DCMAKE_DEBUG_POSTFIX=_d"
cmake_d="$cmake_d -DMATERIALX_BUILD_RENDER=OFF"
cmake_d="$cmake_d -DMATERIALX_BUILD_PYTHON=ON"
cmake_d="$cmake_d -DMATERIALX_INSTALL_PYTHON=OFF"
if [ "$_with_built_python" = true ]; then
cmake_d="$cmake_d -D Python_EXECUTABLE=$_with_built_python_execpath"
fi
cmake $cmake_d ./
make -j$THREADS install
make clean
if [ ! -d $_inst ]; then
ERROR "MaterialX-$MATERIALX_VERSION failed to compile, exiting"
exit 1
fi
magic_compile_set materialx-$MATERIALX_VERSION $materialx_magic
cd $CWD
INFO "Done compiling MaterialX-$MATERIALX_VERSION!"
else
INFO "Own MaterialX-$MATERIALX_VERSION is up to date, nothing to do!"
INFO "If you want to force rebuild of this lib, use the --force-materialx option."
fi
if [ -d $_inst ]; then
_create_inst_shortcut
fi
run_ldconfig "materialx"
}
#### Build USD ####
_init_usd() {
_src=$SRC/USD-$USD_VERSION
@ -3147,7 +3338,7 @@ compile_USD() {
fi
# To be changed each time we make edits that would modify the compiled result!
usd_magic=1
usd_magic=2
_init_usd
# Force having own builds for the dependencies.
@ -3181,18 +3372,46 @@ compile_USD() {
cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst"
# For the reasoning behind these options, please see usd.cmake.
if [ -d $INST/boost ]; then
cmake_d="$cmake_d $cmake_d -D BOOST_ROOT=$INST/boost"
cmake_d="$cmake_d -DBOOST_ROOT=$INST/boost"
fi
if [ -d $INST/tbb ]; then
cmake_d="$cmake_d $cmake_d -D TBB_ROOT_DIR=$INST/tbb"
cmake_d="$cmake_d -DTBB_ROOT_DIR=$INST/tbb"
fi
cmake_d="$cmake_d -DPXR_ENABLE_PYTHON_SUPPORT=OFF"
cmake_d="$cmake_d -DPXR_BUILD_IMAGING=OFF"
cmake_d="$cmake_d -DPXR_ENABLE_PYTHON_SUPPORT=ON"
cmake_d="$cmake_d -DPXR_USE_PYTHON_3=ON"
if [ "$_with_built_python" = true ]; then
cmake_d="$cmake_d -D PYTHON_EXECUTABLE=$_with_built_python_execpath"
fi
cmake_d="$cmake_d -DPXR_BUILD_IMAGING=ON"
cmake_d="$cmake_d -DPXR_BUILD_OPENIMAGEIO_PLUGIN=ON"
if [ -d $INST/openexr ]; then
cmake_d="$cmake_d -DOPENEXR_LOCATION=$INST/openexr"
fi
if [ -d $INST/oiio ]; then
cmake_d="$cmake_d -DOpenImageIO_ROOT=$INST/oiio"
fi
cmake_d="$cmake_d -DPXR_ENABLE_OPENVDB_SUPPORT=ON"
if [ -d $INST/openvdb ]; then
cmake_d="$cmake_d -DOPENVDB_LOCATION=$INST/openvdb"
fi
cmake_d="$cmake_d -DPXR_ENABLE_GL_SUPPORT=ON"
cmake_d="$cmake_d -DPXR_BUILD_TESTS=OFF"
cmake_d="$cmake_d -DBUILD_SHARED_LIBS=ON"
cmake_d="$cmake_d -DPXR_BUILD_MONOLITHIC=ON"
cmake_d="$cmake_d -DPXR_BUILD_EXAMPLES=OFF"
cmake_d="$cmake_d -DPXR_BUILD_TUTORIALS=OFF"
cmake_d="$cmake_d -DPXR_BUILD_USD_TOOLS=OFF"
cmake_d="$cmake_d -DPXR_ENABLE_HDF5_SUPPORT=OFF"
cmake_d="$cmake_d -DPXR_ENABLE_MATERIALX_SUPPORT=OFF"
cmake_d="$cmake_d -DPXR_BUILD_USDVIEW=OFF"
cmake_d="$cmake_d -DPXR_BUILD_MONOLITHIC=ON"
cmake_d="$cmake_d -DBUILD_SHARED_LIBS=ON"
cmake_d="$cmake_d -DCMAKE_DEBUG_POSTFIX=_d"
cmake $cmake_d ./
@ -4205,11 +4424,12 @@ install_DEB() {
git libfreetype6-dev libfontconfig-dev libx11-dev flex bison libxxf86vm-dev \
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
libwayland-dev libdecor-0-dev wayland-protocols libegl-dev libxkbcommon-dev libdbus-1-dev linux-libc-dev \
libvulkan-dev libshaderc-dev \
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \
libopenal-dev libepoxy-dev yasm \
libopenal-dev libepoxy-dev yasm pybind11-dev \
libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \
libgmp-dev libpugixml-dev libpotrace-dev libhpdf-dev libzstd-dev libpystring-dev \
libglfw3-dev"
libglfw3-dev libfribidi-dev libharfbuzz-dev"
VORBIS_USE=true
OGG_USE=true
@ -4393,7 +4613,7 @@ install_DEB() {
boost_version=$(echo `get_package_version_DEB libboost-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
install_packages_DEB libboost-{filesystem,iostreams,locale,regex,system,thread,wave,program-options}$boost_version-dev
install_packages_DEB ${BOOST_DEB_PACKAGE_MODULES[@]/%/$boost_version-dev}
clean_Boost
else
compile_Boost
@ -4585,6 +4805,16 @@ install_DEB() {
compile_ALEMBIC
fi
PRINT ""
if [ "$MATERIALX_SKIP" = true ]; then
WARNING "Skipping MaterialX installation, as requested..."
elif [ "$MATERIALX_FORCE_BUILD" = true ]; then
INFO "Forced MaterialX building, as requested..."
compile_MATERIALX
else
compile_MATERIALX
fi
PRINT ""
if [ "$USD_SKIP" = true ]; then
WARNING "Skipping USD installation, as requested..."
@ -4928,10 +5158,12 @@ install_RPM() {
libtiff-devel libjpeg-devel libpng-devel sqlite-devel fftw-devel SDL2-devel \
libX11-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel \
wayland-devel libdecor-devel wayland-protocols-devel mesa-libEGL-devel libxkbcommon-devel dbus-devel kernel-headers \
vulkan-loader-devel libshaderc-devel \
wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \
libepoxy-devel yasm patch \
libepoxy-devel yasm patch pybind11-devel \
libxml2-devel yaml-cpp-devel tinyxml-devel jemalloc-devel \
gmp-devel pugixml-devel potrace-devel libharu-devel libzstd-devel pystring-devel"
gmp-devel pugixml-devel potrace-devel libharu-devel libzstd-devel pystring-devel \
fribidi-devel harfbuzz-devel"
OPENJPEG_USE=true
VORBIS_USE=true
@ -5312,6 +5544,16 @@ install_RPM() {
compile_ALEMBIC
fi
PRINT ""
if [ "$MATERIALX_SKIP" = true ]; then
WARNING "Skipping MaterialX installation, as requested..."
elif [ "$MATERIALX_FORCE_BUILD" = true ]; then
INFO "Forced MaterialX building, as requested..."
compile_MATERIALX
else
compile_MATERIALX
fi
PRINT ""
if [ "$USD_SKIP" = true ]; then
WARNING "Skipping USD installation, as requested..."
@ -5582,9 +5824,10 @@ install_ARCH() {
_packages="$BASE_DEVEL git cmake fontconfig flex \
libxi libxcursor libxrandr libxinerama libepoxy libdecor libpng libtiff wget openal \
$OPENJPEG_DEV yasm sdl2 fftw \
vulkan-icd-loader vulkan-headers shaderc \
$OPENJPEG_DEV yasm sdl2 fftw pybind11 \
libxml2 yaml-cpp tinyxml python-requests jemalloc gmp potrace pugixml libharu \
zstd pystring"
zstd pystring fribidi harfbuzz"
OPENJPEG_USE=true
VORBIS_USE=true
@ -5916,6 +6159,16 @@ install_ARCH() {
compile_ALEMBIC
fi
PRINT ""
if [ "$MATERIALX_SKIP" = true ]; then
WARNING "Skipping MaterialX installation, as requested..."
elif [ "$MATERIALX_FORCE_BUILD" = true ]; then
INFO "Forced MaterialX building, as requested..."
compile_MATERIALX
else
compile_MATERIALX
fi
PRINT ""
if [ "$USD_SKIP" = true ]; then
WARNING "Skipping USD installation, as requested..."
@ -6207,6 +6460,27 @@ install_OTHER() {
fi
PRINT ""
if [ "$MATERIALX_SKIP" = true ]; then
WARNING "Skipping MaterialX installation, as requested..."
elif [ "$MATERIALX_FORCE_BUILD" = true ]; then
INFO "Forced MaterialX building, as requested..."
compile_MATERIALX
else
compile_MATERIALX
fi
PRINT ""
if [ "$USD_SKIP" = true ]; then
WARNING "Skipping USD installation, as requested..."
elif [ "$USD_FORCE_BUILD" = true ]; then
INFO "Forced USD building, as requested..."
compile_USD
else
compile_USD
fi
if [ "$WITH_OPENCOLLADA" = true ]; then
PRINT ""
if [ "$OPENCOLLADA_SKIP" = true ]; then
@ -6284,7 +6558,8 @@ print_info() {
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CLANG* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
_buildargs="$_buildargs -U *MATERIALX* -U *USD*"
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR* -U *OPENPGL*"
_1="-D WITH_CODEC_SNDFILE=ON"
@ -6471,6 +6746,17 @@ print_info() {
fi
fi
if [ "$MATERIALX_SKIP" = false ]; then
_1="-D WITH_MATERIALX=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
if [ -d $INST/materialx ]; then
_1="-D MaterialX_DIR=$INST/materialx/lib/cmake/MaterialX"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi
fi
if [ "$USD_SKIP" = false ]; then
_1="-D WITH_USD=ON"
PRINT " $_1"

View File

@ -49,7 +49,7 @@ update-code:
#
buildbot:
gcc:
version: '9.0.0'
version: '11.0.0'
cuda10:
version: '10.1.243'
cuda11:

View File

@ -83,7 +83,7 @@ enum_use_layer_samples = (
enum_sampling_pattern = (
('SOBOL_BURLEY', "Sobol-Burley", "Use on-the-fly computed Owen-scrambled Sobol for random sampling", 0),
('TABULATED_SOBOL', "Tabulated Sobol", "Use precomputed tables of Owen-scrambled Sobol for random sampling", 1),
('TABULATED_SOBOL', "Tabulated Sobol", "Use pre-computed tables of Owen-scrambled Sobol for random sampling", 1),
)
enum_emission_sampling = (
@ -905,7 +905,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_fast_gi: BoolProperty(
name="Fast GI Approximation",
description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
description="Approximate diffuse indirect light with background tinted ambient occlusion. "
"This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
default=False,
)
@ -1539,10 +1540,24 @@ class CyclesPreferences(bpy.types.AddonPreferences):
use_metalrt: BoolProperty(
name="MetalRT (Experimental)",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better performance in specific cases. However this support is experimental and some scenes may render incorrectly",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better "
"performance in specific cases. However this support is experimental and some scenes may render incorrectly",
default=False,
)
kernel_optimization_level: EnumProperty(
name="Kernel Optimization",
description="Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. "
"If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set "
"is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds)",
default='FULL',
items=(
('OFF', "Off", "Disable kernel optimization. Slowest rendering, no extra background CPU usage"),
('INTERSECT', "Intersection only", "Optimize only intersection kernels. Faster rendering, negligible extra background CPU usage"),
('FULL', "Full", "Optimize all kernels. Fastest rendering, may result in extra background CPU usage"),
),
)
def find_existing_device_entry(self, device):
for device_entry in self.devices:
if device_entry.id == device[2] and device_entry.type == device[1]:
@ -1711,10 +1726,12 @@ class CyclesPreferences(bpy.types.AddonPreferences):
if compute_device_type == 'METAL':
import platform
# MetalRT only works on Apple Silicon at present, pending argument encoding fixes on AMD
# Kernel specialization is only viable on Apple Silicon at present due to relative compilation speed
if platform.machine() == 'arm64':
row = layout.row()
row.use_property_split = True
row.prop(self, "use_metalrt")
col = layout.column()
col.use_property_split = True
col.prop(self, "kernel_optimization_level")
col.prop(self, "use_metalrt")
def draw(self, context):
self.draw_impl(self.layout, context)

View File

@ -30,7 +30,10 @@ int blender_device_threads(BL::Scene &b_scene)
return 0;
}
DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scene, bool background)
DeviceInfo blender_device_info(BL::Preferences &b_preferences,
BL::Scene &b_scene,
bool background,
bool preview)
{
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
@ -113,6 +116,18 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
device.use_metalrt = true;
}
if (preview) {
/* Disable specialization for preview renders. */
device.kernel_optimization_level = KERNEL_OPTIMIZATION_LEVEL_OFF;
}
else {
device.kernel_optimization_level = (KernelOptimizationLevel)get_enum(
cpreferences,
"kernel_optimization_level",
KERNEL_OPTIMIZATION_NUM_LEVELS,
KERNEL_OPTIMIZATION_LEVEL_FULL);
}
return device;
}

View File

@ -19,7 +19,8 @@ int blender_device_threads(BL::Scene &b_scene);
/* Convert Blender settings to device specification. */
DeviceInfo blender_device_info(BL::Preferences &b_preferences,
BL::Scene &b_scene,
bool background);
bool background,
bool preview);
CCL_NAMESPACE_END

View File

@ -754,7 +754,7 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
BL::Scene b_scene(sceneptr);
DeviceInfo device = blender_device_info(b_preferences, b_scene, true);
DeviceInfo device = blender_device_info(b_preferences, b_scene, true, true);
/* Get denoising parameters from view layer. */
PointerRNA viewlayerptr;

View File

@ -866,7 +866,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* Device */
params.threads = blender_device_threads(b_scene);
params.device = blender_device_info(b_preferences, b_scene, params.background);
params.device = blender_device_info(
b_preferences, b_scene, params.background, b_engine.is_preview());
/* samples */
int samples = get_int(cscene, "samples");

View File

@ -57,22 +57,32 @@ enum DeviceTypeMask {
#define DEVICE_MASK(type) (DeviceTypeMask)(1 << type)
enum KernelOptimizationLevel {
KERNEL_OPTIMIZATION_LEVEL_OFF = 0,
KERNEL_OPTIMIZATION_LEVEL_INTERSECT = 1,
KERNEL_OPTIMIZATION_LEVEL_FULL = 2,
KERNEL_OPTIMIZATION_NUM_LEVELS
};
class DeviceInfo {
public:
DeviceType type;
string description;
string id; /* used for user preferences, should stay fixed with changing hardware config */
int num;
bool display_device; /* GPU is used as a display device. */
bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_light_tree; /* Support light tree. */
bool has_osl; /* Support Open Shading Language. */
bool has_guiding; /* Support path guiding. */
bool has_profiling; /* Supports runtime collection of profiling info. */
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
bool has_gpu_queue; /* Device supports GPU queue. */
bool use_metalrt; /* Use MetalRT to accelerate ray queries (Metal only). */
DenoiserTypeMask denoisers; /* Supported denoiser types. */
bool display_device; /* GPU is used as a display device. */
bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_light_tree; /* Support light tree. */
bool has_osl; /* Support Open Shading Language. */
bool has_guiding; /* Support path guiding. */
bool has_profiling; /* Supports runtime collection of profiling info. */
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
bool has_gpu_queue; /* Device supports GPU queue. */
bool use_metalrt; /* Use MetalRT to accelerate ray queries (Metal only). */
KernelOptimizationLevel kernel_optimization_level; /* Optimization level applied to path tracing
kernels (Metal only). */
DenoiserTypeMask denoisers; /* Supported denoiser types. */
int cpu_threads;
vector<DeviceInfo> multi_devices;
string error_msg;

View File

@ -22,7 +22,7 @@ class MetalDevice;
thread_mutex MetalDevice::existing_devices_mutex;
std::map<int, MetalDevice *> MetalDevice::active_device_ids;
/* Thread-safe device access for async work. Calling code must pass an appropriatelty scoped lock
/* Thread-safe device access for async work. Calling code must pass an appropriately scoped lock
* to existing_devices_mutex to safeguard against destruction of the returned instance. */
MetalDevice *MetalDevice::get_device_by_ID(int ID, thread_scoped_lock &existing_devices_mutex_lock)
{
@ -110,10 +110,6 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
case METAL_GPU_APPLE: {
max_threads_per_threadgroup = 512;
use_metalrt = info.use_metalrt;
/* Specialize the intersection kernels on Apple GPUs by default as these can be built very
* quickly. */
kernel_specialization_level = PSO_SPECIALIZED_INTERSECT;
break;
}
}
@ -126,6 +122,22 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
capture_enabled = true;
}
if (device_vendor == METAL_GPU_APPLE) {
/* Set kernel_specialization_level based on user prefs. */
switch (info.kernel_optimization_level) {
case KERNEL_OPTIMIZATION_LEVEL_OFF:
kernel_specialization_level = PSO_GENERIC;
break;
default:
case KERNEL_OPTIMIZATION_LEVEL_INTERSECT:
kernel_specialization_level = PSO_SPECIALIZED_INTERSECT;
break;
case KERNEL_OPTIMIZATION_LEVEL_FULL:
kernel_specialization_level = PSO_SPECIALIZED_SHADE;
break;
}
}
if (auto envstr = getenv("CYCLES_METAL_SPECIALIZATION_LEVEL")) {
kernel_specialization_level = (MetalPipelineType)atoi(envstr);
}
@ -365,7 +377,8 @@ bool MetalDevice::load_kernels(const uint _kernel_features)
/* Only request generic kernels if they aren't cached in memory. */
if (make_source_and_check_if_compile_needed(PSO_GENERIC)) {
/* If needed, load them asynchronously in order to responsively message progess to the user. */
/* If needed, load them asynchronously in order to responsively message progress to the user.
*/
int this_device_id = this->device_id;
auto compile_kernels_fn = ^() {
compile_and_load(this_device_id, PSO_GENERIC);
@ -389,8 +402,7 @@ bool MetalDevice::make_source_and_check_if_compile_needed(MetalPipelineType pso_
void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
{
/* Thread-safe front-end compilation. Typically the MSL->AIR compilation can take a few seconds,
* so we avoid blocking device teardown if the user cancels a render immediately.
*/
* so we avoid blocking device tear-down if the user cancels a render immediately. */
id<MTLDevice> mtlDevice;
string source;
@ -444,7 +456,7 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
source);
}
const double starttime = time_dt();
double starttime = time_dt();
NSError *error = NULL;
id<MTLLibrary> mtlLibrary = [mtlDevice newLibraryWithSource:@(source.c_str())
@ -457,6 +469,13 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
[options release];
bool blocking_pso_build = (getenv("CYCLES_METAL_PROFILING") ||
MetalDeviceKernels::is_benchmark_warmup());
if (blocking_pso_build) {
MetalDeviceKernels::wait_for_all();
starttime = 0.0;
}
/* Save the compiled MTLLibrary and trigger the AIR->PSO builds (if the MetalDevice still
* exists). */
{
@ -464,6 +483,8 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
if (MetalDevice *instance = get_device_by_ID(device_id, lock)) {
if (mtlLibrary) {
instance->mtlLibrary[pso_type] = mtlLibrary;
starttime = time_dt();
MetalDeviceKernels::load(instance, pso_type);
}
else {
@ -472,6 +493,14 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
}
}
}
if (starttime && blocking_pso_build) {
MetalDeviceKernels::wait_for_all();
metal_printf("Back-end compilation finished in %.1f seconds (%s)\n",
time_dt() - starttime,
kernel_type_as_string(pso_type));
}
}
void MetalDevice::load_texture_info()
@ -832,10 +861,8 @@ void MetalDevice::optimize_for_scene(Scene *scene)
}
/* Block during benchmark warm-up to ensure kernels are cached prior to the observed run. */
for (int i = 0; i < *_NSGetArgc(); i++) {
if (!strcmp((*_NSGetArgv())[i], "--warm-up")) {
specialize_in_background = false;
}
if (MetalDeviceKernels::is_benchmark_warmup()) {
specialize_in_background = false;
}
if (specialize_in_background) {

View File

@ -101,6 +101,8 @@ int get_loaded_kernel_count(MetalDevice const *device, MetalPipelineType pso_typ
bool should_load_kernels(MetalDevice const *device, MetalPipelineType pso_type);
bool load(MetalDevice *device, MetalPipelineType pso_type);
const MetalKernelPipeline *get_best_pipeline(const MetalDevice *device, DeviceKernel kernel);
void wait_for_all();
bool is_benchmark_warmup();
} /* namespace MetalDeviceKernels */

View File

@ -116,19 +116,29 @@ struct ShaderCache {
};
bool ShaderCache::running = true;
std::mutex g_shaderCacheMutex;
std::map<id<MTLDevice>, unique_ptr<ShaderCache>> g_shaderCache;
const int MAX_POSSIBLE_GPUS_ON_SYSTEM = 8;
using DeviceShaderCache = std::pair<id<MTLDevice>, unique_ptr<ShaderCache>>;
int g_shaderCacheCount = 0;
DeviceShaderCache g_shaderCache[MAX_POSSIBLE_GPUS_ON_SYSTEM];
ShaderCache *get_shader_cache(id<MTLDevice> mtlDevice)
{
thread_scoped_lock lock(g_shaderCacheMutex);
auto it = g_shaderCache.find(mtlDevice);
if (it != g_shaderCache.end()) {
return it->second.get();
for (int i = 0; i < g_shaderCacheCount; i++) {
if (g_shaderCache[i].first == mtlDevice) {
return g_shaderCache[i].second.get();
}
}
g_shaderCache[mtlDevice] = make_unique<ShaderCache>(mtlDevice);
return g_shaderCache[mtlDevice].get();
static thread_mutex g_shaderCacheCountMutex;
g_shaderCacheCountMutex.lock();
int index = g_shaderCacheCount++;
g_shaderCacheCountMutex.unlock();
assert(index < MAX_POSSIBLE_GPUS_ON_SYSTEM);
g_shaderCache[index].first = mtlDevice;
g_shaderCache[index].second = make_unique<ShaderCache>(mtlDevice);
return g_shaderCache[index].second.get();
}
ShaderCache::~ShaderCache()
@ -145,7 +155,7 @@ ShaderCache::~ShaderCache()
num_incomplete = int(incomplete_requests);
}
if (num_incomplete) {
if (num_incomplete && !MetalDeviceKernels::is_benchmark_warmup()) {
metal_printf("ShaderCache still busy (incomplete_requests = %d). Terminating...\n",
num_incomplete);
std::terminate();
@ -313,17 +323,15 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
pipeline->threads_per_threadgroup = device->max_threads_per_threadgroup;
if (occupancy_tuning[device_kernel].threads_per_threadgroup) {
pipeline->threads_per_threadgroup =
occupancy_tuning[device_kernel].threads_per_threadgroup;
pipeline->num_threads_per_block =
occupancy_tuning[device_kernel].num_threads_per_block;
pipeline->threads_per_threadgroup = occupancy_tuning[device_kernel].threads_per_threadgroup;
pipeline->num_threads_per_block = occupancy_tuning[device_kernel].num_threads_per_block;
}
/* metalrt options */
pipeline->use_metalrt = device->use_metalrt;
pipeline->metalrt_features = device->use_metalrt ?
(device->kernel_features & METALRT_FEATURE_MASK) :
0;
(device->kernel_features & METALRT_FEATURE_MASK) :
0;
{
thread_scoped_lock lock(cache_mutex);
@ -334,12 +342,6 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
MetalKernelPipeline *ShaderCache::get_best_pipeline(DeviceKernel kernel, const MetalDevice *device)
{
thread_scoped_lock lock(cache_mutex);
auto &collection = pipelines[kernel];
if (collection.empty()) {
return nullptr;
}
/* metalrt options */
bool use_metalrt = device->use_metalrt;
bool device_metalrt_hair = use_metalrt && device->kernel_features & KERNEL_FEATURE_HAIR;
@ -351,34 +353,43 @@ MetalKernelPipeline *ShaderCache::get_best_pipeline(DeviceKernel kernel, const M
device->kernel_features & KERNEL_FEATURE_OBJECT_MOTION;
MetalKernelPipeline *best_pipeline = nullptr;
for (auto &pipeline : collection) {
if (!pipeline->loaded) {
/* still loading - ignore */
continue;
}
while (!best_pipeline) {
{
thread_scoped_lock lock(cache_mutex);
for (auto &pipeline : pipelines[kernel]) {
if (!pipeline->loaded) {
/* still loading - ignore */
continue;
}
bool pipeline_metalrt_hair = pipeline->metalrt_features & KERNEL_FEATURE_HAIR;
bool pipeline_metalrt_hair_thick = pipeline->metalrt_features & KERNEL_FEATURE_HAIR_THICK;
bool pipeline_metalrt_pointcloud = pipeline->metalrt_features & KERNEL_FEATURE_POINTCLOUD;
bool pipeline_metalrt_motion = use_metalrt &&
pipeline->metalrt_features & KERNEL_FEATURE_OBJECT_MOTION;
bool pipeline_metalrt_hair = pipeline->metalrt_features & KERNEL_FEATURE_HAIR;
bool pipeline_metalrt_hair_thick = pipeline->metalrt_features & KERNEL_FEATURE_HAIR_THICK;
bool pipeline_metalrt_pointcloud = pipeline->metalrt_features & KERNEL_FEATURE_POINTCLOUD;
bool pipeline_metalrt_motion = use_metalrt &&
pipeline->metalrt_features & KERNEL_FEATURE_OBJECT_MOTION;
if (pipeline->use_metalrt != use_metalrt || pipeline_metalrt_hair != device_metalrt_hair ||
pipeline_metalrt_hair_thick != device_metalrt_hair_thick ||
pipeline_metalrt_pointcloud != device_metalrt_pointcloud ||
pipeline_metalrt_motion != device_metalrt_motion) {
/* wrong combination of metalrt options */
continue;
}
if (pipeline->use_metalrt != use_metalrt || pipeline_metalrt_hair != device_metalrt_hair ||
pipeline_metalrt_hair_thick != device_metalrt_hair_thick ||
pipeline_metalrt_pointcloud != device_metalrt_pointcloud ||
pipeline_metalrt_motion != device_metalrt_motion) {
/* wrong combination of metalrt options */
continue;
}
if (pipeline->pso_type != PSO_GENERIC) {
if (pipeline->source_md5 == device->source_md5[PSO_SPECIALIZED_INTERSECT] ||
pipeline->source_md5 == device->source_md5[PSO_SPECIALIZED_SHADE]) {
best_pipeline = pipeline.get();
if (pipeline->pso_type != PSO_GENERIC) {
if (pipeline->source_md5 == device->source_md5[PSO_SPECIALIZED_INTERSECT] ||
pipeline->source_md5 == device->source_md5[PSO_SPECIALIZED_SHADE]) {
best_pipeline = pipeline.get();
}
}
else if (!best_pipeline) {
best_pipeline = pipeline.get();
}
}
}
else if (!best_pipeline) {
best_pipeline = pipeline.get();
if (!best_pipeline) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
@ -742,8 +753,7 @@ void MetalKernelPipeline::compile()
if (!num_threads_per_block) {
num_threads_per_block = round_down(pipeline.maxTotalThreadsPerThreadgroup,
pipeline.threadExecutionWidth);
num_threads_per_block = std::max(num_threads_per_block,
(int)pipeline.threadExecutionWidth);
num_threads_per_block = std::max(num_threads_per_block, (int)pipeline.threadExecutionWidth);
}
if (@available(macOS 11.0, *)) {
@ -805,28 +815,26 @@ void MetalKernelPipeline::compile()
bool MetalDeviceKernels::load(MetalDevice *device, MetalPipelineType pso_type)
{
const double starttime = time_dt();
auto shader_cache = get_shader_cache(device->mtlDevice);
for (int i = 0; i < DEVICE_KERNEL_NUM; i++) {
shader_cache->load_kernel((DeviceKernel)i, device, pso_type);
}
if (getenv("CYCLES_METAL_PROFILING")) {
shader_cache->wait_for_all();
metal_printf("Back-end compilation finished in %.1f seconds (%s)\n",
time_dt() - starttime,
kernel_type_as_string(pso_type));
}
return true;
}
void MetalDeviceKernels::wait_for_all()
{
for (int i = 0; i < g_shaderCacheCount; i++) {
g_shaderCache[i].second->wait_for_all();
}
}
bool MetalDeviceKernels::any_specialization_happening_now()
{
/* Return true if any ShaderCaches have ongoing specialization requests (typically there will be
* only 1). */
thread_scoped_lock lock(g_shaderCacheMutex);
for (auto &it : g_shaderCache) {
if (it.second->incomplete_specialization_requests > 0) {
for (int i = 0; i < g_shaderCacheCount; i++) {
if (g_shaderCache[i].second->incomplete_specialization_requests > 0) {
return true;
}
}
@ -857,6 +865,19 @@ const MetalKernelPipeline *MetalDeviceKernels::get_best_pipeline(const MetalDevi
return get_shader_cache(device->mtlDevice)->get_best_pipeline(kernel, device);
}
bool MetalDeviceKernels::is_benchmark_warmup()
{
NSArray *args = [[NSProcessInfo processInfo] arguments];
for (int i = 0; i < args.count; i++) {
if (const char *arg = [[args objectAtIndex:i] cStringUsingEncoding:NSASCIIStringEncoding]) {
if (!strcmp(arg, "--warm-up")) {
return true;
}
}
}
return false;
}
CCL_NAMESPACE_END
#endif /* WITH_METAL*/

View File

@ -202,6 +202,9 @@ MetalDeviceQueue::~MetalDeviceQueue()
assert(mtlCommandBuffer_ == nil);
assert(command_buffers_submitted_ == command_buffers_completed_);
close_compute_encoder();
close_blit_encoder();
if (@available(macos 10.14, *)) {
[shared_event_listener_ release];
[shared_event_ release];
@ -637,9 +640,7 @@ bool MetalDeviceQueue::synchronize()
return false;
}
if (mtlComputeEncoder_) {
close_compute_encoder();
}
close_compute_encoder();
close_blit_encoder();
if (mtlCommandBuffer_) {
@ -855,9 +856,7 @@ id<MTLComputeCommandEncoder> MetalDeviceQueue::get_compute_encoder(DeviceKernel
if (@available(macos 10.14, *)) {
if (timing_shared_event_) {
/* Close the current encoder to ensure we're able to capture per-encoder timing data. */
if (mtlComputeEncoder_) {
close_compute_encoder();
}
close_compute_encoder();
}
if (mtlComputeEncoder_) {
@ -897,9 +896,7 @@ id<MTLBlitCommandEncoder> MetalDeviceQueue::get_blit_encoder()
return mtlBlitEncoder_;
}
if (mtlComputeEncoder_) {
close_compute_encoder();
}
close_compute_encoder();
if (!mtlCommandBuffer_) {
mtlCommandBuffer_ = [mtlCommandQueue_ commandBuffer];
@ -913,12 +910,14 @@ id<MTLBlitCommandEncoder> MetalDeviceQueue::get_blit_encoder()
void MetalDeviceQueue::close_compute_encoder()
{
[mtlComputeEncoder_ endEncoding];
mtlComputeEncoder_ = nil;
if (mtlComputeEncoder_) {
[mtlComputeEncoder_ endEncoding];
mtlComputeEncoder_ = nil;
if (@available(macos 10.14, *)) {
if (timing_shared_event_) {
[mtlCommandBuffer_ encodeSignalEvent:timing_shared_event_ value:timing_shared_event_id_++];
if (@available(macos 10.14, *)) {
if (timing_shared_event_) {
[mtlCommandBuffer_ encodeSignalEvent:timing_shared_event_ value:timing_shared_event_id_++];
}
}
}
}

View File

@ -364,7 +364,9 @@ ccl_device_inline void film_write_emission_or_background_pass(
}
# endif /* __DENOISING_FEATURES__ */
if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
const bool is_shadowcatcher = (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) != 0;
if (!is_shadowcatcher && lightgroup != LIGHTGROUP_NONE &&
kernel_data.film.pass_lightgroup != PASS_UNUSED) {
film_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
contribution);
}
@ -373,13 +375,12 @@ ccl_device_inline void film_write_emission_or_background_pass(
/* Directly visible, write to emission or background pass. */
pass_offset = pass;
}
else if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
else if (is_shadowcatcher) {
/* Don't write any light passes for shadow catcher, for easier
* compositing back together of the combined pass. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) {
return;
}
return;
}
else if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
if (path_flag & PATH_RAY_SURFACE_PASS) {
/* Indirectly visible through reflection. */
const Spectrum diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);

View File

@ -180,8 +180,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
/* Write to render buffer. */
guiding_record_background(kg, state, light_eval, mis_weight);
film_write_surface_emission(
kg, state, light_eval, mis_weight, render_buffer, kernel_data.background.lightgroup);
film_write_surface_emission(kg, state, light_eval, mis_weight, render_buffer, ls.group);
}
}
}

View File

@ -502,8 +502,15 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
rng_state,
ccl_global float *ccl_restrict render_buffer)
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
if (!(kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) &&
!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_CAMERA)) {
!(path_flag & PATH_RAY_CAMERA)) {
return;
}
/* Skip AO for paths that were split off for shadow catchers to avoid double-counting. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
return;
}

View File

@ -979,8 +979,10 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
}
}
/* Update path state */

View File

@ -122,6 +122,7 @@ shader node_image_texture(int use_mapping = 0,
vector Nob = transform("world", "object", N);
/* project from direction vector to barycentric coordinates in triangles */
vector signed_Nob = Nob;
Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
Nob /= (Nob[0] + Nob[1] + Nob[2]);
@ -184,9 +185,10 @@ shader node_image_texture(int use_mapping = 0,
float tmp_alpha;
if (weight[0] > 0.0) {
point UV = point((signed_Nob[0] < 0.0) ? 1.0 - p[1] : p[1], p[2], 0.0);
Color += weight[0] * image_texture_lookup(filename,
p[1],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -198,9 +200,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[0] * tmp_alpha;
}
if (weight[1] > 0.0) {
point UV = point((signed_Nob[1] > 0.0) ? 1.0 - p[0] : p[0], p[2], 0.0);
Color += weight[1] * image_texture_lookup(filename,
p[0],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -212,9 +215,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[1] * tmp_alpha;
}
if (weight[2] > 0.0) {
point UV = point((signed_Nob[2] > 0.0) ? 1.0 - p[1] : p[1], p[0], 0.0);
Color += weight[2] * image_texture_lookup(filename,
p[1],
p[0],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,

View File

@ -32,7 +32,7 @@ static float shutter_curve_eval(float x, array<float> &shutter_curve)
return 1.0f;
}
x *= shutter_curve.size();
x = saturatef(x) * shutter_curve.size() - 1;
int index = (int)x;
float frac = x - index;
if (index < shutter_curve.size() - 1) {

View File

@ -263,8 +263,9 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant)
return estimate;
}
else if (node->type == LightFalloffNode::get_node_type()) {
/* Light Falloff node. */
else if (node->type == LightFalloffNode::get_node_type() ||
node->type == IESLightNode::get_node_type()) {
/* Get strength from Light Falloff and IES texture node. */
ShaderInput *strength_in = node->input("Strength");
is_constant = false;

View File

@ -289,19 +289,24 @@ RenderWork Session::run_update_for_next_iteration()
RenderWork render_work;
thread_scoped_lock scene_lock(scene->mutex);
thread_scoped_lock reset_lock(delayed_reset_.mutex);
bool have_tiles = true;
bool switched_to_new_tile = false;
bool did_reset = false;
const bool did_reset = delayed_reset_.do_reset;
if (delayed_reset_.do_reset) {
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* Perform delayed reset if requested. */
{
thread_scoped_lock reset_lock(delayed_reset_.mutex);
if (delayed_reset_.do_reset) {
did_reset = true;
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
}
}
/* Update number of samples in the integrator.

View File

@ -16,6 +16,7 @@ void util_cdf_invert(const int resolution,
const bool make_symmetric,
vector<float> &inv_cdf)
{
assert(cdf[0] == 0.0f && cdf[resolution] == 1.0f);
const float inv_resolution = 1.0f / (float)resolution;
const float range = to - from;
inv_cdf.resize(resolution);
@ -39,8 +40,8 @@ void util_cdf_invert(const int resolution,
}
else {
for (int i = 0; i < resolution; i++) {
float x = from + range * (float)i * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
float x = (i + 0.5f) * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin() - 1;
float t;
if (index < cdf.size() - 1) {
t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
@ -49,7 +50,7 @@ void util_cdf_invert(const int resolution,
t = 0.0f;
index = resolution;
}
inv_cdf[i] = (index + t) * inv_resolution;
inv_cdf[i] = from + range * (index + t) * inv_resolution;
}
}
}

View File

@ -26,9 +26,11 @@ void util_cdf_evaluate(
cdf[i + 1] = cdf[i] + fabsf(y);
}
/* Normalize the CDF. */
float fac = (cdf[resolution] == 0.0f) ? 0.0f : 1.0f / cdf[resolution];
for (int i = 0; i <= resolution; i++) {
cdf[i] /= cdf[resolution];
cdf[i] *= fac;
}
cdf[resolution] = 1.0f;
}
/* Invert pre-calculated CDF function. */

View File

@ -4,6 +4,7 @@
#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>
#include <mutex>
#include <vector>
@ -14,10 +15,18 @@
namespace {
struct Local;
struct Global;
/**
* This is stored per thread. Align to cache line size to avoid false sharing.
*/
struct alignas(64) Local {
struct alignas(128) Local {
/**
* Retain shared ownership of #Global to make sure that it is not destructed.
*/
std::shared_ptr<Global> global;
/** Helps to find bugs during program shutdown. */
bool destructed = false;
/**
@ -49,7 +58,8 @@ struct alignas(64) Local {
};
/**
* This is a singleton that stores global data.
* This is a singleton that stores global data. It's owned by a `std::shared_ptr` which is owned by
* the static variable in #get_global_ptr and all #Local objects.
*/
struct Global {
/**
@ -71,7 +81,7 @@ struct Global {
* To solve this, the memory counts are added to these global counters when the thread
* exists. The global counters are also used when the entire process starts to exit, because the
* #Local data of the main thread is already destructed when the leak detection happens (during
* destruction of static variables which happens after destruction of threadlocals).
* destruction of static variables which happens after destruction of thread-locals).
*/
std::atomic<int64_t> mem_in_use_outside_locals = 0;
/**
@ -98,10 +108,15 @@ static std::atomic<bool> use_local_counters = true;
*/
static constexpr int64_t peak_update_threshold = 1024 * 1024;
static std::shared_ptr<Global> &get_global_ptr()
{
static std::shared_ptr<Global> global = std::make_shared<Global>();
return global;
}
static Global &get_global()
{
static Global global;
return global;
return *get_global_ptr();
}
static Local &get_local_data()
@ -113,32 +128,32 @@ static Local &get_local_data()
Local::Local()
{
Global &global = get_global();
std::lock_guard lock{global.locals_mutex};
this->global = get_global_ptr();
if (global.locals.empty()) {
std::lock_guard lock{this->global->locals_mutex};
if (this->global->locals.empty()) {
/* This is the first thread creating #Local, it is therefore the main thread because it's
* created through #memory_usage_init. */
this->is_main = true;
}
/* Register self in the global list. */
global.locals.push_back(this);
this->global->locals.push_back(this);
}
Local::~Local()
{
Global &global = get_global();
std::lock_guard lock{global.locals_mutex};
std::lock_guard lock{this->global->locals_mutex};
/* Unregister self from the global list. */
global.locals.erase(std::find(global.locals.begin(), global.locals.end(), this));
this->global->locals.erase(
std::find(this->global->locals.begin(), this->global->locals.end(), this));
/* Don't forget the memory counts stored locally. */
global.blocks_num_outside_locals.fetch_add(this->blocks_num, std::memory_order_relaxed);
global.mem_in_use_outside_locals.fetch_add(this->mem_in_use, std::memory_order_relaxed);
this->global->blocks_num_outside_locals.fetch_add(this->blocks_num, std::memory_order_relaxed);
this->global->mem_in_use_outside_locals.fetch_add(this->mem_in_use, std::memory_order_relaxed);
if (this->is_main) {
/* The main thread started shutting down. Use global counters from now on to avoid accessing
* threadlocals after they have been destructed. */
* thread-locals after they have been destructed. */
use_local_counters.store(false, std::memory_order_relaxed);
}
/* Helps to detect when thread locals are accidentally accessed after destruction. */
@ -164,7 +179,7 @@ static void update_global_peak()
void memory_usage_init()
{
/* Makes sure that the static and threadlocal variables on the main thread are initialized. */
/* Makes sure that the static and thread-local variables on the main thread are initialized. */
get_local_data();
}

@ -1 +1 @@
Subproject commit 96143b1a8b037ea3c81f065f557025db9fe1ace3
Subproject commit bdcfdd47ec3451822b21d1cff2ea2db751093c9a

View File

@ -412,6 +412,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"selected",
"selected and lock unselected",
"selected and unlock unselected",
"screen",
"the lazy dog",
"this legacy pose library to pose assets",
"to the top level of the tree",

View File

@ -542,6 +542,7 @@ class SpellChecker:
"voronoi",
"voxel", "voxels",
"vsync",
"vulkan",
"wireframe",
"zmask",
"ztransp",

View File

@ -1342,7 +1342,7 @@ url_manual_mapping = (
("bpy.types.armature.layers_protected*", "animation/armatures/properties/skeleton.html#bpy-types-armature-layers-protected"),
("bpy.types.assetmetadata.description*", "editors/asset_browser.html#bpy-types-assetmetadata-description"),
("bpy.types.bakesettings.normal_space*", "render/cycles/baking.html#bpy-types-bakesettings-normal-space"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.elastic_deform_type*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-type"),
("bpy.types.brush.texture_sample_bias*", "sculpt_paint/brush/texture.html#bpy-types-brush-texture-sample-bias"),
("bpy.types.brush.use_cloth_collision*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-collision"),
@ -1468,6 +1468,7 @@ url_manual_mapping = (
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.area_radius_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-area-radius-factor"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
@ -1781,6 +1782,7 @@ url_manual_mapping = (
("bpy.types.functionnodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-functionnodefloattoint"),
("bpy.types.functionnodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-functionnodeinputcolor"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodeimageinput*", "modeling/geometry_nodes/input/image_input.html#bpy-types-geometrynodeimageinput"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/is_viewport.html#bpy-types-geometrynodeisviewport"),
("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh_primitives/mesh_circle.html#bpy-types-geometrynodemeshcircle"),
@ -2172,10 +2174,11 @@ url_manual_mapping = (
("bpy.types.bakesettings.margin*", "render/cycles/baking.html#bpy-types-bakesettings-margin"),
("bpy.types.bakesettings.target*", "render/cycles/baking.html#bpy-types-bakesettings-target"),
("bpy.types.brush.cloth_damping*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-damping"),
("bpy.types.brush.deform_target*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-deform-target"),
("bpy.types.brush.falloff_shape*", "sculpt_paint/brush/falloff.html#bpy-types-brush-falloff-shape"),
("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"),
("bpy.types.brush.stroke_method*", "sculpt_paint/brush/stroke.html#bpy-types-brush-stroke-method"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/sculpting/tools/clay_strips.html#bpy-types-brush-tip-roundness"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-tip-roundness"),
("bpy.types.camera.display_size*", "render/cameras.html#bpy-types-camera-display-size"),
("bpy.types.camera.sensor_width*", "render/cameras.html#bpy-types-camera-sensor-width"),
("bpy.types.compositornodedblur*", "compositing/types/filter/directional_blur.html#bpy-types-compositornodedblur"),
@ -2705,6 +2708,7 @@ url_manual_mapping = (
("bpy.types.armature.rigify*", "addons/rigging/rigify/basics.html#bpy-types-armature-rigify"),
("bpy.types.bone.use_deform*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-use-deform"),
("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"),
("bpy.types.brush.direction*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-direction"),
("bpy.types.brush.mask_tool*", "sculpt_paint/sculpting/tools/mask.html#bpy-types-brush-mask-tool"),
("bpy.types.constraint.mute*", "animation/constraints/interface/header.html#bpy-types-constraint-mute"),
("bpy.types.constraint.name*", "animation/constraints/interface/header.html#bpy-types-constraint-name"),
@ -2798,6 +2802,7 @@ url_manual_mapping = (
("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"),
("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"),
("bpy.types.brush.hardness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-hardness"),
("bpy.types.brush.strength*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-strength"),
("bpy.types.curves.surface*", "modeling/curves/primitives.html#bpy-types-curves-surface"),
("bpy.types.curvesmodifier*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-curvesmodifier"),
("bpy.types.ffmpegsettings*", "render/output/properties/output.html#bpy-types-ffmpegsettings"),
@ -3111,6 +3116,7 @@ url_manual_mapping = (
("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"),
("bpy.types.bpy_struct*", "files/data_blocks.html#bpy-types-bpy-struct"),
("bpy.types.brush.rate*", "sculpt_paint/brush/stroke.html#bpy-types-brush-rate"),
("bpy.types.brush.size*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-size"),
("bpy.types.collection*", "scene_layout/collections/collections.html#bpy-types-collection"),
("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"),
("bpy.types.constraint*", "animation/constraints/index.html#bpy-types-constraint"),

View File

@ -81,8 +81,8 @@ class ASSET_OT_open_containing_blend_file(Operator):
@classmethod
def poll(cls, context):
asset_file_handle = getattr(context, 'asset_file_handle', None)
asset_library_ref = getattr(context, 'asset_library_ref', None)
asset_file_handle = getattr(context, "asset_file_handle", None)
asset_library_ref = getattr(context, "asset_library_ref", None)
if not asset_library_ref:
cls.poll_message_set("No asset library selected")

View File

@ -620,7 +620,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
if not view_layers.get("Foreground"):
if len(view_layers) == 1:
fg = view_layers[0]
fg.name = 'Foreground'
fg.name = "Foreground"
else:
fg = view_layers.new("Foreground")

View File

@ -142,7 +142,7 @@ class SCENE_OT_freestyle_add_edge_marks_to_keying_set(Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for i, edge in enumerate(mesh.edges):
if not edge.hide and edge.select:
path = 'edges[%d].use_freestyle_mark' % i
path = "edges[%d].use_freestyle_mark" % i
ks.paths.add(mesh, path, index=0)
bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
return {'FINISHED'}
@ -173,7 +173,7 @@ class SCENE_OT_freestyle_add_face_marks_to_keying_set(Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for i, polygon in enumerate(mesh.polygons):
if not polygon.hide and polygon.select:
path = 'polygons[%d].use_freestyle_mark' % i
path = "polygons[%d].use_freestyle_mark" % i
ks.paths.add(mesh, path, index=0)
bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
return {'FINISHED'}

View File

@ -223,7 +223,7 @@ class SequencerFadesAdd(Operator):
if not self.is_long_enough(sequence, duration):
continue
animated_property = 'volume' if hasattr(sequence, 'volume') else 'blend_alpha'
animated_property = "volume" if hasattr(sequence, "volume") else "blend_alpha"
fade_fcurve = self.fade_find_or_create_fcurve(context, sequence, animated_property)
fades = self.calculate_fades(sequence, fade_fcurve, animated_property, duration)
self.fade_animation_clear(fade_fcurve, fades)

View File

@ -2507,7 +2507,7 @@ class WM_OT_batch_rename(Operator):
('COLLECTION', "Collections", ""),
('MATERIAL', "Materials", ""),
None,
# Enum identifiers are compared with 'object.type'.
# Enum identifiers are compared with `object.type`.
# Follow order in "Add" menu.
('MESH', "Meshes", ""),
('CURVE', "Curves", ""),

View File

@ -66,7 +66,7 @@ class MotionPathButtonsPanel:
col.operator(op_category + ".paths_calculate", text="Calculate...", icon=icon)
# Update All & Clear All.
# Note that 'col' is from inside the preceeding `if` or `else` block.
# Note that `col` is from inside the preceding `if` or `else` block.
row = col.row(align=True)
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
row.operator(op_category + ".paths_clear", text="", icon='X').only_selected = False

View File

@ -87,7 +87,7 @@ class ConstraintButtonsPanel:
@staticmethod
def target_template(layout, con, subtargets=True):
col = layout.column()
col.prop(con, "target") # XXX limiting settings for only 'curves' or some type of object
col.prop(con, "target") # XXX: limiting settings for only `curves` or some type of object.
if con.target and subtargets:
if con.target.type == 'ARMATURE':

View File

@ -87,7 +87,7 @@ class BONE_PT_transform(BoneButtonsPanel, Panel):
row.use_property_decorate = False
row.prop(pchan, "lock_rotation", text="", emboss=False, icon='DECORATE_UNLOCKED')
row = layout.row(align=True)
row.prop(pchan, "rotation_mode", text='Mode')
row.prop(pchan, "rotation_mode", text="Mode")
row.label(text="", icon='BLANK1')
col = layout.column()
@ -403,9 +403,9 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
col.prop(pchan, "ik_rotation_weight", text="IK Rotation Weight", slider=True)
col.active = active
# not supported yet
#row = layout.row()
#row.prop(pchan, "use_ik_linear_control", text="Joint Size")
#row.prop(pchan, "ik_linear_weight", text="Weight", slider=True)
# row = layout.row()
# row.prop(pchan, "use_ik_linear_control", text="Joint Size")
# row.prop(pchan, "ik_linear_weight", text="Weight", slider=True)
class BONE_PT_deform(BoneButtonsPanel, Panel):

View File

@ -12,7 +12,7 @@ class DataButtonsPanel:
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return hasattr(context, 'curves') and context.curves and (engine in cls.COMPAT_ENGINES)
return hasattr(context, "curves") and context.curves and (engine in cls.COMPAT_ENGINES)
class DATA_PT_context_curves(DataButtonsPanel, Panel):
@ -73,8 +73,8 @@ class CURVES_MT_add_attribute(Menu):
layout = self.layout
curves = context.curves
self.add_standard_attribute(layout, curves, 'radius', 'FLOAT', 'POINT')
self.add_standard_attribute(layout, curves, 'color', 'FLOAT_COLOR', 'POINT')
self.add_standard_attribute(layout, curves, "radius", 'FLOAT', 'POINT')
self.add_standard_attribute(layout, curves, "color", 'FLOAT_COLOR', 'POINT')
layout.separator()
@ -102,8 +102,8 @@ class CURVES_UL_attributes(UIList):
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
domain = attribute.bl_rna.properties['domain'].enum_items[attribute.domain]
data_type = attribute.bl_rna.properties["data_type"].enum_items[attribute.data_type]
domain = attribute.bl_rna.properties["domain"].enum_items[attribute.domain]
split = layout.split(factor=0.5)
split.emboss = 'NONE'

View File

@ -551,7 +551,7 @@ class MESH_UL_attributes(UIList):
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
data_type = attribute.bl_rna.properties["data_type"].enum_items[attribute.data_type]
domain_name = self.display_domain_names.get(attribute.domain, "")
@ -658,7 +658,7 @@ class ColorAttributesListBase():
class MESH_UL_color_attributes(UIList, ColorAttributesListBase):
def draw_item(self, _context, layout, data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
data_type = attribute.bl_rna.properties["data_type"].enum_items[attribute.data_type]
domain_name = self.display_domain_names.get(attribute.domain, "")

View File

@ -12,7 +12,7 @@ class DataButtonsPanel:
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return hasattr(context, 'pointcloud') and context.pointcloud and (engine in cls.COMPAT_ENGINES)
return hasattr(context, "pointcloud") and context.pointcloud and (engine in cls.COMPAT_ENGINES)
class DATA_PT_context_pointcloud(DataButtonsPanel, Panel):
@ -53,10 +53,10 @@ class POINTCLOUD_MT_add_attribute(Menu):
layout = self.layout
pointcloud = context.pointcloud
self.add_standard_attribute(layout, pointcloud, 'radius', 'FLOAT', 'POINT')
self.add_standard_attribute(layout, pointcloud, 'color', 'FLOAT_COLOR', 'POINT')
self.add_standard_attribute(layout, pointcloud, 'id', 'INT', 'POINT')
self.add_standard_attribute(layout, pointcloud, 'velocity', 'FLOAT_VECTOR', 'POINT')
self.add_standard_attribute(layout, pointcloud, "radius", 'FLOAT', 'POINT')
self.add_standard_attribute(layout, pointcloud, "color", 'FLOAT_COLOR', 'POINT')
self.add_standard_attribute(layout, pointcloud, "id", 'INT', 'POINT')
self.add_standard_attribute(layout, pointcloud, "velocity", 'FLOAT_VECTOR', 'POINT')
layout.separator()
@ -84,7 +84,7 @@ class POINTCLOUD_UL_attributes(UIList):
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
data_type = attribute.bl_rna.properties["data_type"].enum_items[attribute.data_type]
split = layout.split(factor=0.75)
split.emboss = 'NONE'

View File

@ -68,7 +68,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel):
class VOLUME_UL_grids(UIList):
def draw_item(self, _context, layout, _data, grid, _icon, _active_data, _active_propname, _index):
name = grid.name
data_type = grid.bl_rna.properties['data_type'].enum_items[grid.data_type]
data_type = grid.bl_rna.properties["data_type"].enum_items[grid.data_type]
layout.emboss = 'NONE'
layout.label(text=name)

View File

@ -324,7 +324,7 @@ class RENDER_PT_output_color_management(RenderOutputButtonsPanel, Panel):
col = flow.column()
if image_settings.has_linear_colorspace:
if hasattr(owner, 'linear_colorspace_settings'):
if hasattr(owner, "linear_colorspace_settings"):
col.prop(owner.linear_colorspace_settings, "name", text="Color Space")
else:
col.prop(owner.display_settings, "display_device")

View File

@ -31,10 +31,10 @@ class CONSOLE_MT_view(Menu):
layout = self.layout
props = layout.operator("wm.context_cycle_int", text="Zoom In")
props.data_path = 'space_data.font_size'
props.data_path = "space_data.font_size"
props.reverse = False
props = layout.operator("wm.context_cycle_int", text="Zoom Out")
props.data_path = 'space_data.font_size'
props.data_path = "space_data.font_size"
props.reverse = True
layout.separator()
@ -62,7 +62,7 @@ class CONSOLE_MT_language(Menu):
layout = self.layout
layout.column()
# Collect modules with 'console_*.execute'
# Collect modules with `console_*.execute`.
languages = []
for modname, mod in sys.modules.items():
if modname.startswith("console_") and hasattr(mod, "execute"):

View File

@ -550,7 +550,7 @@ class DOPESHEET_PT_custom_props_action(PropertyPanel, Panel):
bl_space_type = 'DOPESHEET_EDITOR'
bl_category = "Action"
bl_region_type = 'UI'
bl_context = 'data'
bl_context = "data"
_context_path = "active_action"
_property_type = bpy.types.Action

View File

@ -332,6 +332,7 @@ class GRAPH_MT_slider(Menu):
layout.operator("graph.breakdown", text="Breakdown")
layout.operator("graph.blend_to_neighbor", text="Blend to Neighbor")
layout.operator("graph.blend_to_default", text="Blend to Default Value")
layout.operator("graph.ease", text="Ease")
class GRAPH_MT_view_pie(Menu):

View File

@ -742,7 +742,7 @@ class IMAGE_HT_header(Header):
# Snap.
snap_uv_element = tool_settings.snap_uv_element
act_snap_uv_element = tool_settings.bl_rna.properties['snap_uv_element'].enum_items[snap_uv_element]
act_snap_uv_element = tool_settings.bl_rna.properties["snap_uv_element"].enum_items[snap_uv_element]
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_uv", text="")

View File

@ -41,7 +41,7 @@ class NODE_HT_header(Header):
layout.template_header()
# Now expanded via the 'ui_type'
# Now expanded via the `ui_type`.
# layout.prop(snode, "tree_type", text="")
if snode.tree_type == 'ShaderNodeTree':
@ -661,7 +661,7 @@ class NODE_PT_active_node_properties(Panel):
)
def show_socket_input(self, socket):
return hasattr(socket, 'draw') and socket.enabled and not socket.is_linked
return hasattr(socket, "draw") and socket.enabled and not socket.is_linked
class NODE_PT_texture_mapping(Panel):
@ -961,7 +961,7 @@ def node_panel(cls):
node_cls.bl_space_type = 'NODE_EDITOR'
node_cls.bl_region_type = 'UI'
node_cls.bl_category = "Options"
if hasattr(node_cls, 'bl_parent_id'):
if hasattr(node_cls, "bl_parent_id"):
node_cls.bl_parent_id = 'NODE_' + node_cls.bl_parent_id
return node_cls

View File

@ -51,8 +51,8 @@ ToolDef = namedtuple(
"idname",
# The name to display in the interface.
"label",
# Description (for tool-tip), when not set, use the description of 'operator',
# may be a string or a 'function(context, item, key-map) -> string'.
# Description (for tool-tip), when not set, use the description of `operator`,
# may be a string or a `function(context, item, key-map) -> string`.
"description",
# The name of the icon to use (found in `release/datafiles/icons`) or None for no icon.
"icon",
@ -88,7 +88,7 @@ ToolDef = namedtuple(
# Note that this isn't used for Blender's built in tools which use the built-in key-map.
# Keep this functionality since it's likely useful for add-on key-maps.
#
# Warning: currently 'from_dict' this is a list of one item,
# Warning: currently `from_dict` this is a list of one item,
# so internally we can swap the key-map function for the key-map itself.
# This isn't very nice and may change, tool definitions shouldn't care about this.
"keymap",
@ -256,7 +256,7 @@ class ToolSelectPanelHelper:
# tool flattening
#
# usually 'tools' is already expanded into ToolDef
# usually 'tools' is already expanded into `ToolDef`
# but when registering a tool, this can still be a function
# (_tools_flatten is usually called with cls.tools_from_context(context)
# [that already yields from the function])
@ -792,7 +792,7 @@ class ToolSelectPanelHelper:
item, tool, icon_value = cls._tool_get_active(context, space_type, mode, with_icon=True)
if item is None:
return None
# Note: we could show 'item.text' here but it makes the layout jitter when switching tools.
# NOTE: we could show `item.text` here but it makes the layout jitter when switching tools.
# Add some spacing since the icon is currently assuming regular small icon size.
if show_tool_icon_always:
layout.label(text=" " + iface_(item.label, "Operator"), icon_value=icon_value)

View File

@ -2706,7 +2706,7 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
)
# Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
# The keys match image spaces modes: 'context.space_data.mode'.
# The keys match image spaces modes: `context.space_data.mode`.
# The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
@ -2892,7 +2892,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
)
# Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
# The keys match object-modes from: 'context.mode'.
# The keys match object-modes from: `context.mode`.
# The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
@ -3230,7 +3230,7 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
)
# Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
# The keys match sequence editors view type: 'context.space_data.view_type'.
# The keys match sequence editors view type: `context.space_data.view_type`.
# The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [

View File

@ -605,7 +605,7 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "GPU Backend"
bl_label = "GPU Back end"
@classmethod
def poll(cls, _context):
@ -622,7 +622,7 @@ class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
col.prop(system, "gpu_backend")
if system.gpu_backend != gpu.platform.backend_type_get():
layout.label(text="Requires a restart of Blender to take effect.", icon='INFO')
layout.label(text="Requires a restart of Blender to take effect", icon='INFO')
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
@ -1286,7 +1286,7 @@ class ThemeGenericClassGenerator:
def generate_panel_classes_from_theme_areas():
from bpy.types import Theme
for theme_area in Theme.bl_rna.properties['theme_area'].enum_items_static:
for theme_area in Theme.bl_rna.properties["theme_area"].enum_items_static:
if theme_area.identifier in {'USER_INTERFACE', 'STYLE', 'BONE_COLOR_SETS'}:
continue
@ -2324,7 +2324,6 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
({"property": "use_realtime_compositor"}, "T99210"),
),
)

View File

@ -70,7 +70,7 @@ class VIEW3D_HT_tool_header(Header):
layout.popover("VIEW3D_PT_tools_brush_falloff")
layout.popover("VIEW3D_PT_tools_brush_display")
# Note: general mode options should be added to 'draw_mode_settings'.
# NOTE: general mode options should be added to `draw_mode_settings`.
if tool_mode == 'SCULPT':
if is_valid_context:
draw_3d_brush_settings(layout, tool_mode)
@ -889,7 +889,7 @@ class VIEW3D_HT_header(Header):
row = layout.row()
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
# While exposing 'shading.show_xray(_wireframe)' is correct.
# While exposing `shading.show_xray(_wireframe)` is correct.
# this hides the key shortcut from users: T70433.
if has_pose_mode:
draw_depressed = overlay.show_xray_bone
@ -2290,9 +2290,9 @@ class VIEW3D_MT_add(Menu):
def draw(self, context):
layout = self.layout
# note, don't use 'EXEC_SCREEN' or operators won't get the 'v3d' context.
# NOTE: don't use 'EXEC_SCREEN' or operators won't get the `v3d` context.
# Note: was EXEC_AREA, but this context does not have the 'rv3d', which prevents
# NOTE: was `EXEC_AREA`, but this context does not have the `rv3d`, which prevents
# "align_view" to work on first call (see T32719).
layout.operator_context = 'EXEC_REGION_WIN'
@ -3291,23 +3291,23 @@ class VIEW3D_MT_mask(Menu):
layout.separator()
props = layout.operator("sculpt.mask_filter", text='Smooth Mask')
props = layout.operator("sculpt.mask_filter", text="Smooth Mask")
props.filter_type = 'SMOOTH'
props = layout.operator("sculpt.mask_filter", text='Sharpen Mask')
props = layout.operator("sculpt.mask_filter", text="Sharpen Mask")
props.filter_type = 'SHARPEN'
props = layout.operator("sculpt.mask_filter", text='Grow Mask')
props = layout.operator("sculpt.mask_filter", text="Grow Mask")
props.filter_type = 'GROW'
props = layout.operator("sculpt.mask_filter", text='Shrink Mask')
props = layout.operator("sculpt.mask_filter", text="Shrink Mask")
props.filter_type = 'SHRINK'
props = layout.operator("sculpt.mask_filter", text='Increase Contrast')
props = layout.operator("sculpt.mask_filter", text="Increase Contrast")
props.filter_type = 'CONTRAST_INCREASE'
props.auto_iteration_count = False
props = layout.operator("sculpt.mask_filter", text='Decrease Contrast')
props = layout.operator("sculpt.mask_filter", text="Decrease Contrast")
props.filter_type = 'CONTRAST_DECREASE'
props.auto_iteration_count = False
@ -3352,13 +3352,13 @@ class VIEW3D_MT_face_sets(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.face_sets_create", text='Face Set from Masked')
op = layout.operator("sculpt.face_sets_create", text="Face Set from Masked")
op.mode = 'MASKED'
op = layout.operator("sculpt.face_sets_create", text='Face Set from Visible')
op = layout.operator("sculpt.face_sets_create", text="Face Set from Visible")
op.mode = 'VISIBLE'
op = layout.operator("sculpt.face_sets_create", text='Face Set from Edit Mode Selection')
op = layout.operator("sculpt.face_sets_create", text="Face Set from Edit Mode Selection")
op.mode = 'SELECTION'
layout.separator()
@ -3367,10 +3367,10 @@ class VIEW3D_MT_face_sets(Menu):
layout.separator()
op = layout.operator("sculpt.face_set_edit", text='Grow Face Set')
op = layout.operator("sculpt.face_set_edit", text="Grow Face Set")
op.mode = 'GROW'
op = layout.operator("sculpt.face_set_edit", text='Shrink Face Set')
op = layout.operator("sculpt.face_set_edit", text="Shrink Face Set")
op.mode = 'SHRINK'
layout.separator()
@ -3389,18 +3389,18 @@ class VIEW3D_MT_face_sets(Menu):
layout.separator()
op = layout.operator("mesh.face_set_extract", text='Extract Face Set')
op = layout.operator("mesh.face_set_extract", text="Extract Face Set")
layout.separator()
op = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
op = layout.operator("sculpt.face_set_change_visibility", text="Invert Visible Face Sets")
op.mode = 'INVERT'
op = layout.operator("sculpt.reveal_all", text='Show All Face Sets')
op = layout.operator("sculpt.reveal_all", text="Show All Face Sets")
layout.separator()
op = layout.operator("sculpt.face_sets_randomize_colors", text='Randomize Colors')
op = layout.operator("sculpt.face_sets_randomize_colors", text="Randomize Colors")
class VIEW3D_MT_sculpt_set_pivot(Menu):
@ -3431,31 +3431,31 @@ class VIEW3D_MT_face_sets_init(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.face_sets_init", text='By Loose Parts')
op = layout.operator("sculpt.face_sets_init", text="By Loose Parts")
op.mode = 'LOOSE_PARTS'
op = layout.operator("sculpt.face_sets_init", text='By Face Set Boundaries')
op = layout.operator("sculpt.face_sets_init", text="By Face Set Boundaries")
op.mode = 'FACE_SET_BOUNDARIES'
op = layout.operator("sculpt.face_sets_init", text='By Materials')
op = layout.operator("sculpt.face_sets_init", text="By Materials")
op.mode = 'MATERIALS'
op = layout.operator("sculpt.face_sets_init", text='By Normals')
op = layout.operator("sculpt.face_sets_init", text="By Normals")
op.mode = 'NORMALS'
op = layout.operator("sculpt.face_sets_init", text='By UV Seams')
op = layout.operator("sculpt.face_sets_init", text="By UV Seams")
op.mode = 'UV_SEAMS'
op = layout.operator("sculpt.face_sets_init", text='By Edge Creases')
op = layout.operator("sculpt.face_sets_init", text="By Edge Creases")
op.mode = 'CREASES'
op = layout.operator("sculpt.face_sets_init", text='By Edge Bevel Weight')
op = layout.operator("sculpt.face_sets_init", text="By Edge Bevel Weight")
op.mode = 'BEVEL_WEIGHT'
op = layout.operator("sculpt.face_sets_init", text='By Sharp Edges')
op = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
op.mode = 'SHARP_EDGES'
op = layout.operator("sculpt.face_sets_init", text='By Face Maps')
op = layout.operator("sculpt.face_sets_init", text="By Face Maps")
op.mode = 'FACE_MAPS'
@ -3465,13 +3465,13 @@ class VIEW3D_MT_random_mask(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.mask_init", text='Per Vertex')
op = layout.operator("sculpt.mask_init", text="Per Vertex")
op.mode = 'RANDOM_PER_VERTEX'
op = layout.operator("sculpt.mask_init", text='Per Face Set')
op = layout.operator("sculpt.mask_init", text="Per Face Set")
op.mode = 'RANDOM_PER_FACE_SET'
op = layout.operator("sculpt.mask_init", text='Per Loose Part')
op = layout.operator("sculpt.mask_init", text="Per Loose Part")
op.mode = 'RANDOM_PER_LOOSE_PART'
@ -3660,10 +3660,6 @@ class VIEW3D_MT_pose_propagate(Menu):
def draw(self, _context):
layout = self.layout
layout.operator("pose.propagate").mode = 'WHILE_HELD'
layout.separator()
layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
layout.operator("pose.propagate", text="To Last Keyframe (Make Cyclic)").mode = 'LAST_KEY'
@ -5500,23 +5496,23 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
layout = self.layout
pie = layout.menu_pie()
op = pie.operator("paint.mask_flood_fill", text='Invert Mask')
op = pie.operator("paint.mask_flood_fill", text="Invert Mask")
op.mode = 'INVERT'
op = pie.operator("paint.mask_flood_fill", text='Clear Mask')
op = pie.operator("paint.mask_flood_fill", text="Clear Mask")
op.mode = 'VALUE'
op.value = 0.0
op = pie.operator("sculpt.mask_filter", text='Smooth Mask')
op = pie.operator("sculpt.mask_filter", text="Smooth Mask")
op.filter_type = 'SMOOTH'
op = pie.operator("sculpt.mask_filter", text='Sharpen Mask')
op = pie.operator("sculpt.mask_filter", text="Sharpen Mask")
op.filter_type = 'SHARPEN'
op = pie.operator("sculpt.mask_filter", text='Grow Mask')
op = pie.operator("sculpt.mask_filter", text="Grow Mask")
op.filter_type = 'GROW'
op = pie.operator("sculpt.mask_filter", text='Shrink Mask')
op = pie.operator("sculpt.mask_filter", text="Shrink Mask")
op.filter_type = 'SHRINK'
op = pie.operator("sculpt.mask_filter", text='Increase Contrast')
op = pie.operator("sculpt.mask_filter", text="Increase Contrast")
op.filter_type = 'CONTRAST_INCREASE'
op.auto_iteration_count = False
op = pie.operator("sculpt.mask_filter", text='Decrease Contrast')
op = pie.operator("sculpt.mask_filter", text="Decrease Contrast")
op.filter_type = 'CONTRAST_DECREASE'
op.auto_iteration_count = False
@ -5565,16 +5561,16 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
layout = self.layout
pie = layout.menu_pie()
op = pie.operator("sculpt.face_sets_create", text='Face Set from Masked')
op = pie.operator("sculpt.face_sets_create", text="Face Set from Masked")
op.mode = 'MASKED'
op = pie.operator("sculpt.face_sets_create", text='Face Set from Visible')
op = pie.operator("sculpt.face_sets_create", text="Face Set from Visible")
op.mode = 'VISIBLE'
op = pie.operator("sculpt.face_set_change_visibility", text='Invert Visible')
op = pie.operator("sculpt.face_set_change_visibility", text="Invert Visible")
op.mode = 'INVERT'
op = pie.operator("sculpt.reveal_all", text='Show All')
op = pie.operator("sculpt.reveal_all", text="Show All")
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
@ -6216,8 +6212,7 @@ class VIEW3D_PT_shading_compositor(Panel):
@classmethod
def poll(cls, context):
return (context.space_data.shading.type in {'MATERIAL', 'RENDERED'} and
context.preferences.experimental.use_realtime_compositor)
return context.space_data.shading.type in {'MATERIAL', 'RENDERED'}
def draw(self, context):
shading = context.space_data.shading
@ -6229,7 +6224,7 @@ class VIEW3D_PT_shading_compositor(Panel):
row.active = not is_macos
row.prop(shading, "use_compositor", expand=True)
if is_macos and shading.use_compositor != "DISABLED":
self.layout.label(text="Compositor not supported on MacOS.", icon='ERROR')
self.layout.label(text="Compositor not supported on MacOS", icon='ERROR')
class VIEW3D_PT_gizmo_display(Panel):
@ -6974,9 +6969,9 @@ class VIEW3D_PT_snapping(Panel):
col.prop(tool_settings, "use_snap_project")
if 'FACE_NEAREST' in snap_elements:
col.prop(tool_settings, 'use_snap_to_same_target')
col.prop(tool_settings, "use_snap_to_same_target")
if object_mode == 'EDIT':
col.prop(tool_settings, 'snap_face_nearest_steps')
col.prop(tool_settings, "snap_face_nearest_steps")
if 'VOLUME' in snap_elements:
col.prop(tool_settings, "use_snap_peel_object")

View File

@ -1084,7 +1084,7 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
wpaint = tool_settings.weight_paint
mesh = context.object.data
layout.prop(mesh, 'use_mirror_vertex_groups')
layout.prop(mesh, "use_mirror_vertex_groups")
draw_vpaint_symmetry(layout, wpaint, context.object)

View File

@ -597,7 +597,7 @@ class BUILTIN_KSI_DeltaRotation(KeyingSetInfo):
path = keyingsets_utils.path_add_property(base_path, "delta_rotation_quaternion")
elif data.rotation_mode == 'AXIS_ANGLE':
# XXX: for now, this is not available yet
#path = path_add_property(base_path, "delta_rotation_axis_angle")
# path = path_add_property(base_path, "delta_rotation_axis_angle")
return
else:
path = keyingsets_utils.path_add_property(base_path, "delta_rotation_euler")
@ -637,7 +637,7 @@ class BUILTIN_KSI_DeltaScale(KeyingSetInfo):
###############################
# Note that this controls order of options in 'insert keyframe' menu.
# Note that this controls order of options in `insert keyframe` menu.
# Better try to keep some logical order here beyond mere alphabetical one, also because of menu entries shortcut.
# See also T51867.
classes = (

View File

@ -1,29 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*
* An #AnonymousAttributeID is used to identify attributes that are not explicitly named.
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AnonymousAttributeID AnonymousAttributeID;
AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name);
AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_name);
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id);
#ifdef __cplusplus
}
#endif

View File

@ -1,155 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <atomic>
#include <string>
#include "BLI_hash.hh"
#include "BLI_string_ref.hh"
#include "BKE_anonymous_attribute.h"
namespace blender::bke {
/**
* Wrapper for #AnonymousAttributeID with RAII semantics.
* This class should typically not be used directly. Instead use #StrongAnonymousAttributeID or
* #WeakAnonymousAttributeID.
*/
template<bool IsStrongReference> class OwnedAnonymousAttributeID {
private:
const AnonymousAttributeID *data_ = nullptr;
template<bool OtherIsStrongReference> friend class OwnedAnonymousAttributeID;
public:
OwnedAnonymousAttributeID() = default;
/** Create a new anonymous attribute id. */
explicit OwnedAnonymousAttributeID(StringRefNull debug_name)
{
if constexpr (IsStrongReference) {
data_ = BKE_anonymous_attribute_id_new_strong(debug_name.c_str());
}
else {
data_ = BKE_anonymous_attribute_id_new_weak(debug_name.c_str());
}
}
/**
* This transfers ownership, so no incref is necessary.
* The caller has to make sure that it owned the anonymous id.
*/
explicit OwnedAnonymousAttributeID(const AnonymousAttributeID *anonymous_id)
: data_(anonymous_id)
{
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID(const OwnedAnonymousAttributeID<OtherIsStrong> &other)
{
data_ = other.data_;
this->incref();
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID(OwnedAnonymousAttributeID<OtherIsStrong> &&other)
{
data_ = other.data_;
this->incref();
other.decref();
other.data_ = nullptr;
}
~OwnedAnonymousAttributeID()
{
this->decref();
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID &operator=(const OwnedAnonymousAttributeID<OtherIsStrong> &other)
{
if (this == &other) {
return *this;
}
this->~OwnedAnonymousAttributeID();
new (this) OwnedAnonymousAttributeID(other);
return *this;
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID &operator=(OwnedAnonymousAttributeID<OtherIsStrong> &&other)
{
if (this == &other) {
return *this;
}
this->~OwnedAnonymousAttributeID();
new (this) OwnedAnonymousAttributeID(std::move(other));
return *this;
}
operator bool() const
{
return data_ != nullptr;
}
StringRefNull debug_name() const
{
BLI_assert(data_ != nullptr);
return BKE_anonymous_attribute_id_debug_name(data_);
}
bool has_strong_references() const
{
BLI_assert(data_ != nullptr);
return BKE_anonymous_attribute_id_has_strong_references(data_);
}
/** Extract the ownership of the currently wrapped anonymous id. */
const AnonymousAttributeID *extract()
{
const AnonymousAttributeID *extracted_data = data_;
/* Don't decref because the caller becomes the new owner. */
data_ = nullptr;
return extracted_data;
}
/** Get the wrapped anonymous id, without taking ownership. */
const AnonymousAttributeID *get() const
{
return data_;
}
private:
void incref()
{
if (data_ == nullptr) {
return;
}
if constexpr (IsStrongReference) {
BKE_anonymous_attribute_id_increment_strong(data_);
}
else {
BKE_anonymous_attribute_id_increment_weak(data_);
}
}
void decref()
{
if (data_ == nullptr) {
return;
}
if constexpr (IsStrongReference) {
BKE_anonymous_attribute_id_decrement_strong(data_);
}
else {
BKE_anonymous_attribute_id_decrement_weak(data_);
}
}
};
using StrongAnonymousAttributeID = OwnedAnonymousAttributeID<true>;
using WeakAnonymousAttributeID = OwnedAnonymousAttributeID<false>;
} // namespace blender::bke

View File

@ -0,0 +1,105 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <atomic>
#include "BLI_set.hh"
#include "BLI_string_ref.hh"
#include "BLI_user_counter.hh"
namespace blender::bke {
/**
* An #AnonymousAttributeID contains information about a specific anonymous attribute.
* Like normal attributes, anonymous attributes are also identified by their name, so one should
* not have to compare #AnonymousAttributeID pointers.
*
* Anonymous attributes don't need additional information besides their name, with a few
* exceptions:
* - The name of anonymous attributes is generated automatically, so it is generally not human
* readable (just random characters). #AnonymousAttributeID can provide more context as where a
* specific anonymous attribute was created which can simplify debugging.
* - [Not yet supported.] When anonymous attributes are contained in on-disk caches, we have to map
* those back to anonymous attributes at run-time. The issue is that (for various reasons) we
* might change how anonymous attribute names are generated in the future, which would lead to a
* mis-match between stored and new attribute names. To work around it, we should cache
* additional information for anonymous attributes on disk (like which node created it). This
* information can then be used to map stored attributes to their run-time counterpart.
*
* Once created, #AnonymousAttributeID is immutable. Also it is intrinsically reference counted so
* that it can have shared ownership. `std::shared_ptr` can't be used for that purpose here,
* because that is not available in C code. If possible, the #AutoAnonymousAttributeID wrapper
* should be used to avoid manual reference counting in C++ code.
*/
class AnonymousAttributeID {
private:
mutable std::atomic<int> users_ = 1;
protected:
std::string name_;
public:
virtual ~AnonymousAttributeID() = default;
StringRefNull name() const
{
return name_;
}
virtual std::string user_name() const;
void user_add() const
{
users_.fetch_add(1);
}
void user_remove() const
{
const int new_users = users_.fetch_sub(1) - 1;
if (new_users == 0) {
MEM_delete(this);
}
}
};
/** Wrapper for #AnonymousAttributeID that avoids manual reference counting. */
using AutoAnonymousAttributeID = UserCounter<const AnonymousAttributeID>;
/**
* A set of anonymous attribute names that is passed around in geometry nodes.
*/
class AnonymousAttributeSet {
public:
/**
* This uses `std::shared_ptr` because attributes sets are passed around by value during geometry
* nodes evaluation, and this makes it very small if there is no name. Also it makes copying very
* cheap.
*/
std::shared_ptr<Set<std::string>> names;
};
/**
* Can be passed to algorithms which propagate attributes. It can tell the algorithm which
* anonymous attributes should be propagated and can be skipped.
*/
class AnonymousAttributePropagationInfo {
public:
/**
* This uses `std::shared_ptr` because it's usually initialized from an #AnonymousAttributeSet
* and then the set doesn't have to be copied.
*/
std::shared_ptr<Set<std::string>> names;
/**
* Propagate all anonymous attributes even if the set above is empty.
*/
bool propagate_all = true;
/**
* Return true when the anonymous attribute should be propagated and false otherwise.
*/
bool propagate(const AnonymousAttributeID &anonymous_id) const;
};
} // namespace blender::bke

View File

@ -8,23 +8,25 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_span.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BKE_anonymous_attribute.hh"
#include "BKE_anonymous_attribute_id.hh"
#include "BKE_attribute.h"
struct Mesh;
struct PointCloud;
namespace blender::fn {
namespace multi_function {
class MultiFunction;
}
class GField;
} // namespace blender::fn
namespace blender::bke {
/**
* Identifies an attribute that is either named or anonymous.
* Identifies an attribute with optional anonymous attribute information.
* It does not own the identifier, so it is just a reference.
*/
class AttributeIDRef {
@ -38,15 +40,14 @@ class AttributeIDRef {
AttributeIDRef(StringRefNull name);
AttributeIDRef(const char *name);
AttributeIDRef(const std::string &name);
AttributeIDRef(const AnonymousAttributeID &anonymous_id);
AttributeIDRef(const AnonymousAttributeID *anonymous_id);
operator bool() const;
uint64_t hash() const;
bool is_named() const;
bool is_anonymous() const;
StringRef name() const;
const AnonymousAttributeID &anonymous_id() const;
bool should_be_kept() const;
friend bool operator==(const AttributeIDRef &a, const AttributeIDRef &b);
friend std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id);
@ -175,7 +176,7 @@ struct AttributeValidator {
/**
* Single input, single output function that corrects attribute values if necessary.
*/
const fn::MultiFunction *function;
const fn::multi_function::MultiFunction *function;
operator bool() const
{
@ -749,6 +750,7 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes,
eAttrDomainMask domain_mask,
const AnonymousAttributePropagationInfo &propagation_info,
const Set<std::string> &skip = {});
/**
@ -762,6 +764,7 @@ void copy_attribute_domain(AttributeAccessor src_attributes,
MutableAttributeAccessor dst_attributes,
IndexMask selection,
eAttrDomain domain,
const AnonymousAttributePropagationInfo &propagation_info,
const Set<std::string> &skip = {});
bool allow_procedural_attribute_access(StringRef attribute_name);
@ -852,29 +855,31 @@ inline AttributeIDRef::AttributeIDRef(const std::string &name) : name_(name)
}
/* The anonymous id is only borrowed, the caller has to keep a reference to it. */
inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID *anonymous_id)
: anonymous_id_(anonymous_id)
inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID &anonymous_id)
: AttributeIDRef(anonymous_id.name())
{
anonymous_id_ = &anonymous_id;
}
inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID *anonymous_id)
: AttributeIDRef(anonymous_id ? anonymous_id->name() : "")
{
anonymous_id_ = anonymous_id;
}
inline bool operator==(const AttributeIDRef &a, const AttributeIDRef &b)
{
return a.anonymous_id_ == b.anonymous_id_ && a.name_ == b.name_;
return a.name_ == b.name_;
}
inline AttributeIDRef::operator bool() const
{
return this->is_named() || this->is_anonymous();
return !name_.is_empty();
}
inline uint64_t AttributeIDRef::hash() const
{
return get_default_hash_2(name_, anonymous_id_);
}
inline bool AttributeIDRef::is_named() const
{
return !name_.is_empty();
return get_default_hash(name_);
}
inline bool AttributeIDRef::is_anonymous() const
@ -884,7 +889,6 @@ inline bool AttributeIDRef::is_anonymous() const
inline StringRef AttributeIDRef::name() const
{
BLI_assert(this->is_named());
return name_;
}
@ -894,14 +898,4 @@ inline const AnonymousAttributeID &AttributeIDRef::anonymous_id() const
return *anonymous_id_;
}
/**
* \return True if the attribute should not be removed automatically as an optimization during
* processing or copying. Anonymous attributes can be removed when they no longer have any
* references.
*/
inline bool AttributeIDRef::should_be_kept() const
{
return this->is_named() || BKE_anonymous_attribute_id_has_strong_references(anonymous_id_);
}
} // namespace blender::bke

View File

@ -58,7 +58,7 @@ typedef struct BVHTreeFromMesh {
BVHTree_RayCastCallback raycast_callback;
/* Vertex array, so that callbacks have instant access to data. */
const float (*positions)[3];
const float (*vert_positions)[3];
const struct MEdge *edge;
const struct MFace *face;
const int *corner_verts;

View File

@ -72,7 +72,7 @@ typedef struct Cloth {
unsigned char pad2;
short pad3;
struct BVHTree *bvhtree; /* collision tree for this cloth object */
struct BVHTree *bvhselftree; /* collision tree for this cloth object */
struct BVHTree *bvhselftree; /* collision tree for this cloth object (may be same as bvhtree) */
struct MVertTri *tri;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */

View File

@ -54,6 +54,8 @@ typedef struct CollPair {
#else
int ap1, ap2, ap3, bp1, bp2, bp3;
#endif
/* Barycentric weights of the collision point. */
float aw1, aw2, aw3, bw1, bw2, bw3;
int pointsb[4];
} CollPair;

View File

@ -7,7 +7,7 @@
#pragma once
#include "BLI_float3x3.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
struct Depsgraph;

View File

@ -2,7 +2,6 @@
#pragma once
struct CurvesGeometry;
struct Mesh;
/** \file
@ -11,6 +10,9 @@ struct Mesh;
namespace blender::bke {
class CurvesGeometry;
class AnonymousAttributePropagationInfo;
/**
* Extrude all splines in the profile curve along the path of every spline in the curve input.
* Transfer curve attributes to the mesh.
@ -23,11 +25,13 @@ namespace blender::bke {
*/
Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
const CurvesGeometry &profile,
bool fill_caps);
bool fill_caps,
const AnonymousAttributePropagationInfo &propagation_info);
/**
* Create a loose-edge mesh based on the evaluated path of the curve's splines.
* Transfer curve attributes to the mesh.
*/
Mesh *curve_to_wire_mesh(const CurvesGeometry &curve);
Mesh *curve_to_wire_mesh(const CurvesGeometry &curve,
const AnonymousAttributePropagationInfo &propagation_info);
} // namespace blender::bke

View File

@ -17,7 +17,7 @@
#include "BLI_float4x4.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
@ -404,8 +404,10 @@ class CurvesGeometry : public ::CurvesGeometry {
void calculate_bezier_auto_handles();
void remove_points(IndexMask points_to_delete);
void remove_curves(IndexMask curves_to_delete);
void remove_points(IndexMask points_to_delete,
const AnonymousAttributePropagationInfo &propagation_info = {});
void remove_curves(IndexMask curves_to_delete,
const AnonymousAttributePropagationInfo &propagation_info = {});
/**
* Change the direction of selected curves (switch the start and end) without changing their

View File

@ -23,7 +23,6 @@
extern "C" {
#endif
struct AnonymousAttributeID;
struct BMesh;
struct BlendDataReader;
struct BlendWriter;
@ -227,7 +226,7 @@ void *CustomData_add_layer_anonymous(struct CustomData *data,
eCDAllocType alloctype,
void *layer,
int totelem,
const struct AnonymousAttributeID *anonymous_id);
const AnonymousAttributeIDHandle *anonymous_id);
/**
* Frees the active or first data layer with the give type.
@ -275,8 +274,6 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
int type,
const char *name,
int totelem);
void *CustomData_duplicate_referenced_layer_anonymous(
CustomData *data, int type, const struct AnonymousAttributeID *anonymous_id, int totelem);
bool CustomData_is_referenced_layer(struct CustomData *data, int type);
/**

View File

@ -261,18 +261,14 @@ class NormalFieldInput : public GeometryFieldInput {
class AnonymousAttributeFieldInput : public GeometryFieldInput {
private:
/**
* A strong reference is required to make sure that the referenced attribute is not removed
* automatically.
*/
StrongAnonymousAttributeID anonymous_id_;
AutoAnonymousAttributeID anonymous_id_;
std::string producer_name_;
public:
AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id,
AnonymousAttributeFieldInput(AutoAnonymousAttributeID anonymous_id,
const CPPType &type,
std::string producer_name)
: GeometryFieldInput(type, anonymous_id.debug_name()),
: GeometryFieldInput(type, anonymous_id->user_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name)
{
@ -280,7 +276,7 @@ class AnonymousAttributeFieldInput : public GeometryFieldInput {
}
template<typename T>
static fn::Field<T> Create(StrongAnonymousAttributeID anonymous_id, std::string producer_name)
static fn::Field<T> Create(AutoAnonymousAttributeID anonymous_id, std::string producer_name)
{
const CPPType &type = CPPType::get<T>();
auto field_input = std::make_shared<AnonymousAttributeFieldInput>(
@ -288,6 +284,11 @@ class AnonymousAttributeFieldInput : public GeometryFieldInput {
return fn::Field<T>{field_input};
}
const AutoAnonymousAttributeID &anonymous_id() const
{
return anonymous_id_;
}
GVArray get_varray_for_context(const GeometryFieldContext &context,
IndexMask mask) const override;

View File

@ -14,12 +14,12 @@
#include "BLI_function_ref.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector_set.hh"
#include "BKE_anonymous_attribute.hh"
#include "BKE_anonymous_attribute_id.hh"
#include "BKE_attribute.hh"
#include "BKE_geometry_set.h"
@ -213,6 +213,7 @@ struct GeometrySet {
blender::Span<GeometryComponentType> component_types,
GeometryComponentType dst_component_type,
bool include_instances,
const blender::bke::AnonymousAttributePropagationInfo &propagation_info,
blender::Map<blender::bke::AttributeIDRef, blender::bke::AttributeKind> &r_attributes) const;
blender::Vector<GeometryComponentType> gather_component_types(bool include_instances,

View File

@ -9,7 +9,7 @@
#include "DNA_image_types.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::bke::image {

View File

@ -155,7 +155,8 @@ class Instances {
* Remove the indices that are not contained in the mask input, and remove unused instance
* references afterwards.
*/
void remove(const blender::IndexMask mask);
void remove(const blender::IndexMask mask,
const blender::bke::AnonymousAttributePropagationInfo &propagation_info);
/**
* Get an id for every instance. These can be used for e.g. motion blur.
*/

View File

@ -401,7 +401,7 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct
* Compare local and reference data-blocks and create new override operations as needed,
* or reset to reference values if overriding is not allowed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Defining override operations is only mandatory before saving a `.blend` file on disk
* (not for undo!).
@ -410,8 +410,6 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct
* \note This is by far the biggest operation (the more time-consuming) of the three so far,
* since it has to go over all properties in depth (all overridable ones at least).
* Generating differential values and applying overrides are much cheaper.
*
* \return true if any library operation was created.
*/
void BKE_lib_override_library_operations_create(struct Main *bmain,
struct ID *local,
@ -419,12 +417,35 @@ void BKE_lib_override_library_operations_create(struct Main *bmain,
/**
* Check all overrides from given \a bmain and create/update overriding operations as needed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*/
void BKE_lib_override_library_main_operations_create(struct Main *bmain,
bool force_auto,
int *r_report_flags);
/**
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
*/
void BKE_lib_override_library_operations_restore(struct Main *bmain,
struct ID *local,
int *r_report_flags);
/**
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID, for all liboverride IDs tagged as needing such process in given `bmain`.
*
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
*/
void BKE_lib_override_library_main_operations_restore(struct Main *bmain, int *r_report_flags);
/**
* Reset all overrides in given \a id_root, while preserving ID relations.
*

View File

@ -325,7 +325,7 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]
*/
void BKE_mesh_recalc_looptri(const int *corner_verts,
const struct MPoly *mpoly,
const float (*positions)[3],
const float (*vert_positions)[3],
int totloop,
int totpoly,
struct MLoopTri *mlooptri);
@ -339,7 +339,7 @@ void BKE_mesh_recalc_looptri(const int *corner_verts,
*/
void BKE_mesh_recalc_looptri_with_normals(const int *corner_verts,
const struct MPoly *mpoly,
const float (*positions)[3],
const float (*vert_positions)[3],
int totloop,
int totpoly,
struct MLoopTri *mlooptri,
@ -421,7 +421,7 @@ bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
const int *poly_verts,
const float (*positions)[3],
const float (*vert_positions)[3],
float r_no[3]);
/**
@ -430,7 +430,7 @@ void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
* \note Usually #BKE_mesh_poly_normals_ensure is the preferred way to access face normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly(const float (*positions)[3],
void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
int mvert_len,
const int *corner_verts,
int mloop_len,
@ -444,7 +444,7 @@ void BKE_mesh_calc_normals_poly(const float (*positions)[3],
* \note Usually #BKE_mesh_vertex_normals_ensure is the preferred way to access vertex normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly_and_vertex(const float (*positions)[3],
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
int mvert_len,
const int *corner_verts,
int mloop_len,
@ -595,13 +595,13 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
*/
void BKE_mesh_normals_loop_split(const float (*positions)[3],
void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
const struct MEdge *medges,
int numEdges,
const int *corner_verts,
const int *corner_edges,
const int *corner_verts,
const int *corner_edges,
float (*r_loop_normals)[3],
int numLoops,
const struct MPoly *mpolys,
@ -613,7 +613,7 @@ void BKE_mesh_normals_loop_split(const float (*positions)[3],
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2]);
void BKE_mesh_normals_loop_custom_set(const float (*positions)[3],
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
struct MEdge *medges,
@ -626,7 +626,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*positions)[3],
const float (*poly_normals)[3],
int numPolys,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*positions)[3],
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
float (*r_custom_vert_normals)[3],
int numVerts,
@ -690,17 +690,17 @@ void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_
void BKE_mesh_calc_poly_center(const struct MPoly *mpoly,
const int *poly_verts,
const float (*positions)[3],
const float (*vert_positions)[3],
float r_cent[3]);
/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
const int *poly_verts,
const float (*positions)[3]);
const float (*vert_positions)[3]);
float BKE_mesh_calc_area(const struct Mesh *me);
float BKE_mesh_calc_poly_uv_area(const struct MPoly *mpoly, const struct MLoopUV *uv_array);
void BKE_mesh_calc_poly_angles(const struct MPoly *mpoly,
const int *poly_verts,
const float (*positions)[3],
const float (*vert_positions)[3],
float angles[]);
void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash,
@ -890,7 +890,7 @@ bool BKE_mesh_validate_material_indices(struct Mesh *me);
* by importers that load normals (for example).
*/
bool BKE_mesh_validate_arrays(struct Mesh *me,
float (*positions)[3],
float (*vert_positions)[3],
unsigned int totvert,
struct MEdge *medges,
unsigned int totedge,
@ -1064,7 +1064,7 @@ BLI_INLINE MDeformVert *BKE_mesh_deform_verts_for_write(Mesh *mesh)
#ifdef __cplusplus
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_span.hh"
inline blender::Span<blender::float3> Mesh::vert_positions() const
@ -1073,7 +1073,8 @@ inline blender::Span<blender::float3> Mesh::vert_positions() const
}
inline blender::MutableSpan<blender::float3> Mesh::vert_positions_for_write()
{
return {reinterpret_cast<blender::float3 *>(BKE_mesh_vert_positions_for_write(this)), this->totvert};
return {reinterpret_cast<blender::float3 *>(BKE_mesh_vert_positions_for_write(this)),
this->totvert};
}
inline blender::Span<MEdge> Mesh::edges() const

View File

@ -275,7 +275,7 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*positions)[3],
* Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams),
* not some UV layers coordinates.
*/
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*positions)[3],
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
int totvert,
const struct MEdge *edges,
int totedge,
@ -299,7 +299,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*positions)[3],
* Not sure it would be worth the more complex code, though,
* those loops are supposed to be really quick to do.
*/
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*positions)[3],
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
int totvert,
struct MEdge *edges,
int totedge,

View File

@ -8,7 +8,7 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "DNA_meshdata_types.h"
@ -127,7 +127,7 @@ int sample_surface_points_projected(
Vector<int> &r_looptri_indices,
Vector<float3> &r_positions);
float3 compute_bary_coord_in_triangle(Span<float3> positions,
float3 compute_bary_coord_in_triangle(Span<float3> vert_positions,
Span<int> corner_verts,
const MLoopTri &looptri,
const float3 &position);

View File

@ -17,7 +17,7 @@ struct ReportList;
* split normals can be used to recreate the full tangent space.
* NOTE: * The mesh should be made of only tris and quads!
*/
void BKE_mesh_calc_loop_tangent_single_ex(const float (*positions)[3],
void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
int numVerts,
const int *corner_verts,
float (*r_looptangent)[4],
@ -41,7 +41,7 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh,
/**
* See: #BKE_editmesh_loop_tangent_calc (matching logic).
*/
void BKE_mesh_calc_loop_tangent_ex(const float (*positions)[3],
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
const struct MPoly *mpoly,
uint mpoly_len,
const int *corner_verts,

View File

@ -16,7 +16,7 @@
# include "BLI_array.hh"
# include "BLI_bit_vector.hh"
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
# include "BLI_span.hh"

View File

@ -39,40 +39,42 @@ void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip);
*/
void BKE_movieclip_convert_multilayer_ibuf(struct ImBuf *ibuf);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, const struct MovieClipUser *user);
struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
int postprocess_flag);
struct ImBuf *BKE_movieclip_get_stable_ibuf(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
float loc[2],
float *scale,
float *angle,
int postprocess_flag);
struct ImBuf *BKE_movieclip_get_ibuf_flag(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
int flag,
int cache_flag);
void BKE_movieclip_get_size(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
int *width,
int *height);
void BKE_movieclip_get_size_fl(struct MovieClip *clip, struct MovieClipUser *user, float size[2]);
void BKE_movieclip_get_size_fl(struct MovieClip *clip,
const struct MovieClipUser *user,
float size[2]);
int BKE_movieclip_get_duration(struct MovieClip *clip);
float BKE_movieclip_get_fps(struct MovieClip *clip);
void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy);
bool BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user);
bool BKE_movieclip_has_frame(struct MovieClip *clip, const struct MovieClipUser *user);
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr);
void BKE_movieclip_update_scopes(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
struct MovieClipScopes *scopes);
/**
* Get segments of cached frames. useful for debugging cache policies.
*/
void BKE_movieclip_get_cache_segments(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
int *r_totseg,
int **r_points);
@ -105,7 +107,7 @@ float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, floa
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr);
void BKE_movieclip_filename_for_frame(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
char *name);
/**
@ -113,11 +115,11 @@ void BKE_movieclip_filename_for_frame(struct MovieClip *clip,
* Used by a prefetch job which takes care of creating a local copy of the clip.
*/
struct ImBuf *BKE_movieclip_anim_ibuf_for_frame_no_lock(struct MovieClip *clip,
struct MovieClipUser *user);
const struct MovieClipUser *user);
bool BKE_movieclip_has_cached_frame(struct MovieClip *clip, struct MovieClipUser *user);
bool BKE_movieclip_has_cached_frame(struct MovieClip *clip, const struct MovieClipUser *user);
bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip,
struct MovieClipUser *user,
const struct MovieClipUser *user,
struct ImBuf *ibuf);
struct GPUTexture *BKE_movieclip_get_gpu_texture(struct MovieClip *clip,

View File

@ -107,9 +107,6 @@ class GeoNodeExecParams;
class NodeDeclarationBuilder;
class GatherLinkSearchOpParams;
} // namespace nodes
namespace fn {
class MFDataType;
} // namespace fn
namespace realtime_compositor {
class Context;
class NodeOperation;

View File

@ -7,6 +7,7 @@
#include "BLI_cache_mutex.hh"
#include "BLI_multi_value_map.hh"
#include "BLI_resource_scope.hh"
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
@ -24,6 +25,10 @@ namespace blender::nodes {
struct FieldInferencingInterface;
class NodeDeclaration;
struct GeometryNodesLazyFunctionGraphInfo;
namespace anonymous_attribute_lifetime {
struct RelationsInNode;
}
namespace aal = anonymous_attribute_lifetime;
} // namespace blender::nodes
namespace blender {
@ -106,6 +111,8 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
/** Information about how inputs and outputs of the node group interact with fields. */
std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface;
/** Information about usage of anonymous attributes within the group. */
std::unique_ptr<nodes::aal::RelationsInNode> anonymous_attribute_relations;
/**
* For geometry nodes, a lazy function graph with some additional info is cached. This is used to
@ -162,13 +169,6 @@ class bNodeSocketRuntime : NonCopyable, NonMovable {
/** #eNodeTreeChangedFlag. */
uint32_t changed_flag = 0;
/**
* The location of the sockets, in the view-space of the node editor.
* \note Only calculated when drawing.
*/
float locx = 0;
float locy = 0;
/**
* Runtime-only cache of the number of input links, for multi-input sockets,
* including dragged node links that aren't actually in the tree.
@ -330,7 +330,11 @@ inline bool topology_cache_is_available(const bNodeSocket &socket)
namespace node_field_inferencing {
bool update_field_inferencing(const bNodeTree &tree);
}
namespace anonymous_attribute_inferencing {
Array<const nodes::aal::RelationsInNode *> get_relations_by_node(const bNodeTree &tree,
ResourceScope &scope);
bool update_anonymous_attribute_relations(bNodeTree &tree);
} // namespace anonymous_attribute_inferencing
} // namespace blender::bke
/* -------------------------------------------------------------------- */

View File

@ -575,7 +575,7 @@ typedef struct SculptSession {
struct Depsgraph *depsgraph;
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
float (*positions)[3];
float (*vert_positions)[3];
const struct MPoly *mpoly;
const int *corner_verts;

View File

@ -266,7 +266,7 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve
}
/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */
/* particle.cc */
/* Few helpers for count-all etc. */
@ -539,7 +539,7 @@ void BKE_particlesystem_reset_all(struct Object *object);
/* ----------- functions needed only inside particlesystem ------------ */
/* particle.c */
/* particle.cc */
void psys_disable_all(struct Object *ob);
void psys_enable_all(struct Object *ob);

View File

@ -265,7 +265,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
struct Mesh *mesh,
const struct MPoly *mpoly,
const int *corner_verts,
float (*positions)[3],
float (*vert_positions)[3],
int totvert,
struct CustomData *vdata,
struct CustomData *ldata,
@ -582,7 +582,7 @@ typedef struct PBVHVertexIter {
int gridsize;
/* mesh */
float (*mesh_positions)[3];
float (*vert_positions)[3];
float (*vert_normals)[3];
const bool *hide_vert;
int totvert;
@ -642,7 +642,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
} \
} \
else if (vi.mesh_positions) { \
else if (vi.vert_positions) { \
if (vi.respect_hide) { \
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
@ -652,7 +652,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
else { \
BLI_assert(vi.visible); \
} \
vi.co = vi.mesh_positions[vi.vert_indices[vi.gx]]; \
vi.co = vi.vert_positions[vi.vert_indices[vi.gx]]; \
vi.no = vi.vert_normals[vi.vert_indices[vi.gx]]; \
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
if (vi.vmask) { \

View File

@ -4,7 +4,7 @@
#pragma once
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rect.h"
#include "BLI_vector.hh"

View File

@ -11,7 +11,7 @@
# include <mutex>
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
#endif

View File

@ -8,19 +8,19 @@
namespace blender::bke {
struct ConversionFunctions {
const fn::MultiFunction *multi_function;
const mf::MultiFunction *multi_function;
void (*convert_single_to_initialized)(const void *src, void *dst);
void (*convert_single_to_uninitialized)(const void *src, void *dst);
};
class DataTypeConversions {
private:
Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
Map<std::pair<mf::DataType, mf::DataType>, ConversionFunctions> conversions_;
public:
void add(fn::MFDataType from_type,
fn::MFDataType to_type,
const fn::MultiFunction &fn,
void add(mf::DataType from_type,
mf::DataType to_type,
const mf::MultiFunction &fn,
void (*convert_single_to_initialized)(const void *src, void *dst),
void (*convert_single_to_uninitialized)(const void *src, void *dst))
{
@ -28,19 +28,18 @@ class DataTypeConversions {
{&fn, convert_single_to_initialized, convert_single_to_uninitialized});
}
const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
const ConversionFunctions *get_conversion_functions(mf::DataType from, mf::DataType to) const
{
return conversions_.lookup_ptr({from, to});
}
const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
{
return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
fn::MFDataType::ForSingle(to));
return this->get_conversion_functions(mf::DataType::ForSingle(from),
mf::DataType::ForSingle(to));
}
const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
fn::MFDataType to) const
const mf::MultiFunction *get_conversion_multi_function(mf::DataType from, mf::DataType to) const
{
const ConversionFunctions *functions = this->get_conversion_functions(from, to);
return functions ? functions->multi_function : nullptr;
@ -49,7 +48,7 @@ class DataTypeConversions {
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
{
return conversions_.contains(
{fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)});
{mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type)});
}
void convert_to_uninitialized(const CPPType &from_type,

View File

@ -160,7 +160,7 @@ bool BKE_volume_save(const struct Volume *volume,
#ifdef __cplusplus
# include "BLI_float4x4.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_string_ref.hh"
bool BKE_volume_min_max(const Volume *volume, blender::float3 &r_min, blender::float3 &r_max);

View File

@ -64,7 +64,7 @@ set(SRC
intern/anim_path.c
intern/anim_sys.c
intern/anim_visualization.c
intern/anonymous_attribute.cc
intern/anonymous_attribute_id.cc
intern/appdir.c
intern/armature.c
intern/armature_deform.c
@ -229,6 +229,7 @@ set(SRC
intern/nla.c
intern/node.cc
intern/node_runtime.cc
intern/node_tree_anonymous_attributes.cc
intern/node_tree_field_inferencing.cc
intern/node_tree_update.cc
intern/object.cc
@ -243,7 +244,7 @@ set(SRC
intern/paint.cc
intern/paint_canvas.cc
intern/paint_toolslots.c
intern/particle.c
intern/particle.cc
intern/particle_child.c
intern/particle_distribute.c
intern/particle_system.c
@ -315,8 +316,7 @@ set(SRC
BKE_anim_path.h
BKE_anim_visualization.h
BKE_animsys.h
BKE_anonymous_attribute.h
BKE_anonymous_attribute.hh
BKE_anonymous_attribute_id.hh
BKE_appdir.h
BKE_armature.h
BKE_armature.hh

View File

@ -24,7 +24,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
@ -310,7 +310,7 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
BLI_assert(dm->looptris.array_wip == nullptr);
SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip);
std::swap(dm->looptris.array, dm->looptris.array_wip);
if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) ||
(totpoly == 0)) {

View File

@ -1,105 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_anonymous_attribute.hh"
using namespace blender::bke;
/**
* A struct that identifies an attribute. It's lifetime is managed by an atomic reference count.
*
* Additionally, this struct can be strongly or weakly owned. The difference is that strong
* ownership means that attributes with this id will be kept around. Weak ownership just makes sure
* that the struct itself stays alive, but corresponding attributes might still be removed
* automatically.
*/
struct AnonymousAttributeID {
/**
* Total number of references to this attribute id. Once this reaches zero, the struct can be
* freed. This includes strong and weak references.
*/
mutable std::atomic<int> refcount_tot = 0;
/**
* Number of strong references to this attribute id. When this is zero, the corresponding
* attributes can be removed from geometries automatically.
*/
mutable std::atomic<int> refcount_strong = 0;
/**
* Only used to identify this struct in a debugging session.
*/
std::string debug_name;
/**
* Unique name of the this attribute id during the current session.
*/
std::string internal_name;
};
/** Every time this function is called, it outputs a different name. */
static std::string get_new_internal_name()
{
static std::atomic<int> index = 0;
const int next_index = index.fetch_add(1);
return ".a_" + std::to_string(next_index);
}
AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name)
{
AnonymousAttributeID *anonymous_id = new AnonymousAttributeID();
anonymous_id->debug_name = debug_name;
anonymous_id->internal_name = get_new_internal_name();
anonymous_id->refcount_tot.store(1);
return anonymous_id;
}
AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_name)
{
AnonymousAttributeID *anonymous_id = new AnonymousAttributeID();
anonymous_id->debug_name = debug_name;
anonymous_id->internal_name = get_new_internal_name();
anonymous_id->refcount_tot.store(1);
anonymous_id->refcount_strong.store(1);
return anonymous_id;
}
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->refcount_strong.load() >= 1;
}
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_tot.fetch_add(1);
}
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_tot.fetch_add(1);
anonymous_id->refcount_strong.fetch_add(1);
}
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id)
{
const int new_refcount = anonymous_id->refcount_tot.fetch_sub(1) - 1;
if (new_refcount == 0) {
BLI_assert(anonymous_id->refcount_strong == 0);
delete anonymous_id;
}
}
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_strong.fetch_sub(1);
BKE_anonymous_attribute_id_decrement_weak(anonymous_id);
}
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->debug_name.c_str();
}
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->internal_name.c_str();
}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_anonymous_attribute_id.hh"
namespace blender::bke {
std::string AnonymousAttributeID::user_name() const
{
return this->name();
}
bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &anonymous_id) const
{
if (this->propagate_all) {
return true;
}
if (!this->names) {
return false;
}
return this->names->contains_as(anonymous_id.name());
}
} // namespace blender::bke

View File

@ -615,7 +615,7 @@ static void get_domains_types(eAttrDomain domains[ATTR_DOMAIN_NUM])
}
/* Swap corner and face. */
SWAP(eAttrDomain, domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
std::swap(domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
}
int BKE_id_attribute_to_index(const ID *id,

View File

@ -16,7 +16,7 @@
#include "BLI_array_utils.hh"
#include "BLI_color.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "FN_field.hh"
@ -40,13 +40,9 @@ namespace blender::bke {
std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id)
{
if (attribute_id.is_named()) {
if (attribute_id) {
stream << attribute_id.name();
}
else if (attribute_id.is_anonymous()) {
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
stream << "<" << BKE_anonymous_attribute_id_debug_name(&anonymous_id) << ">";
}
else {
stream << "<none>";
}
@ -153,7 +149,7 @@ eAttrDomain attribute_domain_highest_priority(Span<eAttrDomain> domains)
static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer &layer)
{
if (layer.anonymous_id != nullptr) {
return layer.anonymous_id;
return *layer.anonymous_id;
}
return layer.name;
}
@ -207,7 +203,7 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
const int domain_num,
const AttributeIDRef &attribute_id)
{
if (attribute_id.is_named()) {
if (!attribute_id.is_anonymous()) {
char attribute_name_c[MAX_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
@ -261,9 +257,6 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
if (!attribute_id) {
return false;
}
if (attribute_id.is_anonymous()) {
return layer.anonymous_id == &attribute_id.anonymous_id();
}
return layer.name == attribute_id.name();
}
@ -451,14 +444,8 @@ GAttributeWriter CustomDataAttributeProvider::try_get_for_write(
if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) {
continue;
}
if (attribute_id.is_named()) {
CustomData_duplicate_referenced_layer_named(
custom_data, layer.type, layer.name, element_num);
}
else {
CustomData_duplicate_referenced_layer_anonymous(
custom_data, layer.type, &attribute_id.anonymous_id(), element_num);
}
CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, element_num);
const CPPType *type = custom_data_type_to_cpp_type((eCustomDataType)layer.type);
if (type == nullptr) {
continue;
@ -854,7 +841,7 @@ void MutableAttributeAccessor::remove_anonymous()
}
while (!anonymous_ids.is_empty()) {
this->remove(anonymous_ids.pop_last());
this->remove(*anonymous_ids.pop_last());
}
}
@ -883,12 +870,7 @@ GAttributeWriter MutableAttributeAccessor::lookup_for_write(const AttributeIDRef
#ifdef DEBUG
if (attribute) {
auto checker = std::make_shared<FinishCallChecker>();
if (attribute_id.is_named()) {
checker->name = attribute_id.name();
}
else {
checker->name = BKE_anonymous_attribute_id_debug_name(&attribute_id.anonymous_id());
}
checker->name = attribute_id.name();
checker->real_finish_fn = attribute.tag_modified_fn;
attribute.tag_modified_fn = [checker]() {
if (checker->real_finish_fn) {
@ -968,6 +950,7 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes,
const eAttrDomainMask domain_mask,
const AnonymousAttributePropagationInfo &propagation_info,
const Set<std::string> &skip)
{
Vector<AttributeTransferData> attributes;
@ -976,10 +959,10 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
if (!(ATTR_DOMAIN_AS_MASK(meta_data.domain) & domain_mask)) {
return true;
}
if (id.is_named() && skip.contains(id.name())) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (!id.should_be_kept()) {
if (skip.contains(id.name())) {
return true;
}
@ -999,6 +982,7 @@ void copy_attribute_domain(const AttributeAccessor src_attributes,
MutableAttributeAccessor dst_attributes,
const IndexMask selection,
const eAttrDomain domain,
const AnonymousAttributePropagationInfo &propagation_info,
const Set<std::string> &skip)
{
src_attributes.for_all(
@ -1006,10 +990,10 @@ void copy_attribute_domain(const AttributeAccessor src_attributes,
if (meta_data.domain != domain) {
return true;
}
if (id.is_named() && skip.contains(id.name())) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (!id.should_be_kept()) {
if (skip.contains(id.name())) {
return true;
}

View File

@ -335,7 +335,7 @@ namespace attribute_accessor_functions {
template<const ComponentAttributeProviders &providers>
inline bool is_builtin(const void * /*owner*/, const AttributeIDRef &attribute_id)
{
if (!attribute_id.is_named()) {
if (attribute_id.is_anonymous()) {
return false;
}
const StringRef name = attribute_id.name();
@ -345,7 +345,7 @@ inline bool is_builtin(const void * /*owner*/, const AttributeIDRef &attribute_i
template<const ComponentAttributeProviders &providers>
inline GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
{
if (attribute_id.is_named()) {
if (!attribute_id.is_anonymous()) {
const StringRef name = attribute_id.name();
if (const BuiltinAttributeProvider *provider =
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
@ -395,7 +395,7 @@ template<const ComponentAttributeProviders &providers>
inline AttributeValidator lookup_validator(const void * /*owner*/,
const blender::bke::AttributeIDRef &attribute_id)
{
if (!attribute_id.is_named()) {
if (attribute_id.is_anonymous()) {
return {};
}
const BuiltinAttributeProvider *provider =
@ -442,7 +442,7 @@ inline std::optional<AttributeMetaData> lookup_meta_data(const void *owner,
template<const ComponentAttributeProviders &providers>
inline GAttributeWriter lookup_for_write(void *owner, const AttributeIDRef &attribute_id)
{
if (attribute_id.is_named()) {
if (!attribute_id.is_anonymous()) {
const StringRef name = attribute_id.name();
if (const BuiltinAttributeProvider *provider =
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
@ -461,7 +461,7 @@ inline GAttributeWriter lookup_for_write(void *owner, const AttributeIDRef &attr
template<const ComponentAttributeProviders &providers>
inline bool remove(void *owner, const AttributeIDRef &attribute_id)
{
if (attribute_id.is_named()) {
if (!attribute_id.is_anonymous()) {
const StringRef name = attribute_id.name();
if (const BuiltinAttributeProvider *provider =
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
@ -486,7 +486,7 @@ inline bool add(void *owner,
if (contains<providers>(owner, attribute_id)) {
return false;
}
if (attribute_id.is_named()) {
if (!attribute_id.is_anonymous()) {
const StringRef name = attribute_id.name();
if (const BuiltinAttributeProvider *provider =
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {

View File

@ -407,7 +407,7 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
/* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
SWAP(IDProperty *, id_new->properties, id_old->properties);
std::swap(id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_BR = {

View File

@ -237,7 +237,7 @@ static void mesh_faces_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MFace *face = data->face + index;
const float *t0, *t1, *t2, *t3;
@ -272,7 +272,7 @@ static void mesh_looptri_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
positions[data->corner_verts[lt->tri[0]]],
@ -333,7 +333,7 @@ static void mesh_faces_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MFace *face = &data->face[index];
const float *t0, *t1, *t2, *t3;
@ -372,7 +372,7 @@ static void mesh_looptri_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
positions[data->corner_verts[lt->tri[0]]],
@ -442,7 +442,7 @@ static void mesh_edges_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MEdge *edge = data->edge + index;
float nearest_tmp[3], dist_sq;
@ -507,7 +507,7 @@ static void mesh_verts_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float *v = data->positions[index];
const float *v = data->vert_positions[index];
mesh_verts_spherecast_do(index, v, ray, hit);
}
@ -524,7 +524,7 @@ static void mesh_edges_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->positions;
const float(*positions)[3] = data->vert_positions;
const MEdge *edge = &data->edge[index];
const float radius_sq = square_f(ray->radius);
@ -586,7 +586,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->tree = tree;
r_data->positions = reinterpret_cast<const float(*)[3]>(positions);
r_data->vert_positions = positions;
r_data->edge = edge;
r_data->face = face;
r_data->corner_verts = corner_verts;

View File

@ -1119,6 +1119,9 @@ float BKE_camera_multiview_shift_x(const RenderData *rd,
if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
return data->shiftx;
}
if (data->type == CAM_PANO) {
return data->shiftx;
}
/* SCE_VIEWS_SETUP_BASIC */
return camera_stereo3d_shift_x(camera, viewname);
}

View File

@ -461,7 +461,7 @@ void cloth_free_modifier(ClothModifierData *clmd)
BLI_bvhtree_free(cloth->bvhtree);
}
if (cloth->bvhselftree) {
if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
BLI_bvhtree_free(cloth->bvhselftree);
}
@ -538,7 +538,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd)
BLI_bvhtree_free(cloth->bvhtree);
}
if (cloth->bvhselftree) {
if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
BLI_bvhtree_free(cloth->bvhselftree);
}
@ -821,7 +821,14 @@ static bool cloth_from_object(
}
clmd->clothObject->bvhtree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->epsilon);
clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon);
if (compare_ff(clmd->coll_parms->selfepsilon, clmd->coll_parms->epsilon, 1e-6f)) {
/* Share the BVH tree if the epsilon is the same. */
clmd->clothObject->bvhselftree = clmd->clothObject->bvhtree;
}
else {
clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon);
}
return true;
}
@ -1391,7 +1398,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
float co[3], no[3], new_co[3];
float radius;
copy_v3_v3(co, treedata->positions[v_idx]);
copy_v3_v3(co, treedata->vert_positions[v_idx]);
negate_v3_v3(no, vert_normals[v_idx]);
float vec_len = sin(max_diversion);

View File

@ -670,7 +670,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
const bool is_hair = (clmd->hairdata != NULL);
for (int i = 0; i < collision_count; i++, collpair++) {
float i1[3], i2[3], i3[3];
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
zero_v3(i1);
zero_v3(i2);
@ -682,23 +681,13 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
}
/* Compute barycentric coordinates and relative "velocity" for both collision points. */
float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
if (is_hair) {
w2 = line_point_factor_v3(
collpair->pa, cloth->verts[collpair->ap1].tx, cloth->verts[collpair->ap2].tx);
w1 = 1.0f - w2;
interp_v3_v3v3(v1, cloth->verts[collpair->ap1].tv, cloth->verts[collpair->ap2].tv, w2);
}
else {
collision_compute_barycentric(collpair->pa,
cloth->verts[collpair->ap1].tx,
cloth->verts[collpair->ap2].tx,
cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_interpolateOnTriangle(v1,
cloth->verts[collpair->ap1].tv,
cloth->verts[collpair->ap2].tv,
@ -708,14 +697,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
w3);
}
collision_compute_barycentric(collpair->pb,
collmd->current_xnew[collpair->bp1],
collmd->current_xnew[collpair->bp2],
collmd->current_xnew[collpair->bp3],
&u1,
&u2,
&u3);
collision_interpolateOnTriangle(v2,
collmd->current_v[collpair->bp1],
collmd->current_v[collpair->bp2],
@ -834,7 +815,6 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
for (int i = 0; i < collision_count; i++, collpair++) {
float ia[3][3] = {{0.0f}};
float ib[3][3] = {{0.0f}};
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
/* Only handle static collisions here. */
@ -842,22 +822,9 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
continue;
}
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(collpair->pa,
cloth->verts[collpair->ap1].tx,
cloth->verts[collpair->ap2].tx,
cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_compute_barycentric(collpair->pb,
cloth->verts[collpair->bp1].tx,
cloth->verts[collpair->bp2].tx,
cloth->verts[collpair->bp3].tx,
&u1,
&u2,
&u3);
/* Retrieve barycentric coordinates for both collision points. */
float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
/* Calculate relative "velocity". */
collision_interpolateOnTriangle(v1,
@ -1053,6 +1020,23 @@ static void cloth_collision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(pa,
verts1[tri_a->tri[0]].tx,
verts1[tri_a->tri[1]].tx,
verts1[tri_a->tri[2]].tx,
&collpair[index].aw1,
&collpair[index].aw2,
&collpair[index].aw3);
collision_compute_barycentric(pb,
collmd->current_xnew[tri_b->tri[0]],
collmd->current_xnew[tri_b->tri[1]],
collmd->current_xnew[tri_b->tri[2]],
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1115,8 +1099,15 @@ static void cloth_selfcollision(void *__restrict userdata,
float epsilon = clmd->coll_parms->selfepsilon;
float pa[3], pb[3], vect[3];
tri_a = &clmd->clothObject->tri[data->overlap[index].indexA];
tri_b = &clmd->clothObject->tri[data->overlap[index].indexB];
/* Collision math is currently not symmetric, so ensure a stable order for each pair. */
int indexA = data->overlap[index].indexA, indexB = data->overlap[index].indexB;
if (indexA > indexB) {
SWAP(int, indexA, indexB);
}
tri_a = &clmd->clothObject->tri[indexA];
tri_b = &clmd->clothObject->tri[indexB];
BLI_assert(cloth_bvh_selfcollision_is_active(clmd, clmd->clothObject, tri_a, tri_b));
@ -1152,6 +1143,23 @@ static void cloth_selfcollision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(pa,
verts1[tri_a->tri[0]].tx,
verts1[tri_a->tri[1]].tx,
verts1[tri_a->tri[2]].tx,
&collpair[index].aw1,
&collpair[index].aw2,
&collpair[index].aw3);
collision_compute_barycentric(pb,
verts1[tri_b->tri[0]].tx,
verts1[tri_b->tri[1]].tx,
verts1[tri_b->tri[2]].tx,
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1210,6 +1218,20 @@ static void hair_collision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for the collision points. */
collpair[index].aw2 = line_point_factor_v3(
pa, verts1[edge_coll->v1].tx, verts1[edge_coll->v2].tx);
collpair[index].aw1 = 1.0f - collpair[index].aw2;
collision_compute_barycentric(pb,
collmd->current_xnew[tri_coll->tri[0]],
collmd->current_xnew[tri_coll->tri[1]],
collmd->current_xnew[tri_coll->tri[2]],
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1521,8 +1543,9 @@ static bool cloth_bvh_obj_overlap_cb(void *userdata,
static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
{
/* No need for equal combinations (eg. (0,1) & (1,0)). */
if (index_a < index_b) {
/* This shouldn't happen, but just in case. Note that equal combinations
* (eg. (0,1) & (1,0)) would be filtered out by BLI_bvhtree_overlap_self. */
if (index_a != index_b) {
ClothModifierData *clmd = (ClothModifierData *)userdata;
struct Cloth *clothObject = clmd->clothObject;
const MVertTri *tri_a, *tri_b;
@ -1551,6 +1574,7 @@ int cloth_bvh_collision(
BVHTreeOverlap **overlap_obj = NULL;
uint coll_count_self = 0;
BVHTreeOverlap *overlap_self = NULL;
bool bvh_updated = false;
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh == NULL) {
return 0;
@ -1561,6 +1585,7 @@ int cloth_bvh_collision(
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
bvhtree_update_from_cloth(clmd, false, false);
bvh_updated = true;
/* Enable self collision if this is a hair sim */
const bool is_hair = (clmd->hairdata != NULL);
@ -1597,10 +1622,12 @@ int cloth_bvh_collision(
}
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) {
bvhtree_update_from_cloth(clmd, false, true);
if (cloth->bvhselftree != cloth->bvhtree || !bvh_updated) {
bvhtree_update_from_cloth(clmd, false, true);
}
overlap_self = BLI_bvhtree_overlap(
cloth->bvhselftree, cloth->bvhselftree, &coll_count_self, cloth_bvh_self_overlap_cb, clmd);
overlap_self = BLI_bvhtree_overlap_self(
cloth->bvhselftree, &coll_count_self, cloth_bvh_self_overlap_cb, clmd);
}
do {

View File

@ -28,6 +28,8 @@ BLI_CPP_TYPE_MAKE(Material *, CPPTypeFlags::BasicType)
BLI_CPP_TYPE_MAKE(MStringProperty, CPPTypeFlags::None);
BLI_CPP_TYPE_MAKE(blender::bke::AnonymousAttributeSet, CPPTypeFlags::None);
void BKE_cpp_types_init()
{
blender::register_cpp_types();
@ -45,4 +47,6 @@ void BKE_cpp_types_init()
BLI_CPP_TYPE_REGISTER(Material *);
BLI_CPP_TYPE_REGISTER(MStringProperty);
BLI_CPP_TYPE_REGISTER(blender::bke::AnonymousAttributeSet);
}

View File

@ -16,7 +16,7 @@
#include "BLI_ghash.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -704,7 +704,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
*newnu = blender::dna::shallow_copy(*src);
if (pntsu == 1) {
SWAP(int, pntsu, pntsv);
std::swap(pntsu, pntsv);
}
newnu->pntsu = pntsu;
newnu->pntsv = pntsv;
@ -3048,7 +3048,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bevp2 = bevp1 + (bl->nr - 1);
nr = bl->nr / 2;
while (nr--) {
SWAP(BevPoint, *bevp1, *bevp2);
std::swap( *bevp1, *bevp2);
bevp1++;
bevp2--;
}
@ -4437,7 +4437,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (a > 0) {
if (bezt1 != bezt2) {
SWAP(BezTriple, *bezt1, *bezt2);
std::swap(*bezt1, *bezt2);
}
swap_v3_v3(bezt1->vec[0], bezt1->vec[2]);
@ -4446,12 +4446,12 @@ void BKE_nurb_direction_switch(Nurb *nu)
swap_v3_v3(bezt2->vec[0], bezt2->vec[2]);
}
SWAP(uint8_t, bezt1->h1, bezt1->h2);
SWAP(uint8_t, bezt1->f1, bezt1->f3);
std::swap( bezt1->h1, bezt1->h2);
std::swap( bezt1->f1, bezt1->f3);
if (bezt1 != bezt2) {
SWAP(uint8_t, bezt2->h1, bezt2->h2);
SWAP(uint8_t, bezt2->f1, bezt2->f3);
std::swap( bezt2->h1, bezt2->h2);
std::swap( bezt2->f1, bezt2->f3);
bezt1->tilt = -bezt1->tilt;
bezt2->tilt = -bezt2->tilt;
}
@ -4469,7 +4469,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
bp2 = bp1 + (a - 1);
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap( *bp1, *bp2);
a--;
bp1->tilt = -bp1->tilt;
bp2->tilt = -bp2->tilt;
@ -4491,7 +4491,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
fp2 = fp1 + (a - 1);
a /= 2;
while (fp1 != fp2 && a > 0) {
SWAP(float, *fp1, *fp2);
std::swap( *fp1, *fp2);
a--;
fp1++;
fp2--;
@ -4530,7 +4530,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap( *bp1, *bp2);
a--;
bp1++;
bp2--;

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
#include "BLI_devirtualize_parameters.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"
@ -328,18 +327,19 @@ static eAttrDomain get_attribute_domain_for_mesh(const AttributeAccessor &mesh_a
static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attributes,
const AttributeAccessor &mesh_attributes,
const AttributeIDRef &id,
const AttributeMetaData &meta_data)
const AttributeMetaData &meta_data,
const AnonymousAttributePropagationInfo &propagation_info)
{
/* The position attribute has special non-generic evaluation. */
if (id.is_named() && id.name() == "position") {
if (id.name() == "position") {
return false;
}
/* Don't propagate built-in curves attributes that are not built-in on meshes. */
if (curve_attributes.is_builtin(id) && !mesh_attributes.is_builtin(id)) {
return false;
}
if (!id.should_be_kept()) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return false;
}
if (meta_data.data_type == CD_PROP_STRING) {
@ -626,7 +626,8 @@ static void copy_curve_domain_attribute_to_mesh(const ResultOffsets &mesh_offset
Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
const CurvesGeometry &profile,
const bool fill_caps)
const bool fill_caps,
const AnonymousAttributePropagationInfo &propagation_info)
{
const CurvesInfo curves_info = get_curves_info(main, profile);
@ -715,7 +716,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
main_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
if (!should_add_attribute_to_mesh(main_attributes, mesh_attributes, id, meta_data)) {
if (!should_add_attribute_to_mesh(
main_attributes, mesh_attributes, id, meta_data, propagation_info)) {
return true;
}
main_attributes_set.add_new(id);
@ -752,7 +754,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
if (main_attributes.contains(id)) {
return true;
}
if (!should_add_attribute_to_mesh(profile_attributes, mesh_attributes, id, meta_data)) {
if (!should_add_attribute_to_mesh(
profile_attributes, mesh_attributes, id, meta_data, propagation_info)) {
return true;
}
const eAttrDomain src_domain = meta_data.domain;
@ -796,10 +799,11 @@ static CurvesGeometry get_curve_single_vert()
return curves;
}
Mesh *curve_to_wire_mesh(const CurvesGeometry &curve)
Mesh *curve_to_wire_mesh(const CurvesGeometry &curve,
const AnonymousAttributePropagationInfo &propagation_info)
{
static const CurvesGeometry vert_curve = get_curve_single_vert();
return curve_to_mesh_sweep(curve, vert_curve, false);
return curve_to_mesh_sweep(curve, vert_curve, false, propagation_info);
}
} // namespace blender::bke

View File

@ -1047,8 +1047,10 @@ static Array<int> build_point_to_curve_map(const CurvesGeometry &curves)
return point_to_curve_map;
}
static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
const IndexMask points_to_delete)
static CurvesGeometry copy_with_removed_points(
const CurvesGeometry &curves,
const IndexMask points_to_delete,
const AnonymousAttributePropagationInfo &propagation_info)
{
/* Use a map from points to curves to facilitate using an #IndexMask input. */
const Array<int> point_to_curve_map = build_point_to_curve_map(curves);
@ -1093,9 +1095,15 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
CurvesGeometry new_curves{new_point_count, new_curve_count};
Vector<bke::AttributeTransferData> point_attributes = bke::retrieve_attributes_for_transfer(
curves.attributes(), new_curves.attributes_for_write(), ATTR_DOMAIN_MASK_POINT);
curves.attributes(),
new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_POINT,
propagation_info);
Vector<bke::AttributeTransferData> curve_attributes = bke::retrieve_attributes_for_transfer(
curves.attributes(), new_curves.attributes_for_write(), ATTR_DOMAIN_MASK_CURVE);
curves.attributes(),
new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_CURVE,
propagation_info);
threading::parallel_invoke(
256 < new_point_count * new_curve_count,
@ -1144,7 +1152,8 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
return new_curves;
}
void CurvesGeometry::remove_points(const IndexMask points_to_delete)
void CurvesGeometry::remove_points(const IndexMask points_to_delete,
const AnonymousAttributePropagationInfo &propagation_info)
{
if (points_to_delete.is_empty()) {
return;
@ -1152,11 +1161,13 @@ void CurvesGeometry::remove_points(const IndexMask points_to_delete)
if (points_to_delete.size() == this->points_num()) {
*this = {};
}
*this = copy_with_removed_points(*this, points_to_delete);
*this = copy_with_removed_points(*this, points_to_delete, propagation_info);
}
static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
const IndexMask curves_to_delete)
static CurvesGeometry copy_with_removed_curves(
const CurvesGeometry &curves,
const IndexMask curves_to_delete,
const AnonymousAttributePropagationInfo &propagation_info)
{
const Span<int> old_offsets = curves.offsets();
const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert(
@ -1178,9 +1189,15 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
CurvesGeometry new_curves{new_tot_points, new_tot_curves};
Vector<bke::AttributeTransferData> point_attributes = bke::retrieve_attributes_for_transfer(
curves.attributes(), new_curves.attributes_for_write(), ATTR_DOMAIN_MASK_POINT);
curves.attributes(),
new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_POINT,
propagation_info);
Vector<bke::AttributeTransferData> curve_attributes = bke::retrieve_attributes_for_transfer(
curves.attributes(), new_curves.attributes_for_write(), ATTR_DOMAIN_MASK_CURVE);
curves.attributes(),
new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_CURVE,
propagation_info);
threading::parallel_invoke(
256 < new_tot_points * new_tot_curves,
@ -1251,7 +1268,8 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
return new_curves;
}
void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
void CurvesGeometry::remove_curves(const IndexMask curves_to_delete,
const AnonymousAttributePropagationInfo &propagation_info)
{
if (curves_to_delete.is_empty()) {
return;
@ -1260,7 +1278,7 @@ void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
*this = {};
return;
}
*this = copy_with_removed_curves(*this, curves_to_delete);
*this = copy_with_removed_curves(*this, curves_to_delete, propagation_info);
}
template<typename T>
@ -1315,7 +1333,7 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_named() && bezier_handle_names.contains(id.name())) {
if (bezier_handle_names.contains(id.name())) {
return true;
}

Some files were not shown because too many files have changed in this diff Show More