Mesh: Replace MLoop struct with generic attributes #104424

Merged
Hans Goudey merged 261 commits from refactor-mesh-corners-generic into main 2023-03-20 15:55:25 +01:00
181 changed files with 3446 additions and 3250 deletions
Showing only changes of commit 932a211f6c - Show all commits

View File

@ -399,6 +399,26 @@ mark_as_advanced(WITH_SYSTEM_GLOG)
# Freestyle # Freestyle
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# Libraries.
if(UNIX AND NOT APPLE)
# Optionally build without pre-compiled libraries.
# NOTE: this could be supported on all platforms however in practice UNIX is the only platform
# that has good support for detecting installed libraries.
option(WITH_LIBS_PRECOMPILED "\
Detect and link against pre-compiled libraries (typically found under \"../lib/\"). \
Disabling this option will use the system libraries although cached paths \
that point to pre-compiled libraries will be left as-is."
ON
)
mark_as_advanced(WITH_LIBS_PRECOMPILED)
option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF)
if(WITH_STATIC_LIBS)
option(WITH_BOOST_ICU "Boost uses ICU library (required for linking with static Boost built with libicu)." OFF)
mark_as_advanced(WITH_BOOST_ICU)
endif()
endif()
# Misc # Misc
if(WIN32 OR APPLE) if(WIN32 OR APPLE)
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON) option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
@ -406,11 +426,6 @@ endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) option(WITH_INSTALL_PORTABLE "Install redistributable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF)
if(WITH_STATIC_LIBS)
option(WITH_BOOST_ICU "Boost uses ICU library (required for linking with static Boost built with libicu)." OFF)
mark_as_advanced(WITH_BOOST_ICU)
endif()
endif() endif()
option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON) option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON)
@ -993,6 +1008,8 @@ set(PLATFORM_LINKLIBS "")
# - CMAKE_EXE_LINKER_FLAGS_DEBUG # - CMAKE_EXE_LINKER_FLAGS_DEBUG
set(PLATFORM_LINKFLAGS "") set(PLATFORM_LINKFLAGS "")
set(PLATFORM_LINKFLAGS_DEBUG "") set(PLATFORM_LINKFLAGS_DEBUG "")
set(PLATFORM_LINKFLAGS_RELEASE "")
set(PLATFORM_LINKFLAGS_EXECUTABLE "")
if(NOT CMAKE_BUILD_TYPE MATCHES "Release") if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
if(WITH_COMPILER_ASAN) if(WITH_COMPILER_ASAN)
@ -1262,12 +1279,14 @@ endif()
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Configure Bullet # Configure Bullet
if(WITH_BULLET AND WITH_SYSTEM_BULLET) if(WITH_BULLET)
find_package(Bullet) if(WITH_SYSTEM_BULLET)
set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET) find_package(Bullet)
else() set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET)
set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src") else()
# set(BULLET_LIBRARIES "") set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
set(BULLET_LIBRARIES "extern_bullet")
endif()
endif() endif()

View File

@ -29,7 +29,7 @@ elseif(UNIX)
set(USD_PLATFORM_FLAGS set(USD_PLATFORM_FLAGS
-DPYTHON_INCLUDE_DIR=${LIBDIR}/python/include/python${PYTHON_SHORT_VERSION}/ -DPYTHON_INCLUDE_DIR=${LIBDIR}/python/include/python${PYTHON_SHORT_VERSION}/
-DPYTHON_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${SHAREDLIBEXT} -DPYTHON_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${SHAREDLIBEXT}
) )
if(APPLE) if(APPLE)
set(USD_SHARED_LINKER_FLAGS "-Xlinker -undefined -Xlinker dynamic_lookup") set(USD_SHARED_LINKER_FLAGS "-Xlinker -undefined -Xlinker dynamic_lookup")

View File

@ -19,9 +19,13 @@ ENDIF()
SET(_moltenvk_SEARCH_DIRS SET(_moltenvk_SEARCH_DIRS
${MOLTENVK_ROOT_DIR} ${MOLTENVK_ROOT_DIR}
${LIBDIR}/vulkan/MoltenVK
) )
# FIXME: These finder modules typically don't use LIBDIR,
# this should be set by `./build_files/cmake/platform/` instead.
IF(DEFINED LIBDIR)
SET(_moltenvk_SEARCH_DIRS ${_moltenvk_SEARCH_DIRS} ${LIBDIR}/vulkan/MoltenVK)
ENDIF()
FIND_PATH(MOLTENVK_INCLUDE_DIR FIND_PATH(MOLTENVK_INCLUDE_DIR
NAMES NAMES

View File

@ -17,9 +17,13 @@ ENDIF()
SET(_optix_SEARCH_DIRS SET(_optix_SEARCH_DIRS
${OPTIX_ROOT_DIR} ${OPTIX_ROOT_DIR}
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0"
) )
# TODO: Which environment uses this?
if(DEFINED ENV{PROGRAMDATA})
list(APPEND _optix_SEARCH_DIRS "$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0")
endif()
FIND_PATH(OPTIX_INCLUDE_DIR FIND_PATH(OPTIX_INCLUDE_DIR
NAMES NAMES
optix.h optix.h

View File

@ -67,6 +67,8 @@ ENDIF()
STRING(REPLACE "." "" PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) STRING(REPLACE "." "" PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
SET(_PYTHON_ABI_FLAGS "")
SET(_python_SEARCH_DIRS SET(_python_SEARCH_DIRS
${PYTHON_ROOT_DIR} ${PYTHON_ROOT_DIR}
"$ENV{HOME}/py${PYTHON_VERSION_NO_DOTS}" "$ENV{HOME}/py${PYTHON_VERSION_NO_DOTS}"

View File

@ -6,18 +6,80 @@
import re import re
import sys import sys
from typing import Optional
cmakelists_file = sys.argv[-1] cmakelists_file = sys.argv[-1]
def main(): def count_backslashes_before_pos(file_data: str, pos: int) -> int:
slash_count = 0
pos -= 1
while pos >= 0:
if file_data[pos] != '\\':
break
pos -= 1
slash_count += 1
return slash_count
def extract_cmake_string_at_pos(file_data: str, pos_beg: int) -> Optional[str]:
assert file_data[pos_beg - 1] == '"'
pos = pos_beg
# Dummy assignment.
pos_end = pos_beg
while True:
pos_next = file_data.find('"', pos)
if pos_next == -1:
raise Exception("Un-terminated string (parse error?)")
count_slashes = count_backslashes_before_pos(file_data, pos_next)
if (count_slashes % 2) == 0:
pos_end = pos_next
# Found the closing quote.
break
# The quote was back-slash escaped, step over it.
pos = pos_next + 1
file_data[pos_next]
assert file_data[pos_end] == '"'
if pos_beg == pos_end:
return None
# See: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#escape-sequences
text = file_data[pos_beg: pos_end].replace(
# Handle back-slash literals.
"\\\\", "\\",
).replace(
# Handle tabs.
"\\t", "\t",
).replace(
# Handle escaped quotes.
"\\\"", "\"",
).replace(
# Handle tabs.
"\\;", ";",
).replace(
# Handle trailing newlines.
"\\\n", "",
)
return text
def main() -> None:
options = [] options = []
for l in open(cmakelists_file, 'r').readlines(): with open(cmakelists_file, 'r', encoding="utf-8") as fh:
if not l.lstrip().startswith('#'): file_data = fh.read()
l_option = re.sub(r'.*\boption\s*\(\s*(WITH_[a-zA-Z0-9_]+)\s+\"(.*)\"\s*.*', r'\g<1> - \g<2>', l) for m in re.finditer(r"^\s*option\s*\(\s*(WITH_[a-zA-Z0-9_]+)\s+(\")", file_data, re.MULTILINE):
if l_option != l: option_name = m.group(1)
l_option = l_option.strip() option_descr = extract_cmake_string_at_pos(file_data, m.span(2)[1])
if l_option.startswith('WITH_'): if option_descr is None:
options.append(l_option) # Possibly a parsing error, at least show something.
option_descr = "(UNDOCUMENTED)"
options.append("{:s}: {:s}".format(option_name, option_descr))
print('\n'.join(options)) print('\n'.join(options))

View File

@ -550,7 +550,9 @@ function(setup_platform_linker_libs
endif() endif()
if(WIN32 AND NOT UNIX) if(WIN32 AND NOT UNIX)
target_link_libraries(${target} ${PTHREADS_LIBRARIES}) if(DEFINED PTHREADS_LIBRARIES)
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
endif()
endif() endif()
# target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS}) # target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
@ -1115,7 +1117,7 @@ function(find_python_package
# endif() # endif()
# Not set, so initialize. # Not set, so initialize.
else() else()
string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}") string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}")
list(GET _PY_VER_SPLIT 0 _PY_VER_MAJOR) list(GET _PY_VER_SPLIT 0 _PY_VER_MAJOR)
# re-cache # re-cache
@ -1262,7 +1264,7 @@ endmacro()
# Utility to gather and install precompiled shared libraries. # Utility to gather and install precompiled shared libraries.
macro(add_bundled_libraries library_dir) macro(add_bundled_libraries library_dir)
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
set(_library_dir ${LIBDIR}/${library_dir}) set(_library_dir ${LIBDIR}/${library_dir})
if(WIN32) if(WIN32)
file(GLOB _all_library_versions ${_library_dir}/*\.dll) file(GLOB _all_library_versions ${_library_dir}/*\.dll)
@ -1275,7 +1277,7 @@ macro(add_bundled_libraries library_dir)
list(APPEND PLATFORM_BUNDLED_LIBRARY_DIRS ${_library_dir}) list(APPEND PLATFORM_BUNDLED_LIBRARY_DIRS ${_library_dir})
unset(_all_library_versions) unset(_all_library_versions)
unset(_library_dir) unset(_library_dir)
endif() endif()
endmacro() endmacro()
macro(windows_install_shared_manifest) macro(windows_install_shared_manifest)

View File

@ -1,7 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2022 Blender Foundation. All rights reserved. # Copyright 2022 Blender Foundation. All rights reserved.
# Auto update existing CMake caches for new libraries # Auto update existing CMake caches for new libraries.
# Assert that `LIBDIR` is defined.
if(NOT (DEFINED LIBDIR))
message(FATAL_ERROR "Logical error, expected 'LIBDIR' to be defined!")
endif()
# Clear cached variables whose name matches `pattern`. # Clear cached variables whose name matches `pattern`.
function(unset_cache_variables pattern) function(unset_cache_variables pattern)

View File

@ -4,38 +4,52 @@
# Libraries configuration for any *nix system including Linux and Unix (excluding APPLE). # Libraries configuration for any *nix system including Linux and Unix (excluding APPLE).
# Detect precompiled library directory # Detect precompiled library directory
if(NOT DEFINED LIBDIR)
# Path to a locally compiled libraries.
set(LIBDIR_NAME ${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_PROCESSOR})
string(TOLOWER ${LIBDIR_NAME} LIBDIR_NAME)
set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
# Path to precompiled libraries with known glibc 2.28 ABI. if(NOT WITH_LIBS_PRECOMPILED)
set(LIBDIR_GLIBC228_ABI ${CMAKE_SOURCE_DIR}/../lib/linux_x86_64_glibc_228) unset(LIBDIR)
else()
if(NOT DEFINED LIBDIR)
# Path to a locally compiled libraries.
set(LIBDIR_NAME ${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_PROCESSOR})
string(TOLOWER ${LIBDIR_NAME} LIBDIR_NAME)
set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
# Choose the best suitable libraries. # Path to precompiled libraries with known glibc 2.28 ABI.
if(EXISTS ${LIBDIR_NATIVE_ABI}) set(LIBDIR_GLIBC228_ABI ${CMAKE_SOURCE_DIR}/../lib/linux_x86_64_glibc_228)
set(LIBDIR ${LIBDIR_NATIVE_ABI})
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True) # Choose the best suitable libraries.
elseif(EXISTS ${LIBDIR_GLIBC228_ABI}) if(EXISTS ${LIBDIR_NATIVE_ABI})
set(LIBDIR ${LIBDIR_GLIBC228_ABI}) set(LIBDIR ${LIBDIR_NATIVE_ABI})
if(WITH_MEM_JEMALLOC)
# jemalloc provides malloc hooks.
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND False)
else()
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True) set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True)
elseif(EXISTS ${LIBDIR_GLIBC228_ABI})
set(LIBDIR ${LIBDIR_GLIBC228_ABI})
if(WITH_MEM_JEMALLOC)
# jemalloc provides malloc hooks.
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND False)
else()
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True)
endif()
endif() endif()
# Avoid namespace pollustion.
unset(LIBDIR_NATIVE_ABI)
unset(LIBDIR_GLIBC228_ABI)
endif() endif()
# Avoid namespace pollustion. if(NOT (EXISTS ${LIBDIR}))
unset(LIBDIR_NATIVE_ABI) message(STATUS
unset(LIBDIR_GLIBC228_ABI) "Unable to find LIBDIR: ${LIBDIR}, system libraries may be used "
"(disable WITH_LIBS_PRECOMPILED to suppress this message)."
)
unset(LIBDIR)
endif()
endif() endif()
# Support restoring this value once pre-compiled libraries have been handled. # Support restoring this value once pre-compiled libraries have been handled.
set(WITH_STATIC_LIBS_INIT ${WITH_STATIC_LIBS}) set(WITH_STATIC_LIBS_INIT ${WITH_STATIC_LIBS})
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
file(GLOB LIB_SUBDIRS ${LIBDIR}/*) file(GLOB LIB_SUBDIRS ${LIBDIR}/*)
@ -85,7 +99,7 @@ endmacro()
# These are libraries that may be precompiled. For this we disable searching in # These are libraries that may be precompiled. For this we disable searching in
# the system directories so that we don't accidentally use them instead. # the system directories so that we don't accidentally use them instead.
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
without_system_libs_begin() without_system_libs_begin()
endif() endif()
@ -114,7 +128,7 @@ endfunction()
if(NOT WITH_SYSTEM_FREETYPE) if(NOT WITH_SYSTEM_FREETYPE)
# FreeType compiled with Brotli compression for woff2. # FreeType compiled with Brotli compression for woff2.
find_package_wrapper(Freetype REQUIRED) find_package_wrapper(Freetype REQUIRED)
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
find_package_wrapper(Brotli REQUIRED) find_package_wrapper(Brotli REQUIRED)
# NOTE: This is done on WIN32 & APPLE but fails on some Linux systems. # NOTE: This is done on WIN32 & APPLE but fails on some Linux systems.
@ -141,7 +155,7 @@ if(WITH_PYTHON)
if(WITH_PYTHON_MODULE AND NOT WITH_INSTALL_PORTABLE) if(WITH_PYTHON_MODULE AND NOT WITH_INSTALL_PORTABLE)
# Installing into `site-packages`, warn when installing into `./../lib/` # Installing into `site-packages`, warn when installing into `./../lib/`
# which script authors almost certainly don't want. # which script authors almost certainly don't want.
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
path_is_prefix(LIBDIR PYTHON_SITE_PACKAGES _is_prefix) path_is_prefix(LIBDIR PYTHON_SITE_PACKAGES _is_prefix)
if(_is_prefix) if(_is_prefix)
message(WARNING " message(WARNING "
@ -217,7 +231,7 @@ if(WITH_CODEC_SNDFILE)
endif() endif()
if(WITH_CODEC_FFMPEG) if(WITH_CODEC_FFMPEG)
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg) set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg)
# Override FFMPEG components to also include static library dependencies # Override FFMPEG components to also include static library dependencies
# included with precompiled libraries, and to ensure correct link order. # included with precompiled libraries, and to ensure correct link order.
@ -232,7 +246,7 @@ if(WITH_CODEC_FFMPEG)
vpx vpx
x264 x264
xvidcore) xvidcore)
if(EXISTS ${LIBDIR}/ffmpeg/lib/libaom.a) if((DEFINED LIBDIR) AND (EXISTS ${LIBDIR}/ffmpeg/lib/libaom.a))
list(APPEND FFMPEG_FIND_COMPONENTS aom) list(APPEND FFMPEG_FIND_COMPONENTS aom)
endif() endif()
elseif(FFMPEG) elseif(FFMPEG)
@ -430,10 +444,13 @@ if(WITH_OPENIMAGEIO)
${PNG_LIBRARIES} ${PNG_LIBRARIES}
${JPEG_LIBRARIES} ${JPEG_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${BOOST_LIBRARIES}
) )
set(OPENIMAGEIO_DEFINITIONS "") set(OPENIMAGEIO_DEFINITIONS "")
if(WITH_BOOST)
list(APPEND OPENIMAGEIO_LIBRARIES "${BOOST_LIBRARIES}")
endif()
if(WITH_IMAGE_TIFF) if(WITH_IMAGE_TIFF)
list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}") list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}")
endif() endif()
@ -451,7 +468,7 @@ add_bundled_libraries(openimageio/lib)
if(WITH_OPENCOLORIO) if(WITH_OPENCOLORIO)
find_package_wrapper(OpenColorIO 2.0.0) find_package_wrapper(OpenColorIO 2.0.0)
set(OPENCOLORIO_DEFINITIONS) set(OPENCOLORIO_DEFINITIONS "")
set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO) set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO)
endif() endif()
add_bundled_libraries(opencolorio/lib) add_bundled_libraries(opencolorio/lib)
@ -466,7 +483,7 @@ if(WITH_OPENIMAGEDENOISE)
endif() endif()
if(WITH_LLVM) if(WITH_LLVM)
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
set(LLVM_STATIC ON) set(LLVM_STATIC ON)
endif() endif()
@ -480,7 +497,7 @@ if(WITH_LLVM)
endif() endif()
# Symbol conflicts with same UTF library used by OpenCollada # Symbol conflicts with same UTF library used by OpenCollada
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0")) if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0"))
list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY})
endif() endif()
@ -536,7 +553,7 @@ if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
endif() endif()
endif() endif()
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
without_system_libs_end() without_system_libs_end()
endif() endif()
@ -551,9 +568,14 @@ else()
endif() endif()
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT}) # `FindThreads` documentation notes that this may be empty
# used by other platforms # with the system libraries provide threading functionality.
set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) if(CMAKE_THREAD_LIBS_INIT)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT})
# used by other platforms
set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif()
if(CMAKE_DL_LIBS) if(CMAKE_DL_LIBS)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS}) list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS})
@ -575,7 +597,7 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
# #
# Keep last, so indirectly linked libraries don't override our own pre-compiled libs. # Keep last, so indirectly linked libraries don't override our own pre-compiled libs.
if(EXISTS ${LIBDIR}) if(DEFINED LIBDIR)
# Clear the prefix path as it causes the `LIBDIR` to override system locations. # Clear the prefix path as it causes the `LIBDIR` to override system locations.
unset(CMAKE_PREFIX_PATH) unset(CMAKE_PREFIX_PATH)
@ -631,7 +653,7 @@ if(WITH_GHOST_WAYLAND)
# When dynamically linked WAYLAND is used and `${LIBDIR}/wayland` is present, # When dynamically linked WAYLAND is used and `${LIBDIR}/wayland` is present,
# there is no need to search for the libraries as they are not needed for building. # there is no need to search for the libraries as they are not needed for building.
# Only the headers are needed which can reference the known paths. # Only the headers are needed which can reference the known paths.
if(EXISTS "${LIBDIR}/wayland" AND WITH_GHOST_WAYLAND_DYNLOAD) if((DEFINED LIBDIR) AND (EXISTS "${LIBDIR}/wayland" AND WITH_GHOST_WAYLAND_DYNLOAD))
set(_use_system_wayland OFF) set(_use_system_wayland OFF)
else() else()
set(_use_system_wayland ON) set(_use_system_wayland ON)
@ -695,7 +717,7 @@ if(WITH_GHOST_WAYLAND)
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR) add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
endif() endif()
if(EXISTS "${LIBDIR}/wayland/bin/wayland-scanner") if((DEFINED LIBDIR) AND (EXISTS "${LIBDIR}/wayland/bin/wayland-scanner"))
set(WAYLAND_SCANNER "${LIBDIR}/wayland/bin/wayland-scanner") set(WAYLAND_SCANNER "${LIBDIR}/wayland/bin/wayland-scanner")
else() else()
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)

View File

@ -13,10 +13,12 @@ endif()
# Exporting functions from the blender binary gives linker warnings on Apple arm64 systems. # Exporting functions from the blender binary gives linker warnings on Apple arm64 systems.
# Silence them here. # Silence them here.
if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")) if(APPLE)
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
string(APPEND CMAKE_C_FLAGS " -fvisibility=hidden") if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
string(APPEND CMAKE_CXX_FLAGS " -fvisibility=hidden") string(APPEND CMAKE_C_FLAGS " -fvisibility=hidden")
string(APPEND CMAKE_CXX_FLAGS " -fvisibility=hidden")
endif()
endif() endif()
endif() endif()
@ -261,9 +263,11 @@ set(LIB
blender_add_lib(extern_mantaflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") blender_add_lib(extern_mantaflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# The VDB libs above are only added to as INTERFACE libs by blender_add_lib, if(WITH_OPENVDB)
# meaning extern_mantaflow itself actually does not have a dependency on the # The VDB libs above are only added to as INTERFACE libs by blender_add_lib,
# openvdb libraries, and CMAKE is free to link the vdb libs before # meaning extern_mantaflow itself actually does not have a dependency on the
# extern_mantaflow causing linker errors on linux. By explicitly declaring # openvdb libraries, and CMAKE is free to link the vdb libs before
# a dependency here, cmake will do the right thing. # extern_mantaflow causing linker errors on linux. By explicitly declaring
target_link_libraries(extern_mantaflow PRIVATE ${OPENVDB_LIBRARIES}) # a dependency here, cmake will do the right thing.
target_link_libraries(extern_mantaflow PRIVATE ${OPENVDB_LIBRARIES})
endif()

View File

@ -111,8 +111,10 @@ macro(cycles_external_libraries_append libraries)
endif() endif()
if(WITH_OPENIMAGEDENOISE) if(WITH_OPENIMAGEDENOISE)
list(APPEND ${libraries} ${OPENIMAGEDENOISE_LIBRARIES}) list(APPEND ${libraries} ${OPENIMAGEDENOISE_LIBRARIES})
if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64") if(APPLE)
list(APPEND ${libraries} "-framework Accelerate") if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
list(APPEND ${libraries} "-framework Accelerate")
endif()
endif() endif()
endif() endif()
if(WITH_ALEMBIC) if(WITH_ALEMBIC)
@ -136,7 +138,15 @@ macro(cycles_external_libraries_append libraries)
${PYTHON_LIBRARIES} ${PYTHON_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${CMAKE_DL_LIBS} ${CMAKE_DL_LIBS}
${PTHREADS_LIBRARIES} )
if(DEFINED PTHREADS_LIBRARIES)
list(APPEND ${libraries}
${PTHREADS_LIBRARIES}
)
endif()
list(APPEND ${libraries}
${PLATFORM_LINKLIBS} ${PLATFORM_LINKLIBS}
) )

View File

@ -327,10 +327,21 @@ void MetalDevice::make_source(MetalPipelineType pso_type, const uint kernel_feat
# define KERNEL_STRUCT_BEGIN(name, parent) \ # define KERNEL_STRUCT_BEGIN(name, parent) \
string_replace_same_length(source, "kernel_data." #parent ".", "kernel_data_" #parent "_"); string_replace_same_length(source, "kernel_data." #parent ".", "kernel_data_" #parent "_");
bool next_member_is_specialized = true;
# define KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE next_member_is_specialized = false;
/* Add constants to md5 so that 'get_best_pipeline' is able to return a suitable match. */ /* Add constants to md5 so that 'get_best_pipeline' is able to return a suitable match. */
# define KERNEL_STRUCT_MEMBER(parent, _type, name) \ # define KERNEL_STRUCT_MEMBER(parent, _type, name) \
baked_constants += string(#parent "." #name "=") + \ if (next_member_is_specialized) { \
to_string(_type(launch_params.data.parent.name)) + "\n"; baked_constants += string(#parent "." #name "=") + \
to_string(_type(launch_params.data.parent.name)) + "\n"; \
} \
else { \
string_replace( \
source, "kernel_data_" #parent "_" #name, "kernel_data." #parent ".__unused_" #name); \
next_member_is_specialized = true; \
}
# include "kernel/data_template.h" # include "kernel/data_template.h"

View File

@ -49,6 +49,18 @@ struct ShaderCache {
if (MetalInfo::get_device_vendor(mtlDevice) == METAL_GPU_APPLE) { if (MetalInfo::get_device_vendor(mtlDevice) == METAL_GPU_APPLE) {
switch (MetalInfo::get_apple_gpu_architecture(mtlDevice)) { switch (MetalInfo::get_apple_gpu_architecture(mtlDevice)) {
default: default:
case APPLE_M2_BIG:
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_STATES] = {384, 128};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INIT_FROM_CAMERA] = {640, 128};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST] = {1024, 64};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW] = {704, 704};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE] = {640, 32};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_QUEUED_PATHS_ARRAY] = {896, 768};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND] = {512, 128};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW] = {32, 32};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE] = {768, 576};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_SORTED_PATHS_ARRAY] = {896, 768};
break;
case APPLE_M2: case APPLE_M2:
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_STATES] = {32, 32}; occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_STATES] = {32, 32};
occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INIT_FROM_CAMERA] = {832, 32}; occupancy_tuning[DEVICE_KERNEL_INTEGRATOR_INIT_FROM_CAMERA] = {832, 32};
@ -448,13 +460,18 @@ static MTLFunctionConstantValues *GetConstantValues(KernelData const *data = nul
if (!data) { if (!data) {
data = &zero_data; data = &zero_data;
} }
int zero_int = 0; [constant_values setConstantValue:&zero_data type:MTLDataType_int atIndex:Kernel_DummyConstant];
[constant_values setConstantValue:&zero_int type:MTLDataType_int atIndex:Kernel_DummyConstant];
bool next_member_is_specialized = true;
# define KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE next_member_is_specialized = false;
# define KERNEL_STRUCT_MEMBER(parent, _type, name) \ # define KERNEL_STRUCT_MEMBER(parent, _type, name) \
[constant_values setConstantValue:&data->parent.name \ [constant_values setConstantValue:next_member_is_specialized ? (void *)&data->parent.name : \
(void *)&zero_data \
type:MTLDataType_##_type \ type:MTLDataType_##_type \
atIndex:KernelData_##parent##_##name]; atIndex:KernelData_##parent##_##name]; \
next_member_is_specialized = true;
# include "kernel/data_template.h" # include "kernel/data_template.h"

View File

@ -278,7 +278,8 @@ int MetalDeviceQueue::num_concurrent_states(const size_t state_size) const
if (metal_device_->device_vendor == METAL_GPU_APPLE) { if (metal_device_->device_vendor == METAL_GPU_APPLE) {
result *= 4; result *= 4;
if (MetalInfo::get_apple_gpu_architecture(metal_device_->mtlDevice) == APPLE_M2) { /* Increasing the state count doesn't notably benefit M1-family systems. */
if (MetalInfo::get_apple_gpu_architecture(metal_device_->mtlDevice) != APPLE_M1) {
size_t system_ram = system_physical_ram(); size_t system_ram = system_physical_ram();
size_t allocated_so_far = [metal_device_->mtlDevice currentAllocatedSize]; size_t allocated_so_far = [metal_device_->mtlDevice currentAllocatedSize];
size_t max_recommended_working_set = [metal_device_->mtlDevice recommendedMaxWorkingSetSize]; size_t max_recommended_working_set = [metal_device_->mtlDevice recommendedMaxWorkingSetSize];

View File

@ -29,6 +29,7 @@ enum AppleGPUArchitecture {
APPLE_UNKNOWN, APPLE_UNKNOWN,
APPLE_M1, APPLE_M1,
APPLE_M2, APPLE_M2,
APPLE_M2_BIG,
}; };
/* Contains static Metal helper functions. */ /* Contains static Metal helper functions. */

View File

@ -52,7 +52,7 @@ AppleGPUArchitecture MetalInfo::get_apple_gpu_architecture(id<MTLDevice> device)
return APPLE_M1; return APPLE_M1;
} }
else if (strstr(device_name, "M2")) { else if (strstr(device_name, "M2")) {
return APPLE_M2; return get_apple_gpu_core_count(device) <= 10 ? APPLE_M2 : APPLE_M2_BIG;
} }
return APPLE_UNKNOWN; return APPLE_UNKNOWN;
} }

View File

@ -5,6 +5,9 @@ set(INC
.. ..
) )
set(INC_SYS
)
set(SRC set(SRC
node.cpp node.cpp
node_type.cpp node_type.cpp

View File

@ -5,6 +5,9 @@ set(INC
.. ..
) )
set(INC_SYS
)
set(SRC set(SRC
adaptive_sampling.cpp adaptive_sampling.cpp
denoiser.cpp denoiser.cpp

View File

@ -732,25 +732,25 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
endif() endif()
# SYCL_CPP_FLAGS is a variable that the user can set to pass extra compiler options # SYCL_CPP_FLAGS is a variable that the user can set to pass extra compiler options
set(sycl_compiler_flags set(sycl_compiler_flags
${CMAKE_CURRENT_SOURCE_DIR}/${SRC_KERNEL_DEVICE_ONEAPI} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_KERNEL_DEVICE_ONEAPI}
-fsycl -fsycl
-fsycl-unnamed-lambda -fsycl-unnamed-lambda
-fdelayed-template-parsing -fdelayed-template-parsing
-mllvm -inlinedefault-threshold=250 -mllvm -inlinedefault-threshold=250
-mllvm -inlinehint-threshold=350 -mllvm -inlinehint-threshold=350
-fsycl-device-code-split=per_kernel -fsycl-device-code-split=per_kernel
-fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS} -fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS}
-shared -shared
-DWITH_ONEAPI -DWITH_ONEAPI
-ffast-math -ffast-math
-DNDEBUG -DNDEBUG
-O2 -O2
-o ${cycles_kernel_oneapi_lib} -o ${cycles_kernel_oneapi_lib}
-I${CMAKE_CURRENT_SOURCE_DIR}/.. -I${CMAKE_CURRENT_SOURCE_DIR}/..
${SYCL_CPP_FLAGS} ${SYCL_CPP_FLAGS}
) )
if (WITH_CYCLES_ONEAPI_HOST_TASK_EXECUTION) if(WITH_CYCLES_ONEAPI_HOST_TASK_EXECUTION)
list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_TASK) list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_TASK)
endif() endif()

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,9 @@
#ifndef KERNEL_STRUCT_MEMBER #ifndef KERNEL_STRUCT_MEMBER
# define KERNEL_STRUCT_MEMBER(parent, type, name) # define KERNEL_STRUCT_MEMBER(parent, type, name)
#endif #endif
#ifndef KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE
# define KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE
#endif
/* Background. */ /* Background. */
@ -179,9 +182,12 @@ KERNEL_STRUCT_MEMBER(integrator, float, sample_clamp_indirect)
KERNEL_STRUCT_MEMBER(integrator, int, use_caustics) KERNEL_STRUCT_MEMBER(integrator, int, use_caustics)
/* Sampling pattern. */ /* Sampling pattern. */
KERNEL_STRUCT_MEMBER(integrator, int, sampling_pattern) KERNEL_STRUCT_MEMBER(integrator, int, sampling_pattern)
KERNEL_STRUCT_MEMBER(integrator, int, tabulated_sobol_sequence_size)
KERNEL_STRUCT_MEMBER(integrator, int, sobol_index_mask)
KERNEL_STRUCT_MEMBER(integrator, float, scrambling_distance) KERNEL_STRUCT_MEMBER(integrator, float, scrambling_distance)
/* Sobol pattern. */
KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE
KERNEL_STRUCT_MEMBER(integrator, int, tabulated_sobol_sequence_size)
KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE
KERNEL_STRUCT_MEMBER(integrator, int, sobol_index_mask)
/* Volume render. */ /* Volume render. */
KERNEL_STRUCT_MEMBER(integrator, int, use_volumes) KERNEL_STRUCT_MEMBER(integrator, int, use_volumes)
KERNEL_STRUCT_MEMBER(integrator, int, volume_max_steps) KERNEL_STRUCT_MEMBER(integrator, int, volume_max_steps)
@ -216,4 +222,5 @@ KERNEL_STRUCT_END(KernelSVMUsage)
#undef KERNEL_STRUCT_BEGIN #undef KERNEL_STRUCT_BEGIN
#undef KERNEL_STRUCT_MEMBER #undef KERNEL_STRUCT_MEMBER
#undef KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE
#undef KERNEL_STRUCT_END #undef KERNEL_STRUCT_END

View File

@ -616,15 +616,13 @@ ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderCl
float alpha2 = bsdf->alpha_x * bsdf->alpha_y; float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
float cosThetaM = dot(bsdf->N, Ht); float cosThetaM = dot(bsdf->N, Ht);
/* Now calculate G1(i, m) and G1(o, m). */
float G; float G;
if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
/* Eq. 26, 27: now calculate G1(i,m) and G1(o,m). */ G = bsdf_G<MicrofacetType::BECKMANN>(alpha2, cosNI, cosNO);
G = bsdf_beckmann_G1(bsdf->alpha_x, cosNI) * bsdf_beckmann_G1(bsdf->alpha_x, cosNO);
} }
else { /* bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID assumed */ else { /* bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID assumed */
/* Eq. 34: now calculate G1(i,m) and G1(o,m). */ G = bsdf_G<MicrofacetType::GGX>(alpha2, cosNI, cosNO);
G = (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNI * cosNI) / (cosNI * cosNI)))) *
(2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNO * cosNO) / (cosNO * cosNO))));
} }
/* /*

View File

@ -20,6 +20,7 @@
#include "kernel/osl/globals.h" #include "kernel/osl/globals.h"
#include "kernel/osl/services.h" #include "kernel/osl/services.h"
#include "kernel/osl/types.h"
#include "util/foreach.h" #include "util/foreach.h"
#include "util/log.h" #include "util/log.h"
@ -119,6 +120,8 @@ ustring OSLRenderServices::u_u("u");
ustring OSLRenderServices::u_v("v"); ustring OSLRenderServices::u_v("v");
ustring OSLRenderServices::u_empty; ustring OSLRenderServices::u_empty;
ImageManager *OSLRenderServices::image_manager = nullptr;
OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system, int device_type) OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system, int device_type)
: OSL::RendererServices(texture_system), device_type_(device_type) : OSL::RendererServices(texture_system), device_type_(device_type)
{ {
@ -1154,7 +1157,7 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
/* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */ /* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */
if (it != textures.end()) { if (it != textures.end()) {
if (it->second->type != OSLTextureHandle::OIIO) { if (it->second->type != OSLTextureHandle::OIIO) {
return (TextureSystem::TextureHandle *)it->second.get(); return reinterpret_cast<TextureSystem::TextureHandle *>(it->second.get());
} }
} }
@ -1173,16 +1176,53 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
/* Assign OIIO texture handle and return. */ /* Assign OIIO texture handle and return. */
it->second->oiio_handle = handle; it->second->oiio_handle = handle;
return (TextureSystem::TextureHandle *)it->second.get(); return reinterpret_cast<TextureSystem::TextureHandle *>(it->second.get());
} }
else { else {
if (it != textures.end() && it->second->type == OSLTextureHandle::SVM && /* Construct GPU texture handle for existing textures. */
it->second->svm_slots[0].w == -1) { if (it != textures.end()) {
return reinterpret_cast<TextureSystem::TextureHandle *>( switch (it->second->type) {
static_cast<uintptr_t>(it->second->svm_slots[0].y + 1)); case OSLTextureHandle::OIIO:
return NULL;
case OSLTextureHandle::SVM:
if (!it->second->handle.empty() && it->second->handle.get_manager() != image_manager) {
it.clear();
break;
}
return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
it->second->svm_slots[0].y);
case OSLTextureHandle::IES:
if (!it->second->handle.empty() && it->second->handle.get_manager() != image_manager) {
it.clear();
break;
}
return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_IES |
it->second->svm_slots[0].y);
case OSLTextureHandle::AO:
return reinterpret_cast<TextureSystem::TextureHandle *>(
OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 1);
case OSLTextureHandle::BEVEL:
return reinterpret_cast<TextureSystem::TextureHandle *>(
OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 2);
}
} }
return NULL; if (!image_manager) {
return NULL;
}
/* Load new textures using SVM image manager. */
ImageHandle handle = image_manager->add_image(filename.string(), ImageParams());
if (handle.empty()) {
return NULL;
}
if (!textures.insert(filename, new OSLTextureHandle(handle))) {
return NULL;
}
return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
handle.svm_slot());
} }
} }

View File

@ -16,6 +16,8 @@
#include <OSL/oslexec.h> #include <OSL/oslexec.h>
#include <OSL/rendererservices.h> #include <OSL/rendererservices.h>
#include "scene/image.h"
#ifdef WITH_PTEX #ifdef WITH_PTEX
class PtexCache; class PtexCache;
#endif #endif
@ -54,10 +56,20 @@ struct OSLTextureHandle : public OIIO::RefCnt {
{ {
} }
OSLTextureHandle(const ImageHandle &handle)
: type(SVM),
svm_slots(handle.get_svm_slots()),
oiio_handle(nullptr),
processor(nullptr),
handle(handle)
{
}
Type type; Type type;
vector<int4> svm_slots; vector<int4> svm_slots;
OSL::TextureSystem::TextureHandle *oiio_handle; OSL::TextureSystem::TextureHandle *oiio_handle;
ColorSpaceProcessor *processor; ColorSpaceProcessor *processor;
ImageHandle handle;
}; };
typedef OIIO::intrusive_ptr<OSLTextureHandle> OSLTextureHandleRef; typedef OIIO::intrusive_ptr<OSLTextureHandle> OSLTextureHandleRef;
@ -324,6 +336,8 @@ class OSLRenderServices : public OSL::RendererServices {
* shading system. */ * shading system. */
OSLTextureHandleMap textures; OSLTextureHandleMap textures;
static ImageManager *image_manager;
private: private:
int device_type_; int device_type_;
}; };

View File

@ -1443,6 +1443,8 @@ OSL_NOISE_IMPL(osl_snoise, snoise)
/* Texturing */ /* Texturing */
#include "kernel/svm/ies.h"
ccl_device_extern ccl_private OSLTextureOptions *osl_get_texture_options( ccl_device_extern ccl_private OSLTextureOptions *osl_get_texture_options(
ccl_private ShaderGlobals *sg) ccl_private ShaderGlobals *sg)
{ {
@ -1548,25 +1550,31 @@ ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
ccl_private float *dalphady, ccl_private float *dalphady,
ccl_private void *errormessage) ccl_private void *errormessage)
{ {
if (!texture_handle) { const unsigned int type = OSL_TEXTURE_HANDLE_TYPE(texture_handle);
return false; const unsigned int slot = OSL_TEXTURE_HANDLE_SLOT(texture_handle);
switch (type) {
case OSL_TEXTURE_HANDLE_TYPE_SVM: {
const float4 rgba = kernel_tex_image_interp(nullptr, slot, s, 1.0f - t);
if (nchannels > 0)
result[0] = rgba.x;
if (nchannels > 1)
result[1] = rgba.y;
if (nchannels > 2)
result[2] = rgba.z;
if (alpha)
*alpha = rgba.w;
return true;
}
case OSL_TEXTURE_HANDLE_TYPE_IES: {
if (nchannels > 0)
result[0] = kernel_ies_interp(nullptr, slot, s, t);
return true;
}
default: {
return false;
}
} }
/* Only SVM textures are supported. */
int id = static_cast<int>(reinterpret_cast<size_t>(texture_handle) - 1);
const float4 rgba = kernel_tex_image_interp(nullptr, id, s, 1.0f - t);
if (nchannels > 0)
result[0] = rgba.x;
if (nchannels > 1)
result[1] = rgba.y;
if (nchannels > 2)
result[2] = rgba.z;
if (alpha)
*alpha = rgba.w;
return true;
} }
ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg, ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
@ -1586,25 +1594,26 @@ ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
ccl_private float *dalphady, ccl_private float *dalphady,
ccl_private void *errormessage) ccl_private void *errormessage)
{ {
if (!texture_handle) { const unsigned int type = OSL_TEXTURE_HANDLE_TYPE(texture_handle);
return false; const unsigned int slot = OSL_TEXTURE_HANDLE_SLOT(texture_handle);
switch (type) {
case OSL_TEXTURE_HANDLE_TYPE_SVM: {
const float4 rgba = kernel_tex_image_interp_3d(nullptr, slot, *P, INTERPOLATION_NONE);
if (nchannels > 0)
result[0] = rgba.x;
if (nchannels > 1)
result[1] = rgba.y;
if (nchannels > 2)
result[2] = rgba.z;
if (alpha)
*alpha = rgba.w;
return true;
}
default: {
return false;
}
} }
/* Only SVM textures are supported. */
int id = static_cast<int>(reinterpret_cast<size_t>(texture_handle) - 1);
const float4 rgba = kernel_tex_image_interp_3d(nullptr, id, *P, INTERPOLATION_NONE);
if (nchannels > 0)
result[0] = rgba.x;
if (nchannels > 1)
result[1] = rgba.y;
if (nchannels > 2)
result[2] = rgba.z;
if (alpha)
*alpha = rgba.w;
return true;
} }
ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg, ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg,

View File

@ -96,4 +96,13 @@ struct OSLNoiseOptions {
struct OSLTextureOptions { struct OSLTextureOptions {
}; };
#define OSL_TEXTURE_HANDLE_TYPE_IES ((uintptr_t)0x2 << 30)
#define OSL_TEXTURE_HANDLE_TYPE_SVM ((uintptr_t)0x1 << 30)
#define OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL ((uintptr_t)0x3 << 30)
#define OSL_TEXTURE_HANDLE_TYPE(handle) \
((unsigned int)((uintptr_t)(handle) & ((uintptr_t)0x3 << 30)))
#define OSL_TEXTURE_HANDLE_SLOT(handle) \
((unsigned int)((uintptr_t)(handle) & ((uintptr_t)0x3FFFFFFF)))
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -84,6 +84,7 @@ ccl_device_inline float kernel_ies_interp(KernelGlobals kg, int slot, float h_an
return max(cubic_interp(a, b, c, d, h_frac), 0.0f); return max(cubic_interp(a, b, c, d, h_frac), 0.0f);
} }
#ifdef __SVM__
ccl_device_noinline void svm_node_ies(KernelGlobals kg, ccl_device_noinline void svm_node_ies(KernelGlobals kg,
ccl_private ShaderData *sd, ccl_private ShaderData *sd,
ccl_private float *stack, ccl_private float *stack,
@ -105,5 +106,6 @@ ccl_device_noinline void svm_node_ies(KernelGlobals kg,
stack_store_float(stack, fac_offset, fac); stack_store_float(stack, fac_offset, fac);
} }
} }
#endif
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -34,8 +34,6 @@ CCL_NAMESPACE_BEGIN
#define VOLUME_BOUNDS_MAX 1024 #define VOLUME_BOUNDS_MAX 1024
#define BECKMANN_TABLE_SIZE 256
#define SHADER_NONE (~0) #define SHADER_NONE (~0)
#define OBJECT_NONE (~0) #define OBJECT_NONE (~0)
#define PRIM_NONE (~0) #define PRIM_NONE (~0)
@ -1187,9 +1185,8 @@ typedef enum KernelBVHLayout {
#include "kernel/data_template.h" #include "kernel/data_template.h"
typedef struct KernelTables { typedef struct KernelTables {
int beckmann_offset;
int filter_table_offset; int filter_table_offset;
int pad1, pad2; int pad1, pad2, pad3;
} KernelTables; } KernelTables;
static_assert_align(KernelTables, 16); static_assert_align(KernelTables, 16);

View File

@ -222,6 +222,11 @@ VDBImageLoader *ImageHandle::vdb_loader(const int tile_index) const
return NULL; return NULL;
} }
ImageManager *ImageHandle::get_manager() const
{
return manager;
}
bool ImageHandle::operator==(const ImageHandle &other) const bool ImageHandle::operator==(const ImageHandle &other) const
{ {
return manager == other.manager && tile_slots == other.tile_slots; return manager == other.manager && tile_slots == other.tile_slots;

View File

@ -153,6 +153,8 @@ class ImageHandle {
VDBImageLoader *vdb_loader(const int tile_index = 0) const; VDBImageLoader *vdb_loader(const int tile_index = 0) const;
ImageManager *get_manager() const;
protected: protected:
vector<int> tile_slots; vector<int> tile_slots;
ImageManager *manager; ImageManager *manager;

View File

@ -184,9 +184,19 @@ void OSLShaderManager::device_update_specific(Device *device,
* is being freed after the Session is freed. * is being freed after the Session is freed.
*/ */
thread_scoped_lock lock(ss_shared_mutex); thread_scoped_lock lock(ss_shared_mutex);
/* Set current image manager during the lock, so that there is no conflict with other shader
* manager instances.
*
* It is used in "OSLRenderServices::get_texture_handle" called during optimization below to
* load images for the GPU. */
OSLRenderServices::image_manager = scene->image_manager;
for (const auto &[device_type, ss] : ss_shared) { for (const auto &[device_type, ss] : ss_shared) {
ss->optimize_all_groups(); ss->optimize_all_groups();
} }
OSLRenderServices::image_manager = nullptr;
} }
/* load kernels */ /* load kernels */
@ -213,6 +223,22 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *s
og->bump_state.clear(); og->bump_state.clear();
og->background_state.reset(); og->background_state.reset();
}); });
/* Remove any textures specific to an image manager from shared render services textures, since
* the image manager may get destroyed next. */
for (const auto &[device_type, ss] : ss_shared) {
OSLRenderServices *services = static_cast<OSLRenderServices *>(ss->renderer());
for (auto it = services->textures.begin(); it != services->textures.end(); ++it) {
if (it->second->handle.get_manager() == scene->image_manager) {
/* Don't lock again, since the iterator already did so. */
services->textures.erase(it->first, false);
it.clear();
/* Iterator was invalidated, start from the beginning again. */
it = services->textures.begin();
}
}
}
} }
void OSLShaderManager::texture_system_init() void OSLShaderManager::texture_system_init()

View File

@ -32,114 +32,6 @@ namespace OCIO = OCIO_NAMESPACE;
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
thread_mutex ShaderManager::lookup_table_mutex; thread_mutex ShaderManager::lookup_table_mutex;
vector<float> ShaderManager::beckmann_table;
bool ShaderManager::beckmann_table_ready = false;
/* Beckmann sampling precomputed table, see bsdf_microfacet.h */
/* 2D slope distribution (alpha = 1.0) */
static float beckmann_table_P22(const float slope_x, const float slope_y)
{
return expf(-(slope_x * slope_x + slope_y * slope_y));
}
/* maximal slope amplitude (range that contains 99.99% of the distribution) */
static float beckmann_table_slope_max()
{
return 6.0;
}
/* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
* see T50176 for details
*/
#if defined(_MSC_VER) && (_MSC_VER == 1900)
# define MSVC_VOLATILE volatile
#else
# define MSVC_VOLATILE
#endif
/* Paper used: Importance Sampling Microfacet-Based BSDFs with the
* Distribution of Visible Normals. Supplemental Material 2/2.
*
* http://hal.inria.fr/docs/01/00/66/20/ANNEX/supplemental2.pdf
*/
static void beckmann_table_rows(float *table, int row_from, int row_to)
{
/* allocate temporary data */
const int DATA_TMP_SIZE = 512;
vector<double> slope_x(DATA_TMP_SIZE);
vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
/* loop over incident directions */
for (int index_theta = row_from; index_theta < row_to; index_theta++) {
/* incident vector */
const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
/* for a given incident vector
* integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
slope_x[0] = (double)-beckmann_table_slope_max();
CDF_P22_omega_i[0] = 0;
for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
/* slope_x */
slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
2.0f * beckmann_table_slope_max() * index_slope_x /
(DATA_TMP_SIZE - 1.0f));
/* dot product with incident vector */
float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
/* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
float P22_omega_i = 0.0f;
for (int j = 0; j < 100; ++j) {
float slope_y = -beckmann_table_slope_max() +
2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
}
/* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
}
/* renormalize CDF_P22_omega_i */
for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
/* loop over random number U1 */
int index_slope_x = 0;
for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
/* inverse CDF_P22_omega_i, solve Eq.(11) */
while (CDF_P22_omega_i[index_slope_x] <= U)
++index_slope_x;
const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
(CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
/* store value */
table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
(float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
}
}
}
#undef MSVC_VOLATILE
static void beckmann_table_build(vector<float> &table)
{
table.resize(BECKMANN_TABLE_SIZE * BECKMANN_TABLE_SIZE);
/* multithreaded build */
TaskPool pool;
for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
pool.wait_work();
}
/* Shader */ /* Shader */
@ -491,7 +383,6 @@ bool Shader::need_update_geometry() const
ShaderManager::ShaderManager() ShaderManager::ShaderManager()
{ {
update_flags = UPDATE_ALL; update_flags = UPDATE_ALL;
beckmann_table_offset = TABLE_OFFSET_INVALID;
init_xyz_transforms(); init_xyz_transforms();
} }
@ -663,22 +554,6 @@ void ShaderManager::device_update_common(Device * /*device*/,
dscene->shaders.copy_to_device(); dscene->shaders.copy_to_device();
/* lookup tables */
KernelTables *ktables = &dscene->data.tables;
/* beckmann lookup table */
if (beckmann_table_offset == TABLE_OFFSET_INVALID) {
if (!beckmann_table_ready) {
thread_scoped_lock lock(lookup_table_mutex);
if (!beckmann_table_ready) {
beckmann_table_build(beckmann_table);
beckmann_table_ready = true;
}
}
beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
}
ktables->beckmann_offset = (int)beckmann_table_offset;
/* integrator */ /* integrator */
KernelIntegrator *kintegrator = &dscene->data.integrator; KernelIntegrator *kintegrator = &dscene->data.integrator;
kintegrator->use_volumes = has_volumes; kintegrator->use_volumes = has_volumes;
@ -700,8 +575,6 @@ void ShaderManager::device_update_common(Device * /*device*/,
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene) void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
{ {
scene->lookup_tables->remove_table(&beckmann_table_offset);
dscene->shaders.free(); dscene->shaders.free();
} }
@ -844,7 +717,6 @@ uint ShaderManager::get_kernel_features(Scene *scene)
void ShaderManager::free_memory() void ShaderManager::free_memory()
{ {
beckmann_table.free_memory();
#ifdef WITH_OSL #ifdef WITH_OSL
OSLShaderManager::free_memory(); OSLShaderManager::free_memory();

View File

@ -232,10 +232,6 @@ class ShaderManager {
AttributeIDMap unique_attribute_id; AttributeIDMap unique_attribute_id;
static thread_mutex lookup_table_mutex; static thread_mutex lookup_table_mutex;
static vector<float> beckmann_table;
static bool beckmann_table_ready;
size_t beckmann_table_offset;
uint get_graph_kernel_features(ShaderGraph *graph); uint get_graph_kernel_features(ShaderGraph *graph);

View File

@ -5,6 +5,9 @@ set(INC
.. ..
) )
set(INC_SYS
)
set(SRC set(SRC
buffers.cpp buffers.cpp
denoising.cpp denoising.cpp

View File

@ -360,6 +360,15 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${INC_DST}/${_name}-client-protocol.c COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${INC_DST}/${_name}-client-protocol.c
DEPENDS ${INC_DST}/${_name}-client-protocol.h DEPENDS ${INC_DST}/${_name}-client-protocol.h
) )
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
# Prevent warnings/failure to compile with generated `WL_PRIVATE` declarations.
set_source_files_properties(
"${INC_DST}/${_name}-client-protocol.c"
PROPERTIES COMPILE_FLAGS "-Wno-missing-variable-declarations"
)
endif()
list(APPEND SRC list(APPEND SRC
${INC_DST}/${_name}-client-protocol.c ${INC_DST}/${_name}-client-protocol.c
${INC_DST}/${_name}-client-protocol.h ${INC_DST}/${_name}-client-protocol.h

View File

@ -41,10 +41,11 @@ if(WIN32 AND NOT UNIX)
list(APPEND INC_SYS list(APPEND INC_SYS
${PTHREADS_INC} ${PTHREADS_INC}
) )
if(DEFINED PTHREADS_LIBRARIES)
list(APPEND LIB list(APPEND LIB
${PTHREADS_LIBRARIES} ${PTHREADS_LIBRARIES}
) )
endif()
endif() endif()
# Jemalloc 5.0.0+ needs extra configuration. # Jemalloc 5.0.0+ needs extra configuration.

View File

@ -20,7 +20,6 @@ set(SRC
) )
set(LIB set(LIB
extern_bullet
${BULLET_LIBRARIES} ${BULLET_LIBRARIES}
) )

@ -1 +1 @@
Subproject commit bf49eeaa14c445d3c53068203fdf91bff568fe64 Subproject commit 6fcd157f2497d9ba4ba82191cb2abf3de11a0394

@ -1 +1 @@
Subproject commit 0f72f6c85c3743a9072273acb6a8a34b1cf1064b Subproject commit 9d538629bb8a425991c7d10a49bab1ba0788c18f

View File

@ -1587,8 +1587,9 @@ class WM_OT_properties_edit(Operator):
elif self.property_type == 'STRING': elif self.property_type == 'STRING':
self.default_string = rna_data["default"] self.default_string = rna_data["default"]
elif self.property_type in {'BOOL', 'BOOL_ARRAY'}: elif self.property_type in {'BOOL', 'BOOL_ARRAY'}:
self.default_int = self._convert_new_value_array(rna_data["default"], bool, 32) self.default_bool = self._convert_new_value_array(rna_data["default"], bool, 32)
elif self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
if self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
self.array_length = len(item[name]) self.array_length = len(item[name])
# The dictionary does not contain the description if it was empty. # The dictionary does not contain the description if it was empty.

View File

@ -50,5 +50,7 @@ else()
add_executable(blender-thumbnailer ${SRC} ${SRC_CMD}) add_executable(blender-thumbnailer ${SRC} ${SRC_CMD})
setup_platform_linker_flags(blender-thumbnailer) setup_platform_linker_flags(blender-thumbnailer)
target_link_libraries(blender-thumbnailer bf_blenlib) target_link_libraries(blender-thumbnailer bf_blenlib)
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES}) if(DEFINED PTHREADS_LIBRARIES)
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES})
endif()
endif() endif()

View File

@ -753,20 +753,6 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
const AnonymousAttributePropagationInfo &propagation_info, const AnonymousAttributePropagationInfo &propagation_info,
const Set<std::string> &skip = {}); const Set<std::string> &skip = {});
/**
* Copy attributes for the domain based on the elementwise mask.
*
* \param mask_indices: Indexed elements to copy from the source data-block.
* \param domain: Attribute domain to transfer.
* \param skip: Named attributes to ignore/skip.
*/
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); bool allow_procedural_attribute_access(StringRef attribute_name);
extern const char *no_procedural_access_message; extern const char *no_procedural_access_message;

View File

@ -30,17 +30,6 @@
namespace blender::bke { namespace blender::bke {
template<typename T, BLI_ENABLE_IF(std::is_integral_v<T>)>
constexpr IndexRange offsets_to_range(Span<T> offsets, int64_t index)
{
BLI_assert(index >= 0);
BLI_assert(index < offsets.size());
const int offset = offsets[index];
const int offset_next = offsets[index + 1];
return {offset, offset_next - offset};
}
namespace curves::nurbs { namespace curves::nurbs {
struct BasisCache { struct BasisCache {
@ -81,7 +70,7 @@ class CurvesGeometryRuntime {
* evaluated points, Bezier curve vector segments, different resolutions per curve, etc. * evaluated points, Bezier curve vector segments, different resolutions per curve, etc.
*/ */
mutable Vector<int> evaluated_offsets_cache; mutable Vector<int> evaluated_offsets_cache;
mutable Vector<int> bezier_evaluated_offsets; mutable Vector<int> all_bezier_evaluated_offsets;
mutable CacheMutex offsets_cache_mutex; mutable CacheMutex offsets_cache_mutex;
mutable Vector<curves::nurbs::BasisCache> nurbs_basis_cache; mutable Vector<curves::nurbs::BasisCache> nurbs_basis_cache;
@ -303,25 +292,14 @@ class CurvesGeometry : public ::CurvesGeometry {
int evaluated_points_num() const; int evaluated_points_num() const;
/** /**
* Access a range of indices of point data for a specific curve. * The offsets of every curve's evaluated points.
* Call #evaluated_offsets() first to ensure that the evaluated offsets cache is current.
*/ */
IndexRange evaluated_points_for_curve(int index) const; OffsetIndices<int> evaluated_points_by_curve() const;
IndexRange evaluated_points_for_curves(IndexRange curves) const;
/** /**
* The index of the first evaluated point for every curve. The size of this span is one larger * Retrieve offsets into a Bezier curve's evaluated points for each control point. Stored in the
* than the number of curves. Consider using #evaluated_points_for_curve rather than using the * same format as #OffsetIndices. Call #evaluated_points_by_curve() first to ensure that the
* offsets directly. * evaluated offsets cache is current.
*/
Span<int> evaluated_offsets() const;
/** Makes sure the data described by #evaluated_offsets if necessary. */
void ensure_evaluated_offsets() const;
/**
* Retrieve offsets into a Bezier curve's evaluated points for each control point.
* Call #ensure_evaluated_offsets() first to ensure that the evaluated offsets cache is current.
*/ */
Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const; Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const;
@ -489,6 +467,17 @@ inline float3 decode_surface_bary_coord(const float2 &v)
return {v.x, v.y, 1.0f - v.x - v.y}; return {v.x, v.y, 1.0f - v.x - v.y};
} }
/**
* Return a range used to retrieve values from an array of values stored per point, but with an
* extra element at the end of each curve. This is useful for offsets within curves, where it is
* convenient to store the first 0 and have the last offset be the total result curve size, using
* the same rules as #OffsetIndices.
*/
inline IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
{
return {curve_index + points.start(), points.size() + 1};
}
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -567,8 +556,9 @@ bool point_is_sharp(Span<int8_t> handle_types_left, Span<int8_t> handle_types_ri
* point edges generate the number of edges specified by the resolution, vector segments only * point edges generate the number of edges specified by the resolution, vector segments only
* generate one edge. * generate one edge.
* *
* The size of the offsets array must be the same as the number of points. The value at each index * The expectations for the result \a evaluated_offsets are the same as for #OffsetIndices, so the
* is the evaluated point offset including the following segment. * size must be one greater than the number of points. The value at each index is the evaluated
* point at the start of that segment.
*/ */
void calculate_evaluated_offsets(Span<int8_t> handle_types_left, void calculate_evaluated_offsets(Span<int8_t> handle_types_left,
Span<int8_t> handle_types_right, Span<int8_t> handle_types_right,
@ -668,7 +658,7 @@ void evaluate_segment(const float3 &point_0,
void calculate_evaluated_positions(Span<float3> positions, void calculate_evaluated_positions(Span<float3> positions,
Span<float3> handles_left, Span<float3> handles_left,
Span<float3> handles_right, Span<float3> handles_right,
Span<int> evaluated_offsets, OffsetIndices<int> evaluated_offsets,
MutableSpan<float3> evaluated_positions); MutableSpan<float3> evaluated_positions);
/** /**
@ -676,7 +666,7 @@ void calculate_evaluated_positions(Span<float3> positions,
* #evaluated_offsets. Unlike other curve types, for Bezier curves generic data and positions * #evaluated_offsets. Unlike other curve types, for Bezier curves generic data and positions
* are treated separately, since attribute values aren't stored for the handle control points. * are treated separately, since attribute values aren't stored for the handle control points.
*/ */
void interpolate_to_evaluated(GSpan src, Span<int> evaluated_offsets, GMutableSpan dst); void interpolate_to_evaluated(GSpan src, OffsetIndices<int> evaluated_offsets, GMutableSpan dst);
} // namespace bezier } // namespace bezier
@ -702,12 +692,12 @@ int calculate_evaluated_num(int points_num, bool cyclic, int resolution);
void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst); void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst);
/** /**
* Evaluate the Catmull Rom curve. The size of each segment and its offset in the #dst span * Evaluate the Catmull Rom curve. The placement of each segment in the #dst span is desribed by
* is encoded in #evaluated_offsets, with the same method as #CurvesGeometry::offsets(). * #evaluated_offsets.
*/ */
void interpolate_to_evaluated(const GSpan src, void interpolate_to_evaluated(const GSpan src,
const bool cyclic, const bool cyclic,
const Span<int> evaluated_offsets, const OffsetIndices<int> evaluated_offsets,
GMutableSpan dst); GMutableSpan dst);
void calculate_basis(const float parameter, float4 &r_weights); void calculate_basis(const float parameter, float4 &r_weights);
@ -877,36 +867,22 @@ inline OffsetIndices<int> CurvesGeometry::points_by_curve() const
inline int CurvesGeometry::evaluated_points_num() const inline int CurvesGeometry::evaluated_points_num() const
{ {
/* This could avoid calculating offsets in the future in simple circumstances. */ /* This could avoid calculating offsets in the future in simple circumstances. */
return this->evaluated_offsets().last(); return this->evaluated_points_by_curve().total_size();
}
inline IndexRange CurvesGeometry::evaluated_points_for_curve(int index) const
{
BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
return offsets_to_range(this->runtime->evaluated_offsets_cache.as_span(), index);
}
inline IndexRange CurvesGeometry::evaluated_points_for_curves(const IndexRange curves) const
{
BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
BLI_assert(this->curve_num > 0);
const int offset = this->runtime->evaluated_offsets_cache[curves.start()];
const int offset_next = this->runtime->evaluated_offsets_cache[curves.one_after_last()];
return {offset, offset_next - offset};
} }
inline Span<int> CurvesGeometry::bezier_evaluated_offsets_for_curve(const int curve_index) const inline Span<int> CurvesGeometry::bezier_evaluated_offsets_for_curve(const int curve_index) const
{ {
const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices points_by_curve = this->points_by_curve();
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
return this->runtime->bezier_evaluated_offsets.as_span().slice(points); const IndexRange range = curves::per_curve_point_offsets_range(points, curve_index);
return this->runtime->all_bezier_evaluated_offsets.as_span().slice(range);
} }
inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index, inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index,
const bool cyclic) const const bool cyclic) const
{ {
BLI_assert(cyclic == this->cyclic()[curve_index]); BLI_assert(cyclic == this->cyclic()[curve_index]);
const IndexRange points = this->evaluated_points_for_curve(curve_index); const IndexRange points = this->evaluated_points_by_curve()[curve_index];
const int start = points.start() + curve_index; const int start = points.start() + curve_index;
return {start, curves::segments_num(points.size(), cyclic)}; return {start, curves::segments_num(points.size(), cyclic)};
} }

View File

@ -76,14 +76,17 @@ struct CurvePoint : public CurveSegment {
* [0, range_size) can be iterated over an arbitrary amount of times in between. * [0, range_size) can be iterated over an arbitrary amount of times in between.
*/ */
class IndexRangeCyclic { class IndexRangeCyclic {
/* Index to the start and end of the iterated range. /**
* Index to the start and end of the iterated range.
*/ */
int start_ = 0; int start_ = 0;
int end_ = 0; int end_ = 0;
/* Size of the underlying iterable range. /**
* Size of the underlying iterable range.
*/ */
int range_size_ = 0; int range_size_ = 0;
/* Number of times the range end is passed when the range is iterated. /**
* Number of times the range end is passed when the range is iterated.
*/ */
int cycles_ = 0; int cycles_ = 0;
@ -519,18 +522,22 @@ void fill_points(const CurvesGeometry &curves,
} }
/** /**
* Copy only the attributes on the curve domain, but not the offsets or any point attributes, * Create new curves with the same number of curves as the input, but no points. Copy all curve
* meant for operations that change the number of points but not the number of curves. * domain attributes to the new curves, except the offsets encoding the size of each curve.
*
* Used for operations that change the number of points but not the number of curves, allowing
* creation of the new offsets directly inside the new array.
*
* \warning The returned curves have invalid offsets! * \warning The returned curves have invalid offsets!
*/ */
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves); bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves);
/** /**
* Copy the size of every curve in #curve_ranges to the corresponding index in #counts. * Copy the number of points in every curve in #curve_ranges to the corresponding index in #sizes.
*/ */
void fill_curve_counts(const bke::CurvesGeometry &curves, void copy_curve_sizes(const bke::CurvesGeometry &curves,
Span<IndexRange> curve_ranges, Span<IndexRange> curve_ranges,
MutableSpan<int> counts); MutableSpan<int> sizes);
IndexMask indices_for_type(const VArray<int8_t> &types, IndexMask indices_for_type(const VArray<int8_t> &types,
const std::array<int, CURVE_TYPES_NUM> &type_counts, const std::array<int, CURVE_TYPES_NUM> &type_counts,

View File

@ -92,8 +92,10 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(int dtdata_type);
DT_TYPE_SHAPEKEY, \ DT_TYPE_SHAPEKEY, \
DT_TYPE_MPROPCOL_VERT, \ DT_TYPE_MPROPCOL_VERT, \
DT_TYPE_MLOOPCOL_VERT, \ DT_TYPE_MLOOPCOL_VERT, \
DT_TYPE_MPROPCOL_VERT | DT_TYPE_MLOOPCOL_VERT, \
DT_TYPE_MPROPCOL_LOOP, \ DT_TYPE_MPROPCOL_LOOP, \
DT_TYPE_MLOOPCOL_LOOP, \ DT_TYPE_MLOOPCOL_LOOP, \
DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP, \
DT_TYPE_UV) DT_TYPE_UV)
enum { enum {

View File

@ -139,6 +139,13 @@ typedef struct Global {
* Typically Python drivers. * Typically Python drivers.
*/ */
char autoexec_fail[200]; char autoexec_fail[200];
/**
* Has there been an opengl deprecation call detected when running on a none OpenGL backend.
*/
bool opengl_deprecation_usage_detected;
const char *opengl_deprecation_usage_filename;
int opengl_deprecation_usage_lineno;
} Global; } Global;
/* **************** GLOBAL ********************* */ /* **************** GLOBAL ********************* */

View File

@ -10,6 +10,8 @@
/** Temp constant defined for these functions only. */ /** Temp constant defined for these functions only. */
#define NLASTRIP_MIN_LEN_THRESH 0.1f #define NLASTRIP_MIN_LEN_THRESH 0.1f
#include "DNA_listBase.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -295,6 +297,11 @@ void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip);
*/ */
void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip); void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip);
/**
* Recalculate the Blendin and Blendout values after a strip transform update.
*/
void BKE_nlastrip_recalculate_blend(struct NlaStrip *strip);
/** /**
* Find (and set) a unique name for a strip from the whole AnimData block * Find (and set) a unique name for a strip from the whole AnimData block
* Uses a similar method to the BLI method, but is implemented differently * Uses a similar method to the BLI method, but is implemented differently

View File

@ -559,15 +559,16 @@ if(WIN32)
endif() endif()
if(WITH_AUDASPACE) if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS} ${AUDASPACE_C_INCLUDE_DIRS}
) )
list(APPEND LIB if(WITH_SYSTEM_AUDASPACE)
${AUDASPACE_C_LIBRARIES} list(APPEND LIB
${AUDASPACE_PY_LIBRARIES} ${AUDASPACE_C_LIBRARIES}
) ${AUDASPACE_PY_LIBRARIES}
)
endif()
add_definitions(-DWITH_AUDASPACE)
endif() endif()
if(WITH_BULLET) if(WITH_BULLET)
@ -577,13 +578,6 @@ if(WITH_BULLET)
list(APPEND INC list(APPEND INC
../../../intern/rigidbody ../../../intern/rigidbody
) )
if(NOT WITH_SYSTEM_BULLET)
list(APPEND LIB
extern_bullet
)
endif()
list(APPEND LIB list(APPEND LIB
bf_intern_rigidbody bf_intern_rigidbody
@ -843,6 +837,7 @@ if(WITH_GTESTS)
intern/lib_id_remapper_test.cc intern/lib_id_remapper_test.cc
intern/lib_id_test.cc intern/lib_id_test.cc
intern/lib_remap_test.cc intern/lib_remap_test.cc
intern/nla_test.cc
intern/tracking_test.cc intern/tracking_test.cc
) )
set(TEST_INC set(TEST_INC
@ -853,4 +848,4 @@ if(WITH_GTESTS)
# RNA_prototypes.h # RNA_prototypes.h
add_dependencies(bf_blenkernel_tests bf_rna) add_dependencies(bf_blenkernel_tests bf_rna)
endif() endif()

View File

@ -913,38 +913,6 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
return attributes; return attributes;
} }
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(
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) {
if (meta_data.domain != domain) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (skip.contains(id.name())) {
return true;
}
const GVArray src = src_attributes.lookup(id, meta_data.domain);
BLI_assert(src);
/* Copy attribute. */
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, domain, meta_data.data_type);
array_utils::copy(src, selection, dst.span);
dst.finish();
return true;
});
}
} // namespace blender::bke } // namespace blender::bke
/** \} */ /** \} */

View File

@ -33,20 +33,21 @@ void calculate_evaluated_offsets(const Span<int8_t> handle_types_left,
MutableSpan<int> evaluated_offsets) MutableSpan<int> evaluated_offsets)
{ {
const int size = handle_types_left.size(); const int size = handle_types_left.size();
BLI_assert(evaluated_offsets.size() == size); BLI_assert(evaluated_offsets.size() == size + 1);
evaluated_offsets.first() = 0;
if (size == 1) { if (size == 1) {
evaluated_offsets.first() = 1; evaluated_offsets.last() = 1;
return; return;
} }
int offset = 0; int offset = 0;
for (const int i : IndexRange(size - 1)) { for (const int i : IndexRange(size - 1)) {
offset += segment_is_vector(handle_types_left, handle_types_right, i) ? 1 : resolution;
evaluated_offsets[i] = offset; evaluated_offsets[i] = offset;
offset += segment_is_vector(handle_types_left, handle_types_right, i) ? 1 : resolution;
} }
evaluated_offsets.last(1) = offset;
if (cyclic) { if (cyclic) {
offset += last_cyclic_segment_is_vector(handle_types_left, handle_types_right) ? 1 : offset += last_cyclic_segment_is_vector(handle_types_left, handle_types_right) ? 1 :
resolution; resolution;
@ -233,12 +234,11 @@ void evaluate_segment(const float3 &point_0,
void calculate_evaluated_positions(const Span<float3> positions, void calculate_evaluated_positions(const Span<float3> positions,
const Span<float3> handles_left, const Span<float3> handles_left,
const Span<float3> handles_right, const Span<float3> handles_right,
const Span<int> evaluated_offsets, const OffsetIndices<int> evaluated_offsets,
MutableSpan<float3> evaluated_positions) MutableSpan<float3> evaluated_positions)
{ {
BLI_assert(evaluated_offsets.last() == evaluated_positions.size()); BLI_assert(evaluated_offsets.total_size() == evaluated_positions.size());
BLI_assert(evaluated_offsets.size() == positions.size()); if (evaluated_offsets.total_size() == 1) {
if (evaluated_offsets.last() == 1) {
evaluated_positions.first() = positions.first(); evaluated_positions.first() = positions.first();
return; return;
} }
@ -248,29 +248,29 @@ void calculate_evaluated_positions(const Span<float3> positions,
handles_right.first(), handles_right.first(),
handles_left[1], handles_left[1],
positions[1], positions[1],
evaluated_positions.take_front(evaluated_offsets.first())); evaluated_positions.slice(evaluated_offsets[0]));
/* Give each task fewer segments as the resolution gets larger. */ /* Give each task fewer segments as the resolution gets larger. */
const int grain_size = std::max<int>(evaluated_positions.size() / positions.size() * 32, 1); const int grain_size = std::max<int>(evaluated_positions.size() / positions.size() * 32, 1);
threading::parallel_for( const IndexRange inner_segments = positions.index_range().drop_back(1).drop_front(1);
positions.index_range().drop_back(1).drop_front(1), grain_size, [&](IndexRange range) { threading::parallel_for(inner_segments, grain_size, [&](IndexRange range) {
for (const int i : range) { for (const int i : range) {
const IndexRange evaluated_range = offsets_to_range(evaluated_offsets, i - 1); const IndexRange evaluated_range = evaluated_offsets[i];
if (evaluated_range.size() == 1) { if (evaluated_range.size() == 1) {
evaluated_positions[evaluated_range.first()] = positions[i]; evaluated_positions[evaluated_range.first()] = positions[i];
} }
else { else {
evaluate_segment(positions[i], evaluate_segment(positions[i],
handles_right[i], handles_right[i],
handles_left[i + 1], handles_left[i + 1],
positions[i + 1], positions[i + 1],
evaluated_positions.slice(evaluated_range)); evaluated_positions.slice(evaluated_range));
} }
} }
}); });
/* Evaluate the final cyclic segment if necessary. */ /* Evaluate the final cyclic segment if necessary. */
const IndexRange last_segment_points = offsets_to_range(evaluated_offsets, positions.size() - 2); const IndexRange last_segment_points = evaluated_offsets[positions.index_range().last()];
if (last_segment_points.size() == 1) { if (last_segment_points.size() == 1) {
evaluated_positions.last() = positions.last(); evaluated_positions.last() = positions.last();
} }
@ -295,34 +295,34 @@ static inline void linear_interpolation(const T &a, const T &b, MutableSpan<T> d
template<typename T> template<typename T>
static void interpolate_to_evaluated(const Span<T> src, static void interpolate_to_evaluated(const Span<T> src,
const Span<int> evaluated_offsets, const OffsetIndices<int> evaluated_offsets,
MutableSpan<T> dst) MutableSpan<T> dst)
{ {
BLI_assert(!src.is_empty()); BLI_assert(!src.is_empty());
BLI_assert(evaluated_offsets.size() == src.size()); BLI_assert(evaluated_offsets.total_size() == dst.size());
BLI_assert(evaluated_offsets.last() == dst.size());
if (src.size() == 1) { if (src.size() == 1) {
BLI_assert(dst.size() == 1); BLI_assert(dst.size() == 1);
dst.first() = src.first(); dst.first() = src.first();
return; return;
} }
linear_interpolation(src.first(), src[1], dst.take_front(evaluated_offsets.first())); linear_interpolation(src.first(), src[1], dst.slice(evaluated_offsets[0]));
threading::parallel_for( threading::parallel_for(
src.index_range().drop_back(1).drop_front(1), 512, [&](IndexRange range) { src.index_range().drop_back(1).drop_front(1), 512, [&](IndexRange range) {
for (const int i : range) { for (const int i : range) {
const IndexRange segment_points = offsets_to_range(evaluated_offsets, i - 1); const IndexRange segment = evaluated_offsets[i];
linear_interpolation(src[i], src[i + 1], dst.slice(segment_points)); linear_interpolation(src[i], src[i + 1], dst.slice(segment));
} }
}); });
const IndexRange last_segment_points(evaluated_offsets.last(1), const IndexRange last_segment = evaluated_offsets[src.index_range().last()];
evaluated_offsets.last() - evaluated_offsets.last(1)); linear_interpolation(src.last(), src.first(), dst.slice(last_segment));
linear_interpolation(src.last(), src.first(), dst.slice(last_segment_points));
} }
void interpolate_to_evaluated(const GSpan src, const Span<int> evaluated_offsets, GMutableSpan dst) void interpolate_to_evaluated(const GSpan src,
const OffsetIndices<int> evaluated_offsets,
GMutableSpan dst)
{ {
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);

View File

@ -123,7 +123,7 @@ static void interpolate_to_evaluated(const Span<T> src,
template<typename T> template<typename T>
static void interpolate_to_evaluated(const Span<T> src, static void interpolate_to_evaluated(const Span<T> src,
const bool cyclic, const bool cyclic,
const Span<int> evaluated_offsets, const OffsetIndices<int> evaluated_offsets,
MutableSpan<T> dst) MutableSpan<T> dst)
{ {
@ -131,7 +131,7 @@ static void interpolate_to_evaluated(const Span<T> src,
src, src,
cyclic, cyclic,
[evaluated_offsets](const int segment_i) -> IndexRange { [evaluated_offsets](const int segment_i) -> IndexRange {
return bke::offsets_to_range(evaluated_offsets, segment_i); return evaluated_offsets[segment_i];
}, },
dst); dst);
} }
@ -149,7 +149,7 @@ void interpolate_to_evaluated(const GSpan src,
void interpolate_to_evaluated(const GSpan src, void interpolate_to_evaluated(const GSpan src,
const bool cyclic, const bool cyclic,
const Span<int> evaluated_offsets, const OffsetIndices<int> evaluated_offsets,
GMutableSpan dst) GMutableSpan dst)
{ {
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {

View File

@ -165,7 +165,7 @@ static void mark_bezier_vector_edges_sharp(const int profile_point_num,
for (const int i : IndexRange(profile_point_num).drop_front(1)) { for (const int i : IndexRange(profile_point_num).drop_front(1)) {
if (curves::bezier::point_is_sharp(handle_types_left, handle_types_right, i)) { if (curves::bezier::point_is_sharp(handle_types_left, handle_types_right, i)) {
const int offset = main_edges_start + main_segment_num * control_point_offsets[i - 1]; const int offset = main_edges_start + main_segment_num * control_point_offsets[i];
sharp_edges.slice(offset, main_segment_num).fill(true); sharp_edges.slice(offset, main_segment_num).fill(true);
} }
} }
@ -245,8 +245,8 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
result.main_indices.reinitialize(result.total); result.main_indices.reinitialize(result.total);
result.profile_indices.reinitialize(result.total); result.profile_indices.reinitialize(result.total);
info.main.ensure_evaluated_offsets(); const OffsetIndices<int> main_offsets = info.main.evaluated_points_by_curve();
info.profile.ensure_evaluated_offsets(); const OffsetIndices<int> profile_offsets = info.profile.evaluated_points_by_curve();
int mesh_index = 0; int mesh_index = 0;
int vert_offset = 0; int vert_offset = 0;
@ -255,7 +255,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
int poly_offset = 0; int poly_offset = 0;
for (const int i_main : info.main.curves_range()) { for (const int i_main : info.main.curves_range()) {
const bool main_cyclic = info.main_cyclic[i_main]; const bool main_cyclic = info.main_cyclic[i_main];
const int main_point_num = info.main.evaluated_points_for_curve(i_main).size(); const int main_point_num = main_offsets.size(i_main);
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic); const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
for (const int i_profile : info.profile.curves_range()) { for (const int i_profile : info.profile.curves_range()) {
result.vert[mesh_index] = vert_offset; result.vert[mesh_index] = vert_offset;
@ -267,7 +267,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
result.profile_indices[mesh_index] = i_profile; result.profile_indices[mesh_index] = i_profile;
const bool profile_cyclic = info.profile_cyclic[i_profile]; const bool profile_cyclic = info.profile_cyclic[i_profile];
const int profile_point_num = info.profile.evaluated_points_for_curve(i_profile).size(); const int profile_point_num = profile_offsets.size(i_profile);
const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic); const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic);
const bool has_caps = fill_caps && !main_cyclic && profile_cyclic; const bool has_caps = fill_caps && !main_cyclic && profile_cyclic;
@ -376,13 +376,19 @@ static void foreach_curve_combination(const CurvesInfo &info,
const ResultOffsets &offsets, const ResultOffsets &offsets,
const Fn &fn) const Fn &fn)
{ {
const OffsetIndices<int> main_offsets = info.main.evaluated_points_by_curve();
const OffsetIndices<int> profile_offsets = info.profile.evaluated_points_by_curve();
const OffsetIndices<int> vert_offsets(offsets.vert);
const OffsetIndices<int> edge_offsets(offsets.edge);
const OffsetIndices<int> poly_offsets(offsets.poly);
const OffsetIndices<int> loop_offsets(offsets.loop);
threading::parallel_for(IndexRange(offsets.total), 512, [&](IndexRange range) { threading::parallel_for(IndexRange(offsets.total), 512, [&](IndexRange range) {
for (const int i : range) { for (const int i : range) {
const int i_main = offsets.main_indices[i]; const int i_main = offsets.main_indices[i];
const int i_profile = offsets.profile_indices[i]; const int i_profile = offsets.profile_indices[i];
const IndexRange main_points = info.main.evaluated_points_for_curve(i_main); const IndexRange main_points = main_offsets[i_main];
const IndexRange profile_points = info.profile.evaluated_points_for_curve(i_profile); const IndexRange profile_points = profile_offsets[i_profile];
const bool main_cyclic = info.main_cyclic[i_main]; const bool main_cyclic = info.main_cyclic[i_main];
const bool profile_cyclic = info.profile_cyclic[i_profile]; const bool profile_cyclic = info.profile_cyclic[i_profile];
@ -398,10 +404,10 @@ static void foreach_curve_combination(const CurvesInfo &info,
profile_cyclic, profile_cyclic,
curves::segments_num(main_points.size(), main_cyclic), curves::segments_num(main_points.size(), main_cyclic),
curves::segments_num(profile_points.size(), profile_cyclic), curves::segments_num(profile_points.size(), profile_cyclic),
offsets_to_range(offsets.vert.as_span(), i), vert_offsets[i],
offsets_to_range(offsets.edge.as_span(), i), edge_offsets[i],
offsets_to_range(offsets.poly.as_span(), i), poly_offsets[i],
offsets_to_range(offsets.loop.as_span(), i)}); loop_offsets[i]});
} }
}); });
} }
@ -569,7 +575,7 @@ static void copy_profile_point_domain_attribute_to_mesh(const CurvesInfo &curves
template<typename T> template<typename T>
static void copy_indices_to_offset_ranges(const VArray<T> &src, static void copy_indices_to_offset_ranges(const VArray<T> &src,
const Span<int> curve_indices, const Span<int> curve_indices,
const Span<int> mesh_offsets, const OffsetIndices<int> mesh_offsets,
MutableSpan<T> dst) MutableSpan<T> dst)
{ {
/* This unnecessarily instantiates the "is single" case (which should be handled elsewhere if /* This unnecessarily instantiates the "is single" case (which should be handled elsewhere if
@ -578,7 +584,7 @@ static void copy_indices_to_offset_ranges(const VArray<T> &src,
devirtualize_varray(src, [&](const auto &src) { devirtualize_varray(src, [&](const auto &src) {
threading::parallel_for(curve_indices.index_range(), 512, [&](IndexRange range) { threading::parallel_for(curve_indices.index_range(), 512, [&](IndexRange range) {
for (const int i : range) { for (const int i : range) {
dst.slice(offsets_to_range(mesh_offsets, i)).fill(src[curve_indices[i]]); dst.slice(mesh_offsets[i]).fill(src[curve_indices[i]]);
} }
}); });
}); });

View File

@ -760,6 +760,7 @@ static void create_samples(CurveProfile *profile,
} }
BLI_assert(n_added == n_segments); /* n_added is just used for this assert, could remove it. */ BLI_assert(n_added == n_segments); /* n_added is just used for this assert, could remove it. */
UNUSED_VARS_NDEBUG(n_added);
/* Sample the points and add them to the locations table. */ /* Sample the points and add them to the locations table. */
for (int i_sample = 0, i = 0; i < totedges; i++) { for (int i_sample = 0, i = 0; i < totedges; i++) {

View File

@ -455,18 +455,18 @@ template<typename CountFn> void build_offsets(MutableSpan<int> offsets, const Co
static void calculate_evaluated_offsets(const CurvesGeometry &curves, static void calculate_evaluated_offsets(const CurvesGeometry &curves,
MutableSpan<int> offsets, MutableSpan<int> offsets,
MutableSpan<int> bezier_evaluated_offsets) MutableSpan<int> all_bezier_offsets)
{ {
const OffsetIndices points_by_curve = curves.points_by_curve(); const OffsetIndices points_by_curve = curves.points_by_curve();
VArray<int8_t> types = curves.curve_types(); const VArray<int8_t> types = curves.curve_types();
VArray<int> resolution = curves.resolution(); const VArray<int> resolution = curves.resolution();
VArray<bool> cyclic = curves.cyclic(); const VArray<bool> cyclic = curves.cyclic();
VArraySpan<int8_t> handle_types_left{curves.handle_types_left()}; const VArraySpan<int8_t> handle_types_left{curves.handle_types_left()};
VArraySpan<int8_t> handle_types_right{curves.handle_types_right()}; const VArraySpan<int8_t> handle_types_right{curves.handle_types_right()};
VArray<int8_t> nurbs_orders = curves.nurbs_orders(); const VArray<int8_t> nurbs_orders = curves.nurbs_orders();
VArray<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes(); const VArray<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes();
build_offsets(offsets, [&](const int curve_index) -> int { build_offsets(offsets, [&](const int curve_index) -> int {
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
@ -476,13 +476,15 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves,
points.size(), cyclic[curve_index], resolution[curve_index]); points.size(), cyclic[curve_index], resolution[curve_index]);
case CURVE_TYPE_POLY: case CURVE_TYPE_POLY:
return points.size(); return points.size();
case CURVE_TYPE_BEZIER: case CURVE_TYPE_BEZIER: {
const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
curves::bezier::calculate_evaluated_offsets(handle_types_left.slice(points), curves::bezier::calculate_evaluated_offsets(handle_types_left.slice(points),
handle_types_right.slice(points), handle_types_right.slice(points),
cyclic[curve_index], cyclic[curve_index],
resolution[curve_index], resolution[curve_index],
bezier_evaluated_offsets.slice(points)); all_bezier_offsets.slice(offsets));
return bezier_evaluated_offsets[points.last()]; return all_bezier_offsets[offsets.last()];
}
case CURVE_TYPE_NURBS: case CURVE_TYPE_NURBS:
return curves::nurbs::calculate_evaluated_num(points.size(), return curves::nurbs::calculate_evaluated_num(points.size(),
nurbs_orders[curve_index], nurbs_orders[curve_index],
@ -495,27 +497,32 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves,
}); });
} }
void CurvesGeometry::ensure_evaluated_offsets() const OffsetIndices<int> CurvesGeometry::evaluated_points_by_curve() const
{ {
if (this->is_single_type(CURVE_TYPE_POLY)) {
/* When all the curves are poly curves, the evaluated offsets are the same as the control
* point offsets, so it's possible to completely avoid building a new offsets array. */
this->runtime->offsets_cache_mutex.ensure(
[&]() { this->runtime->evaluated_offsets_cache.clear_and_shrink(); });
return this->points_by_curve();
}
this->runtime->offsets_cache_mutex.ensure([&]() { this->runtime->offsets_cache_mutex.ensure([&]() {
this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1); this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1);
if (this->has_curve_with_type(CURVE_TYPE_BEZIER)) { if (this->has_curve_with_type(CURVE_TYPE_BEZIER)) {
this->runtime->bezier_evaluated_offsets.resize(this->points_num()); this->runtime->all_bezier_evaluated_offsets.resize(this->points_num() + this->curves_num());
} }
else { else {
this->runtime->bezier_evaluated_offsets.clear_and_shrink(); this->runtime->all_bezier_evaluated_offsets.clear_and_shrink();
} }
calculate_evaluated_offsets( calculate_evaluated_offsets(*this,
*this, this->runtime->evaluated_offsets_cache, this->runtime->bezier_evaluated_offsets); this->runtime->evaluated_offsets_cache,
this->runtime->all_bezier_evaluated_offsets);
}); });
}
Span<int> CurvesGeometry::evaluated_offsets() const return OffsetIndices<int>(this->runtime->evaluated_offsets_cache);
{
this->ensure_evaluated_offsets();
return this->runtime->evaluated_offsets_cache;
} }
IndexMask CurvesGeometry::indices_for_curve_type(const CurveType type, IndexMask CurvesGeometry::indices_for_curve_type(const CurveType type,
@ -557,14 +564,16 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
MutableSpan<curves::nurbs::BasisCache> basis_caches(this->runtime->nurbs_basis_cache); MutableSpan<curves::nurbs::BasisCache> basis_caches(this->runtime->nurbs_basis_cache);
const OffsetIndices<int> points_by_curve = this->points_by_curve(); const OffsetIndices<int> points_by_curve = this->points_by_curve();
VArray<bool> cyclic = this->cyclic(); const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
VArray<int8_t> orders = this->nurbs_orders(); const VArray<bool> cyclic = this->cyclic();
VArray<int8_t> knots_modes = this->nurbs_knots_modes(); const VArray<int8_t> orders = this->nurbs_orders();
const VArray<int8_t> knots_modes = this->nurbs_knots_modes();
threading::parallel_for(nurbs_mask.index_range(), 64, [&](const IndexRange range) { threading::parallel_for(nurbs_mask.index_range(), 64, [&](const IndexRange range) {
Vector<float, 32> knots;
for (const int curve_index : nurbs_mask.slice(range)) { for (const int curve_index : nurbs_mask.slice(range)) {
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
const int8_t order = orders[curve_index]; const int8_t order = orders[curve_index];
const bool is_cyclic = cyclic[curve_index]; const bool is_cyclic = cyclic[curve_index];
@ -575,8 +584,7 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
continue; continue;
} }
const int knots_num = curves::nurbs::knots_num(points.size(), order, is_cyclic); knots.reinitialize(curves::nurbs::knots_num(points.size(), order, is_cyclic));
Array<float> knots(knots_num);
curves::nurbs::calculate_knots(points.size(), mode, order, is_cyclic, knots); curves::nurbs::calculate_knots(points.size(), mode, order, is_cyclic, knots);
curves::nurbs::calculate_basis_cache(points.size(), curves::nurbs::calculate_basis_cache(points.size(),
evaluated_points.size(), evaluated_points.size(),
@ -603,24 +611,25 @@ Span<float3> CurvesGeometry::evaluated_positions() const
this->runtime->evaluated_positions_span = evaluated_positions; this->runtime->evaluated_positions_span = evaluated_positions;
const OffsetIndices<int> points_by_curve = this->points_by_curve(); const OffsetIndices<int> points_by_curve = this->points_by_curve();
VArray<int8_t> types = this->curve_types(); const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
VArray<bool> cyclic = this->cyclic(); const VArray<int8_t> types = this->curve_types();
VArray<int> resolution = this->resolution(); const VArray<bool> cyclic = this->cyclic();
Span<float3> positions = this->positions(); const VArray<int> resolution = this->resolution();
const Span<float3> positions = this->positions();
Span<float3> handle_positions_left = this->handle_positions_left(); const Span<float3> handle_positions_left = this->handle_positions_left();
Span<float3> handle_positions_right = this->handle_positions_right(); const Span<float3> handle_positions_right = this->handle_positions_right();
Span<int> bezier_evaluated_offsets = this->runtime->bezier_evaluated_offsets; const Span<int> all_bezier_evaluated_offsets = this->runtime->all_bezier_evaluated_offsets;
VArray<int8_t> nurbs_orders = this->nurbs_orders(); const VArray<int8_t> nurbs_orders = this->nurbs_orders();
Span<float> nurbs_weights = this->nurbs_weights(); const Span<float> nurbs_weights = this->nurbs_weights();
this->ensure_nurbs_basis_cache(); this->ensure_nurbs_basis_cache();
threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
for (const int curve_index : curves_range) { for (const int curve_index : curves_range) {
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
switch (types[curve_index]) { switch (types[curve_index]) {
case CURVE_TYPE_CATMULL_ROM: case CURVE_TYPE_CATMULL_ROM:
@ -633,22 +642,23 @@ Span<float3> CurvesGeometry::evaluated_positions() const
case CURVE_TYPE_POLY: case CURVE_TYPE_POLY:
evaluated_positions.slice(evaluated_points).copy_from(positions.slice(points)); evaluated_positions.slice(evaluated_points).copy_from(positions.slice(points));
break; break;
case CURVE_TYPE_BEZIER: case CURVE_TYPE_BEZIER: {
const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
curves::bezier::calculate_evaluated_positions( curves::bezier::calculate_evaluated_positions(
positions.slice(points), positions.slice(points),
handle_positions_left.slice(points), handle_positions_left.slice(points),
handle_positions_right.slice(points), handle_positions_right.slice(points),
bezier_evaluated_offsets.slice(points), all_bezier_evaluated_offsets.slice(offsets),
evaluated_positions.slice(evaluated_points)); evaluated_positions.slice(evaluated_points));
break; break;
case CURVE_TYPE_NURBS: { }
case CURVE_TYPE_NURBS:
curves::nurbs::interpolate_to_evaluated(this->runtime->nurbs_basis_cache[curve_index], curves::nurbs::interpolate_to_evaluated(this->runtime->nurbs_basis_cache[curve_index],
nurbs_orders[curve_index], nurbs_orders[curve_index],
nurbs_weights.slice_safe(points), nurbs_weights.slice_safe(points),
positions.slice(points), positions.slice(points),
evaluated_positions.slice(evaluated_points)); evaluated_positions.slice(evaluated_points));
break; break;
}
default: default:
BLI_assert_unreachable(); BLI_assert_unreachable();
break; break;
@ -662,6 +672,7 @@ Span<float3> CurvesGeometry::evaluated_positions() const
Span<float3> CurvesGeometry::evaluated_tangents() const Span<float3> CurvesGeometry::evaluated_tangents() const
{ {
this->runtime->tangent_cache_mutex.ensure([&]() { this->runtime->tangent_cache_mutex.ensure([&]() {
const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
const Span<float3> evaluated_positions = this->evaluated_positions(); const Span<float3> evaluated_positions = this->evaluated_positions();
const VArray<bool> cyclic = this->cyclic(); const VArray<bool> cyclic = this->cyclic();
@ -670,7 +681,7 @@ Span<float3> CurvesGeometry::evaluated_tangents() const
threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
for (const int curve_index : curves_range) { for (const int curve_index : curves_range) {
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points), curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points),
cyclic[curve_index], cyclic[curve_index],
tangents.slice(evaluated_points)); tangents.slice(evaluated_points));
@ -694,7 +705,7 @@ Span<float3> CurvesGeometry::evaluated_tangents() const
continue; continue;
} }
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
const float epsilon = 1e-6f; const float epsilon = 1e-6f;
if (!math::almost_equal_relative( if (!math::almost_equal_relative(
@ -729,7 +740,7 @@ static void evaluate_generic_data_for_curve(
const VArray<int8_t> &types, const VArray<int8_t> &types,
const VArray<bool> &cyclic, const VArray<bool> &cyclic,
const VArray<int> &resolution, const VArray<int> &resolution,
const Span<int> bezier_evaluated_offsets, const Span<int> all_bezier_evaluated_offsets,
const Span<curves::nurbs::BasisCache> nurbs_basis_cache, const Span<curves::nurbs::BasisCache> nurbs_basis_cache,
const VArray<int8_t> &nurbs_orders, const VArray<int8_t> &nurbs_orders,
const Span<float> nurbs_weights, const Span<float> nurbs_weights,
@ -744,9 +755,12 @@ static void evaluate_generic_data_for_curve(
case CURVE_TYPE_POLY: case CURVE_TYPE_POLY:
dst.copy_from(src); dst.copy_from(src);
break; break;
case CURVE_TYPE_BEZIER: case CURVE_TYPE_BEZIER: {
curves::bezier::interpolate_to_evaluated(src, bezier_evaluated_offsets.slice(points), dst); const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
curves::bezier::interpolate_to_evaluated(
src, all_bezier_evaluated_offsets.slice(offsets), dst);
break; break;
}
case CURVE_TYPE_NURBS: case CURVE_TYPE_NURBS:
curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index], curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index],
nurbs_orders[curve_index], nurbs_orders[curve_index],
@ -761,6 +775,7 @@ Span<float3> CurvesGeometry::evaluated_normals() const
{ {
this->runtime->normal_cache_mutex.ensure([&]() { this->runtime->normal_cache_mutex.ensure([&]() {
const OffsetIndices<int> points_by_curve = this->points_by_curve(); const OffsetIndices<int> points_by_curve = this->points_by_curve();
const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
const VArray<int8_t> types = this->curve_types(); const VArray<int8_t> types = this->curve_types();
const VArray<bool> cyclic = this->cyclic(); const VArray<bool> cyclic = this->cyclic();
const VArray<int8_t> normal_mode = this->normal_mode(); const VArray<int8_t> normal_mode = this->normal_mode();
@ -784,7 +799,7 @@ Span<float3> CurvesGeometry::evaluated_normals() const
Vector<float> evaluated_tilts; Vector<float> evaluated_tilts;
for (const int curve_index : curves_range) { for (const int curve_index : curves_range) {
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
switch (normal_mode[curve_index]) { switch (normal_mode[curve_index]) {
case NORMAL_MODE_Z_UP: case NORMAL_MODE_Z_UP:
curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points), curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points),
@ -813,7 +828,7 @@ Span<float3> CurvesGeometry::evaluated_normals() const
types, types,
cyclic, cyclic,
resolution, resolution,
this->runtime->bezier_evaluated_offsets.as_span(), this->runtime->all_bezier_evaluated_offsets.as_span(),
this->runtime->nurbs_basis_cache.as_span(), this->runtime->nurbs_basis_cache.as_span(),
nurbs_orders, nurbs_orders,
nurbs_weights, nurbs_weights,
@ -839,13 +854,13 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices points_by_curve = this->points_by_curve();
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
BLI_assert(src.size() == points.size()); BLI_assert(src.size() == points.size());
BLI_assert(dst.size() == this->evaluated_points_for_curve(curve_index).size()); BLI_assert(dst.size() == this->evaluated_points_by_curve().size(curve_index));
evaluate_generic_data_for_curve(curve_index, evaluate_generic_data_for_curve(curve_index,
points, points,
this->curve_types(), this->curve_types(),
this->cyclic(), this->cyclic(),
this->resolution(), this->resolution(),
this->runtime->bezier_evaluated_offsets.as_span(), this->runtime->all_bezier_evaluated_offsets.as_span(),
this->runtime->nurbs_basis_cache.as_span(), this->runtime->nurbs_basis_cache.as_span(),
this->nurbs_orders(), this->nurbs_orders(),
this->nurbs_weights(), this->nurbs_weights(),
@ -858,6 +873,7 @@ void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst)
BLI_assert(this->runtime->offsets_cache_mutex.is_cached()); BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached()); BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached());
const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices points_by_curve = this->points_by_curve();
const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve();
const VArray<int8_t> types = this->curve_types(); const VArray<int8_t> types = this->curve_types();
const VArray<int> resolution = this->resolution(); const VArray<int> resolution = this->resolution();
const VArray<bool> cyclic = this->cyclic(); const VArray<bool> cyclic = this->cyclic();
@ -867,13 +883,13 @@ void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst)
threading::parallel_for(this->curves_range(), 512, [&](IndexRange curves_range) { threading::parallel_for(this->curves_range(), 512, [&](IndexRange curves_range) {
for (const int curve_index : curves_range) { for (const int curve_index : curves_range) {
const IndexRange points = points_by_curve[curve_index]; const IndexRange points = points_by_curve[curve_index];
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
evaluate_generic_data_for_curve(curve_index, evaluate_generic_data_for_curve(curve_index,
points, points,
types, types,
cyclic, cyclic,
resolution, resolution,
this->runtime->bezier_evaluated_offsets, this->runtime->all_bezier_evaluated_offsets,
this->runtime->nurbs_basis_cache, this->runtime->nurbs_basis_cache,
nurbs_orders, nurbs_orders,
nurbs_weights, nurbs_weights,
@ -892,13 +908,14 @@ void CurvesGeometry::ensure_evaluated_lengths() const
this->runtime->evaluated_length_cache.resize(total_num); this->runtime->evaluated_length_cache.resize(total_num);
MutableSpan<float> evaluated_lengths = this->runtime->evaluated_length_cache; MutableSpan<float> evaluated_lengths = this->runtime->evaluated_length_cache;
Span<float3> evaluated_positions = this->evaluated_positions(); const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
VArray<bool> curves_cyclic = this->cyclic(); const Span<float3> evaluated_positions = this->evaluated_positions();
const VArray<bool> curves_cyclic = this->cyclic();
threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
for (const int curve_index : curves_range) { for (const int curve_index : curves_range) {
const bool cyclic = curves_cyclic[curve_index]; const bool cyclic = curves_cyclic[curve_index];
const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index); const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic); const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic);
length_parameterize::accumulate_lengths(evaluated_positions.slice(evaluated_points), length_parameterize::accumulate_lengths(evaluated_positions.slice(evaluated_points),
cyclic, cyclic,
@ -910,7 +927,7 @@ void CurvesGeometry::ensure_evaluated_lengths() const
void CurvesGeometry::ensure_can_interpolate_to_evaluated() const void CurvesGeometry::ensure_can_interpolate_to_evaluated() const
{ {
this->ensure_evaluated_offsets(); this->evaluated_points_by_curve();
this->ensure_nurbs_basis_cache(); this->ensure_nurbs_basis_cache();
} }

View File

@ -10,16 +10,16 @@
namespace blender::bke::curves { namespace blender::bke::curves {
void fill_curve_counts(const bke::CurvesGeometry &curves, void copy_curve_sizes(const bke::CurvesGeometry &curves,
const Span<IndexRange> curve_ranges, const Span<IndexRange> curve_ranges,
MutableSpan<int> counts) MutableSpan<int> sizes)
{ {
const OffsetIndices points_by_curve = curves.points_by_curve(); const OffsetIndices points_by_curve = curves.points_by_curve();
threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) { threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) {
for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) { for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) {
threading::parallel_for(curves_range, 4096, [&](IndexRange range) { threading::parallel_for(curves_range, 4096, [&](IndexRange range) {
for (const int i : range) { for (const int i : range) {
counts[i] = points_by_curve.size(i); sizes[i] = points_by_curve.size(i);
} }
}); });
} }

View File

@ -5285,7 +5285,6 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
default: default:
return nullptr; return nullptr;
} }
return nullptr;
} }
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type) eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)

View File

@ -237,9 +237,11 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
return DT_MULTILAYER_INDEX_UV; return DT_MULTILAYER_INDEX_UV;
case DT_TYPE_MPROPCOL_VERT: case DT_TYPE_MPROPCOL_VERT:
case DT_TYPE_MLOOPCOL_VERT: case DT_TYPE_MLOOPCOL_VERT:
case DT_TYPE_MPROPCOL_VERT | DT_TYPE_MLOOPCOL_VERT:
return DT_MULTILAYER_INDEX_VCOL_VERT; return DT_MULTILAYER_INDEX_VCOL_VERT;
case DT_TYPE_MPROPCOL_LOOP: case DT_TYPE_MPROPCOL_LOOP:
case DT_TYPE_MLOOPCOL_LOOP: case DT_TYPE_MLOOPCOL_LOOP:
case DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP:
return DT_MULTILAYER_INDEX_VCOL_LOOP; return DT_MULTILAYER_INDEX_VCOL_LOOP;
default: default:
return DT_MULTILAYER_INDEX_INVALID; return DT_MULTILAYER_INDEX_INVALID;

View File

@ -144,6 +144,7 @@ namespace blender::bke {
static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves) static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves)
{ {
const OffsetIndices points_by_curve = curves.points_by_curve(); const OffsetIndices points_by_curve = curves.points_by_curve();
const OffsetIndices evaluated_points_by_curve = curves.evaluated_points_by_curve();
const VArray<int8_t> types = curves.curve_types(); const VArray<int8_t> types = curves.curve_types();
const VArray<int> resolutions = curves.resolution(); const VArray<int> resolutions = curves.resolution();
const VArray<bool> curves_cyclic = curves.cyclic(); const VArray<bool> curves_cyclic = curves.cyclic();
@ -160,7 +161,7 @@ static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves
for (const int i_curve : range) { for (const int i_curve : range) {
const IndexRange points = points_by_curve[i_curve]; const IndexRange points = points_by_curve[i_curve];
const IndexRange evaluated_points = curves.evaluated_points_for_curve(i_curve); const IndexRange evaluated_points = evaluated_points_by_curve[i_curve];
MutableSpan<float3> curve_normals = results.as_mutable_span().slice(points); MutableSpan<float3> curve_normals = results.as_mutable_span().slice(points);
@ -181,7 +182,7 @@ static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves
curve_normals.first() = normals.first(); curve_normals.first() = normals.first();
const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve); const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
for (const int i : IndexRange(points.size()).drop_front(1)) { for (const int i : IndexRange(points.size()).drop_front(1)) {
curve_normals[i] = normals[offsets[i - 1]]; curve_normals[i] = normals[offsets[i]];
} }
break; break;
} }
@ -242,7 +243,7 @@ static VArray<float> construct_curve_length_gvarray(const CurvesGeometry &curves
{ {
curves.ensure_evaluated_lengths(); curves.ensure_evaluated_lengths();
VArray<bool> cyclic = curves.cyclic(); const VArray<bool> cyclic = curves.cyclic();
VArray<float> lengths = VArray<float>::ForFunc( VArray<float> lengths = VArray<float>::ForFunc(
curves.curves_num(), [&curves, cyclic = std::move(cyclic)](int64_t index) { curves.curves_num(), [&curves, cyclic = std::move(cyclic)](int64_t index) {
return curves.evaluated_length_total_for_curve(index, cyclic[index]); return curves.evaluated_length_total_for_curve(index, cyclic[index]);

View File

@ -1566,7 +1566,6 @@ bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_not_found) bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_not_found)
{ {
bGPDlayer *gpl; bGPDlayer *gpl;
int i = 0;
/* error checking */ /* error checking */
if (ELEM(NULL, gpd, gpd->layers.first)) { if (ELEM(NULL, gpd, gpd->layers.first)) {
@ -1578,7 +1577,6 @@ bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_
if (STREQ(name, gpl->info)) { if (STREQ(name, gpl->info)) {
return gpl; return gpl;
} }
i++;
} }
/* no such layer */ /* no such layer */

View File

@ -971,7 +971,7 @@ static float *gpencil_stroke_points_from_editcurve_adaptive_resolu(
MEM_freeN(segment_point_lengths); MEM_freeN(segment_point_lengths);
*r_points_len = points_len; *r_points_len = points_len;
return (float(*))r_points; return (float *)r_points;
} }
/** /**
@ -1012,7 +1012,7 @@ static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point
} }
*r_points_len = points_len; *r_points_len = points_len;
return (float(*))r_points; return (float *)r_points;
} }
void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps, void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps,

View File

@ -636,8 +636,6 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
} }
return false; return false;
return false;
} }
LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index) LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index)
@ -1210,6 +1208,7 @@ static void layer_collection_sync(ViewLayer *view_layer,
layer_resync->layer->layer_collections = new_lb_layer; layer_resync->layer->layer_collections = new_lb_layer;
BLI_assert(BLI_listbase_count(&layer_resync->collection->children) - skipped_children == BLI_assert(BLI_listbase_count(&layer_resync->collection->children) - skipped_children ==
BLI_listbase_count(&new_lb_layer)); BLI_listbase_count(&new_lb_layer));
UNUSED_VARS_NDEBUG(skipped_children);
/* Update bases etc. for objects. */ /* Update bases etc. for objects. */
layer_collection_objects_sync(view_layer, layer_collection_objects_sync(view_layer,

View File

@ -1521,6 +1521,30 @@ void BKE_nlastrip_recalculate_bounds(NlaStrip *strip)
nlastrip_fix_resize_overlaps(strip); nlastrip_fix_resize_overlaps(strip);
} }
void BKE_nlastrip_recalculate_blend(NlaStrip *strip)
{
/* check if values need to be re-calculated. */
if (strip->blendin == 0 && strip->blendout == 0) {
return;
}
const double strip_len = strip->end - strip->start;
double blend_in = strip->blendin;
double blend_out = strip->blendout;
double blend_in_max = strip_len - blend_out;
CLAMP_MIN(blend_in_max, 0);
/* blend-out is limited to the length of the strip. */
CLAMP(blend_in, 0, blend_in_max);
CLAMP(blend_out, 0, strip_len - blend_in);
strip->blendin = blend_in;
strip->blendout = blend_out;
}
/* Animated Strips ------------------------------------------- */ /* Animated Strips ------------------------------------------- */
bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt) bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
@ -1854,6 +1878,7 @@ void BKE_nla_validate_state(AnimData *adt)
for (strip = nlt->strips.first; strip; strip = strip->next) { for (strip = nlt->strips.first; strip; strip = strip->next) {
/* auto-blending first */ /* auto-blending first */
BKE_nlastrip_validate_autoblends(nlt, strip); BKE_nlastrip_validate_autoblends(nlt, strip);
BKE_nlastrip_recalculate_blend(strip);
} }
} }
} }

View File

@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
#include "BKE_nla.h"
#include "DNA_anim_types.h"
#include "DNA_nla_types.h"
#include "MEM_guardedalloc.h"
#include "testing/testing.h"
namespace blender::bke::tests {
TEST(nla_strip, BKE_nlastrip_recalculate_blend)
{
NlaStrip strip{};
strip.blendin = 4.0;
strip.blendout = 5.0;
strip.start = 1;
strip.end = 10;
/* Scaling a strip up doesn't affect the blend in/out value */
strip.end = 20;
BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 4.0);
EXPECT_FLOAT_EQ(strip.blendout, 5.0);
/* Scaling a strip down affects the blend-in value before the blend-out value */
strip.end = 7;
BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 1.0);
EXPECT_FLOAT_EQ(strip.blendout, 5.0);
/* Scaling a strip down to nothing updates the blend in/out values accordingly */
strip.end = 1.1;
BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 0.0);
EXPECT_FLOAT_EQ(strip.blendout, 0.1);
}
} // namespace blender::bke::tests

View File

@ -2629,8 +2629,6 @@ bool BKE_sculpt_attribute_exists(Object *ob,
CustomData *cdata = sculpt_get_cdata(ob, domain); CustomData *cdata = sculpt_get_cdata(ob, domain);
return CustomData_get_named_layer_index(cdata, proptype, name) != -1; return CustomData_get_named_layer_index(cdata, proptype, name) != -1;
return false;
} }
static SculptAttribute *sculpt_alloc_attr(SculptSession *ss) static SculptAttribute *sculpt_alloc_attr(SculptSession *ss)

View File

@ -464,11 +464,11 @@ static void subdiv_vertex_orco_evaluate(const SubdivMeshContext *ctx,
if (ctx->orco) { if (ctx->orco) {
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data); copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data);
if (ctx->cloth_orco) { if (ctx->cloth_orco) {
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data + 3); copy_v3_v3(ctx->cloth_orco[subdiv_vertex_index], vertex_data + 3);
} }
} }
else if (ctx->cloth_orco) { else if (ctx->cloth_orco) {
copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data); copy_v3_v3(ctx->cloth_orco[subdiv_vertex_index], vertex_data);
} }
} }
} }

View File

@ -39,6 +39,18 @@ template<typename T> class OffsetIndices {
return size; return size;
} }
/** Return the total number of elements in the the referenced arrays. */
T total_size() const
{
return offsets_.last();
}
/** Return the number of ranges encoded by the offsets. */
T ranges_num() const
{
return offsets_.size() - 1;
}
IndexRange operator[](const int64_t index) const IndexRange operator[](const int64_t index) const
{ {
BLI_assert(index >= 0); BLI_assert(index >= 0);
@ -56,6 +68,17 @@ template<typename T> class OffsetIndices {
const int64_t size = end - begin; const int64_t size = end - begin;
return IndexRange(begin, size); return IndexRange(begin, size);
} }
/**
* Return a subset of the offsets desribing the specified range of source elements.
* This is a slice into the source ranges rather than the indexed elements described by the
* offset values.
*/
OffsetIndices slice(const IndexRange range) const
{
BLI_assert(offsets_.index_range().drop_back(1).contains(range.last()));
return OffsetIndices(offsets_.slice(range.start(), range.one_after_last()));
}
}; };
/** /**

View File

@ -361,7 +361,6 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx,
{ {
const uint poly_num = (uint)sf_ctx->poly_nr + 1; const uint poly_num = (uint)sf_ctx->poly_nr + 1;
uint eed_index = 0; uint eed_index = 0;
int totvert_new = 0;
bool changed = false; bool changed = false;
PolyInfo *poly_info; PolyInfo *poly_info;
@ -453,7 +452,6 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx,
if (eve->user_flag != 1) { if (eve->user_flag != 1) {
BLI_remlink(&sf_ctx->fillvertbase, eve); BLI_remlink(&sf_ctx->fillvertbase, eve);
BLI_addtail(remvertbase, eve); BLI_addtail(remvertbase, eve);
totvert_new--;
} }
else { else {
eve->user_flag = 0; eve->user_flag = 0;

View File

@ -196,11 +196,9 @@ TEST(task, MempoolIterTLS)
int i; int i;
/* Add numbers negative `1..ITEMS_NUM` inclusive. */ /* Add numbers negative `1..ITEMS_NUM` inclusive. */
int items_num = 0;
for (i = 0; i < ITEMS_NUM; i++) { for (i = 0; i < ITEMS_NUM; i++) {
data[i] = (int *)BLI_mempool_alloc(mempool); data[i] = (int *)BLI_mempool_alloc(mempool);
*data[i] = -(i + 1); *data[i] = -(i + 1);
items_num++;
} }
TaskParallelSettings settings; TaskParallelSettings settings;

View File

@ -179,12 +179,6 @@ if(WITH_BULLET)
${BULLET_INCLUDE_DIRS} ${BULLET_INCLUDE_DIRS}
../../../intern/rigidbody ../../../intern/rigidbody
) )
if(NOT WITH_SYSTEM_BULLET)
list(APPEND LIB
extern_bullet
)
endif()
list(APPEND LIB list(APPEND LIB
${BULLET_LIBRARIES} ${BULLET_LIBRARIES}
) )

View File

@ -149,14 +149,12 @@ void BM_face_interp_from_face_ex(BMesh *bm,
float *w = BLI_array_alloca(w, f_src->len); float *w = BLI_array_alloca(w, f_src->len);
float co[2]; float co[2];
int i;
if (f_src != f_dst) { if (f_src != f_dst) {
BM_elem_attrs_copy(bm, bm, f_src, f_dst); BM_elem_attrs_copy(bm, bm, f_src, f_dst);
} }
/* interpolate */ /* interpolate */
i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
do { do {
mul_v2_m3v3(co, axis_mat, l_iter->v->co); mul_v2_m3v3(co, axis_mat, l_iter->v->co);
@ -165,7 +163,7 @@ void BM_face_interp_from_face_ex(BMesh *bm,
if (do_vertex) { if (do_vertex) {
CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data); CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
} }
} while ((void)i++, (l_iter = l_iter->next) != l_first); } while ((l_iter = l_iter->next) != l_first);
} }
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex) void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)

View File

@ -1342,10 +1342,9 @@ bool BM_mesh_intersect(BMesh *bm,
GHASH_ITER (gh_iter, s.face_edges) { GHASH_ITER (gh_iter, s.face_edges) {
struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter); struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
LinkNode **node_prev_p; LinkNode **node_prev_p;
uint i;
node_prev_p = &e_ls_base->list; node_prev_p = &e_ls_base->list;
for (i = 0, node = e_ls_base->list; node; i++, node = node->next) { for (node = e_ls_base->list; node; node = node->next) {
BMEdge *e = node->link; BMEdge *e = node->link;
if (BM_elem_flag_test(e, BM_ELEM_TAG)) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
/* allocated by arena, don't free */ /* allocated by arena, don't free */

View File

@ -16,6 +16,8 @@ set(INC
../../../../intern/guardedalloc ../../../../intern/guardedalloc
) )
set(INC_SYS
)
set(SRC set(SRC
intern/compile_state.cc intern/compile_state.cc

View File

@ -35,7 +35,6 @@ set(INC
# dna_type_offsets.h # dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern ${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern
${OPENSUBDIV_INCLUDE_DIRS}
) )
set(SRC set(SRC
@ -724,6 +723,12 @@ if(WITH_DRAW_DEBUG)
add_definitions(-DWITH_DRAW_DEBUG) add_definitions(-DWITH_DRAW_DEBUG)
endif() endif()
if(WITH_OPENSUBDIV)
list(APPEND INC_SYS
${OPENSUBDIV_INCLUDE_DIRS}
)
endif()
if(WITH_MOD_FLUID) if(WITH_MOD_FLUID)
list(APPEND INC list(APPEND INC
../../../intern/mantaflow/extern ../../../intern/mantaflow/extern

View File

@ -29,6 +29,8 @@
#include "GPU_texture.h" #include "GPU_texture.h"
#include "compositor_engine.h" /* Own include. */
namespace blender::draw::compositor { namespace blender::draw::compositor {
class TexturePool : public realtime_compositor::TexturePool { class TexturePool : public realtime_compositor::TexturePool {

View File

@ -67,7 +67,6 @@ static const char *workbench_lighting_mode_to_str(int light)
return "_matcap"; return "_matcap";
case V3D_LIGHTING_FLAT: case V3D_LIGHTING_FLAT:
return "_flat"; return "_flat";
return "";
} }
} }

View File

@ -42,6 +42,7 @@ using blender::Array;
using blender::ColorGeometry4f; using blender::ColorGeometry4f;
using blender::float3; using blender::float3;
using blender::IndexRange; using blender::IndexRange;
using blender::OffsetIndices;
using blender::Span; using blender::Span;
/* See: edit_curve_point_vert.glsl for duplicate includes. */ /* See: edit_curve_point_vert.glsl for duplicate includes. */
@ -103,14 +104,14 @@ static void curve_eval_render_wire_verts_edges_len_get(const blender::bke::Curve
int *r_vert_len, int *r_vert_len,
int *r_edge_len) int *r_edge_len)
{ {
*r_curve_len = curves.curves_num(); const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
*r_vert_len = curves.evaluated_points_num();
*r_edge_len = 0;
const blender::VArray<bool> cyclic = curves.cyclic(); const blender::VArray<bool> cyclic = curves.cyclic();
*r_curve_len = curves.curves_num();
*r_vert_len = points_by_curve.total_size();
*r_edge_len = 0;
for (const int i : curves.curves_range()) { for (const int i : curves.curves_range()) {
const IndexRange points = curves.evaluated_points_for_curve(i); *r_edge_len += blender::bke::curves::segments_num(points_by_curve.size(i), cyclic[i]);
*r_edge_len += blender::bke::curves::segments_num(points.size(), cyclic[i]);
} }
} }
@ -480,6 +481,7 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
static void curve_create_attribute(CurveRenderData *rdata, GPUVertBuf *vbo_attr) static void curve_create_attribute(CurveRenderData *rdata, GPUVertBuf *vbo_attr)
{ {
using namespace blender;
if (rdata->curve_eval == nullptr) { if (rdata->curve_eval == nullptr) {
return; return;
} }
@ -493,18 +495,17 @@ static void curve_create_attribute(CurveRenderData *rdata, GPUVertBuf *vbo_attr)
GPU_vertbuf_init_with_format(vbo_attr, &format); GPU_vertbuf_init_with_format(vbo_attr, &format);
GPU_vertbuf_data_alloc(vbo_attr, vert_len); GPU_vertbuf_data_alloc(vbo_attr, vert_len);
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(rdata->curve_eval->geometry);
rdata->curve_eval->geometry);
curves.ensure_can_interpolate_to_evaluated(); curves.ensure_can_interpolate_to_evaluated();
const blender::VArraySpan<ColorGeometry4f> colors = curves.attributes().lookup<ColorGeometry4f>( const VArraySpan<ColorGeometry4f> colors = curves.attributes().lookup<ColorGeometry4f>(
".viewer", ATTR_DOMAIN_POINT); ".viewer", ATTR_DOMAIN_POINT);
ColorGeometry4f *vbo_data = static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(vbo_attr)); ColorGeometry4f *vbo_data = static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(vbo_attr));
curves.interpolate_to_evaluated(colors, curves.interpolate_to_evaluated(colors, MutableSpan<ColorGeometry4f>{vbo_data, vert_len});
blender::MutableSpan<ColorGeometry4f>{vbo_data, vert_len});
} }
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines) static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
{ {
using namespace blender;
if (rdata->curve_eval == nullptr) { if (rdata->curve_eval == nullptr) {
return; return;
} }
@ -518,11 +519,12 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPUIndexBufBuilder elb; GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len); GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(rdata->curve_eval->geometry);
rdata->curve_eval->geometry); const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
const blender::VArray<bool> cyclic = curves.cyclic(); const VArray<bool> cyclic = curves.cyclic();
for (const int i : curves.curves_range()) { for (const int i : curves.curves_range()) {
const IndexRange points = curves.evaluated_points_for_curve(i); const IndexRange points = points_by_curve[i];
if (cyclic[i] && points.size() > 1) { if (cyclic[i] && points.size() > 1) {
GPU_indexbuf_add_generic_vert(&elb, points.last()); GPU_indexbuf_add_generic_vert(&elb, points.last());
} }

View File

@ -17,6 +17,8 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
anim_channels_defines.c anim_channels_defines.c

View File

@ -343,8 +343,12 @@ static void fcurve_scene_coord_range_get(Scene *scene,
int end = fcu->totvert; int end = fcu->totvert;
if (use_preview_only) { if (use_preview_only) {
start = scene->r.psfra; /* Preview frame ranges need to be converted to bezt array indices. */
end = min_ii(scene->r.pefra + 1, fcu->totvert); bool replace = false;
start = BKE_fcurve_bezt_binarysearch_index(
fcu->bezt, scene->r.psfra, fcu->totvert, &replace);
end = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, scene->r.pefra, fcu->totvert, &replace);
} }
if (fcu->bezt) { if (fcu->bezt) {

View File

@ -887,8 +887,7 @@ void ANIM_fmodifier_panels(const bContext *C,
if (!panels_match) { if (!panels_match) {
UI_panels_free_instanced(C, region); UI_panels_free_instanced(C, region);
FModifier *fcm = fmodifiers->first; for (FModifier *fcm = fmodifiers->first; fcm; fcm = fcm->next) {
for (int i = 0; fcm; i++, fcm = fcm->next) {
char panel_idname[MAX_NAME]; char panel_idname[MAX_NAME];
panel_id_fn(fcm, panel_idname); panel_id_fn(fcm, panel_idname);

View File

@ -19,6 +19,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
armature_add.c armature_add.c
armature_edit.c armature_edit.c

View File

@ -17,6 +17,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
curve_ops.c curve_ops.c
editcurve.c editcurve.c

View File

@ -18,6 +18,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
gizmo_draw_utils.c gizmo_draw_utils.c
gizmo_geometry.h gizmo_geometry.h

View File

@ -18,6 +18,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
annotate_draw.c annotate_draw.c
annotate_paint.c annotate_paint.c

View File

@ -26,6 +26,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
eyedroppers/eyedropper_color.cc eyedroppers/eyedropper_color.cc
eyedroppers/eyedropper_colorband.cc eyedroppers/eyedropper_colorband.cc

View File

@ -4197,11 +4197,9 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
/* compute max needed width and total height */ /* compute max needed width and total height */
int toth = 0; int toth = 0;
int totitem = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) { LISTBASE_FOREACH (uiItem *, item, &litem->items) {
ui_item_size(item, &itemw, &itemh); ui_item_size(item, &itemw, &itemh);
toth += itemh; toth += itemh;
totitem++;
} }
/* compute sizes */ /* compute sizes */

View File

@ -2291,8 +2291,7 @@ void uiTemplateModifiers(uiLayout * /*layout*/, bContext *C)
if (!panels_match) { if (!panels_match) {
UI_panels_free_instanced(C, region); UI_panels_free_instanced(C, region);
ModifierData *md = static_cast<ModifierData *>(modifiers->first); for (ModifierData *md = static_cast<ModifierData *>(modifiers->first); md; md = md->next) {
for (int i = 0; md; i++, md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type)); const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
if (mti->panelRegister == nullptr) { if (mti->panelRegister == nullptr) {
continue; continue;
@ -2451,9 +2450,10 @@ void uiTemplateConstraints(uiLayout * /*layout*/, bContext *C, bool use_bone_con
if (!panels_match) { if (!panels_match) {
UI_panels_free_instanced(C, region); UI_panels_free_instanced(C, region);
bConstraint *con = (constraints == nullptr) ? nullptr : for (bConstraint *con =
static_cast<bConstraint *>(constraints->first); (constraints == nullptr) ? nullptr : static_cast<bConstraint *>(constraints->first);
for (int i = 0; con; i++, con = con->next) { con;
con = con->next) {
/* Don't show invalid/legacy constraints. */ /* Don't show invalid/legacy constraints. */
if (con->type == CONSTRAINT_TYPE_NULL) { if (con->type == CONSTRAINT_TYPE_NULL) {
continue; continue;
@ -2543,8 +2543,8 @@ void uiTemplateGpencilModifiers(uiLayout * /*layout*/, bContext *C)
if (!panels_match) { if (!panels_match) {
UI_panels_free_instanced(C, region); UI_panels_free_instanced(C, region);
GpencilModifierData *md = static_cast<GpencilModifierData *>(modifiers->first); for (GpencilModifierData *md = static_cast<GpencilModifierData *>(modifiers->first); md;
for (int i = 0; md; i++, md = md->next) { md = md->next) {
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info( const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(
GpencilModifierType(md->type)); GpencilModifierType(md->type));
if (mti->panelRegister == nullptr) { if (mti->panelRegister == nullptr) {
@ -2617,8 +2617,7 @@ void uiTemplateShaderFx(uiLayout * /*layout*/, bContext *C)
if (!panels_match) { if (!panels_match) {
UI_panels_free_instanced(C, region); UI_panels_free_instanced(C, region);
ShaderFxData *fx = static_cast<ShaderFxData *>(shaderfx->first); for (ShaderFxData *fx = static_cast<ShaderFxData *>(shaderfx->first); fx; fx = fx->next) {
for (int i = 0; fx; i++, fx = fx->next) {
char panel_idname[MAX_NAME]; char panel_idname[MAX_NAME];
shaderfx_panel_id(fx, panel_idname); shaderfx_panel_id(fx, panel_idname);

View File

@ -13,6 +13,9 @@ set(INC
../../../../intern/guardedalloc ../../../../intern/guardedalloc
) )
set(INC_SYS
)
set(SRC set(SRC
mask_add.c mask_add.c
mask_draw.c mask_draw.c

View File

@ -291,6 +291,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b); BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b);
BLI_assert(tot == uid_end - uid_start); BLI_assert(tot == uid_end - uid_start);
UNUSED_VARS_NDEBUG(tot);
#if 0 #if 0
printf("%s: found contiguous edge loop of (%d)\n", __func__, uid_end - uid_start); printf("%s: found contiguous edge loop of (%d)\n", __func__, uid_end - uid_start);

View File

@ -29,6 +29,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
object_add.cc object_add.cc
object_bake.c object_bake.c

View File

@ -60,6 +60,11 @@ static const EnumPropertyItem DT_layer_items[] = {
{DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"}, {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
#endif #endif
{DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"}, {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
{DT_TYPE_MPROPCOL_VERT | DT_TYPE_MLOOPCOL_VERT,
"COLOR_VERTEX",
0,
"Colors",
"Color Attributes"},
RNA_ENUM_ITEM_HEADING(N_("Edge Data"), NULL), RNA_ENUM_ITEM_HEADING(N_("Edge Data"), NULL),
{DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"}, {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
@ -74,7 +79,11 @@ static const EnumPropertyItem DT_layer_items[] = {
RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), NULL), RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), NULL),
{DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"}, {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
{DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP, "VCOL", 0, "Colors", "Color Attributes"}, {DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP,
"COLOR_CORNER",
0,
"Colors",
"Color Attributes"},
{DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"}, {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
RNA_ENUM_ITEM_HEADING(N_("Face Data"), NULL), RNA_ENUM_ITEM_HEADING(N_("Face Data"), NULL),
@ -93,7 +102,7 @@ static void dt_add_vcol_layers(CustomData *cdata,
int *r_totitem) int *r_totitem)
{ {
int types[2] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR}; int types[2] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR};
int idx = 0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
eCustomDataType type = types[i]; eCustomDataType type = types[i];
@ -106,9 +115,8 @@ static void dt_add_vcol_layers(CustomData *cdata,
RNA_enum_item_add_separator(r_item, r_totitem); RNA_enum_item_add_separator(r_item, r_totitem);
for (int j = 0; j < num_data; j++) { for (int j = 0; j < num_data; j++) {
EnumPropertyItem tmp_item; EnumPropertyItem tmp_item = {0};
tmp_item.value = idx++;
tmp_item.value = j;
tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(cdata, type, j); tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(cdata, type, j);
RNA_enum_item_add(r_item, r_totitem, &tmp_item); RNA_enum_item_add(r_item, r_totitem, &tmp_item);
} }

View File

@ -17,6 +17,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
dynamicpaint_ops.c dynamicpaint_ops.c
particle_boids.c particle_boids.c

View File

@ -20,6 +20,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
area.c area.c
area_query.c area_query.c

View File

@ -983,13 +983,6 @@ static void region_azone_tab_plus(ScrArea *area, AZone *az, ARegion *region)
const float tab_size_x = 0.7f * U.widget_unit; const float tab_size_x = 0.7f * U.widget_unit;
const float tab_size_y = 0.4f * U.widget_unit; const float tab_size_y = 0.4f * U.widget_unit;
int tot = 0;
LISTBASE_FOREACH (AZone *, azt, &area->actionzones) {
if (azt->edge == az->edge) {
tot++;
}
}
switch (az->edge) { switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT: { case AE_TOP_TO_BOTTOMRIGHT: {
int add = (region->winrct.ymax == area->totrct.ymin) ? 1 : 0; int add = (region->winrct.ymax == area->totrct.ymin) ? 1 : 0;

View File

@ -30,15 +30,18 @@ set(LIB
) )
if(WITH_AUDASPACE) if(WITH_AUDASPACE)
list(APPEND LIB
bf_intern_audaspace
)
list(APPEND INC_SYS list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS} ${AUDASPACE_C_INCLUDE_DIRS}
) )
list(APPEND LIB if(WITH_SYSTEM_AUDASPACE)
bf_intern_audaspace list(APPEND LIB
${AUDASPACE_C_LIBRARIES}
${AUDASPACE_C_LIBRARIES} ${AUDASPACE_PY_LIBRARIES}
${AUDASPACE_PY_LIBRARIES} )
) endif()
add_definitions(-DWITH_AUDASPACE) add_definitions(-DWITH_AUDASPACE)
endif() endif()

View File

@ -19,6 +19,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
action_buttons.c action_buttons.c
action_data.c action_data.c

View File

@ -19,6 +19,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
buttons_context.c buttons_context.c
buttons_ops.c buttons_ops.c

View File

@ -22,6 +22,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
clip_buttons.c clip_buttons.c
clip_dopesheet_draw.c clip_dopesheet_draw.c

View File

@ -16,6 +16,9 @@ set(INC
${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern ${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern
) )
set(INC_SYS
)
set(SRC set(SRC
console_draw.c console_draw.c
console_ops.c console_ops.c

View File

@ -24,6 +24,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
asset_catalog_tree_view.cc asset_catalog_tree_view.cc
file_draw.c file_draw.c

View File

@ -19,6 +19,9 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS
)
set(SRC set(SRC
graph_buttons.c graph_buttons.c
graph_draw.c graph_draw.c
@ -39,15 +42,18 @@ set(LIB
) )
if(WITH_AUDASPACE) if(WITH_AUDASPACE)
list(APPEND LIB
bf_intern_audaspace
)
list(APPEND INC_SYS list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS} ${AUDASPACE_C_INCLUDE_DIRS}
) )
list(APPEND LIB if(WITH_SYSTEM_AUDASPACE)
bf_intern_audaspace list(APPEND LIB
${AUDASPACE_C_LIBRARIES}
${AUDASPACE_C_LIBRARIES} ${AUDASPACE_PY_LIBRARIES}
${AUDASPACE_PY_LIBRARIES} )
) endif()
add_definitions(-DWITH_AUDASPACE) add_definitions(-DWITH_AUDASPACE)
endif() endif()

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