Compare commits

..

5 Commits

1491 changed files with 19588 additions and 42777 deletions

View File

@@ -2,7 +2,7 @@
# Configuration of clang-format # Configuration of clang-format
# ============================= # =============================
# #
# Tested to work with versions: 8 to 11. # Tested to work with versions: 6 to 8.
# This causes parameters on continuations to align to the opening brace. # This causes parameters on continuations to align to the opening brace.
# #
@@ -255,6 +255,7 @@ ForEachMacros:
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
- SEQ_ALL_BEGIN - SEQ_ALL_BEGIN
- SEQ_CURRENT_BEGIN
- SURFACE_QUAD_ITER_BEGIN - SURFACE_QUAD_ITER_BEGIN
- foreach - foreach
- ED_screen_areas_iter - ED_screen_areas_iter
@@ -263,5 +264,8 @@ ForEachMacros:
- MAP_SLOT_PROBING_BEGIN - MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN - VECTOR_SET_SLOT_PROBING_BEGIN
StatementMacros: # Use once we bump the minimum version to version 8.
- PyObject_VAR_HEAD # # Without this string literals that in-line 'STRINGIFY' behave strangely (a bug?).
# StatementMacros:
# - PyObject_VAR_HEAD
# - STRINGIFY

View File

@@ -35,13 +35,12 @@ Checks: >
-modernize-use-auto, -modernize-use-auto,
-modernize-use-trailing-return-type, -modernize-use-trailing-return-type,
-modernize-avoid-c-arrays, -modernize-avoid-c-arrays,
-modernize-use-equals-default,
-modernize-use-nodiscard, -modernize-use-nodiscard,
-modernize-loop-convert, -modernize-loop-convert,
-modernize-pass-by-value, -modernize-pass-by-value,
# Cannot be enabled yet, because using raw string literals in tests breaks
# the windows compiler currently.
-modernize-raw-string-literal
WarningsAsErrors: '*'
CheckOptions: CheckOptions:
- key: modernize-use-default-member-init.UseAssignment - key: modernize-use-default-member-init.UseAssignment
value: 1 value: 1

3
.gitignore vendored
View File

@@ -46,6 +46,3 @@ Desktop.ini
# smoke simulation noise tile (generated) # smoke simulation noise tile (generated)
waveletNoiseTile.bin waveletNoiseTile.bin
# testing environment
/Testing

View File

@@ -236,7 +236,9 @@ option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on
mark_as_advanced(WITH_AUDASPACE) mark_as_advanced(WITH_AUDASPACE)
mark_as_advanced(WITH_SYSTEM_AUDASPACE) mark_as_advanced(WITH_SYSTEM_AUDASPACE)
set_and_warn_dependency(WITH_AUDASPACE WITH_SYSTEM_AUDASPACE OFF) if(NOT WITH_AUDASPACE)
set(WITH_SYSTEM_AUDASPACE OFF)
endif()
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON) option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
@@ -520,10 +522,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
mark_as_advanced(WITH_LINKER_LLD) mark_as_advanced(WITH_LINKER_LLD)
endif() endif()
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
mark_as_advanced(WITH_COMPILER_ASAN)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
mark_as_advanced(WITH_COMPILER_ASAN)
if(WITH_COMPILER_ASAN) if(WITH_COMPILER_ASAN)
set(_asan_defaults "\ set(_asan_defaults "\
-fsanitize=address \ -fsanitize=address \
@@ -702,8 +704,10 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF") message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
endif() endif()
set_and_warn_dependency(WITH_PYTHON WITH_CYCLES OFF) if(NOT WITH_PYTHON)
set_and_warn_dependency(WITH_PYTHON WITH_DRACO OFF) set(WITH_CYCLES OFF)
set(WITH_DRACO OFF)
endif()
if(WITH_DRACO AND NOT WITH_PYTHON_INSTALL) if(WITH_DRACO AND NOT WITH_PYTHON_INSTALL)
message(STATUS "WITH_DRACO requires WITH_PYTHON_INSTALL to be ON, disabling WITH_DRACO for now") message(STATUS "WITH_DRACO requires WITH_PYTHON_INSTALL to be ON, disabling WITH_DRACO for now")
@@ -775,7 +779,6 @@ if(WITH_INSTALL_PORTABLE)
endif() endif()
if(WITH_GHOST_SDL OR WITH_HEADLESS) if(WITH_GHOST_SDL OR WITH_HEADLESS)
message(STATUS "Disabling Ghost Wayland, X11, Input IME, and OpenXR")
set(WITH_GHOST_WAYLAND OFF) set(WITH_GHOST_WAYLAND OFF)
set(WITH_GHOST_X11 OFF) set(WITH_GHOST_X11 OFF)
set(WITH_X11_XINPUT OFF) set(WITH_X11_XINPUT OFF)
@@ -806,7 +809,7 @@ endif()
if(NOT WITH_CUDA_DYNLOAD) if(NOT WITH_CUDA_DYNLOAD)
find_package(CUDA) find_package(CUDA)
if(NOT CUDA_FOUND) if(NOT CUDA_FOUND)
message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead") message("CUDA toolkit not found, using dynamic runtime loading of libraries instead")
set(WITH_CUDA_DYNLOAD ON) set(WITH_CUDA_DYNLOAD ON)
endif() endif()
endif() endif()
@@ -1232,7 +1235,6 @@ if(WITH_OPENMP)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}") string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}") string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}") string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
else() else()
# Typically avoid adding flags as defines but we can't # Typically avoid adding flags as defines but we can't
# pass OpenMP flags to the linker for static builds, meaning # pass OpenMP flags to the linker for static builds, meaning
@@ -1243,7 +1245,6 @@ if(WITH_OPENMP)
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
endif() endif()
else() else()
message(STATUS "OpenMP not found, disabling WITH_OPENMP")
set(WITH_OPENMP OFF) set(WITH_OPENMP OFF)
endif() endif()
@@ -1319,7 +1320,6 @@ list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
if(WITH_BULLET AND WITH_SYSTEM_BULLET) if(WITH_BULLET AND WITH_SYSTEM_BULLET)
find_package(Bullet) find_package(Bullet)
if(NOT BULLET_FOUND) if(NOT BULLET_FOUND)
message(STATUS "Bullet not found, disabling WITH_BULLET")
set(WITH_BULLET OFF) set(WITH_BULLET OFF)
endif() endif()
else() else()
@@ -1955,10 +1955,10 @@ if(FIRST_RUN)
info_cfg_option(WITH_JACK) info_cfg_option(WITH_JACK)
info_cfg_option(WITH_JACK_DYNLOAD) info_cfg_option(WITH_JACK_DYNLOAD)
info_cfg_option(WITH_OPENAL) info_cfg_option(WITH_OPENAL)
info_cfg_option(WITH_PULSEAUDIO)
info_cfg_option(WITH_PULSEAUDIO_DYNLOAD)
info_cfg_option(WITH_SDL) info_cfg_option(WITH_SDL)
info_cfg_option(WITH_SDL_DYNLOAD) info_cfg_option(WITH_SDL_DYNLOAD)
info_cfg_option(WITH_PULSEAUDIO)
info_cfg_option(WITH_PULSEAUDIO_DYNLOAD)
info_cfg_option(WITH_WASAPI) info_cfg_option(WITH_WASAPI)
info_cfg_text("Compression:") info_cfg_text("Compression:")

View File

@@ -128,14 +128,8 @@ Utilities
* source_archive: * source_archive:
Create a compressed archive of the source code. Create a compressed archive of the source code.
* source_archive_complete:
Create a compressed archive of the source code and all the libraries of dependencies.
* update: * update:
Updates git and all submodules and svn. updates git and all submodules
* update_code:
Updates git and all submodules but not svn.
* format: * format:
Format source code using clang (uses PATHS if passed in). For example:: Format source code using clang (uses PATHS if passed in). For example::
@@ -480,9 +474,6 @@ check_smatch: .FORCE
cd "$(BUILD_DIR)" ; \ cd "$(BUILD_DIR)" ; \
$(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py" $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py"
check_mypy: .FORCE
$(PYTHON) "$(BLENDER_DIR)/source/tools/check_source/check_mypy.py"
check_spelling_py: .FORCE check_spelling_py: .FORCE
cd "$(BUILD_DIR)" ; \ cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \ PYTHONIOENCODING=utf_8 $(PYTHON) \
@@ -517,13 +508,6 @@ check_descriptions: .FORCE
source_archive: .FORCE source_archive: .FORCE
python3 ./build_files/utils/make_source_archive.py python3 ./build_files/utils/make_source_archive.py
source_archive_complete: .FORCE
cmake -S "$(BLENDER_DIR)/build_files/build_environment" -B"$(BUILD_DIR)/source_archive" \
-DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE) -DPACKAGE_USE_UPSTREAM_SOURCES=OFF
# This assumes CMake is still using a default `PACKAGE_DIR` variable:
python3 ./build_files/utils/make_source_archive.py --include-packages "$(BUILD_DIR)/source_archive/packages"
INKSCAPE_BIN?="inkscape" INKSCAPE_BIN?="inkscape"
icons: .FORCE icons: .FORCE
BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \
@@ -538,9 +522,6 @@ icons_geom: .FORCE
update: .FORCE update: .FORCE
$(PYTHON) ./build_files/utils/make_update.py $(PYTHON) ./build_files/utils/make_update.py
update_code: .FORCE
$(PYTHON) ./build_files/utils/make_update.py --no-libraries
format: .FORCE format: .FORCE
PATH="../lib/${OS_NCASE}_${CPU}/llvm/bin/:../lib/${OS_NCASE}_centos7_${CPU}/llvm/bin/:../lib/${OS_NCASE}/llvm/bin/:$(PATH)" \ PATH="../lib/${OS_NCASE}_${CPU}/llvm/bin/:../lib/${OS_NCASE}_centos7_${CPU}/llvm/bin/:../lib/${OS_NCASE}/llvm/bin/:$(PATH)" \
$(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS) $(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS)

View File

@@ -12,7 +12,7 @@ function(download_source dep)
if(NOT EXISTS ${TARGET_FILE}) if(NOT EXISTS ${TARGET_FILE})
message("Checking source : ${dep} - source not found downloading from ${TARGET_URI}") message("Checking source : ${dep} - source not found downloading from ${TARGET_URI}")
file(DOWNLOAD ${TARGET_URI} ${TARGET_FILE} file(DOWNLOAD ${TARGET_URI} ${TARGET_FILE}
TIMEOUT 1800 # seconds TIMEOUT 60 # seconds
EXPECTED_HASH ${TARGET_HASH_TYPE}=${TARGET_HASH} EXPECTED_HASH ${TARGET_HASH_TYPE}=${TARGET_HASH}
TLS_VERIFY ON TLS_VERIFY ON
SHOW_PROGRESS SHOW_PROGRESS

View File

@@ -68,6 +68,7 @@ set(OPENIMAGEIO_EXTRA_ARGS
-DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/ -DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/
-DBoost_NO_SYSTEM_PATHS=ON -DBoost_NO_SYSTEM_PATHS=ON
-DBoost_NO_BOOST_CMAKE=ON -DBoost_NO_BOOST_CMAKE=ON
-OIIO_BUILD_CPP11=ON
-DUSE_LIBSQUISH=OFF -DUSE_LIBSQUISH=OFF
-DUSE_QT5=OFF -DUSE_QT5=OFF
-DUSE_NUKE=OFF -DUSE_NUKE=OFF

View File

@@ -21,8 +21,7 @@ if(WIN32)
endif() endif()
option(WITH_WEBP "Enable building of oiio with webp support" OFF) option(WITH_WEBP "Enable building of oiio with webp support" OFF)
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF) option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES) set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with")
if(NOT BUILD_MODE) if(NOT BUILD_MODE)
set(BUILD_MODE "Release") set(BUILD_MODE "Release")
@@ -37,8 +36,14 @@ else(BUILD_MODE STREQUAL "Debug")
endif() endif()
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files") set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")
# This path must be hard-coded like this, so that the GNUmakefile knows where it is and can pass it to make_source_archive.py: # look in blenders source folder for packages directory, if that exists
set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages") # it will our package folder, otherwise it will be in the build folder
if(EXISTS "${CMAKE_SOURCE_DIR}/../../packages")
set(PACKAGE_DIR_DEFAULT "${CMAKE_SOURCE_DIR}/../../packages")
else()
set(PACKAGE_DIR_DEFAULT "${CMAKE_CURRENT_BINARY_DIR}/packages")
endif()
set(PACKAGE_DIR ${PACKAGE_DIR_DEFAULT} CACHE STRING "Path for downloaded source files")
option(PACKAGE_USE_UPSTREAM_SOURCES "Use soures upstream to download the package sources, when OFF the blender mirror will be used" ON) option(PACKAGE_USE_UPSTREAM_SOURCES "Use soures upstream to download the package sources, when OFF the blender mirror will be used" ON)
file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR) file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)

View File

@@ -63,19 +63,3 @@ diff -Naur org/CMakeLists.txt external_osl/CMakeLists.txt
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem") set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
if (OSL_NO_DEFAULT_TEXTURESYSTEM) if (OSL_NO_DEFAULT_TEXTURESYSTEM)
diff --git a/src/liboslexec/llvm_util.cpp b/src/liboslexec/llvm_util.cpp
index 445f6400..3d468de2 100644
--- a/src/liboslexec/llvm_util.cpp
+++ b/src/liboslexec/llvm_util.cpp
@@ -3430,8 +3430,9 @@ LLVM_Util::call_function (llvm::Value *func, cspan<llvm::Value *> args)
#endif
//llvm_gen_debug_printf (std::string("start ") + std::string(name));
#if OSL_LLVM_VERSION >= 110
- OSL_DASSERT(llvm::isa<llvm::Function>(func));
- llvm::Value *r = builder().CreateCall(llvm::cast<llvm::Function>(func), llvm::ArrayRef<llvm::Value *>(args.data(), args.size()));
+ llvm::Value* r = builder().CreateCall(
+ llvm::cast<llvm::FunctionType>(func->getType()->getPointerElementType()), func,
+ llvm::ArrayRef<llvm::Value*>(args.data(), args.size()));
#else
llvm::Value *r = builder().CreateCall (func, llvm::ArrayRef<llvm::Value *>(args.data(), args.size()));
#endif

View File

@@ -85,8 +85,8 @@ class VersionInfo:
version_number = int(self._parse_header_file(blender_h, 'BLENDER_VERSION')) version_number = int(self._parse_header_file(blender_h, 'BLENDER_VERSION'))
version_number_patch = int(self._parse_header_file(blender_h, 'BLENDER_VERSION_PATCH')) version_number_patch = int(self._parse_header_file(blender_h, 'BLENDER_VERSION_PATCH'))
version_numbers = (version_number // 100, version_number % 100, version_number_patch) version_numbers = (version_number // 100, version_number % 100, version_number_patch)
self.short_version = "%d.%d" % (version_numbers[0], version_numbers[1]) self.short_version = "%d.%02d" % (version_numbers[0], version_numbers[1])
self.version = "%d.%d.%d" % version_numbers self.version = "%d.%02d.%d" % version_numbers
self.version_cycle = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE') self.version_cycle = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE')
self.hash = self._parse_header_file(buildinfo_h, 'BUILD_HASH')[1:-1] self.hash = self._parse_header_file(buildinfo_h, 'BUILD_HASH')[1:-1]

View File

@@ -75,7 +75,7 @@ FIND_PATH(OSL_SHADER_DIR
/usr/share/OSL/ /usr/share/OSL/
/usr/include/OSL/ /usr/include/OSL/
PATH_SUFFIXES PATH_SUFFIXES
share/OSL/shaders shaders
) )
# handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if # handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if

View File

@@ -28,14 +28,6 @@ if sys.version_info.major < 3:
sys.version.partition(" ")[0]) sys.version.partition(" ")[0])
sys.exit(1) sys.exit(1)
import os
from os.path import (
dirname,
join,
normpath,
splitext,
)
from cmake_consistency_check_config import ( from cmake_consistency_check_config import (
IGNORE_SOURCE, IGNORE_SOURCE,
IGNORE_SOURCE_MISSING, IGNORE_SOURCE_MISSING,
@@ -45,35 +37,32 @@ from cmake_consistency_check_config import (
BUILD_DIR, BUILD_DIR,
) )
from typing import (
Callable,
Dict,
Generator,
Iterator,
List,
Optional,
Tuple,
)
import os
from os.path import (
dirname,
join,
normpath,
splitext,
)
global_h = set() global_h = set()
global_c = set() global_c = set()
global_refs: Dict[str, List[Tuple[str, int]]] = {} global_refs = {}
# Flatten `IGNORE_SOURCE_MISSING` to avoid nested looping. # Flatten `IGNORE_SOURCE_MISSING` to avoid nested looping.
IGNORE_SOURCE_MISSING_FLAT = [ IGNORE_SOURCE_MISSING = [
(k, ignore_path) for k, ig_list in IGNORE_SOURCE_MISSING (k, ignore_path) for k, ig_list in IGNORE_SOURCE_MISSING
for ignore_path in ig_list for ignore_path in ig_list
] ]
# Ignore cmake file, path pairs. # Ignore cmake file, path pairs.
global_ignore_source_missing: Dict[str, List[str]] = {} global_ignore_source_missing = {}
for k, v in IGNORE_SOURCE_MISSING_FLAT: for k, v in IGNORE_SOURCE_MISSING:
global_ignore_source_missing.setdefault(k, []).append(v) global_ignore_source_missing.setdefault(k, []).append(v)
del IGNORE_SOURCE_MISSING_FLAT
def replace_line(f: str, i: int, text: str, keep_indent: bool = True) -> None: def replace_line(f, i, text, keep_indent=True):
file_handle = open(f, 'r') file_handle = open(f, 'r')
data = file_handle.readlines() data = file_handle.readlines()
file_handle.close() file_handle.close()
@@ -88,10 +77,7 @@ def replace_line(f: str, i: int, text: str, keep_indent: bool = True) -> None:
file_handle.close() file_handle.close()
def source_list( def source_list(path, filename_check=None):
path: str,
filename_check: Optional[Callable[[str], bool]] = None,
) -> Generator[str, None, None]:
for dirpath, dirnames, filenames in os.walk(path): for dirpath, dirnames, filenames in os.walk(path):
# skip '.git' # skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")] dirnames[:] = [d for d in dirnames if not d.startswith(".")]
@@ -102,37 +88,37 @@ def source_list(
# extension checking # extension checking
def is_cmake(filename: str) -> bool: def is_cmake(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext == ".cmake") or (filename == "CMakeLists.txt") return (ext == ".cmake") or (filename == "CMakeLists.txt")
def is_c_header(filename: str) -> bool: def is_c_header(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"}) return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename: str) -> bool: def is_c(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"}) return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
def is_c_any(filename: str) -> bool: def is_c_any(filename):
return is_c(filename) or is_c_header(filename) return is_c(filename) or is_c_header(filename)
def cmake_get_src(f: str) -> None: def cmake_get_src(f):
sources_h = [] sources_h = []
sources_c = [] sources_c = []
filen = open(f, "r", encoding="utf8") filen = open(f, "r", encoding="utf8")
it: Optional[Iterator[str]] = iter(filen) it = iter(filen)
found = False found = False
i = 0 i = 0
# print(f) # print(f)
def is_definition(l: str, f: str, i: int, name: str) -> bool: def is_definition(l, f, i, name):
if l.startswith("unset("): if l.startswith("unset("):
return False return False
@@ -145,7 +131,6 @@ def cmake_get_src(f: str) -> None:
if l.endswith(")"): if l.endswith(")"):
raise Exception("strict formatting not kept 'list(APPEND %s...)' on 1 line %s:%d" % (name, f, i)) raise Exception("strict formatting not kept 'list(APPEND %s...)' on 1 line %s:%d" % (name, f, i))
return True return True
return False
while it is not None: while it is not None:
context_name = "" context_name = ""
@@ -284,7 +269,7 @@ def cmake_get_src(f: str) -> None:
filen.close() filen.close()
def is_ignore_source(f: str, ignore_used: List[bool]) -> bool: def is_ignore_source(f, ignore_used):
for index, ignore_path in enumerate(IGNORE_SOURCE): for index, ignore_path in enumerate(IGNORE_SOURCE):
if ignore_path in f: if ignore_path in f:
ignore_used[index] = True ignore_used[index] = True
@@ -292,7 +277,7 @@ def is_ignore_source(f: str, ignore_used: List[bool]) -> bool:
return False return False
def is_ignore_cmake(f: str, ignore_used: List[bool]) -> bool: def is_ignore_cmake(f, ignore_used):
for index, ignore_path in enumerate(IGNORE_CMAKE): for index, ignore_path in enumerate(IGNORE_CMAKE):
if ignore_path in f: if ignore_path in f:
ignore_used[index] = True ignore_used[index] = True
@@ -300,7 +285,7 @@ def is_ignore_cmake(f: str, ignore_used: List[bool]) -> bool:
return False return False
def main() -> None: def main():
print("Scanning:", SOURCE_DIR) print("Scanning:", SOURCE_DIR)
@@ -374,7 +359,7 @@ def main() -> None:
if "extern" not in f: if "extern" not in f:
i = 1 i = 1
try: try:
for _ in open(f, "r", encoding="utf8"): for l in open(f, "r", encoding="utf8"):
i += 1 i += 1
except UnicodeDecodeError: except UnicodeDecodeError:
print("Non utf8: %s:%d" % (f, i)) print("Non utf8: %s:%d" % (f, i))

View File

@@ -25,14 +25,6 @@ import subprocess
import sys import sys
import os import os
from typing import (
Any,
Callable,
List,
Tuple,
)
USE_QUIET = (os.environ.get("QUIET", None) is not None) USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [ CHECKER_IGNORE_PREFIX = [
@@ -51,7 +43,7 @@ CHECKER_ARGS = [
] ]
def main() -> None: def main():
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX) source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
check_commands = [] check_commands = []
@@ -60,19 +52,18 @@ def main() -> None:
# ~if "source/blender" not in c: # ~if "source/blender" not in c:
# ~ continue # ~ continue
cmd = ( cmd = ([CHECKER_BIN] +
[CHECKER_BIN] + CHECKER_ARGS +
CHECKER_ARGS + [c] +
[c] + [("-I%s" % i) for i in inc_dirs] +
[("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs]
[("-D%s" % d) for d in defs] )
)
check_commands.append((c, cmd)) check_commands.append((c, cmd))
process_functions = [] process_functions = []
def my_process(i: int, c: str, cmd: str) -> subprocess.Popen[Any]: def my_process(i, c, cmd):
if not USE_QUIET: if not USE_QUIET:
percent = 100.0 * (i / (len(check_commands) - 1)) percent = 100.0 * (i / (len(check_commands) - 1))
percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:"

View File

@@ -25,12 +25,6 @@ import subprocess
import sys import sys
import os import os
from typing import (
Any,
List,
)
USE_QUIET = (os.environ.get("QUIET", None) is not None) USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [ CHECKER_IGNORE_PREFIX = [
@@ -53,26 +47,25 @@ if USE_QUIET:
CHECKER_ARGS.append("--quiet") CHECKER_ARGS.append("--quiet")
def main() -> None: def main():
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX) source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
source_defines = project_source_info.build_defines_as_args() source_defines = project_source_info.build_defines_as_args()
check_commands = [] check_commands = []
for c, inc_dirs, defs in source_info: for c, inc_dirs, defs in source_info:
cmd = ( cmd = ([CHECKER_BIN] +
[CHECKER_BIN] + CHECKER_ARGS +
CHECKER_ARGS + [c] +
[c] + [("-I%s" % i) for i in inc_dirs] +
[("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] +
[("-D%s" % d) for d in defs] + source_defines
source_defines )
)
check_commands.append((c, cmd)) check_commands.append((c, cmd))
process_functions = [] process_functions = []
def my_process(i: int, c: str, cmd: List[str]) -> subprocess.Popen[Any]: def my_process(i, c, cmd):
if not USE_QUIET: if not USE_QUIET:
percent = 100.0 * (i / len(check_commands)) percent = 100.0 * (i / len(check_commands))
percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:"

View File

@@ -9,10 +9,10 @@ set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE) set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEBUG ON CACHE BOOL "" FORCE) set(WITH_CYCLES_DEBUG ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_NATIVE_ONLY ON CACHE BOOL "" FORCE) set(WITH_CYCLES_NATIVE_ONLY ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
set(WITH_GTESTS ON CACHE BOOL "" FORCE) set(WITH_GTESTS ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS OFF CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS OFF CACHE BOOL "" FORCE)
set(WITH_PYTHON_SAFETY ON CACHE BOOL "" FORCE) set(WITH_PYTHON_SAFETY ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
if(WIN32) if(WIN32)
set(WITH_WINDOWS_BUNDLE_CRT OFF CACHE BOOL "" FORCE) set(WITH_WINDOWS_BUNDLE_CRT OFF CACHE BOOL "" FORCE)
endif() endif()

View File

@@ -37,7 +37,6 @@ set(WITH_LZO ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE) set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE) set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE) set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
@@ -48,6 +47,8 @@ set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE) set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_POTRACE ON CACHE BOOL "" FORCE) set(WITH_POTRACE ON CACHE BOOL "" FORCE)
set(WITH_PUGIXML ON CACHE BOOL "" FORCE) set(WITH_PUGIXML ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_POTRACE ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE)

View File

@@ -10,14 +10,14 @@ set(WITH_HEADLESS ON CACHE BOOL "" FORCE)
# disable audio, its possible some devs may want this but for now disable # disable audio, its possible some devs may want this but for now disable
# so the python module doesn't hold the audio device and loads quickly. # so the python module doesn't hold the audio device and loads quickly.
set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE) set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE) set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_JACK OFF CACHE BOOL "" FORCE) set(WITH_JACK OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_WASAPI OFF CACHE BOOL "" FORCE) set(WITH_WASAPI OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
# other features which are not especially useful as a python module # other features which are not especially useful as a python module
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)

View File

@@ -7,8 +7,8 @@
set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE) set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE) set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
set(WITH_BOOST OFF CACHE BOOL "" FORCE) set(WITH_BOOST OFF CACHE BOOL "" FORCE)
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE) set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE) set(WITH_BULLET OFF CACHE BOOL "" FORCE)
@@ -18,9 +18,9 @@ set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE) set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE) set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES OFF CACHE BOOL "" FORCE) set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_EMBREE OFF CACHE BOOL "" FORCE) set(WITH_CYCLES_EMBREE OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE) set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
set(WITH_DRACO OFF CACHE BOOL "" FORCE) set(WITH_DRACO OFF CACHE BOOL "" FORCE)
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE) set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE) set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
@@ -44,11 +44,12 @@ set(WITH_LZO OFF CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE) set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM OFF CACHE BOOL "" FORCE) set(WITH_MOD_OCEANSIM OFF CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE) set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
set(WITH_NANOVDB OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE) set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_WASAPI OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEDENOISE OFF CACHE BOOL "" FORCE) set(WITH_OPENIMAGEDENOISE OFF CACHE BOOL "" FORCE)
set(WITH_XR_OPENXR OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE) set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE) set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE) set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
@@ -56,12 +57,11 @@ set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_POTRACE OFF CACHE BOOL "" FORCE) set(WITH_POTRACE OFF CACHE BOOL "" FORCE)
set(WITH_PUGIXML OFF CACHE BOOL "" FORCE) set(WITH_PUGIXML OFF CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_NANOVDB OFF CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_TBB OFF CACHE BOOL "" FORCE) set(WITH_TBB OFF CACHE BOOL "" FORCE)
set(WITH_USD OFF CACHE BOOL "" FORCE) set(WITH_USD OFF CACHE BOOL "" FORCE)
set(WITH_WASAPI OFF CACHE BOOL "" FORCE)
set(WITH_XR_OPENXR OFF CACHE BOOL "" FORCE)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE) set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE)

View File

@@ -4,9 +4,9 @@
# cmake -C../blender/build_files/cmake/config/blender_release.cmake ../blender # cmake -C../blender/build_files/cmake/config/blender_release.cmake ../blender
# #
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE) set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
set(WITH_ASSERT_ABORT OFF CACHE BOOL "" FORCE) set(WITH_ASSERT_ABORT OFF CACHE BOOL "" FORCE)
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE) set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
set(WITH_BULLET ON CACHE BOOL "" FORCE) set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE) set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
@@ -21,8 +21,8 @@ set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_GMP ON CACHE BOOL "" FORCE) set(WITH_GMP ON CACHE BOOL "" FORCE)
set(WITH_HARU ON CACHE BOOL "" FORCE) set(WITH_HARU ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE) set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE) set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
@@ -38,7 +38,6 @@ set(WITH_LZO ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE) set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE) set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE) set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
@@ -49,6 +48,8 @@ set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE) set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_POTRACE ON CACHE BOOL "" FORCE) set(WITH_POTRACE ON CACHE BOOL "" FORCE)
set(WITH_PUGIXML ON CACHE BOOL "" FORCE) set(WITH_PUGIXML ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_POTRACE ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE)

View File

@@ -15,24 +15,24 @@ set(WITH_PYTHON_INSTALL OFF CACHE BOOL "" FORCE)
# disable audio, its possible some devs may want this but for now disable # disable audio, its possible some devs may want this but for now disable
# so the python module doesn't hold the audio device and loads quickly. # so the python module doesn't hold the audio device and loads quickly.
set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE) set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE) set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_JACK OFF CACHE BOOL "" FORCE) set(WITH_JACK OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_WASAPI OFF CACHE BOOL "" FORCE) set(WITH_WASAPI OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
# other features which are not especially useful as a python module # other features which are not especially useful as a python module
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
set(WITH_NANOVDB OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_NANOVDB OFF CACHE BOOL "" FORCE)
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
# Depends on Python install, do this to quiet warning. # Depends on Python install, do this to quiet warning.
set(WITH_DRACO OFF CACHE BOOL "" FORCE) set(WITH_DRACO OFF CACHE BOOL "" FORCE)

View File

@@ -0,0 +1,119 @@
#!/usr/bin/env python3
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
def print_help(targets):
print("CMake quicky wrapper, no valid targets given.")
print(" * targets can contain a subset of the full target name.")
print(" * arguments with a '-' prefix are passed onto make.")
print(" * this must run from the cmake build dir")
print(" * alias this with a short command for speedy access, in bash:")
print(" alias mk='../blender/build_files/cmake/example_scripts/make_quicky.py'")
print("")
print(" eg: make_quicky.py -j3 extern python")
print(" ...will execute")
print(" make -j3 extern_binreloc extern_glew bf_python bf_python_ext blender/fast")
print("")
print("Target List:")
for t in targets:
print(" %s" % t)
print("...exiting")
def main():
targets = set()
# collect targets
makefile = open("Makefile", "r")
for line in makefile:
line = line.rstrip()
if not line or line[0] in ". \t@$#":
continue
line = line.split("#", 1)[0]
if ":" not in line:
continue
line = line.split(":", 1)[0]
if "/" in line: # cmake terget options, dont need these
continue
targets.add(line)
makefile.close()
# remove cmake targets
bad = set([
"help",
"clean",
"all",
"preinstall",
"install",
"default_target",
"edit_cache",
"cmake_force",
"rebuild_cache",
"depend",
"cmake_check_build_system",
])
targets -= set(bad)
# parse args
targets = list(targets)
targets.sort()
import sys
if len(sys.argv) == 1:
print_help(targets)
return
targets_new = []
args = []
for arg in sys.argv[1:]:
if arg[0] in "/-":
args.append(arg)
else:
found = False
for t in targets:
if arg in t and t not in targets_new:
targets_new.append(t)
found = True
if not found:
print("Error '%s' not found in...")
for t in targets:
print(" %s" % t)
print("...aborting.")
return
# execute
cmd = ["make"] + args + targets_new + ["blender/fast"]
print("cmake building with targets: %s" % " ".join(targets_new))
print("executing: %s" % " ".join(cmd))
import subprocess
subprocess.call(cmd)
if __name__ == "__main__":
main()

View File

@@ -56,7 +56,6 @@ list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES})
if(WITH_OPENAL) if(WITH_OPENAL)
find_package(OpenAL) find_package(OpenAL)
if(NOT OPENAL_FOUND) if(NOT OPENAL_FOUND)
message(WARNING "OpenAL not found, disabling WITH_OPENAL")
set(WITH_OPENAL OFF) set(WITH_OPENAL OFF)
endif() endif()
endif() endif()
@@ -66,7 +65,6 @@ if(WITH_JACK)
NAMES jackmp NAMES jackmp
) )
if(NOT JACK_FRAMEWORK) if(NOT JACK_FRAMEWORK)
message(STATUS "JACK not found, disabling WITH_JACK")
set(WITH_JACK OFF) set(WITH_JACK OFF)
else() else()
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
@@ -104,7 +102,6 @@ endif()
if(WITH_USD) if(WITH_USD)
find_package(USD) find_package(USD)
if(NOT USD_FOUND) if(NOT USD_FOUND)
message(STATUS "USD not found, disabling WITH_USD")
set(WITH_USD OFF) set(WITH_USD OFF)
endif() endif()
endif() endif()
@@ -149,7 +146,7 @@ if(WITH_PYTHON)
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}") set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}") set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}") set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}")
# set(PYTHON_LIBRARY python${PYTHON_VERSION}) # set(PYTHON_LIBRARY python${PYTHON_VERSION})
# set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled # set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
@@ -311,7 +308,7 @@ if(WITH_OPENCOLORIO)
if(NOT OPENCOLORIO_FOUND) if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF) set(WITH_OPENCOLORIO OFF)
message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO") message(STATUS "OpenColorIO not found")
endif() endif()
endif() endif()
@@ -360,7 +357,7 @@ if(WITH_CYCLES_OSL)
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR) if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
set(OSL_FOUND TRUE) set(OSL_FOUND TRUE)
else() else()
message(WARNING "OSL not found, disabling WITH_CYCLES_OSL") message(STATUS "OSL not found")
set(WITH_CYCLES_OSL OFF) set(WITH_CYCLES_OSL OFF)
endif() endif()
endif() endif()
@@ -388,7 +385,7 @@ if(WITH_OPENIMAGEDENOISE)
if(NOT OPENIMAGEDENOISE_FOUND) if(NOT OPENIMAGEDENOISE_FOUND)
set(WITH_OPENIMAGEDENOISE OFF) set(WITH_OPENIMAGEDENOISE OFF)
message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE") message(STATUS "OpenImageDenoise not found")
endif() endif()
endif() endif()
@@ -416,7 +413,7 @@ if(WITH_OPENMP)
set(OpenMP_LINKER_FLAGS "-L'${LIBDIR}/openmp/lib' -lomp") set(OpenMP_LINKER_FLAGS "-L'${LIBDIR}/openmp/lib' -lomp")
# Copy libomp.dylib to allow executables like datatoc and tests to work. # Copy libomp.dylib to allow executables like datatoc and tests to work.
# `@executable_path/../Resources/lib/` `LC_ID_DYLIB` is added by the deps builder. # `@executable_path/../Resources/lib/` is a default dylib search path.
# For single config generator datatoc, tests etc. # For single config generator datatoc, tests etc.
execute_process( execute_process(
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib

View File

@@ -149,6 +149,11 @@ add_definitions(-D_WIN32_WINNT=0x601)
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake) include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
remove_cc_flag("/MDd" "/MD" "/Zi") remove_cc_flag("/MDd" "/MD" "/Zi")
if(WITH_WINDOWS_PDB)
set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
endif()
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
string(APPEND CMAKE_CXX_FLAGS " ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ") string(APPEND CMAKE_CXX_FLAGS " ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
@@ -157,21 +162,6 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj")
endif() endif()
# X64 ASAN is available and usable on MSVC 16.9 preview 4 and up)
if(WITH_COMPILER_ASAN AND MSVC AND NOT MSVC_CLANG)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28.29828)
#set a flag so we don't have to do this comparison all the time
SET(MSVC_ASAN On)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address")
string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
else()
message("-- ASAN not supported on MSVC ${CMAKE_CXX_COMPILER_VERSION}")
endif()
endif()
# C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up # C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up
if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG) if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS " /permissive-") string(APPEND CMAKE_CXX_FLAGS " /permissive-")
@@ -184,41 +174,14 @@ if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
set(WITH_WINDOWS_SCCACHE Off) set(WITH_WINDOWS_SCCACHE Off)
endif() endif()
# Debug Symbol format
# sccache # MSVC_ASAN # format # why
# On # On # Z7 # sccache will only play nice with Z7
# On # Off # Z7 # sccache will only play nice with Z7
# Off # On # Zi # Asan will not play nice with Edit and Continue
# Off # Off # ZI # Neither asan nor sscache is enabled Edit and Continue is available
# Release Symbol format
# sccache # MSVC_ASAN # format # why
# On # On # Z7 # sccache will only play nice with Z7
# On # Off # Z7 # sccache will only play nice with Z7
# Off # On # Zi # Asan will not play nice with Edit and Continue
# Off # Off # Zi # Edit and Continue disables some optimizations
if(WITH_WINDOWS_SCCACHE) if(WITH_WINDOWS_SCCACHE)
set(CMAKE_C_COMPILER_LAUNCHER sccache) set(CMAKE_C_COMPILER_LAUNCHER sccache)
set(CMAKE_CXX_COMPILER_LAUNCHER sccache) set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
set(SYMBOL_FORMAT /Z7) set(SYMBOL_FORMAT /Z7)
set(SYMBOL_FORMAT_RELEASE /Z7)
else() else()
unset(CMAKE_C_COMPILER_LAUNCHER) unset(CMAKE_C_COMPILER_LAUNCHER)
unset(CMAKE_CXX_COMPILER_LAUNCHER) unset(CMAKE_CXX_COMPILER_LAUNCHER)
if(MSVC_ASAN) set(SYMBOL_FORMAT /ZI)
set(SYMBOL_FORMAT /Z7)
set(SYMBOL_FORMAT_RELEASE /Z7)
else()
set(SYMBOL_FORMAT /ZI)
set(SYMBOL_FORMAT_RELEASE /Zi)
endif()
endif()
if(WITH_WINDOWS_PDB)
set(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}")
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
endif() endif()
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}") string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}")
@@ -227,11 +190,9 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_C_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}") string(APPEND CMAKE_C_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}") string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_C_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}") string(APPEND CMAKE_C_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}") string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}") string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
unset(SYMBOL_FORMAT) unset(SYMBOL_FORMAT)
unset(SYMBOL_FORMAT_RELEASE)
# JMC is available on msvc 15.8 (1915) and up # JMC is available on msvc 15.8 (1915) and up
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG) if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC") string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC")

View File

@@ -44,15 +44,6 @@ __all__ = (
"init", "init",
) )
from typing import (
Callable,
Generator,
List,
Optional,
Union,
Tuple,
)
import sys import sys
if sys.version_info.major < 3: if sys.version_info.major < 3:
@@ -79,11 +70,10 @@ SOURCE_DIR = abspath(SOURCE_DIR)
SIMPLE_PROJECTFILE = False SIMPLE_PROJECTFILE = False
# must initialize from 'init' # must initialize from 'init'
CMAKE_DIR = "" CMAKE_DIR = None
PROJECT_DIR = ""
def init(cmake_path: str) -> bool: def init(cmake_path):
global CMAKE_DIR, PROJECT_DIR global CMAKE_DIR, PROJECT_DIR
# get cmake path # get cmake path
@@ -101,10 +91,7 @@ def init(cmake_path: str) -> bool:
return True return True
def source_list( def source_list(path, filename_check=None):
path: str,
filename_check: Optional[Callable[[str], bool]] = None,
) -> Generator[str, None, None]:
for dirpath, dirnames, filenames in os.walk(path): for dirpath, dirnames, filenames in os.walk(path):
# skip '.git' # skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")] dirnames[:] = [d for d in dirnames if not d.startswith(".")]
@@ -116,57 +103,53 @@ def source_list(
# extension checking # extension checking
def is_cmake(filename: str) -> bool: def is_cmake(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext == ".cmake") or (filename.endswith("CMakeLists.txt")) return (ext == ".cmake") or (filename.endswith("CMakeLists.txt"))
def is_c_header(filename: str) -> bool: def is_c_header(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"}) return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_py(filename: str) -> bool: def is_py(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext == ".py") return (ext == ".py")
def is_glsl(filename: str) -> bool: def is_glsl(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext == ".glsl") return (ext == ".glsl")
def is_c(filename: str) -> bool: def is_c(filename):
ext = splitext(filename)[1] ext = splitext(filename)[1]
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"}) return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"})
def is_c_any(filename: str) -> bool: def is_c_any(filename):
return is_c(filename) or is_c_header(filename) return is_c(filename) or is_c_header(filename)
def is_svn_file(filename: str) -> bool: def is_svn_file(filename):
dn, fn = os.path.split(filename) dn, fn = os.path.split(filename)
filename_svn = join(dn, ".svn", "text-base", "%s.svn-base" % fn) filename_svn = join(dn, ".svn", "text-base", "%s.svn-base" % fn)
return exists(filename_svn) return exists(filename_svn)
def is_project_file(filename: str) -> bool: def is_project_file(filename):
return (is_c_any(filename) or is_cmake(filename) or is_glsl(filename)) # and is_svn_file(filename) return (is_c_any(filename) or is_cmake(filename) or is_glsl(filename)) # and is_svn_file(filename)
def cmake_advanced_info() -> Union[Tuple[List[str], List[Tuple[str, str]]], Tuple[None, None]]: def cmake_advanced_info():
""" Extract includes and defines from cmake. """ Extract includes and defines from cmake.
""" """
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM") make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
if make_exe is None:
print("Make command not found in: %r not found" % project_path)
return None, None
make_exe_basename = os.path.basename(make_exe) make_exe_basename = os.path.basename(make_exe)
def create_eclipse_project() -> str: def create_eclipse_project():
print("CMAKE_DIR %r" % CMAKE_DIR) print("CMAKE_DIR %r" % CMAKE_DIR)
if sys.platform == "win32": if sys.platform == "win32":
raise Exception("Error: win32 is not supported") raise Exception("Error: win32 is not supported")
@@ -236,7 +219,7 @@ def cmake_advanced_info() -> Union[Tuple[List[str], List[Tuple[str, str]]], Tupl
return includes, defines return includes, defines
def cmake_cache_var(var: str) -> Optional[str]: def cmake_cache_var(var):
with open(os.path.join(CMAKE_DIR, "CMakeCache.txt"), encoding='utf-8') as cache_file: with open(os.path.join(CMAKE_DIR, "CMakeCache.txt"), encoding='utf-8') as cache_file:
lines = [ lines = [
l_strip for l in cache_file l_strip for l in cache_file
@@ -250,12 +233,12 @@ def cmake_cache_var(var: str) -> Optional[str]:
return None return None
def cmake_compiler_defines() -> Optional[List[str]]: def cmake_compiler_defines():
compiler = cmake_cache_var("CMAKE_C_COMPILER") # could do CXX too compiler = cmake_cache_var("CMAKE_C_COMPILER") # could do CXX too
if compiler is None: if compiler is None:
print("Couldn't find the compiler, os defines will be omitted...") print("Couldn't find the compiler, os defines will be omitted...")
return None return
import tempfile import tempfile
temp_c = tempfile.mkstemp(suffix=".c")[1] temp_c = tempfile.mkstemp(suffix=".c")[1]
@@ -272,5 +255,5 @@ def cmake_compiler_defines() -> Optional[List[str]]:
return lines return lines
def project_name_get() -> Optional[str]: def project_name_get():
return cmake_cache_var("CMAKE_PROJECT_NAME") return cmake_cache_var("CMAKE_PROJECT_NAME")

View File

@@ -34,45 +34,30 @@ if sys.version_info.major < 3:
import os import os
from os.path import join, dirname, normpath, abspath from os.path import join, dirname, normpath, abspath
import subprocess
from typing import (
Any,
Callable,
Generator,
List,
Optional,
Sequence,
Tuple,
Union,
cast,
)
SOURCE_DIR = join(dirname(__file__), "..", "..") SOURCE_DIR = join(dirname(__file__), "..", "..")
SOURCE_DIR = normpath(SOURCE_DIR) SOURCE_DIR = normpath(SOURCE_DIR)
SOURCE_DIR = abspath(SOURCE_DIR) SOURCE_DIR = abspath(SOURCE_DIR)
def is_c_header(filename: str) -> bool: def is_c_header(filename):
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"}) return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename: str) -> bool: def is_c(filename):
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"}) return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"})
def is_c_any(filename: str) -> bool: def is_c_any(filename):
return is_c(filename) or is_c_header(filename) return os.path.s_c(filename) or is_c_header(filename)
# copied from project_info.py # copied from project_info.py
CMAKE_DIR = "." CMAKE_DIR = "."
def cmake_cache_var_iter() -> Generator[Tuple[str, str, str], None, None]: def cmake_cache_var_iter():
import re import re
re_cache = re.compile(r'([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$') re_cache = re.compile(r'([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$')
with open(join(CMAKE_DIR, "CMakeCache.txt"), 'r', encoding='utf-8') as cache_file: with open(join(CMAKE_DIR, "CMakeCache.txt"), 'r', encoding='utf-8') as cache_file:
@@ -83,22 +68,14 @@ def cmake_cache_var_iter() -> Generator[Tuple[str, str, str], None, None]:
yield (var, type_ or "", val) yield (var, type_ or "", val)
def cmake_cache_var(var: str) -> Optional[str]: def cmake_cache_var(var):
for var_iter, type_iter, value_iter in cmake_cache_var_iter(): for var_iter, type_iter, value_iter in cmake_cache_var_iter():
if var == var_iter: if var == var_iter:
return value_iter return value_iter
return None return None
def cmake_cache_var_or_exit(var: str) -> str: def do_ignore(filepath, ignore_prefix_list):
value = cmake_cache_var(var)
if value is None:
print("Unable to find %r exiting!" % value)
sys.exit(1)
return value
def do_ignore(filepath: str, ignore_prefix_list: Optional[Sequence[str]]) -> bool:
if ignore_prefix_list is None: if ignore_prefix_list is None:
return False return False
@@ -106,13 +83,12 @@ def do_ignore(filepath: str, ignore_prefix_list: Optional[Sequence[str]]) -> boo
return any([relpath.startswith(prefix) for prefix in ignore_prefix_list]) return any([relpath.startswith(prefix) for prefix in ignore_prefix_list])
def makefile_log() -> List[str]: def makefile_log():
import subprocess import subprocess
import time import time
# support both make and ninja # support both make and ninja
make_exe = cmake_cache_var_or_exit("CMAKE_MAKE_PROGRAM") make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
make_exe_basename = os.path.basename(make_exe) make_exe_basename = os.path.basename(make_exe)
if make_exe_basename.startswith(("make", "gmake")): if make_exe_basename.startswith(("make", "gmake")):
@@ -126,37 +102,26 @@ def makefile_log() -> List[str]:
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
) )
if process is None:
print("Can't execute process")
sys.exit(1)
while process.poll(): while process.poll():
time.sleep(1) time.sleep(1)
# We know this is always true based on the input arguments to `Popen`. out = process.stdout.read()
stdout: IO[bytes] = process.stdout # type: ignore process.stdout.close()
out = stdout.read()
stdout.close()
print("done!", len(out), "bytes") print("done!", len(out), "bytes")
return cast(List[str], out.decode("utf-8", errors="ignore").split("\n")) return out.decode("utf-8", errors="ignore").split("\n")
def build_info( def build_info(use_c=True, use_cxx=True, ignore_prefix_list=None):
use_c: bool = True,
use_cxx: bool = True,
ignore_prefix_list: Optional[List[str]] = None,
) -> List[Tuple[str, List[str], List[str]]]:
makelog = makefile_log() makelog = makefile_log()
source = [] source = []
compilers = [] compilers = []
if use_c: if use_c:
compilers.append(cmake_cache_var_or_exit("CMAKE_C_COMPILER")) compilers.append(cmake_cache_var("CMAKE_C_COMPILER"))
if use_cxx: if use_cxx:
compilers.append(cmake_cache_var_or_exit("CMAKE_CXX_COMPILER")) compilers.append(cmake_cache_var("CMAKE_CXX_COMPILER"))
print("compilers:", " ".join(compilers)) print("compilers:", " ".join(compilers))
@@ -166,7 +131,7 @@ def build_info(
for line in makelog: for line in makelog:
args: Union[str, List[str]] = line.split() args = line.split()
if not any([(c in args) for c in compilers]): if not any([(c in args) for c in compilers]):
continue continue
@@ -211,40 +176,29 @@ def build_info(
return source return source
def build_defines_as_source() -> str: def build_defines_as_source():
""" """
Returns a string formatted as an include: Returns a string formatted as an include:
'#defines A=B\n#define....' '#defines A=B\n#define....'
""" """
import subprocess import subprocess
# works for both gcc and clang # works for both gcc and clang
cmd = (cmake_cache_var_or_exit("CMAKE_C_COMPILER"), "-dM", "-E", "-") cmd = (cmake_cache_var("CMAKE_C_COMPILER"), "-dM", "-E", "-")
process = subprocess.Popen( return subprocess.Popen(cmd,
cmd, stdout=subprocess.PIPE,
stdout=subprocess.PIPE, stdin=subprocess.DEVNULL,
stdin=subprocess.DEVNULL, ).stdout.read().strip().decode('ascii')
)
# We know this is always true based on the input arguments to `Popen`.
stdout: IO[bytes] = process.stdout # type: ignore
return cast(str, stdout.read().strip().decode('ascii'))
def build_defines_as_args() -> List[str]: def build_defines_as_args():
return [ return [("-D" + "=".join(l.split(maxsplit=2)[1:]))
("-D" + "=".join(l.split(maxsplit=2)[1:])) for l in build_defines_as_source().split("\n")
for l in build_defines_as_source().split("\n") if l.startswith('#define')]
if l.startswith('#define')
]
# could be moved elsewhere!, this just happens to be used by scripts that also # could be moved elsewhere!, this just happens to be used by scripts that also
# use this module. # use this module.
def queue_processes( def queue_processes(process_funcs, job_total=-1):
process_funcs: Sequence[Tuple[Callable[..., subprocess.Popen[Any]], Tuple[Any, ...]]],
job_total: int =-1,
) -> None:
""" Takes a list of function arg pairs, each function must return a process """ Takes a list of function arg pairs, each function must return a process
""" """
@@ -263,7 +217,7 @@ def queue_processes(
else: else:
import time import time
processes: List[subprocess.Popen[Any]] = [] processes = []
for func, args in process_funcs: for func, args in process_funcs:
# wait until a thread is free # wait until a thread is free
while 1: while 1:
@@ -280,7 +234,7 @@ def queue_processes(
processes.append(func(*args)) processes.append(func(*args))
def main() -> None: def main():
if not os.path.exists(join(CMAKE_DIR, "CMakeCache.txt")): if not os.path.exists(join(CMAKE_DIR, "CMakeCache.txt")):
print("This script must run from the cmake build dir") print("This script must run from the cmake build dir")
return return

View File

@@ -1,12 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import dataclasses import dataclasses
import os import os
import re import re
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import Iterable, TextIO, Optional, Any, Union from typing import Iterable, TextIO
# This script can run from any location, # This script can run from any location,
# output is created in the $CWD # output is created in the $CWD
@@ -19,43 +18,21 @@ SKIP_NAMES = {
".gitignore", ".gitignore",
".gitmodules", ".gitmodules",
".arcconfig", ".arcconfig",
".svn",
} }
def main() -> None: def main() -> None:
output_dir = Path(".").absolute()
blender_srcdir = Path(__file__).absolute().parent.parent.parent blender_srcdir = Path(__file__).absolute().parent.parent.parent
cli_parser = argparse.ArgumentParser(
description=f"Create a tarball of the Blender sources, optionally including sources of dependencies.",
epilog="This script is intended to be run by `make source_archive_complete`.",
)
cli_parser.add_argument(
"-p",
"--include-packages",
type=Path,
default=None,
metavar="PACKAGE_PATH",
help="Include all source files from the given package directory as well.",
)
cli_args = cli_parser.parse_args()
print(f"Source dir: {blender_srcdir}") print(f"Source dir: {blender_srcdir}")
curdir = blender_srcdir.parent
os.chdir(curdir)
blender_srcdir = blender_srcdir.relative_to(curdir)
print(f"Output dir: {curdir}")
version = parse_blender_version(blender_srcdir) version = parse_blender_version(blender_srcdir)
tarball = tarball_path(curdir, version, cli_args) manifest = output_dir / f"blender-{version}-manifest.txt"
manifest = manifest_path(tarball) tarball = output_dir / f"blender-{version}.tar.xz"
packages_dir = packages_path(curdir, cli_args)
create_manifest(version, manifest, blender_srcdir, packages_dir) os.chdir(blender_srcdir)
create_tarball(version, tarball, manifest, blender_srcdir, packages_dir) create_manifest(version, manifest)
create_tarball(version, tarball, manifest)
create_checksum_file(tarball) create_checksum_file(tarball)
cleanup(manifest) cleanup(manifest)
print("Done!") print("Done!")
@@ -107,109 +84,43 @@ def parse_blender_version(blender_srcdir: Path) -> BlenderVersion:
) )
def tarball_path(output_dir: Path, version: BlenderVersion, cli_args: Any) -> Path:
extra = ""
if cli_args.include_packages:
extra = "-with-libraries"
return output_dir / f"blender{extra}-{version}.tar.xz"
def manifest_path(tarball: Path) -> Path:
"""Return the manifest path for the given tarball path.
>>> from pathlib import Path
>>> tarball = Path("/home/sybren/workspace/blender-git/blender-test.tar.gz")
>>> manifest_path(tarball).as_posix()
'/home/sybren/workspace/blender-git/blender-test-manifest.txt'
"""
# ".tar.gz" is seen as two suffixes.
without_suffix = tarball.with_suffix("").with_suffix("")
name = without_suffix.name
return without_suffix.with_name(f"{name}-manifest.txt")
def packages_path(current_directory: Path, cli_args: Any) -> Optional[Path]:
if not cli_args.include_packages:
return None
abspath = cli_args.include_packages.absolute()
# os.path.relpath() can return paths like "../../packages", where
# Path.relative_to() will not go up directories (so its return value never
# has "../" in there).
relpath = os.path.relpath(abspath, current_directory)
return Path(relpath)
### Manifest creation ### Manifest creation
def create_manifest( def create_manifest(version: BlenderVersion, outpath: Path) -> None:
version: BlenderVersion,
outpath: Path,
blender_srcdir: Path,
packages_dir: Optional[Path],
) -> None:
print(f'Building manifest of files: "{outpath}"...', end="", flush=True) print(f'Building manifest of files: "{outpath}"...', end="", flush=True)
with outpath.open("w", encoding="utf-8") as outfile: with outpath.open("w", encoding="utf-8") as outfile:
main_files_to_manifest(blender_srcdir, outfile) main_files_to_manifest(outfile)
submodules_to_manifest(blender_srcdir, version, outfile) submodules_to_manifest(version, outfile)
if packages_dir:
packages_to_manifest(outfile, packages_dir)
print("OK") print("OK")
def main_files_to_manifest(blender_srcdir: Path, outfile: TextIO) -> None: def main_files_to_manifest(outfile: TextIO) -> None:
assert not blender_srcdir.is_absolute() for path in git_ls_files():
for path in git_ls_files(blender_srcdir):
print(path, file=outfile) print(path, file=outfile)
def submodules_to_manifest( def submodules_to_manifest(version: BlenderVersion, outfile: TextIO) -> None:
blender_srcdir: Path, version: BlenderVersion, outfile: TextIO
) -> None:
skip_addon_contrib = version.is_release skip_addon_contrib = version.is_release
assert not blender_srcdir.is_absolute()
for line in git_command("-C", blender_srcdir, "submodule"): for line in git_command("submodule"):
submodule = line.split()[1] submodule = line.split()[1]
# Don't use native slashes as GIT for MS-Windows outputs forward slashes. # Don't use native slashes as GIT for MS-Windows outputs forward slashes.
if skip_addon_contrib and submodule == "release/scripts/addons_contrib": if skip_addon_contrib and submodule == "release/scripts/addons_contrib":
continue continue
for path in git_ls_files(blender_srcdir / submodule): for path in git_ls_files(Path(submodule)):
print(path, file=outfile) print(path, file=outfile)
def packages_to_manifest(outfile: TextIO, packages_dir: Path) -> None: def create_tarball(version: BlenderVersion, tarball: Path, manifest: Path) -> None:
for path in packages_dir.glob("*"):
if not path.is_file():
continue
if path.name in SKIP_NAMES:
continue
print(path, file=outfile)
### Higher-level functions
def create_tarball(
version: BlenderVersion, tarball: Path, manifest: Path, blender_srcdir: Path, packages_dir: Optional[Path]
) -> None:
print(f'Creating archive: "{tarball}" ...', end="", flush=True) print(f'Creating archive: "{tarball}" ...', end="", flush=True)
command = ["tar"]
# Requires GNU `tar`, since `--transform` is used. # Requires GNU `tar`, since `--transform` is used.
if packages_dir: command = [
command += ["--transform", f"s,{packages_dir}/,packages/,g"] "tar",
command += [
"--transform", "--transform",
f"s,^{blender_srcdir.name}/,blender-{version}/,g", f"s,^,blender-{version}/,g",
"--use-compress-program=xz -9", "--use-compress-program=xz -9",
"--create", "--create",
f"--file={tarball}", f"--file={tarball}",
@@ -219,8 +130,7 @@ def create_tarball(
"--owner=0", "--owner=0",
"--group=0", "--group=0",
] ]
subprocess.run(command, check=True, timeout=300)
subprocess.run(command, check=True, timeout=3600)
print("OK") print("OK")
@@ -264,7 +174,7 @@ def git_ls_files(directory: Path = Path(".")) -> Iterable[Path]:
yield path yield path
def git_command(*cli_args: Union[bytes, str, Path] ) -> Iterable[str]: def git_command(*cli_args) -> Iterable[str]:
"""Generator, yields lines of output from a Git command.""" """Generator, yields lines of output from a Git command."""
command = ("git", *cli_args) command = ("git", *cli_args)

View File

@@ -9,10 +9,14 @@ if "%BUILD_WITH_SCCACHE%"=="1" (
if "%WITH_CLANG%"=="1" ( if "%WITH_CLANG%"=="1" (
set CLANG_CMAKE_ARGS=-T"llvm" set CLANG_CMAKE_ARGS=-T"llvm"
) if "%WITH_ASAN%"=="1" (
if "%WITH_ASAN%"=="1" (
set ASAN_CMAKE_ARGS=-DWITH_COMPILER_ASAN=On set ASAN_CMAKE_ARGS=-DWITH_COMPILER_ASAN=On
)
) else (
if "%WITH_ASAN%"=="1" (
echo ASAN is only supported with clang.
exit /b 1
)
) )
if "%WITH_PYDEBUG%"=="1" ( if "%WITH_PYDEBUG%"=="1" (

View File

@@ -46,10 +46,16 @@ set LLVM_DIR=
set CFLAGS=-m64 -fmsc-version=1914 set CFLAGS=-m64 -fmsc-version=1914
set CXXFLAGS=-m64 -fmsc-version=1914 set CXXFLAGS=-m64 -fmsc-version=1914
) )
if "%WITH_ASAN%"=="1" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
)
) )
if "%WITH_ASAN%"=="1" ( if "%WITH_ASAN%"=="1" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On if "%WITH_CLANG%" == "" (
echo ASAN is only supported with clang.
exit /b 1
)
) )
if NOT "%verbose%" == "" ( if NOT "%verbose%" == "" (

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = "V3.0" PROJECT_NUMBER = "V2.93"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View File

@@ -22,7 +22,7 @@
This script generates the blender.1 man page, embedding the help text This script generates the blender.1 man page, embedding the help text
from the Blender executable itself. Invoke it as follows: from the Blender executable itself. Invoke it as follows:
blender.1.py --blender <path-to-blender> --output <output-filename> blender.1.py <path-to-blender> <output-filename>
where <path-to-blender> is the path to the Blender executable, where <path-to-blender> is the path to the Blender executable,
and <output-filename> is where to write the generated man page. and <output-filename> is where to write the generated man page.
@@ -30,147 +30,108 @@ and <output-filename> is where to write the generated man page.
# <pep8 compliant> # <pep8 compliant>
import argparse
import os import os
import subprocess import subprocess
import sys import sys
import time import time
from typing import (
Dict,
TextIO,
)
def man_format(data):
def man_format(data: str) -> str:
data = data.replace("-", "\\-") data = data.replace("-", "\\-")
data = data.replace("\t", " ") data = data.replace("\t", " ")
return data return data
def blender_extract_info(blender_bin: str) -> Dict[str, str]: if len(sys.argv) != 3:
import getopt
raise getopt.GetoptError("Usage: %s <path-to-blender> <output-filename>" % sys.argv[0])
blender_env = { blender_bin = sys.argv[1]
"ASAN_OPTIONS": "exitcode=0:" + os.environ.get("ASAN_OPTIONS", ""), outfilename = sys.argv[2]
}
blender_help = subprocess.run( cmd = [blender_bin, "--help"]
[blender_bin, "--help"], print(" executing:", " ".join(cmd))
env=blender_env, ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "")
check=True, blender_help = subprocess.run(
stdout=subprocess.PIPE, cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8")
).stdout.decode(encoding="utf-8") blender_version = subprocess.run(
[blender_bin, "--version"], env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip()
blender_version, blender_date = (blender_version.split("build") + [None, None])[0:2]
blender_version = blender_version.rstrip().partition(" ")[2] # remove 'Blender' prefix.
if blender_date is None:
# Happens when built without WITH_BUILD_INFO e.g.
date_string = time.strftime("%B %d, %Y", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))))
else:
blender_date = blender_date.strip().partition(" ")[2] # remove 'date:' prefix
date_string = time.strftime("%B %d, %Y", time.strptime(blender_date, "%Y-%m-%d"))
blender_version_ouput = subprocess.run( outfile = open(outfilename, "w")
[blender_bin, "--version"], fw = outfile.write
env=blender_env,
check=True,
stdout=subprocess.PIPE,
).stdout.decode(encoding="utf-8")
# Extract information from the version string. fw('.TH "BLENDER" "1" "%s" "Blender %s"\n' % (date_string, blender_version.replace(".", "\\&.")))
# Note that some internal modules may print errors (e.g. color management),
# check for each lines prefix to ensure these aren't included.
blender_version = ""
blender_date = ""
for l in blender_version_ouput.split("\n"):
if l.startswith("Blender "):
# Remove 'Blender' prefix.
blender_version = l.split(" ", 1)[1].strip()
elif l.lstrip().startswith("build date:"):
# Remove 'build date:' prefix.
blender_date = l.split(":", 1)[1].strip()
if blender_version and blender_date:
break
if not blender_date: fw('''
# Happens when built without WITH_BUILD_INFO e.g.
date_string = time.strftime("%B %d, %Y", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))))
else:
date_string = time.strftime("%B %d, %Y", time.strptime(blender_date, "%Y-%m-%d"))
return {
"help": blender_help,
"version": blender_version,
"date": date_string,
}
def man_page_from_blender_help(fh: TextIO, blender_bin: str) -> None:
blender_info = blender_extract_info(blender_bin)
# Header Content.
fh.write(
'.TH "BLENDER" "1" "%s" "Blender %s"\n' %
(blender_info["date"], blender_info["version"].replace(".", "\\&."))
)
fh.write(r'''
.SH NAME .SH NAME
blender \- a full-featured 3D application''') blender \- a full-featured 3D application''')
fh.write(r''' fw('''
.SH SYNOPSIS .SH SYNOPSIS
.B blender [args ...] [file] [args ...]''') .B blender [args ...] [file] [args ...]''')
fh.write(r''' fw('''
.br .br
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
.B blender .B blender
is a full-featured 3D application. It supports the entirety of the 3D pipeline - ''' is a full-featured 3D application. It supports the entirety of the 3D pipeline - modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing.
'''modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing.
Use Blender to create 3D images and animations, films and commercials, content for games, ''' Use Blender to create 3D images and animations, films and commercials, content for games, architectural and industrial visualizatons, and scientific visualizations.
r'''architectural and industrial visualizatons, and scientific visualizations.
https://www.blender.org''') https://www.blender.org''')
fh.write(r''' fw('''
.SH OPTIONS''') .SH OPTIONS''')
fh.write("\n\n") fw("\n\n")
# Body Content. lines = [line.rstrip() for line in blender_help.split("\n")]
lines = [line.rstrip() for line in blender_info["help"].split("\n")] while lines:
l = lines.pop(0)
if l.startswith("Environment Variables:"):
fw('.SH "ENVIRONMENT VARIABLES"\n')
elif l.endswith(":"): # one line
fw('.SS "%s"\n\n' % l)
elif l.startswith("-") or l.startswith("/"): # can be multi line
while lines: fw('.TP\n')
l = lines.pop(0) fw('.B %s\n' % man_format(l))
if l.startswith("Environment Variables:"):
fh.write('.SH "ENVIRONMENT VARIABLES"\n')
elif l.endswith(":"): # One line.
fh.write('.SS "%s"\n\n' % l)
elif l.startswith("-") or l.startswith("/"): # Can be multi line.
fh.write('.TP\n')
fh.write('.B %s\n' % man_format(l))
while lines: while lines:
# line with no # line with no
if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # No white space. if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # no white space
break break
if not l: # Second blank line. if not l: # second blank line
fh.write('.IP\n') fw('.IP\n')
else:
fh.write('.br\n')
l = lines.pop(0)
if l:
assert(l.startswith('\t'))
l = l[1:] # Remove first white-space (tab).
fh.write('%s\n' % man_format(l))
else:
if not l.strip():
fh.write('.br\n')
else: else:
fh.write('%s\n' % man_format(l)) fw('.br\n')
# Footer Content. l = lines.pop(0)
l = l[1:] # remove first whitespace (tab)
fh.write(r''' fw('%s\n' % man_format(l))
else:
if not l.strip():
fw('.br\n')
else:
fw('%s\n' % man_format(l))
# footer
fw('''
.br .br
.SH SEE ALSO .SH SEE ALSO
.B luxrender(1) .B luxrender(1)
@@ -182,33 +143,5 @@ This manpage was written for a Debian GNU/Linux system by Daniel Mester
<cyril.brulebois@enst-bretagne.fr> and Dan Eicher <dan@trollwerks.org>. <cyril.brulebois@enst-bretagne.fr> and Dan Eicher <dan@trollwerks.org>.
''') ''')
outfile.close()
def create_argparse() -> argparse.ArgumentParser: print("written:", outfilename)
parser = argparse.ArgumentParser()
parser.add_argument(
"--output",
required=True,
help="The man page to write to."
)
parser.add_argument(
"--blender",
required=True,
help="Path to the blender binary."
)
return parser
def main() -> None:
parser = create_argparse()
args = parser.parse_args()
blender_bin = args.blender
output_filename = args.output
with open(output_filename, "w", encoding="utf-8") as fh:
man_page_from_blender_help(fh, blender_bin)
if __name__ == "__main__":
main()

View File

@@ -61,3 +61,4 @@ def unregister():
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -1,2 +1,2 @@
Sphinx==3.5.3 Sphinx==3.5.1
sphinx_rtd_theme==0.5.2 sphinx_rtd_theme==0.5.1

View File

@@ -50,8 +50,7 @@ you should be able to find the poll function with no knowledge of C.
Blender does have the functionality for poll functions to describe why they fail, Blender does have the functionality for poll functions to describe why they fail,
but its currently not used much, if you're interested to help improve the API but its currently not used much, if you're interested to help improve the API
feel free to add calls to :class:`bpy.types.Operator.poll_message_set` (``CTX_wm_operator_poll_msg_set`` in C) feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails, e.g:
where its not obvious why poll fails, e.g:
>>> bpy.ops.gpencil.draw() >>> bpy.ops.gpencil.draw()
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into

View File

@@ -553,7 +553,7 @@ def example_extract_docstring(filepath):
line_no += 1 line_no += 1
else: else:
file.close() file.close()
return "", 0, False return "", 0
for line in file: for line in file:
line_no += 1 line_no += 1
@@ -563,17 +563,15 @@ def example_extract_docstring(filepath):
text.append(line.rstrip()) text.append(line.rstrip())
line_no += 1 line_no += 1
line_no_has_content = False
# Skip over blank lines so the Python code doesn't have blank lines at the top. # Skip over blank lines so the Python code doesn't have blank lines at the top.
for line in file: for line in file:
if line.strip(): if line.strip():
line_no_has_content = True
break break
line_no += 1 line_no += 1
file.close() file.close()
return "\n".join(text), line_no, line_no_has_content return "\n".join(text), line_no
def title_string(text, heading_char, double=False): def title_string(text, heading_char, double=False):
@@ -592,18 +590,16 @@ def write_example_ref(ident, fw, example_id, ext="py"):
filepath = os.path.join("..", "examples", "%s.%s" % (example_id, ext)) filepath = os.path.join("..", "examples", "%s.%s" % (example_id, ext))
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath) filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
text, line_no, line_no_has_content = example_extract_docstring(filepath_full) text, line_no = example_extract_docstring(filepath_full)
for line in text.split("\n"): for line in text.split("\n"):
fw("%s\n" % (ident + line).rstrip()) fw("%s\n" % (ident + line).rstrip())
fw("\n") fw("\n")
# Some files only contain a doc-string. fw("%s.. literalinclude:: %s\n" % (ident, filepath))
if line_no_has_content: if line_no > 0:
fw("%s.. literalinclude:: %s\n" % (ident, filepath)) fw("%s :lines: %d-\n" % (ident, line_no))
if line_no > 0: fw("\n")
fw("%s :lines: %d-\n" % (ident, line_no))
fw("\n")
EXAMPLE_SET_USED.add(example_id) EXAMPLE_SET_USED.add(example_id)
else: else:
if bpy.app.debug: if bpy.app.debug:
@@ -1412,8 +1408,7 @@ def pyrna2sphinx(basepath):
else: else:
fw(" .. attribute:: %s\n\n" % prop.identifier) fw(" .. attribute:: %s\n\n" % prop.identifier)
if prop.description: if prop.description:
write_indented_lines(" ", fw, prop.description, False) fw(" %s\n\n" % prop.description)
fw("\n")
# special exception, can't use generic code here for enums # special exception, can't use generic code here for enums
if prop.type == "enum": if prop.type == "enum":

View File

@@ -109,7 +109,3 @@ endif()
if(WITH_MOD_FLUID) if(WITH_MOD_FLUID)
add_subdirectory(mantaflow) add_subdirectory(mantaflow)
endif() endif()
if (WITH_COMPOSITOR)
add_subdirectory(smaa_areatex)
endif()

View File

@@ -42,7 +42,6 @@ set(SRC
src/devices/NULLDevice.cpp src/devices/NULLDevice.cpp
src/devices/ReadDevice.cpp src/devices/ReadDevice.cpp
src/devices/SoftwareDevice.cpp src/devices/SoftwareDevice.cpp
src/devices/ThreadedDevice.cpp
src/Exception.cpp src/Exception.cpp
src/file/File.cpp src/file/File.cpp
src/file/FileManager.cpp src/file/FileManager.cpp
@@ -149,7 +148,6 @@ set(PUBLIC_HDR
include/devices/NULLDevice.h include/devices/NULLDevice.h
include/devices/ReadDevice.h include/devices/ReadDevice.h
include/devices/SoftwareDevice.h include/devices/SoftwareDevice.h
include/devices/ThreadedDevice.h
include/Exception.h include/Exception.h
include/file/File.h include/file/File.h
include/file/FileManager.h include/file/FileManager.h

View File

@@ -255,7 +255,6 @@ protected:
/** /**
* This function tells the device, to start or pause playback. * This function tells the device, to start or pause playback.
* \param playing True if device should playback. * \param playing True if device should playback.
* \note This method is only called when the device is locked.
*/ */
virtual void playing(bool playing)=0; virtual void playing(bool playing)=0;

View File

@@ -1,95 +0,0 @@
/*******************************************************************************
* Copyright 2009-2016 Jörg Müller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
#pragma once
/**
* @file ThreadedDevice.h
* @ingroup plugin
* The ThreadedDevice class.
*/
#include "devices/SoftwareDevice.h"
#include <thread>
AUD_NAMESPACE_BEGIN
/**
* This device extends the SoftwareDevice with code for running mixing in a separate thread.
*/
class AUD_PLUGIN_API ThreadedDevice : public SoftwareDevice
{
private:
/**
* Whether there is currently playback.
*/
bool m_playing;
/**
* Whether the current playback should stop.
*/
bool m_stop;
/**
* The streaming thread.
*/
std::thread m_thread;
/**
* Starts the streaming thread.
*/
AUD_LOCAL void start();
/**
* Streaming thread main function.
*/
AUD_LOCAL virtual void runMixingThread()=0;
// delete copy constructor and operator=
ThreadedDevice(const ThreadedDevice&) = delete;
ThreadedDevice& operator=(const ThreadedDevice&) = delete;
protected:
virtual void playing(bool playing);
/**
* Empty default constructor. To setup the device call the function create()
* and to uninitialize call destroy().
*/
ThreadedDevice();
/**
* Indicates that the mixing thread should be stopped.
* \return Whether the mixing thread should be stopping.
* \warning For thread safety, the device needs to be locked, when this method is called.
*/
inline bool shouldStop() { return m_stop; }
/**
* This method needs to be called when the mixing thread is stopping.
* \warning For thread safety, the device needs to be locked, when this method is called.
*/
inline void doStop() { m_stop = m_playing = false; }
/**
* Stops all playback and notifies the mixing thread to stop.
* \warning The device has to be unlocked to not run into a deadlock.
*/
void stopMixingThread();
};
AUD_NAMESPACE_END

View File

@@ -27,9 +27,9 @@ void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data
{ {
PulseAudioDevice* device = (PulseAudioDevice*)data; PulseAudioDevice* device = (PulseAudioDevice*)data;
std::lock_guard<ILockable> lock(*device);
device->m_state = AUD_pa_context_get_state(context); device->m_state = AUD_pa_context_get_state(context);
AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0);
} }
void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t num_bytes, void *data) void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t num_bytes, void *data)
@@ -68,40 +68,29 @@ void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
} }
} }
void PulseAudioDevice::runMixingThread() void PulseAudioDevice::playing(bool playing)
{ {
for(;;) m_playback = playing;
{
{
std::lock_guard<ILockable> lock(*this);
if(shouldStop()) AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
{
AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
doStop();
return;
}
}
if(AUD_pa_stream_is_corked(m_stream))
AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
}
} }
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) : PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
m_playback(false),
m_state(PA_CONTEXT_UNCONNECTED), m_state(PA_CONTEXT_UNCONNECTED),
m_buffersize(buffersize), m_buffersize(buffersize),
m_underflows(0) m_underflows(0)
{ {
m_mainloop = AUD_pa_mainloop_new(); m_mainloop = AUD_pa_threaded_mainloop_new();
m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str()); AUD_pa_threaded_mainloop_lock(m_mainloop);
m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str());
if(!m_context) if(!m_context)
{ {
AUD_pa_mainloop_free(m_mainloop); AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio."); AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
} }
@@ -110,21 +99,26 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr); AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
AUD_pa_threaded_mainloop_start(m_mainloop);
while(m_state != PA_CONTEXT_READY) while(m_state != PA_CONTEXT_READY)
{ {
switch(m_state) switch(m_state)
{ {
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context); AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context); AUD_pa_context_unref(m_context);
AUD_pa_mainloop_free(m_mainloop); AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio."); AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
break; break;
default: default:
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr); AUD_pa_threaded_mainloop_wait(m_mainloop);
break; break;
} }
} }
@@ -172,10 +166,13 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
if(!m_stream) if(!m_stream)
{ {
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context); AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context); AUD_pa_context_unref(m_context);
AUD_pa_mainloop_free(m_mainloop); AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not create PulseAudio stream."); AUD_THROW(DeviceException, "Could not create PulseAudio stream.");
} }
@@ -191,27 +188,32 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
buffer_attr.prebuf = -1U; buffer_attr.prebuf = -1U;
buffer_attr.tlength = buffersize; buffer_attr.tlength = buffersize;
if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0) if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
{ {
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context); AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context); AUD_pa_context_unref(m_context);
AUD_pa_mainloop_free(m_mainloop); AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect PulseAudio stream."); AUD_THROW(DeviceException, "Could not connect PulseAudio stream.");
} }
AUD_pa_threaded_mainloop_unlock(m_mainloop);
create(); create();
} }
PulseAudioDevice::~PulseAudioDevice() PulseAudioDevice::~PulseAudioDevice()
{ {
stopMixingThread(); AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context); AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context); AUD_pa_context_unref(m_context);
AUD_pa_mainloop_free(m_mainloop); AUD_pa_threaded_mainloop_free(m_mainloop);
destroy(); destroy();
} }

View File

@@ -26,7 +26,7 @@
* The PulseAudioDevice class. * The PulseAudioDevice class.
*/ */
#include "devices/ThreadedDevice.h" #include "devices/SoftwareDevice.h"
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
@@ -35,10 +35,15 @@ AUD_NAMESPACE_BEGIN
/** /**
* This device plays back through PulseAudio, the simple direct media layer. * This device plays back through PulseAudio, the simple direct media layer.
*/ */
class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice
{ {
private: private:
pa_mainloop* m_mainloop; /**
* Whether there is currently playback.
*/
volatile bool m_playback;
pa_threaded_mainloop* m_mainloop;
pa_context* m_context; pa_context* m_context;
pa_stream* m_stream; pa_stream* m_stream;
pa_context_state_t m_state; pa_context_state_t m_state;
@@ -69,15 +74,13 @@ private:
*/ */
AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data); AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
// delete copy constructor and operator= // delete copy constructor and operator=
PulseAudioDevice(const PulseAudioDevice&) = delete; PulseAudioDevice(const PulseAudioDevice&) = delete;
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete; PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
protected:
virtual void playing(bool playing);
public: public:
/** /**
* Opens the PulseAudio audio device for playback. * Opens the PulseAudio audio device for playback.

View File

@@ -24,14 +24,18 @@ PULSEAUDIO_SYMBOL(pa_context_unref);
PULSEAUDIO_SYMBOL(pa_stream_begin_write); PULSEAUDIO_SYMBOL(pa_stream_begin_write);
PULSEAUDIO_SYMBOL(pa_stream_connect_playback); PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork); PULSEAUDIO_SYMBOL(pa_stream_cork);
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new); PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr); PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback); PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback);
PULSEAUDIO_SYMBOL(pa_stream_set_write_callback); PULSEAUDIO_SYMBOL(pa_stream_set_write_callback);
PULSEAUDIO_SYMBOL(pa_stream_write); PULSEAUDIO_SYMBOL(pa_stream_write);
PULSEAUDIO_SYMBOL(pa_mainloop_free); PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
PULSEAUDIO_SYMBOL(pa_mainloop_get_api); PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
PULSEAUDIO_SYMBOL(pa_mainloop_new); PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
PULSEAUDIO_SYMBOL(pa_mainloop_iterate); PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait);

View File

@@ -31,43 +31,63 @@ template <class T> void SafeRelease(T **ppT)
} }
} }
void WASAPIDevice::runMixingThread() void WASAPIDevice::start()
{
lock();
if(!m_playing)
{
if(m_thread.joinable())
m_thread.join();
m_playing = true;
m_thread = std::thread(&WASAPIDevice::updateStream, this);
}
unlock();
}
void WASAPIDevice::updateStream()
{ {
UINT32 buffer_size; UINT32 buffer_size;
UINT32 padding;
UINT32 length;
data_t* buffer; data_t* buffer;
if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
return;
IAudioRenderClient* render_client = nullptr; IAudioRenderClient* render_client = nullptr;
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
return;
UINT32 padding;
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
{ {
std::lock_guard<ILockable> lock(*this); SafeRelease(&render_client);
return;
}
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); UINT32 length = buffer_size - padding;
if(FAILED(m_audio_client->GetBufferSize(&buffer_size))) if(FAILED(render_client->GetBuffer(length, &buffer)))
goto init_error; {
SafeRelease(&render_client);
return;
}
if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client)))) lock();
goto init_error;
if(FAILED(m_audio_client->GetCurrentPadding(&padding))) mix((data_t*)buffer, length);
goto init_error;
length = buffer_size - padding; unlock();
if(FAILED(render_client->GetBuffer(length, &buffer))) if(FAILED(render_client->ReleaseBuffer(length, 0)))
goto init_error; {
SafeRelease(&render_client);
mix((data_t*)buffer, length); return;
if(FAILED(render_client->ReleaseBuffer(length, 0)))
{
init_error:
SafeRelease(&render_client);
doStop();
return;
}
} }
m_audio_client->Start(); m_audio_client->Start();
@@ -76,38 +96,58 @@ void WASAPIDevice::runMixingThread()
for(;;) for(;;)
{ {
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
{ {
std::lock_guard<ILockable> lock(*this); m_audio_client->Stop();
SafeRelease(&render_client);
return;
}
if(FAILED(m_audio_client->GetCurrentPadding(&padding))) length = buffer_size - padding;
goto stop_thread;
length = buffer_size - padding; if(FAILED(render_client->GetBuffer(length, &buffer)))
{
m_audio_client->Stop();
SafeRelease(&render_client);
return;
}
if(FAILED(render_client->GetBuffer(length, &buffer))) lock();
goto stop_thread;
mix((data_t*)buffer, length); mix((data_t*)buffer, length);
if(FAILED(render_client->ReleaseBuffer(length, 0))) unlock();
goto stop_thread;
// stop thread if(FAILED(render_client->ReleaseBuffer(length, 0)))
if(shouldStop()) {
{ m_audio_client->Stop();
stop_thread: SafeRelease(&render_client);
m_audio_client->Stop(); return;
SafeRelease(&render_client); }
doStop();
return; // stop thread
} if(!m_playing)
{
m_audio_client->Stop();
SafeRelease(&render_client);
return;
} }
std::this_thread::sleep_for(sleepDuration); std::this_thread::sleep_for(sleepDuration);
} }
} }
void WASAPIDevice::playing(bool playing)
{
if(!m_playing && playing)
start();
else
m_playing = playing;
}
WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
m_playing(false),
m_imm_device_enumerator(nullptr), m_imm_device_enumerator(nullptr),
m_imm_device(nullptr), m_imm_device(nullptr),
m_audio_client(nullptr), m_audio_client(nullptr),
@@ -285,7 +325,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
WASAPIDevice::~WASAPIDevice() WASAPIDevice::~WASAPIDevice()
{ {
stopMixingThread(); lock();
stopAll();
unlock();
if(m_thread.joinable())
m_thread.join();
SafeRelease(&m_audio_client); SafeRelease(&m_audio_client);
SafeRelease(&m_imm_device); SafeRelease(&m_imm_device);

View File

@@ -26,7 +26,7 @@
* The WASAPIDevice class. * The WASAPIDevice class.
*/ */
#include "devices/ThreadedDevice.h" #include "devices/SoftwareDevice.h"
#include <thread> #include <thread>
@@ -40,23 +40,41 @@ AUD_NAMESPACE_BEGIN
/** /**
* This device plays back through WASAPI, the Windows audio API. * This device plays back through WASAPI, the Windows audio API.
*/ */
class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice class AUD_PLUGIN_API WASAPIDevice : public SoftwareDevice
{ {
private: private:
/**
* Whether there is currently playback.
*/
bool m_playing;
IMMDeviceEnumerator* m_imm_device_enumerator; IMMDeviceEnumerator* m_imm_device_enumerator;
IMMDevice* m_imm_device; IMMDevice* m_imm_device;
IAudioClient* m_audio_client; IAudioClient* m_audio_client;
WAVEFORMATEXTENSIBLE m_wave_format_extensible; WAVEFORMATEXTENSIBLE m_wave_format_extensible;
/**
* The streaming thread.
*/
std::thread m_thread;
/**
* Starts the streaming thread.
*/
AUD_LOCAL void start();
/** /**
* Streaming thread main function. * Streaming thread main function.
*/ */
AUD_LOCAL void runMixingThread(); AUD_LOCAL void updateStream();
// delete copy constructor and operator= // delete copy constructor and operator=
WASAPIDevice(const WASAPIDevice&) = delete; WASAPIDevice(const WASAPIDevice&) = delete;
WASAPIDevice& operator=(const WASAPIDevice&) = delete; WASAPIDevice& operator=(const WASAPIDevice&) = delete;
protected:
virtual void playing(bool playing);
public: public:
/** /**
* Opens the WASAPI audio device for playback. * Opens the WASAPI audio device for playback.

View File

@@ -737,7 +737,7 @@ void SoftwareDevice::mix(data_t* buffer, int length)
{ {
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));
std::lock_guard<ILockable> lock(*this); std::lock_guard<std::recursive_mutex> lock(m_mutex);
{ {
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound; std::shared_ptr<SoftwareDevice::SoftwareHandle> sound;
@@ -880,7 +880,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<IReader> reader, b
// play sound // play sound
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound = std::shared_ptr<SoftwareDevice::SoftwareHandle>(new SoftwareDevice::SoftwareHandle(this, reader, pitch, resampler, mapper, keep)); std::shared_ptr<SoftwareDevice::SoftwareHandle> sound = std::shared_ptr<SoftwareDevice::SoftwareHandle>(new SoftwareDevice::SoftwareHandle(this, reader, pitch, resampler, mapper, keep));
std::lock_guard<ILockable> lock(*this); std::lock_guard<std::recursive_mutex> lock(m_mutex);
m_playingSounds.push_back(sound); m_playingSounds.push_back(sound);
@@ -897,7 +897,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<ISound> sound, boo
void SoftwareDevice::stopAll() void SoftwareDevice::stopAll()
{ {
std::lock_guard<ILockable> lock(*this); std::lock_guard<std::recursive_mutex> lock(m_mutex);
while(!m_playingSounds.empty()) while(!m_playingSounds.empty())
m_playingSounds.front()->stop(); m_playingSounds.front()->stop();

View File

@@ -1,65 +0,0 @@
/*******************************************************************************
* Copyright 2009-2016 Jörg Müller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
#include "devices/ThreadedDevice.h"
#include <mutex>
AUD_NAMESPACE_BEGIN
void ThreadedDevice::start()
{
std::lock_guard<ILockable> lock(*this);
// thread is still running, we can abort stopping it
if(m_stop)
m_stop = false;
// thread is not running, let's start it
else if(!m_playing)
{
if(m_thread.joinable())
m_thread.join();
m_playing = true;
m_thread = std::thread(&ThreadedDevice::runMixingThread, this);
}
}
void ThreadedDevice::playing(bool playing)
{
if((!m_playing || m_stop) && playing)
start();
else
m_stop = true;
}
ThreadedDevice::ThreadedDevice() :
m_playing(false),
m_stop(false)
{
}
void aud::ThreadedDevice::stopMixingThread()
{
stopAll();
if(m_thread.joinable())
m_thread.join();
}
AUD_NAMESPACE_END

View File

@@ -1,26 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2017, Blender Foundation
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): IRIE Shinsuke
#
# ***** END GPL LICENSE BLOCK *****
add_executable(smaa_areatex smaa_areatex.cpp)

View File

@@ -1,5 +0,0 @@
Project: smaa-cpp
URL: https://github.com/iRi-E/smaa-cpp
License: MIT
Upstream version: 0.4.0
Local modifications:

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,6 @@
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@@ -41,9 +41,6 @@ class AddPresetIntegrator(AddPresetBase, Operator):
"cycles.caustics_reflective", "cycles.caustics_reflective",
"cycles.caustics_refractive", "cycles.caustics_refractive",
"cycles.blur_glossy" "cycles.blur_glossy"
"cycles.use_fast_gi"
"cycles.ao_bounces"
"cycles.ao_bounces_render"
] ]
preset_subdir = "cycles/integrator" preset_subdir = "cycles/integrator"

View File

@@ -801,22 +801,17 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
items=enum_texture_limit items=enum_texture_limit
) )
use_fast_gi: BoolProperty(
name="Fast GI Approximation",
description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
default=False,
)
ao_bounces: IntProperty( ao_bounces: IntProperty(
name="AO Bounces", name="AO Bounces",
default=1, default=0,
description="After this number of light bounces, use approximate global illumination. 0 disables this feature", description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
min=0, max=1024, min=0, max=1024,
) )
ao_bounces_render: IntProperty( ao_bounces_render: IntProperty(
name="AO Bounces Render", name="AO Bounces Render",
default=1, default=0,
description="After this number of light bounces, use approximate global illumination. 0 disables this feature", description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
min=0, max=1024, min=0, max=1024,
) )

View File

@@ -526,35 +526,6 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
col.prop(cscene, "caustics_refractive", text="Refractive") col.prop(cscene, "caustics_refractive", text="Refractive")
class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel):
bl_label = "Fast GI Approximation"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "CYCLES_RENDER_PT_light_paths"
def draw_header(self, context):
scene = context.scene
cscene = scene.cycles
self.layout.prop(cscene, "use_fast_gi", text="")
def draw(self, context):
scene = context.scene
cscene = scene.cycles
world = scene.world
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column(align=True)
col.prop(cscene, "ao_bounces", text="Viewport Bounces")
col.prop(cscene, "ao_bounces_render", text="Render Bounces")
if world:
light = world.light_settings
layout.prop(light, "distance", text="AO Distance")
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel): class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
bl_label = "Motion Blur" bl_label = "Motion Blur"
bl_options = {'DEFAULT_CLOSED'} bl_options = {'DEFAULT_CLOSED'}
@@ -775,7 +746,7 @@ class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
col = layout.column() col = layout.column()
col.prop(rd, "use_save_buffers") col.prop(rd, "use_save_buffers")
col.prop(rd, "use_persistent_data", text="Persistent Data") col.prop(rd, "use_persistent_data", text="Persistent Images")
class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel): class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
@@ -1438,15 +1409,15 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface') panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel): class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
bl_label = "Beam Shape" bl_label = "Spot Shape"
bl_parent_id = "CYCLES_LIGHT_PT_light" bl_parent_id = "CYCLES_LIGHT_PT_light"
bl_context = "data" bl_context = "data"
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
if context.light.type in {'SPOT', 'AREA'}: light = context.light
return context.light and CyclesButtonsPanel.poll(context) return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@@ -1454,12 +1425,9 @@ class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
layout.use_property_split = True layout.use_property_split = True
col = layout.column() col = layout.column()
if light.type == 'SPOT': col.prop(light, "spot_size", text="Size")
col.prop(light, "spot_size", text="Spot Size") col.prop(light, "spot_blend", text="Blend", slider=True)
col.prop(light, "spot_blend", text="Blend", slider=True) col.prop(light, "show_cone")
col.prop(light, "show_cone")
elif light.type == 'AREA':
col.prop(light, "spread", text="Spread")
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel): class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
@@ -2070,6 +2038,7 @@ class CYCLES_RENDER_PT_simplify_viewport(CyclesButtonsPanel, Panel):
col.prop(rd, "simplify_subdivision", text="Max Subdivision") col.prop(rd, "simplify_subdivision", text="Max Subdivision")
col.prop(rd, "simplify_child_particles", text="Child Particles") col.prop(rd, "simplify_child_particles", text="Child Particles")
col.prop(cscene, "texture_limit", text="Texture Limit") col.prop(cscene, "texture_limit", text="Texture Limit")
col.prop(cscene, "ao_bounces", text="AO Bounces")
col.prop(rd, "simplify_volumes", text="Volume Resolution") col.prop(rd, "simplify_volumes", text="Volume Resolution")
@@ -2095,6 +2064,7 @@ class CYCLES_RENDER_PT_simplify_render(CyclesButtonsPanel, Panel):
col.prop(rd, "simplify_subdivision_render", text="Max Subdivision") col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
col.prop(rd, "simplify_child_particles_render", text="Child Particles") col.prop(rd, "simplify_child_particles_render", text="Child Particles")
col.prop(cscene, "texture_limit_render", text="Texture Limit") col.prop(cscene, "texture_limit_render", text="Texture Limit")
col.prop(cscene, "ao_bounces_render", text="AO Bounces")
class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel): class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
@@ -2272,7 +2242,6 @@ classes = (
CYCLES_RENDER_PT_light_paths_max_bounces, CYCLES_RENDER_PT_light_paths_max_bounces,
CYCLES_RENDER_PT_light_paths_clamping, CYCLES_RENDER_PT_light_paths_clamping,
CYCLES_RENDER_PT_light_paths_caustics, CYCLES_RENDER_PT_light_paths_caustics,
CYCLES_RENDER_PT_light_paths_fast_gi,
CYCLES_RENDER_PT_volumes, CYCLES_RENDER_PT_volumes,
CYCLES_RENDER_PT_subdivision, CYCLES_RENDER_PT_subdivision,
CYCLES_RENDER_PT_hair, CYCLES_RENDER_PT_hair,
@@ -2315,7 +2284,7 @@ classes = (
CYCLES_LIGHT_PT_preview, CYCLES_LIGHT_PT_preview,
CYCLES_LIGHT_PT_light, CYCLES_LIGHT_PT_light,
CYCLES_LIGHT_PT_nodes, CYCLES_LIGHT_PT_nodes,
CYCLES_LIGHT_PT_beam_shape, CYCLES_LIGHT_PT_spot,
CYCLES_WORLD_PT_preview, CYCLES_WORLD_PT_preview,
CYCLES_WORLD_PT_surface, CYCLES_WORLD_PT_surface,
CYCLES_WORLD_PT_volume, CYCLES_WORLD_PT_volume,
@@ -2345,7 +2314,7 @@ classes = (
node_panel(CYCLES_WORLD_PT_settings_surface), node_panel(CYCLES_WORLD_PT_settings_surface),
node_panel(CYCLES_WORLD_PT_settings_volume), node_panel(CYCLES_WORLD_PT_settings_volume),
node_panel(CYCLES_LIGHT_PT_light), node_panel(CYCLES_LIGHT_PT_light),
node_panel(CYCLES_LIGHT_PT_beam_shape) node_panel(CYCLES_LIGHT_PT_spot),
) )

View File

@@ -217,18 +217,6 @@ def do_versions(self):
baov.name = caov.get("name", "AOV") baov.name = caov.get("name", "AOV")
baov.type = "COLOR" if caov.get("type", 1) == 1 else "VALUE" baov.type = "COLOR" if caov.get("type", 1) == 1 else "VALUE"
if version <= (2, 93, 16):
cscene = scene.cycles
ao_bounces = cscene.get("ao_bounces", 0)
ao_bounces_render = cscene.get("ao_bounces_render", 0)
if scene.render.use_simplify and (ao_bounces or ao_bounces_render):
cscene.use_fast_gi = True
cscene.ao_bounces = ao_bounces
cscene.ao_bounces_render = ao_bounces_render
else:
cscene.ao_bounces = 1
cscene.ao_bounces_render = 1
# Lamps # Lamps
for light in bpy.data.lights: for light in bpy.data.lights:
if light.library not in libraries: if light.library not in libraries:

View File

@@ -29,7 +29,7 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image, int frame)
{ {
} }
bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) bool BlenderImageLoader::load_metadata(ImageMetaData &metadata)
{ {
metadata.width = b_image.size()[0]; metadata.width = b_image.size()[0];
metadata.height = b_image.size()[1]; metadata.height = b_image.size()[1];
@@ -171,7 +171,7 @@ BlenderPointDensityLoader::BlenderPointDensityLoader(BL::Depsgraph b_depsgraph,
{ {
} }
bool BlenderPointDensityLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) bool BlenderPointDensityLoader::load_metadata(ImageMetaData &metadata)
{ {
metadata.channels = 4; metadata.channels = 4;
metadata.width = b_node.resolution(); metadata.width = b_node.resolution();

View File

@@ -27,7 +27,7 @@ class BlenderImageLoader : public ImageLoader {
public: public:
BlenderImageLoader(BL::Image b_image, int frame); BlenderImageLoader(BL::Image b_image, int frame);
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override; bool load_metadata(ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata, bool load_pixels(const ImageMetaData &metadata,
void *pixels, void *pixels,
const size_t pixels_size, const size_t pixels_size,
@@ -44,7 +44,7 @@ class BlenderPointDensityLoader : public ImageLoader {
public: public:
BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node); BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node);
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override; bool load_metadata(ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata, bool load_pixels(const ImageMetaData &metadata,
void *pixels, void *pixels,
const size_t pixels_size, const size_t pixels_size,

View File

@@ -82,7 +82,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_axisu(transform_get_column(&tfm, 0)); light->set_axisu(transform_get_column(&tfm, 0));
light->set_axisv(transform_get_column(&tfm, 1)); light->set_axisv(transform_get_column(&tfm, 1));
light->set_sizeu(b_area_light.size()); light->set_sizeu(b_area_light.size());
light->set_spread(b_area_light.spread());
switch (b_area_light.shape()) { switch (b_area_light.shape()) {
case BL::AreaLight::shape_SQUARE: case BL::AreaLight::shape_SQUARE:
light->set_sizev(light->get_sizeu()); light->set_sizev(light->get_sizeu());

View File

@@ -375,7 +375,7 @@ static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool
case BL::Attribute::domain_POINT: case BL::Attribute::domain_POINT:
element = ATTR_ELEMENT_VERTEX; element = ATTR_ELEMENT_VERTEX;
break; break;
case BL::Attribute::domain_FACE: case BL::Attribute::domain_POLYGON:
element = ATTR_ELEMENT_FACE; element = ATTR_ELEMENT_FACE;
break; break;
default: default:

View File

@@ -143,6 +143,12 @@ void BlenderSession::create_session()
session->scene = scene; session->scene = scene;
/* There is no single depsgraph to use for the entire render.
* So we need to handle this differently.
*
* We could loop over the final render result render layers in pipeline and keep Cycles unaware
* of multiple layers, or perhaps move syncing further down in the pipeline.
*/
/* create sync */ /* create sync */
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
BL::Object b_camera_override(b_engine.camera_override()); BL::Object b_camera_override(b_engine.camera_override());
@@ -207,7 +213,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
if (scene->params.modified(scene_params) || session->params.modified(session_params) || if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
!this->b_render.use_persistent_data()) { !scene_params.persistent_data) {
/* if scene or session parameters changed, it's easier to simply re-create /* if scene or session parameters changed, it's easier to simply re-create
* them rather than trying to distinguish which settings need to be updated * them rather than trying to distinguish which settings need to be updated
*/ */
@@ -219,6 +225,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
} }
session->progress.reset(); session->progress.reset();
scene->reset();
session->tile_manager.set_tile_order(session_params.tile_order); session->tile_manager.set_tile_order(session_params.tile_order);
@@ -227,15 +234,12 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
*/ */
session->stats.mem_peak = session->stats.mem_used; session->stats.mem_peak = session->stats.mem_used;
if (is_new_session) { /* There is no single depsgraph to use for the entire render.
/* Sync object should be re-created for new scene. */ * See note on create_session().
delete sync; */
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); /* sync object should be re-created */
} delete sync;
else { sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
/* Sync recalculations to do just the required updates. */
sync->sync_recalc(b_depsgraph, b_v3d);
}
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL); BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
BL::RegionView3D b_null_region_view3d(PointerRNA_NULL); BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
@@ -498,7 +502,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* Compute render passes and film settings. */ /* Compute render passes and film settings. */
vector<Pass> passes = sync->sync_render_passes( vector<Pass> passes = sync->sync_render_passes(
b_scene, b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising); b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising);
/* Set buffer params, using film settings from sync_render_passes. */ /* Set buffer params, using film settings from sync_render_passes. */
buffer_params.passes = passes; buffer_params.passes = passes;
@@ -594,6 +598,18 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* clear callback */ /* clear callback */
session->write_render_tile_cb = function_null; session->write_render_tile_cb = function_null;
session->update_render_tile_cb = function_null; session->update_render_tile_cb = function_null;
/* TODO: find a way to clear this data for persistent data render */
#if 0
/* free all memory used (host and device), so we wouldn't leave render
* engine with extra memory allocated
*/
session->device_free();
delete sync;
sync = NULL;
#endif
} }
static int bake_pass_filter_get(const int pass_filter) static int bake_pass_filter_get(const int pass_filter)

View File

@@ -211,11 +211,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
} }
} }
if (b_v3d) { BlenderViewportParameters new_viewport_parameters(b_v3d);
BlenderViewportParameters new_viewport_parameters(b_v3d); if (viewport_parameters.modified(new_viewport_parameters)) {
if (viewport_parameters.modified(new_viewport_parameters)) { world_recalc = true;
world_recalc = true;
}
} }
} }
@@ -360,7 +358,7 @@ void BlenderSync::sync_integrator()
integrator->set_adaptive_min_samples(adaptive_min_samples); integrator->set_adaptive_min_samples(adaptive_min_samples);
if (get_boolean(cscene, "use_fast_gi")) { if (b_scene.render().use_simplify()) {
if (preview) { if (preview) {
integrator->set_ao_bounces(get_int(cscene, "ao_bounces")); integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
} }
@@ -569,8 +567,7 @@ int BlenderSync::get_denoising_pass(BL::RenderPass &b_pass)
return -1; return -1;
} }
vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene, vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
BL::RenderLayer &b_rlay,
BL::ViewLayer &b_view_layer, BL::ViewLayer &b_view_layer,
bool adaptive_sampling, bool adaptive_sampling,
const DenoiseParams &denoising) const DenoiseParams &denoising)
@@ -581,7 +578,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene,
for (BL::RenderPass &b_pass : b_rlay.passes) { for (BL::RenderPass &b_pass : b_rlay.passes) {
PassType pass_type = get_pass_type(b_pass); PassType pass_type = get_pass_type(b_pass);
if (pass_type == PASS_MOTION && b_scene.render().use_motion_blur()) if (pass_type == PASS_MOTION && scene->integrator->get_motion_blur())
continue; continue;
if (pass_type != PASS_NONE) if (pass_type != PASS_NONE)
Pass::add(pass_type, passes, b_pass.name().c_str()); Pass::add(pass_type, passes, b_pass.name().c_str());
@@ -760,6 +757,7 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background) SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
{ {
BL::RenderSettings r = b_scene.render();
SceneParams params; SceneParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system"); const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
@@ -783,6 +781,11 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
params.hair_shape = (CurveShapeType)get_enum( params.hair_shape = (CurveShapeType)get_enum(
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK); csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
if (background && params.shadingsystem != SHADINGSYSTEM_OSL)
params.persistent_data = r.use_persistent_data();
else
params.persistent_data = false;
int texture_limit; int texture_limit;
if (background) { if (background) {
texture_limit = RNA_enum_get(&cscene, "texture_limit_render"); texture_limit = RNA_enum_get(&cscene, "texture_limit_render");

View File

@@ -74,8 +74,7 @@ class BlenderSync {
int height, int height,
void **python_thread_state); void **python_thread_state);
void sync_view_layer(BL::SpaceView3D &b_v3d, BL::ViewLayer &b_view_layer); void sync_view_layer(BL::SpaceView3D &b_v3d, BL::ViewLayer &b_view_layer);
vector<Pass> sync_render_passes(BL::Scene &b_scene, vector<Pass> sync_render_passes(BL::RenderLayer &b_render_layer,
BL::RenderLayer &b_render_layer,
BL::ViewLayer &b_view_layer, BL::ViewLayer &b_view_layer,
bool adaptive_sampling, bool adaptive_sampling,
const DenoiseParams &denoising); const DenoiseParams &denoising);

View File

@@ -26,7 +26,7 @@
#ifdef WITH_OPENVDB #ifdef WITH_OPENVDB
# include <openvdb/openvdb.h> # include <openvdb/openvdb.h>
openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume, openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume,
const struct VolumeGrid *grid); struct VolumeGrid *grid);
#endif #endif
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
@@ -41,7 +41,7 @@ class BlenderSmokeLoader : public ImageLoader {
mesh_texture_space(b_mesh, texspace_loc, texspace_size); mesh_texture_space(b_mesh, texspace_loc, texspace_size);
} }
bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override bool load_metadata(ImageMetaData &metadata) override
{ {
if (!b_domain) { if (!b_domain) {
return false; return false;
@@ -227,7 +227,7 @@ class BlenderVolumeLoader : public VDBImageLoader {
const bool unload = !b_volume_grid.is_loaded(); const bool unload = !b_volume_grid.is_loaded();
::Volume *volume = (::Volume *)b_volume.ptr.data; ::Volume *volume = (::Volume *)b_volume.ptr.data;
const VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data; VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data;
grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
if (unload) { if (unload) {

View File

@@ -619,7 +619,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
info.num = 0; info.num = 0;
info.has_half_images = true; info.has_half_images = true;
info.has_nanovdb = true;
info.has_volume_decoupled = true; info.has_volume_decoupled = true;
info.has_branched_path = true; info.has_branched_path = true;
info.has_adaptive_stop_per_sample = true; info.has_adaptive_stop_per_sample = true;
@@ -666,7 +665,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
/* Accumulate device info. */ /* Accumulate device info. */
info.has_half_images &= device.has_half_images; info.has_half_images &= device.has_half_images;
info.has_nanovdb &= device.has_nanovdb;
info.has_volume_decoupled &= device.has_volume_decoupled; info.has_volume_decoupled &= device.has_volume_decoupled;
info.has_branched_path &= device.has_branched_path; info.has_branched_path &= device.has_branched_path;
info.has_adaptive_stop_per_sample &= device.has_adaptive_stop_per_sample; info.has_adaptive_stop_per_sample &= device.has_adaptive_stop_per_sample;

View File

@@ -78,7 +78,6 @@ class DeviceInfo {
int num; int num;
bool display_device; /* GPU is used as a display device. */ bool display_device; /* GPU is used as a display device. */
bool has_half_images; /* Support half-float textures. */ bool has_half_images; /* Support half-float textures. */
bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_volume_decoupled; /* Decoupled volume shading. */ bool has_volume_decoupled; /* Decoupled volume shading. */
bool has_branched_path; /* Supports branched path tracing. */ bool has_branched_path; /* Supports branched path tracing. */
bool has_adaptive_stop_per_sample; /* Per-sample adaptive sampling stopping. */ bool has_adaptive_stop_per_sample; /* Per-sample adaptive sampling stopping. */
@@ -100,7 +99,6 @@ class DeviceInfo {
cpu_threads = 0; cpu_threads = 0;
display_device = false; display_device = false;
has_half_images = false; has_half_images = false;
has_nanovdb = false;
has_volume_decoupled = false; has_volume_decoupled = false;
has_branched_path = true; has_branched_path = true;
has_adaptive_stop_per_sample = false; has_adaptive_stop_per_sample = false;

View File

@@ -1654,7 +1654,6 @@ void device_cpu_info(vector<DeviceInfo> &devices)
info.has_adaptive_stop_per_sample = true; info.has_adaptive_stop_per_sample = true;
info.has_osl = true; info.has_osl = true;
info.has_half_images = true; info.has_half_images = true;
info.has_nanovdb = true;
info.has_profiling = true; info.has_profiling = true;
info.denoisers = DENOISER_NLM; info.denoisers = DENOISER_NLM;
if (openimagedenoise_supported()) { if (openimagedenoise_supported()) {

View File

@@ -128,7 +128,6 @@ void device_cuda_info(vector<DeviceInfo> &devices)
info.num = num; info.num = num;
info.has_half_images = (major >= 3); info.has_half_images = (major >= 3);
info.has_nanovdb = true;
info.has_volume_decoupled = false; info.has_volume_decoupled = false;
info.has_adaptive_stop_per_sample = false; info.has_adaptive_stop_per_sample = false;
info.denoisers = DENOISER_NLM; info.denoisers = DENOISER_NLM;

View File

@@ -46,13 +46,10 @@ class MultiDevice : public Device {
list<SubDevice> devices, denoising_devices; list<SubDevice> devices, denoising_devices;
device_ptr unique_key; device_ptr unique_key;
vector<vector<SubDevice *>> peer_islands; vector<vector<SubDevice *>> peer_islands;
bool use_denoising;
bool matching_rendering_and_denoising_devices; bool matching_rendering_and_denoising_devices;
MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_) MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
: Device(info, stats, profiler, background_), : Device(info, stats, profiler, background_), unique_key(1)
unique_key(1),
use_denoising(!info.denoising_devices.empty())
{ {
foreach (DeviceInfo &subinfo, info.multi_devices) { foreach (DeviceInfo &subinfo, info.multi_devices) {
/* Always add CPU devices at the back since GPU devices can change /* Always add CPU devices at the back since GPU devices can change
@@ -197,7 +194,6 @@ class MultiDevice : public Device {
if (!sub.device->load_kernels(requested_features)) if (!sub.device->load_kernels(requested_features))
return false; return false;
use_denoising = requested_features.use_denoising;
if (requested_features.use_denoising) { if (requested_features.use_denoising) {
/* Only need denoising feature, everything else is unused. */ /* Only need denoising feature, everything else is unused. */
DeviceRequestedFeatures denoising_features; DeviceRequestedFeatures denoising_features;
@@ -404,7 +400,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size; size_t existing_size = mem.device_size;
/* The tile buffers are allocated on each device (see below), so copy to all of them */ /* The tile buffers are allocated on each device (see below), so copy to all of them */
if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) { if (strcmp(mem.name, "RenderBuffers") == 0) {
foreach (SubDevice &sub, devices) { foreach (SubDevice &sub, devices) {
mem.device = sub.device; mem.device = sub.device;
mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0; mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
@@ -470,7 +466,7 @@ class MultiDevice : public Device {
/* This is a hack to only allocate the tile buffers on denoising devices /* This is a hack to only allocate the tile buffers on denoising devices
* Similarly the tile buffers also need to be allocated separately on all devices so any * Similarly the tile buffers also need to be allocated separately on all devices so any
* overlap rendered for denoising does not interfere with each other */ * overlap rendered for denoising does not interfere with each other */
if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) { if (strcmp(mem.name, "RenderBuffers") == 0) {
vector<device_ptr> device_pointers; vector<device_ptr> device_pointers;
device_pointers.reserve(devices.size()); device_pointers.reserve(devices.size());
@@ -522,7 +518,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size; size_t existing_size = mem.device_size;
/* Free memory that was allocated for all devices (see above) on each device */ /* Free memory that was allocated for all devices (see above) on each device */
if (mem.type == MEM_PIXELS || (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising)) { if (strcmp(mem.name, "RenderBuffers") == 0 || mem.type == MEM_PIXELS) {
foreach (SubDevice &sub, devices) { foreach (SubDevice &sub, devices) {
mem.device = sub.device; mem.device = sub.device;
mem.device_pointer = sub.ptr_map[key]; mem.device_pointer = sub.ptr_map[key];

View File

@@ -126,9 +126,6 @@ void device_opencl_info(vector<DeviceInfo> &devices)
/* Check OpenCL extensions */ /* Check OpenCL extensions */
info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos; info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
/* Disabled for now due to apparent AMD driver bug. */
info.has_nanovdb = platform_name != "AMD Accelerated Parallel Processing";
devices.push_back(info); devices.push_back(info);
num_devices++; num_devices++;
} }

View File

@@ -362,7 +362,7 @@ class OptiXDevice : public CUDADevice {
} }
} }
OptixModuleCompileOptions module_options = {}; OptixModuleCompileOptions module_options;
module_options.maxRegisterCount = 0; // Do not set an explicit register limit module_options.maxRegisterCount = 0; // Do not set an explicit register limit
# ifdef WITH_CYCLES_DEBUG # ifdef WITH_CYCLES_DEBUG
module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0; module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0;
@@ -377,7 +377,7 @@ class OptiXDevice : public CUDADevice {
module_options.numBoundValues = 0; module_options.numBoundValues = 0;
# endif # endif
OptixPipelineCompileOptions pipeline_options = {}; OptixPipelineCompileOptions pipeline_options;
// Default to no motion blur and two-level graph, since it is the fastest option // Default to no motion blur and two-level graph, since it is the fastest option
pipeline_options.usesMotionBlur = false; pipeline_options.usesMotionBlur = false;
pipeline_options.traversableGraphFlags = pipeline_options.traversableGraphFlags =
@@ -477,7 +477,7 @@ class OptiXDevice : public CUDADevice {
# if OPTIX_ABI_VERSION >= 36 # if OPTIX_ABI_VERSION >= 36
if (DebugFlags().optix.curves_api && requested_features.use_hair_thick) { if (DebugFlags().optix.curves_api && requested_features.use_hair_thick) {
OptixBuiltinISOptions builtin_options = {}; OptixBuiltinISOptions builtin_options;
builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE; builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
builtin_options.usesMotionBlur = false; builtin_options.usesMotionBlur = false;
@@ -571,7 +571,7 @@ class OptiXDevice : public CUDADevice {
stack_size[PG_HITS_MOTION].cssIS + stack_size[PG_HITS_MOTION].cssAH); stack_size[PG_HITS_MOTION].cssIS + stack_size[PG_HITS_MOTION].cssAH);
# endif # endif
OptixPipelineLinkOptions link_options = {}; OptixPipelineLinkOptions link_options;
link_options.maxTraceDepth = 1; link_options.maxTraceDepth = 1;
# ifdef WITH_CYCLES_DEBUG # ifdef WITH_CYCLES_DEBUG
link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL; link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL;
@@ -953,7 +953,7 @@ class OptiXDevice : public CUDADevice {
} }
// Create OptiX denoiser handle on demand when it is first used // Create OptiX denoiser handle on demand when it is first used
OptixDenoiserOptions denoiser_options = {}; OptixDenoiserOptions denoiser_options;
assert(task.denoising.input_passes >= 1 && task.denoising.input_passes <= 3); assert(task.denoising.input_passes >= 1 && task.denoising.input_passes <= 3);
denoiser_options.inputKind = static_cast<OptixDenoiserInputKind>( denoiser_options.inputKind = static_cast<OptixDenoiserInputKind>(
OPTIX_DENOISER_INPUT_RGB + (task.denoising.input_passes - 1)); OPTIX_DENOISER_INPUT_RGB + (task.denoising.input_passes - 1));
@@ -1157,7 +1157,7 @@ class OptiXDevice : public CUDADevice {
// Compute memory usage // Compute memory usage
OptixAccelBufferSizes sizes = {}; OptixAccelBufferSizes sizes = {};
OptixAccelBuildOptions options = {}; OptixAccelBuildOptions options;
options.operation = operation; options.operation = operation;
if (background) { if (background) {
// Prefer best performance and lowest memory consumption in background // Prefer best performance and lowest memory consumption in background
@@ -1195,7 +1195,7 @@ class OptiXDevice : public CUDADevice {
} }
// Finally build the acceleration structure // Finally build the acceleration structure
OptixAccelEmitDesc compacted_size_prop = {}; OptixAccelEmitDesc compacted_size_prop;
compacted_size_prop.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE; compacted_size_prop.type = OPTIX_PROPERTY_TYPE_COMPACTED_SIZE;
// A tiny space was allocated for this property at the end of the temporary buffer above // A tiny space was allocated for this property at the end of the temporary buffer above
// Make sure this pointer is 8-byte aligned // Make sure this pointer is 8-byte aligned

View File

@@ -2036,9 +2036,7 @@ string OpenCLDevice::kernel_build_options(const string *debug_src)
# endif # endif
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (info.has_nanovdb) { build_options += "-DWITH_NANOVDB ";
build_options += "-DWITH_NANOVDB ";
}
# endif # endif
return build_options; return build_options;

View File

@@ -93,7 +93,6 @@ set(SRC_BVH_HEADERS
bvh/bvh_local.h bvh/bvh_local.h
bvh/bvh_traversal.h bvh/bvh_traversal.h
bvh/bvh_types.h bvh/bvh_types.h
bvh/bvh_util.h
bvh/bvh_volume.h bvh/bvh_volume.h
bvh/bvh_volume_all.h bvh/bvh_volume_all.h
bvh/bvh_embree.h bvh/bvh_embree.h

View File

@@ -29,11 +29,10 @@
# include "kernel/bvh/bvh_embree.h" # include "kernel/bvh/bvh_embree.h"
#endif #endif
#include "kernel/bvh/bvh_types.h"
#include "kernel/bvh/bvh_util.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
#include "kernel/bvh/bvh_types.h"
#ifndef __KERNEL_OPTIX__ #ifndef __KERNEL_OPTIX__
/* Regular BVH traversal */ /* Regular BVH traversal */
@@ -534,4 +533,97 @@ ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
} }
#endif /* __VOLUME_RECORD_ALL__ */ #endif /* __VOLUME_RECORD_ALL__ */
/* Ray offset to avoid self intersection.
*
* This function should be used to compute a modified ray start position for
* rays leaving from a surface. */
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
{
#ifdef __INTERSECTION_REFINE__
const float epsilon_f = 1e-5f;
/* ideally this should match epsilon_f, but instancing and motion blur
* precision makes it problematic */
const float epsilon_test = 1.0f;
const int epsilon_i = 32;
float3 res;
/* x component */
if (fabsf(P.x) < epsilon_test) {
res.x = P.x + Ng.x * epsilon_f;
}
else {
uint ix = __float_as_uint(P.x);
ix += ((ix ^ __float_as_uint(Ng.x)) >> 31) ? -epsilon_i : epsilon_i;
res.x = __uint_as_float(ix);
}
/* y component */
if (fabsf(P.y) < epsilon_test) {
res.y = P.y + Ng.y * epsilon_f;
}
else {
uint iy = __float_as_uint(P.y);
iy += ((iy ^ __float_as_uint(Ng.y)) >> 31) ? -epsilon_i : epsilon_i;
res.y = __uint_as_float(iy);
}
/* z component */
if (fabsf(P.z) < epsilon_test) {
res.z = P.z + Ng.z * epsilon_f;
}
else {
uint iz = __float_as_uint(P.z);
iz += ((iz ^ __float_as_uint(Ng.z)) >> 31) ? -epsilon_i : epsilon_i;
res.z = __uint_as_float(iz);
}
return res;
#else
const float epsilon_f = 1e-4f;
return P + epsilon_f * Ng;
#endif
}
#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
/* ToDo: Move to another file? */
ccl_device int intersections_compare(const void *a, const void *b)
{
const Intersection *isect_a = (const Intersection *)a;
const Intersection *isect_b = (const Intersection *)b;
if (isect_a->t < isect_b->t)
return -1;
else if (isect_a->t > isect_b->t)
return 1;
else
return 0;
}
#endif
#if defined(__SHADOW_RECORD_ALL__)
ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
{
# ifdef __KERNEL_GPU__
/* Use bubble sort which has more friendly memory pattern on GPU. */
bool swapped;
do {
swapped = false;
for (int j = 0; j < num_hits - 1; ++j) {
if (hits[j].t > hits[j + 1].t) {
struct Intersection tmp = hits[j];
hits[j] = hits[j + 1];
hits[j + 1] = tmp;
swapped = true;
}
}
--num_hits;
} while (swapped);
# else
qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
# endif
}
#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -180,10 +180,25 @@ ccl_device_inline
/* todo: optimize so primitive visibility flag indicates if /* todo: optimize so primitive visibility flag indicates if
* the primitive has a transparent shadow shader? */ * the primitive has a transparent shadow shader? */
const int flags = intersection_get_shader_flags(kg, isect_array); int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
int shader = 0;
#ifdef __HAIR__
if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
{
shader = kernel_tex_fetch(__tri_shader, prim);
}
#ifdef __HAIR__
else {
float4 str = kernel_tex_fetch(__curves, prim);
shader = __float_as_int(str.z);
}
#endif
int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
/* if no transparent shadows, all light is blocked */ /* if no transparent shadows, all light is blocked */
if (!(flags & SD_HAS_TRANSPARENT_SHADOW)) { if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
return true; return true;
} }
/* if maximum number of hits reached, block all light */ /* if maximum number of hits reached, block all light */

View File

@@ -1,162 +0,0 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
CCL_NAMESPACE_BEGIN
/* Ray offset to avoid self intersection.
*
* This function should be used to compute a modified ray start position for
* rays leaving from a surface. */
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
{
#ifdef __INTERSECTION_REFINE__
const float epsilon_f = 1e-5f;
/* ideally this should match epsilon_f, but instancing and motion blur
* precision makes it problematic */
const float epsilon_test = 1.0f;
const int epsilon_i = 32;
float3 res;
/* x component */
if (fabsf(P.x) < epsilon_test) {
res.x = P.x + Ng.x * epsilon_f;
}
else {
uint ix = __float_as_uint(P.x);
ix += ((ix ^ __float_as_uint(Ng.x)) >> 31) ? -epsilon_i : epsilon_i;
res.x = __uint_as_float(ix);
}
/* y component */
if (fabsf(P.y) < epsilon_test) {
res.y = P.y + Ng.y * epsilon_f;
}
else {
uint iy = __float_as_uint(P.y);
iy += ((iy ^ __float_as_uint(Ng.y)) >> 31) ? -epsilon_i : epsilon_i;
res.y = __uint_as_float(iy);
}
/* z component */
if (fabsf(P.z) < epsilon_test) {
res.z = P.z + Ng.z * epsilon_f;
}
else {
uint iz = __float_as_uint(P.z);
iz += ((iz ^ __float_as_uint(Ng.z)) >> 31) ? -epsilon_i : epsilon_i;
res.z = __uint_as_float(iz);
}
return res;
#else
const float epsilon_f = 1e-4f;
return P + epsilon_f * Ng;
#endif
}
#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
/* ToDo: Move to another file? */
ccl_device int intersections_compare(const void *a, const void *b)
{
const Intersection *isect_a = (const Intersection *)a;
const Intersection *isect_b = (const Intersection *)b;
if (isect_a->t < isect_b->t)
return -1;
else if (isect_a->t > isect_b->t)
return 1;
else
return 0;
}
#endif
#if defined(__SHADOW_RECORD_ALL__)
ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
{
kernel_assert(num_hits > 0);
# ifdef __KERNEL_GPU__
/* Use bubble sort which has more friendly memory pattern on GPU. */
bool swapped;
do {
swapped = false;
for (int j = 0; j < num_hits - 1; ++j) {
if (hits[j].t > hits[j + 1].t) {
struct Intersection tmp = hits[j];
hits[j] = hits[j + 1];
hits[j + 1] = tmp;
swapped = true;
}
}
--num_hits;
} while (swapped);
# else
qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
# endif
}
#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
/* Utility to quickly get a shader flags from an intersection. */
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals *ccl_restrict kg,
const Intersection *isect)
{
const int prim = kernel_tex_fetch(__prim_index, isect->prim);
int shader = 0;
#ifdef __HAIR__
if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
{
shader = kernel_tex_fetch(__tri_shader, prim);
}
#ifdef __HAIR__
else {
float4 str = kernel_tex_fetch(__curves, prim);
shader = __float_as_int(str.z);
}
#endif
return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
}
ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict kg,
const Intersection *isect)
{
const int prim = kernel_tex_fetch(__prim_index, isect->prim);
int shader = 0;
#ifdef __HAIR__
if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
{
shader = kernel_tex_fetch(__tri_shader, prim);
}
#ifdef __HAIR__
else {
float4 str = kernel_tex_fetch(__curves, prim);
shader = __float_as_int(str.z);
}
#endif
return shader & SHADER_MASK;
}
CCL_NAMESPACE_END

View File

@@ -119,11 +119,11 @@ ccl_device_inline bool lamp_light_sample(
klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
float3 axisv = make_float3( float3 axisv = make_float3(
klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
float invarea = fabsf(klight->area.invarea); float invarea = fabsf(klight->area.invarea);
bool is_round = (klight->area.invarea < 0.0f); bool is_round = (klight->area.invarea < 0.0f);
if (dot(ls->P - P, Ng) > 0.0f) { if (dot(ls->P - P, D) > 0.0f) {
return false; return false;
} }
@@ -136,37 +136,19 @@ ccl_device_inline bool lamp_light_sample(
} }
else { else {
inplane = ls->P; inplane = ls->P;
ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true);
float3 sample_axisu = axisu;
float3 sample_axisv = axisv;
if (klight->area.tan_spread > 0.0f) {
if (!light_spread_clamp_area_light(
P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
return false;
}
}
ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true);
inplane = ls->P - inplane; inplane = ls->P - inplane;
} }
ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f; ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f; ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
ls->Ng = Ng; ls->Ng = D;
ls->D = normalize_len(ls->P - P, &ls->t); ls->D = normalize_len(ls->P - P, &ls->t);
ls->eval_fac = 0.25f * invarea; ls->eval_fac = 0.25f * invarea;
if (klight->area.tan_spread > 0.0f) {
/* Area Light spread angle attenuation */
ls->eval_fac *= light_spread_attenuation(
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
}
if (is_round) { if (is_round) {
ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t); ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
} }
} }
} }
@@ -301,28 +283,9 @@ ccl_device bool lamp_light_eval(
ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t); ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
} }
else { else {
float3 sample_axisu = axisu; ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
float3 sample_axisv = axisv;
if (klight->area.tan_spread > 0.0f) {
if (!light_spread_clamp_area_light(
P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
return false;
}
}
ls->pdf = rect_light_sample(P, &light_P, sample_axisu, sample_axisv, 0, 0, false);
} }
ls->eval_fac = 0.25f * invarea; ls->eval_fac = 0.25f * invarea;
if (klight->area.tan_spread > 0.0f) {
/* Area Light spread angle attenuation */
ls->eval_fac *= light_spread_attenuation(
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
if (ls->eval_fac == 0.0f) {
return false;
}
}
} }
else { else {
return false; return false;

View File

@@ -146,70 +146,6 @@ ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot
return attenuation; return attenuation;
} }
ccl_device float light_spread_attenuation(const float3 D,
const float3 lightNg,
const float tan_spread,
const float normalize_spread)
{
/* Model a soft-box grid, computing the ratio of light not hidden by the
* slats of the grid at a given angle. (see D10594). */
const float cos_a = -dot(D, lightNg);
const float sin_a = safe_sqrtf(1.0f - sqr(cos_a));
const float tan_a = sin_a / cos_a;
return max((1.0f - (tan_spread * tan_a)) * normalize_spread, 0.0f);
}
/* Compute subset of area light that actually has an influence on the shading point, to
* reduce noise with low spread. */
ccl_device bool light_spread_clamp_area_light(const float3 P,
const float3 lightNg,
float3 *lightP,
float3 *axisu,
float3 *axisv,
const float tan_spread)
{
/* Closest point in area light plane and distance to that plane. */
const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg;
const float t = len(closest_P - P);
/* Radius of circle on area light that actually affects the shading point. */
const float radius = t / tan_spread;
/* TODO: would be faster to store as normalized vector + length, also in rect_light_sample. */
float len_u, len_v;
const float3 u = normalize_len(*axisu, &len_u);
const float3 v = normalize_len(*axisv, &len_v);
/* Local uv coordinates of closest point. */
const float closest_u = dot(u, closest_P - *lightP);
const float closest_v = dot(v, closest_P - *lightP);
/* Compute rectangle encompassing the circle that affects the shading point,
* clamped to the bounds of the area light. */
const float min_u = max(closest_u - radius, -len_u * 0.5f);
const float max_u = min(closest_u + radius, len_u * 0.5f);
const float min_v = max(closest_v - radius, -len_v * 0.5f);
const float max_v = min(closest_v + radius, len_v * 0.5f);
/* Skip if rectangle is empty. */
if (min_u >= max_u || min_v >= max_v) {
return false;
}
/* Compute new area light center position and axes from rectangle in local
* uv coordinates. */
const float new_center_u = 0.5f * (min_u + max_u);
const float new_center_v = 0.5f * (min_v + max_v);
const float new_len_u = 0.5f * (max_u - min_u);
const float new_len_v = 0.5f * (max_v - min_v);
*lightP = *lightP + new_center_u * u + new_center_v * v;
*axisu = u * new_len_u * 2.0f;
*axisv = v * new_len_v * 2.0f;
return true;
}
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
{ {
float cos_pi = dot(Ng, I); float cos_pi = dot(Ng, I);

View File

@@ -65,6 +65,7 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg,
uint visibility = path_state_ray_visibility(kg, state); uint visibility = path_state_ray_visibility(kg, state);
if (path_state_ao_bounce(kg, state)) { if (path_state_ao_bounce(kg, state)) {
visibility = PATH_RAY_SHADOW;
ray->t = kernel_data.background.ao_distance; ray->t = kernel_data.background.ao_distance;
} }
@@ -415,13 +416,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
break; break;
} }
else if (path_state_ao_bounce(kg, state)) { else if (path_state_ao_bounce(kg, state)) {
if (intersection_get_shader_flags(kg, &isect) & break;
(SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
}
else {
break;
}
} }
/* Setup shader data. */ /* Setup shader data. */
@@ -559,13 +554,7 @@ ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg,
break; break;
} }
else if (path_state_ao_bounce(kg, state)) { else if (path_state_ao_bounce(kg, state)) {
if (intersection_get_shader_flags(kg, &isect) & break;
(SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
}
else {
break;
}
} }
/* Setup shader data. */ /* Setup shader data. */

View File

@@ -895,8 +895,6 @@ enum ShaderDataFlag {
SD_HAS_CONSTANT_EMISSION = (1 << 27), SD_HAS_CONSTANT_EMISSION = (1 << 27),
/* Needs to access attributes for volume rendering */ /* Needs to access attributes for volume rendering */
SD_NEED_VOLUME_ATTRIBUTES = (1 << 28), SD_NEED_VOLUME_ATTRIBUTES = (1 << 28),
/* Shader has emission */
SD_HAS_EMISSION = (1 << 29),
SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME | SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME |
SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR | SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR |
@@ -1503,9 +1501,9 @@ typedef struct KernelAreaLight {
float axisu[3]; float axisu[3];
float invarea; float invarea;
float axisv[3]; float axisv[3];
float tan_spread; float pad1;
float dir[3]; float dir[3];
float normalize_spread; float pad2;
} KernelAreaLight; } KernelAreaLight;
typedef struct KernelDistantLight { typedef struct KernelDistantLight {

View File

@@ -88,13 +88,6 @@ point wrap(point value, point max, point min)
wrap(value[2], max[2], min[2])); wrap(value[2], max[2], min[2]));
} }
/* Built in OSL faceforward is `(dot(I, Nref) > 0) ? -N : N;` which is different to
* GLSL `dot(Nref, I) < 0 ? N : -N` for zero values. */
point compatible_faceforward(point vec, point incident, point reference)
{
return dot(reference, incident) < 0.0 ? vec : -vec;
}
matrix euler_to_mat(point euler) matrix euler_to_mat(point euler)
{ {
float cx = cos(euler[0]); float cx = cos(euler[0]);

View File

@@ -46,12 +46,6 @@ shader node_vector_math(string math_type = "add",
else if (math_type == "reflect") { else if (math_type == "reflect") {
Vector = reflect(Vector1, normalize(Vector2)); Vector = reflect(Vector1, normalize(Vector2));
} }
else if (math_type == "refract") {
Vector = refract(Vector1, normalize(Vector2), Scale);
}
else if (math_type == "faceforward") {
Vector = compatible_faceforward(Vector1, Vector2, Vector3);
}
else if (math_type == "dot_product") { else if (math_type == "dot_product") {
Value = dot(Vector1, Vector2); Value = dot(Vector1, Vector2);
} }

View File

@@ -44,26 +44,26 @@ ccl_device void svm_node_vector_math(KernelGlobals *kg,
int *offset) int *offset)
{ {
uint value_stack_offset, vector_stack_offset; uint value_stack_offset, vector_stack_offset;
uint a_stack_offset, b_stack_offset, param1_stack_offset; uint a_stack_offset, b_stack_offset, scale_stack_offset;
svm_unpack_node_uchar3( svm_unpack_node_uchar3(
inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &param1_stack_offset); inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &scale_stack_offset);
svm_unpack_node_uchar2(outputs_stack_offsets, &value_stack_offset, &vector_stack_offset); svm_unpack_node_uchar2(outputs_stack_offsets, &value_stack_offset, &vector_stack_offset);
float3 a = stack_load_float3(stack, a_stack_offset); float3 a = stack_load_float3(stack, a_stack_offset);
float3 b = stack_load_float3(stack, b_stack_offset); float3 b = stack_load_float3(stack, b_stack_offset);
float3 c = make_float3(0.0f, 0.0f, 0.0f); float3 c = make_float3(0.0f, 0.0f, 0.0f);
float param1 = stack_load_float(stack, param1_stack_offset); float scale = stack_load_float(stack, scale_stack_offset);
float value; float value;
float3 vector; float3 vector;
/* 3 Vector Operators */ /* 3 Vector Operators */
if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD) { if (type == NODE_VECTOR_MATH_WRAP) {
uint4 extra_node = read_node(kg, offset); uint4 extra_node = read_node(kg, offset);
c = stack_load_float3(stack, extra_node.x); c = stack_load_float3(stack, extra_node.x);
} }
svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, c, param1); svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, c, scale);
if (stack_valid(value_stack_offset)) if (stack_valid(value_stack_offset))
stack_store_float(stack, value_stack_offset, value); stack_store_float(stack, value_stack_offset, value);

View File

@@ -22,7 +22,7 @@ ccl_device void svm_vector_math(float *value,
float3 a, float3 a,
float3 b, float3 b,
float3 c, float3 c,
float param1) float scale)
{ {
switch (type) { switch (type) {
case NODE_VECTOR_MATH_ADD: case NODE_VECTOR_MATH_ADD:
@@ -46,12 +46,6 @@ ccl_device void svm_vector_math(float *value,
case NODE_VECTOR_MATH_REFLECT: case NODE_VECTOR_MATH_REFLECT:
*vector = reflect(a, b); *vector = reflect(a, b);
break; break;
case NODE_VECTOR_MATH_REFRACT:
*vector = refract(a, normalize(b), param1);
break;
case NODE_VECTOR_MATH_FACEFORWARD:
*vector = faceforward(a, b, c);
break;
case NODE_VECTOR_MATH_DOT_PRODUCT: case NODE_VECTOR_MATH_DOT_PRODUCT:
*value = dot(a, b); *value = dot(a, b);
break; break;
@@ -62,7 +56,7 @@ ccl_device void svm_vector_math(float *value,
*value = len(a); *value = len(a);
break; break;
case NODE_VECTOR_MATH_SCALE: case NODE_VECTOR_MATH_SCALE:
*vector = a * param1; *vector = a * scale;
break; break;
case NODE_VECTOR_MATH_NORMALIZE: case NODE_VECTOR_MATH_NORMALIZE:
*vector = safe_normalize(a); *vector = safe_normalize(a);
@@ -104,7 +98,7 @@ ccl_device void svm_vector_math(float *value,
*vector = make_float3(tanf(a.x), tanf(a.y), tanf(a.z)); *vector = make_float3(tanf(a.x), tanf(a.y), tanf(a.z));
break; break;
default: default:
*vector = zero_float3(); *vector = make_float3(0.0f, 0.0f, 0.0f);
*value = 0.0f; *value = 0.0f;
} }
} }
@@ -242,15 +236,10 @@ ccl_device float3 svm_math_blackbody_color(float t)
return make_float3(4.70366907f, 0.0f, 0.0f); return make_float3(4.70366907f, 0.0f, 0.0f);
} }
/* Manually align for readability. */ int i = (t >= 6365.0f) ?
/* clang-format off */ 5 :
int i = (t >= 6365.0f) ? 5 : (t >= 3315.0f) ? 4 :
(t >= 3315.0f) ? 4 : (t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
(t >= 1902.0f) ? 3 :
(t >= 1449.0f) ? 2 :
(t >= 1167.0f) ? 1 :
0;
/* clang-format on */
ccl_constant float *r = blackbody_table_r[i]; ccl_constant float *r = blackbody_table_r[i];
ccl_constant float *g = blackbody_table_g[i]; ccl_constant float *g = blackbody_table_g[i];

View File

@@ -339,8 +339,6 @@ typedef enum NodeVectorMathType {
NODE_VECTOR_MATH_SINE, NODE_VECTOR_MATH_SINE,
NODE_VECTOR_MATH_COSINE, NODE_VECTOR_MATH_COSINE,
NODE_VECTOR_MATH_TANGENT, NODE_VECTOR_MATH_TANGENT,
NODE_VECTOR_MATH_REFRACT,
NODE_VECTOR_MATH_FACEFORWARD,
} NodeVectorMathType; } NodeVectorMathType;
typedef enum NodeClampType { typedef enum NodeClampType {

View File

@@ -396,10 +396,6 @@ static void add_uvs(AlembicProcedural *proc,
ccl::set<chrono_t> times = get_relevant_sample_times(proc, time_sampling, uvs.getNumSamples()); ccl::set<chrono_t> times = get_relevant_sample_times(proc, time_sampling, uvs.getNumSamples());
/* Keys used to determine if the UVs do actually change over time. */
ArraySample::Key previous_indices_key;
ArraySample::Key previous_values_key;
foreach (chrono_t time, times) { foreach (chrono_t time, times) {
if (progress.get_cancel()) { if (progress.get_cancel()) {
return; return;
@@ -426,32 +422,21 @@ static void add_uvs(AlembicProcedural *proc,
float2 *data_float2 = reinterpret_cast<float2 *>(data.data()); float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
const ArraySample::Key indices_key = uvsample.getIndices()->getKey(); const unsigned int *indices = uvsample.getIndices()->get();
const ArraySample::Key values_key = uvsample.getVals()->getKey(); const V2f *values = uvsample.getVals()->get();
if (indices_key == previous_indices_key && values_key == previous_values_key) { for (const int3 &loop : *triangles_loops) {
attr.data.reuse_data_for_last_time(time); unsigned int v0 = indices[loop.x];
} unsigned int v1 = indices[loop.y];
else { unsigned int v2 = indices[loop.z];
const unsigned int *indices = uvsample.getIndices()->get();
const V2f *values = uvsample.getVals()->get();
for (const int3 &loop : *triangles_loops) { data_float2[0] = make_float2(values[v0][0], values[v0][1]);
unsigned int v0 = indices[loop.x]; data_float2[1] = make_float2(values[v1][0], values[v1][1]);
unsigned int v1 = indices[loop.y]; data_float2[2] = make_float2(values[v2][0], values[v2][1]);
unsigned int v2 = indices[loop.z]; data_float2 += 3;
data_float2[0] = make_float2(values[v0][0], values[v0][1]);
data_float2[1] = make_float2(values[v1][0], values[v1][1]);
data_float2[2] = make_float2(values[v2][0], values[v2][1]);
data_float2 += 3;
}
attr.data.add_data(data, time);
} }
previous_indices_key = indices_key; attr.data.add_data(data, time);
previous_values_key = values_key;
} }
} }
@@ -751,11 +736,6 @@ void AlembicObject::load_all_data(AlembicProcedural *proc,
ccl::set<chrono_t> times = get_relevant_sample_times( ccl::set<chrono_t> times = get_relevant_sample_times(
proc, *time_sampling, schema.getNumSamples()); proc, *time_sampling, schema.getNumSamples());
/* Key used to determine if the triangles change over time, if the key is the same as the
* last one, we can avoid creating a new entry in the cache and simply point to the last
* frame. */
ArraySample::Key previous_key;
/* read topology */ /* read topology */
foreach (chrono_t time, times) { foreach (chrono_t time, times) {
if (progress.get_cancel()) { if (progress.get_cancel()) {
@@ -767,27 +747,22 @@ void AlembicObject::load_all_data(AlembicProcedural *proc,
add_positions(sample.getPositions(), time, cached_data); add_positions(sample.getPositions(), time, cached_data);
/* Only copy triangles for other frames if the topology is changing over time as well. */ /* Only copy triangles for other frames if the topology is changing over time as well.
*
* TODO(@kevindietrich): even for dynamic simulations, this is a waste of memory and
* processing time if only the positions are changing in a subsequence of frames but we
* cannot optimize in this current system if the attributes are changing over time as well,
* as we need valid data for each time point. This can be solved by using reference counting
* on the ccl::array and simply share the array across frames. */
if (schema.getTopologyVariance() != kHomogenousTopology || cached_data.triangles.size() == 0) { if (schema.getTopologyVariance() != kHomogenousTopology || cached_data.triangles.size() == 0) {
const ArraySample::Key key = sample.getFaceIndices()->getKey(); /* start by reading the face sets (per face shader), as we directly split polygons to
* triangles
*/
array<int> polygon_to_shader;
read_face_sets(schema, polygon_to_shader, iss);
if (key == previous_key) { add_triangles(
cached_data.triangles.reuse_data_for_last_time(time); sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader);
cached_data.triangles_loops.reuse_data_for_last_time(time);
cached_data.shader.reuse_data_for_last_time(time);
}
else {
/* start by reading the face sets (per face shader), as we directly split polygons to
* triangles
*/
array<int> polygon_to_shader;
read_face_sets(schema, polygon_to_shader, iss);
add_triangles(
sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader);
}
previous_key = key;
} }
if (normals.valid()) { if (normals.valid()) {
@@ -1407,15 +1382,6 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
need_data_updates = true; need_data_updates = true;
} }
/* Check if the shaders were modified. */
if (object->used_shaders_is_modified() && object->get_object() &&
object->get_object()->get_geometry()) {
Geometry *geometry = object->get_object()->get_geometry();
array<Node *> used_shaders = object->get_used_shaders();
geometry->set_used_shaders(used_shaders);
need_shader_updates = true;
}
/* Check for changes in shaders (e.g. newly requested attributes). */ /* Check for changes in shaders (e.g. newly requested attributes). */
foreach (Node *shader_node, object->get_used_shaders()) { foreach (Node *shader_node, object->get_used_shaders()) {
Shader *shader = static_cast<Shader *>(shader_node); Shader *shader = static_cast<Shader *>(shader_node);
@@ -1595,11 +1561,6 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame
Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
/* Make sure shader ids are also updated. */
if (mesh->used_shaders_is_modified()) {
mesh->tag_shader_modified();
}
cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket()); cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
@@ -1667,11 +1628,6 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame
Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
/* Make sure shader ids are also updated. */
if (mesh->used_shaders_is_modified()) {
mesh->tag_shader_modified();
}
/* Cycles overwrites the original triangles when computing displacement, so we always have to /* Cycles overwrites the original triangles when computing displacement, so we always have to
* repass the data if something is animated (vertices most likely) to avoid buffer overflows. */ * repass the data if something is animated (vertices most likely) to avoid buffer overflows. */
if (!cached_data.is_constant()) { if (!cached_data.is_constant()) {
@@ -1762,11 +1718,6 @@ void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t fra
Hair *hair = static_cast<Hair *>(object->get_geometry()); Hair *hair = static_cast<Hair *>(object->get_geometry());
/* Make sure shader ids are also updated. */
if (hair->used_shaders_is_modified()) {
hair->tag_curve_shader_modified();
}
cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket()); cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket()); cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());

View File

@@ -43,14 +43,14 @@ struct MatrixSamplesData {
Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling; Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling;
}; };
/* Helpers to detect if some type is a `ccl::array`. */ /* Helpers to detect if some type is a ccl::array. */
template<typename> struct is_array : public std::false_type { template<typename> struct is_array : public std::false_type {
}; };
template<typename T> struct is_array<array<T>> : public std::true_type { template<typename T> struct is_array<array<T>> : public std::true_type {
}; };
/* Holds the data for a cache lookup at a given time, as well as information to /* Holds the data for a cache lookup at a given time, as well as informations to
* help disambiguate successes or failures to get data from the cache. */ * help disambiguate successes or failures to get data from the cache. */
template<typename T> class CacheLookupResult { template<typename T> class CacheLookupResult {
enum class State { enum class State {
@@ -128,25 +128,12 @@ template<typename T> class CacheLookupResult {
* The data is supposed to be stored in chronological order, and is looked up using the current * The data is supposed to be stored in chronological order, and is looked up using the current
* animation time in seconds using the TimeSampling from the Alembic property. */ * animation time in seconds using the TimeSampling from the Alembic property. */
template<typename T> class DataStore { template<typename T> class DataStore {
/* Holds information to map a cache entry for a given time to an index into the data array. */ struct DataTimePair {
struct TimeIndexPair {
/* Frame time for this entry. */
double time = 0; double time = 0;
/* Frame time for the data pointed to by `index`. */ T data{};
double source_time = 0;
/* Index into the data array. */
size_t index = 0;
}; };
/* This is the actual data that is stored. We deduplicate data across frames to avoid storing vector<DataTimePair> data{};
* values if they have not changed yet (e.g. the triangles for a building before fracturing, or a
* fluid simulation before a break or splash) */
vector<T> data{};
/* This is used to map they entry for a given time to an index into the data array, multiple
* frames can point to the same index. */
vector<TimeIndexPair> index_data_map{};
Alembic::AbcCoreAbstract::TimeSampling time_sampling{}; Alembic::AbcCoreAbstract::TimeSampling time_sampling{};
double last_loaded_time = std::numeric_limits<double>::max(); double last_loaded_time = std::numeric_limits<double>::max();
@@ -170,21 +157,17 @@ template<typename T> class DataStore {
return CacheLookupResult<T>::no_data_found_for_time(); return CacheLookupResult<T>::no_data_found_for_time();
} }
const TimeIndexPair &index = get_index_for_time(time); std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
index_pair = time_sampling.getNearIndex(time, data.size());
DataTimePair &data_pair = data[index_pair.first];
if (index.index == -1ul) { if (last_loaded_time == data_pair.time) {
return CacheLookupResult<T>::no_data_found_for_time();
}
if (last_loaded_time == index.time || last_loaded_time == index.source_time) {
return CacheLookupResult<T>::already_loaded(); return CacheLookupResult<T>::already_loaded();
} }
last_loaded_time = index.source_time; last_loaded_time = data_pair.time;
assert(index.index < data.size()); return CacheLookupResult<T>::new_data(&data_pair.data);
return CacheLookupResult<T>::new_data(&data[index.index]);
} }
/* get the data for the specified time, but do not check if the data was already loaded for this /* get the data for the specified time, but do not check if the data was already loaded for this
@@ -195,34 +178,22 @@ template<typename T> class DataStore {
return CacheLookupResult<T>::no_data_found_for_time(); return CacheLookupResult<T>::no_data_found_for_time();
} }
const TimeIndexPair &index = get_index_for_time(time); std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
index_pair = time_sampling.getNearIndex(time, data.size());
if (index.index == -1ul) { DataTimePair &data_pair = data[index_pair.first];
return CacheLookupResult<T>::no_data_found_for_time(); return CacheLookupResult<T>::new_data(&data_pair.data);
}
assert(index.index < data.size());
return CacheLookupResult<T>::new_data(&data[index.index]);
} }
void add_data(T &data_, double time) void add_data(T &data_, double time)
{ {
index_data_map.push_back({time, time, data.size()});
if constexpr (is_array<T>::value) { if constexpr (is_array<T>::value) {
data.emplace_back(); data.emplace_back();
data.back().steal_data(data_); data.back().data.steal_data(data_);
data.back().time = time;
return; return;
} }
data.push_back(data_); data.push_back({time, data_});
}
void reuse_data_for_last_time(double time)
{
const TimeIndexPair &data_index = index_data_map.back();
index_data_map.push_back({time, data_index.source_time, data_index.index});
} }
bool is_constant() const bool is_constant() const
@@ -239,7 +210,6 @@ template<typename T> class DataStore {
{ {
invalidate_last_loaded_time(); invalidate_last_loaded_time();
data.clear(); data.clear();
index_data_map.clear();
} }
void invalidate_last_loaded_time() void invalidate_last_loaded_time()
@@ -262,14 +232,6 @@ template<typename T> class DataStore {
T value = result.get_data(); T value = result.get_data();
node->set(*socket, value); node->set(*socket, value);
} }
private:
const TimeIndexPair &get_index_for_time(double time) const
{
std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
index_pair = time_sampling.getNearIndex(time, index_data_map.size());
return index_data_map[index_pair.first];
}
}; };
/* Actual cache for the stored data. /* Actual cache for the stored data.
@@ -481,23 +443,16 @@ class AlembicProcedural : public Procedural {
* invocation, and updates the data on subsequent invocations if the frame changed. */ * invocation, and updates the data on subsequent invocations if the frame changed. */
void generate(Scene *scene, Progress &progress); void generate(Scene *scene, Progress &progress);
/* Tag for an update only if something was modified. */
void tag_update(Scene *scene);
/* This should be called by scene exporters to request the rendering of an object located
* in the Alembic archive at the given path.
*
* Since we lazily load object, the function does not validate the existence of the object
* in the archive. If no objects with such path if found in the archive during the next call
* to `generate`, it will be ignored.
*
* Returns a pointer to an existing or a newly created AlembicObject for the given path. */
AlembicObject *get_or_create_object(const ustring &path);
private:
/* Add an object to our list of objects, and tag the socket as modified. */ /* Add an object to our list of objects, and tag the socket as modified. */
void add_object(AlembicObject *object); void add_object(AlembicObject *object);
/* Tag for an update only if something was modified. */
void tag_update(Scene *scene);
/* Returns a pointer to an existing or a newly created AlembicObject for the given path. */
AlembicObject *get_or_create_object(const ustring &path);
private:
/* Load the data for all the objects whose data has not yet been loaded. */ /* Load the data for all the objects whose data has not yet been loaded. */
void load_objects(Progress &progress); void load_objects(Progress &progress);

View File

@@ -130,14 +130,6 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
void Background::tag_update(Scene *scene) void Background::tag_update(Scene *scene)
{ {
Shader *bg_shader = get_shader(scene);
if (bg_shader && bg_shader->is_modified()) {
/* Tag as modified to update the KernelBackground visibility information.
* We only tag the use_shader socket as modified as it is related to the shader
* and to avoid doing unnecessary updates anywhere else. */
tag_use_shader_modified();
}
if (ao_factor_is_modified() || use_ao_is_modified()) { if (ao_factor_is_modified() || use_ao_is_modified()) {
scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED); scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED);
} }

View File

@@ -90,7 +90,6 @@ void Geometry::clear(bool preserve_shaders)
transform_applied = false; transform_applied = false;
transform_negative_scaled = false; transform_negative_scaled = false;
transform_normal = transform_identity(); transform_normal = transform_identity();
tag_modified();
} }
bool Geometry::need_attribute(Scene *scene, AttributeStandard std) bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
@@ -1364,6 +1363,7 @@ void GeometryManager::device_update_bvh(Device *device,
} }
dscene->data.bvh.root = pack.root_index; dscene->data.bvh.root = pack.root_index;
dscene->data.bvh.bvh_layout = bparams.bvh_layout;
dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions(); dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions();
/* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */ /* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */
@@ -1583,6 +1583,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
dscene->tri_vnormal.tag_realloc(); dscene->tri_vnormal.tag_realloc();
dscene->tri_vindex.tag_realloc(); dscene->tri_vindex.tag_realloc();
dscene->tri_patch.tag_realloc(); dscene->tri_patch.tag_realloc();
dscene->tri_vnormal.tag_realloc();
dscene->tri_patch_uv.tag_realloc(); dscene->tri_patch_uv.tag_realloc();
dscene->tri_shader.tag_realloc(); dscene->tri_shader.tag_realloc();
dscene->patches.tag_realloc(); dscene->patches.tag_realloc();
@@ -1915,12 +1916,9 @@ void GeometryManager::device_update(Device *device,
} }
} }
/* Update the BVH even when there is no geometry so the kernel's BVH data is still valid, /* update the bvh even when there is no geometry so the kernel bvh data is still valid,
* especially when removing all of the objects during interactive renders. * especially when removing all of the objects during interactive renders */
* Also update the BVH if the transformations change, we cannot rely on tagging the Geometry bool need_update_scene_bvh = (scene->bvh == nullptr);
* as modified in this case, as we may accumulate displacement if the vertices do not also
* change. */
bool need_update_scene_bvh = (scene->bvh == nullptr || (update_flags & TRANSFORM_MODIFIED) != 0);
{ {
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {
@@ -1962,6 +1960,7 @@ void GeometryManager::device_update(Device *device,
scene->update_stats->geometry.times.add_entry({"device_update (compute bounds)", time}); scene->update_stats->geometry.times.add_entry({"device_update (compute bounds)", time});
} }
}); });
vector<Object *> volume_objects;
foreach (Object *object, scene->objects) { foreach (Object *object, scene->objects) {
object->compute_bounds(motion_blur); object->compute_bounds(motion_blur);
} }
@@ -1983,11 +1982,6 @@ void GeometryManager::device_update(Device *device,
} }
} }
/* Always set BVH layout again after displacement where it was set to none,
* to avoid ray-tracing at that stage. */
dscene->data.bvh.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
device->get_bvh_layout_mask());
{ {
scoped_callback_timer timer([scene](double time) { scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) { if (scene->update_stats) {

View File

@@ -189,8 +189,6 @@ class GeometryManager {
GEOMETRY_ADDED = MESH_ADDED | HAIR_ADDED, GEOMETRY_ADDED = MESH_ADDED | HAIR_ADDED,
GEOMETRY_REMOVED = MESH_REMOVED | HAIR_REMOVED, GEOMETRY_REMOVED = MESH_REMOVED | HAIR_REMOVED,
TRANSFORM_MODIFIED = (1 << 10),
/* tag everything in the manager for an update */ /* tag everything in the manager for an update */
UPDATE_ALL = ~0u, UPDATE_ALL = ~0u,

View File

@@ -303,8 +303,7 @@ ImageManager::ImageManager(const DeviceInfo &info)
animation_frame = 0; animation_frame = 0;
/* Set image limits */ /* Set image limits */
features.has_half_float = info.has_half_images; has_half_images = info.has_half_images;
features.has_nanovdb = info.has_nanovdb;
} }
ImageManager::~ImageManager() ImageManager::~ImageManager()
@@ -348,7 +347,7 @@ void ImageManager::load_image_metadata(Image *img)
metadata = ImageMetaData(); metadata = ImageMetaData();
metadata.colorspace = img->params.colorspace; metadata.colorspace = img->params.colorspace;
if (img->loader->load_metadata(features, metadata)) { if (img->loader->load_metadata(metadata)) {
assert(metadata.type != IMAGE_DATA_NUM_TYPES); assert(metadata.type != IMAGE_DATA_NUM_TYPES);
} }
else { else {
@@ -357,10 +356,15 @@ void ImageManager::load_image_metadata(Image *img)
metadata.detect_colorspace(); metadata.detect_colorspace();
assert(features.has_half_float || /* No half textures on OpenCL, use full float instead. */
(metadata.type != IMAGE_DATA_TYPE_HALF4 && metadata.type != IMAGE_DATA_TYPE_HALF)); if (!has_half_images) {
assert(features.has_nanovdb || (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT || if (metadata.type == IMAGE_DATA_TYPE_HALF4) {
metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3)); metadata.type = IMAGE_DATA_TYPE_FLOAT4;
}
else if (metadata.type == IMAGE_DATA_TYPE_HALF) {
metadata.type = IMAGE_DATA_TYPE_FLOAT;
}
}
img->need_metadata = false; img->need_metadata = false;
} }

View File

@@ -97,13 +97,6 @@ class ImageMetaData {
void detect_colorspace(); void detect_colorspace();
}; };
/* Information about supported features that Image loaders can use. */
class ImageDeviceFeatures {
public:
bool has_half_float;
bool has_nanovdb;
};
/* Image loader base class, that can be subclassed to load image data /* Image loader base class, that can be subclassed to load image data
* from custom sources (file, memory, procedurally generated, etc). */ * from custom sources (file, memory, procedurally generated, etc). */
class ImageLoader { class ImageLoader {
@@ -112,7 +105,7 @@ class ImageLoader {
virtual ~ImageLoader(){}; virtual ~ImageLoader(){};
/* Load metadata without actual image yet, should be fast. */ /* Load metadata without actual image yet, should be fast. */
virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) = 0; virtual bool load_metadata(ImageMetaData &metadata) = 0;
/* Load actual image contents. */ /* Load actual image contents. */
virtual bool load_pixels(const ImageMetaData &metadata, virtual bool load_pixels(const ImageMetaData &metadata,
@@ -219,8 +212,7 @@ class ImageManager {
private: private:
bool need_update_; bool need_update_;
bool has_half_images;
ImageDeviceFeatures features;
thread_mutex device_mutex; thread_mutex device_mutex;
thread_mutex images_mutex; thread_mutex images_mutex;

View File

@@ -30,7 +30,7 @@ OIIOImageLoader::~OIIOImageLoader()
{ {
} }
bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) bool OIIOImageLoader::load_metadata(ImageMetaData &metadata)
{ {
/* Perform preliminary checks, with meaningful logging. */ /* Perform preliminary checks, with meaningful logging. */
if (!path_exists(filepath.string())) { if (!path_exists(filepath.string())) {
@@ -76,7 +76,7 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMe
} }
/* check if it's half float */ /* check if it's half float */
if (spec.format == TypeDesc::HALF && features.has_half_float) { if (spec.format == TypeDesc::HALF) {
is_half = true; is_half = true;
} }

View File

@@ -26,7 +26,7 @@ class OIIOImageLoader : public ImageLoader {
OIIOImageLoader(const string &filepath); OIIOImageLoader(const string &filepath);
~OIIOImageLoader(); ~OIIOImageLoader();
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override; bool load_metadata(ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata, bool load_pixels(const ImageMetaData &metadata,
void *pixels, void *pixels,

View File

@@ -40,7 +40,7 @@ SkyLoader::SkyLoader(float sun_elevation,
SkyLoader::~SkyLoader(){}; SkyLoader::~SkyLoader(){};
bool SkyLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) bool SkyLoader::load_metadata(ImageMetaData &metadata)
{ {
metadata.width = 512; metadata.width = 512;
metadata.height = 128; metadata.height = 128;

View File

@@ -34,7 +34,7 @@ class SkyLoader : public ImageLoader {
float ozone_density); float ozone_density);
~SkyLoader(); ~SkyLoader();
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override; bool load_metadata(ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata, bool load_pixels(const ImageMetaData &metadata,
void *pixels, void *pixels,

View File

@@ -34,7 +34,7 @@ VDBImageLoader::~VDBImageLoader()
{ {
} }
bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
{ {
#ifdef WITH_OPENVDB #ifdef WITH_OPENVDB
if (!grid) { if (!grid) {
@@ -56,71 +56,55 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
if (grid->isType<openvdb::FloatGrid>()) { if (grid->isType<openvdb::FloatGrid>()) {
metadata.channels = 1; metadata.channels = 1;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
}
# endif # endif
} }
else if (grid->isType<openvdb::Vec3fGrid>()) { else if (grid->isType<openvdb::Vec3fGrid>()) {
metadata.channels = 3; metadata.channels = 3;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
}
# endif # endif
} }
else if (grid->isType<openvdb::BoolGrid>()) { else if (grid->isType<openvdb::BoolGrid>()) {
metadata.channels = 1; metadata.channels = 1;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::DoubleGrid>()) { else if (grid->isType<openvdb::DoubleGrid>()) {
metadata.channels = 1; metadata.channels = 1;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::Int32Grid>()) { else if (grid->isType<openvdb::Int32Grid>()) {
metadata.channels = 1; metadata.channels = 1;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::Int64Grid>()) { else if (grid->isType<openvdb::Int64Grid>()) {
metadata.channels = 1; metadata.channels = 1;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::Vec3IGrid>()) { else if (grid->isType<openvdb::Vec3IGrid>()) {
metadata.channels = 3; metadata.channels = 3;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::Vec3dGrid>()) { else if (grid->isType<openvdb::Vec3dGrid>()) {
metadata.channels = 3; metadata.channels = 3;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (features.has_nanovdb) { nanogrid = nanovdb::openToNanoVDB(
nanogrid = nanovdb::openToNanoVDB( openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
}
# endif # endif
} }
else if (grid->isType<openvdb::MaskGrid>()) { else if (grid->isType<openvdb::MaskGrid>()) {
@@ -134,25 +118,21 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
} }
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (nanogrid) { metadata.byte_size = nanogrid.size();
metadata.byte_size = nanogrid.size(); if (metadata.channels == 1) {
if (metadata.channels == 1) { metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT; }
} else {
else { metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3; }
} # else
if (metadata.channels == 1) {
metadata.type = IMAGE_DATA_TYPE_FLOAT;
}
else {
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
} }
else
# endif # endif
{
if (metadata.channels == 1) {
metadata.type = IMAGE_DATA_TYPE_FLOAT;
}
else {
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
}
}
/* Set transform from object space to voxel index. */ /* Set transform from object space to voxel index. */
openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4(); openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
@@ -163,29 +143,20 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
} }
} }
Transform texture_to_index;
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (nanogrid) { Transform texture_to_index = transform_identity();
texture_to_index = transform_identity(); # else
} openvdb::Coord min = bbox.min();
else Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
transform_scale(dim.x(), dim.y(), dim.z());
# endif # endif
{
openvdb::Coord min = bbox.min();
texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
transform_scale(dim.x(), dim.y(), dim.z());
}
metadata.transform_3d = transform_inverse(index_to_object * texture_to_index); metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
metadata.use_transform_3d = true; metadata.use_transform_3d = true;
# ifndef WITH_NANOVDB
(void)features;
# endif
return true; return true;
#else #else
(void)metadata; (void)metadata;
(void)features;
return false; return false;
#endif #endif
} }
@@ -194,52 +165,48 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
{ {
#ifdef WITH_OPENVDB #ifdef WITH_OPENVDB
# ifdef WITH_NANOVDB # ifdef WITH_NANOVDB
if (nanogrid) { memcpy(pixels, nanogrid.data(), nanogrid.size());
memcpy(pixels, nanogrid.data(), nanogrid.size()); # else
if (grid->isType<openvdb::FloatGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3fGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
}
else if (grid->isType<openvdb::BoolGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
}
else if (grid->isType<openvdb::DoubleGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
}
else if (grid->isType<openvdb::Int32Grid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
}
else if (grid->isType<openvdb::Int64Grid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3IGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3dGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
}
else if (grid->isType<openvdb::MaskGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
} }
else
# endif # endif
{
if (grid->isType<openvdb::FloatGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3fGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
}
else if (grid->isType<openvdb::BoolGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
}
else if (grid->isType<openvdb::DoubleGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
}
else if (grid->isType<openvdb::Int32Grid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
}
else if (grid->isType<openvdb::Int64Grid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3IGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
}
else if (grid->isType<openvdb::Vec3dGrid>()) {
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
bbox, (openvdb::Vec3f *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
}
else if (grid->isType<openvdb::MaskGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
}
}
return true; return true;
#else #else
(void)pixels; (void)pixels;

View File

@@ -33,8 +33,7 @@ class VDBImageLoader : public ImageLoader {
VDBImageLoader(const string &grid_name); VDBImageLoader(const string &grid_name);
~VDBImageLoader(); ~VDBImageLoader();
virtual bool load_metadata(const ImageDeviceFeatures &features, virtual bool load_metadata(ImageMetaData &metadata) override;
ImageMetaData &metadata) override;
virtual bool load_pixels(const ImageMetaData &metadata, virtual bool load_pixels(const ImageMetaData &metadata,
void *pixels, void *pixels,

View File

@@ -129,7 +129,6 @@ NODE_DEFINE(Light)
SOCKET_VECTOR(axisv, "Axis V", zero_float3()); SOCKET_VECTOR(axisv, "Axis V", zero_float3());
SOCKET_FLOAT(sizev, "Size V", 1.0f); SOCKET_FLOAT(sizev, "Size V", 1.0f);
SOCKET_BOOLEAN(round, "Round", false); SOCKET_BOOLEAN(round, "Round", false);
SOCKET_FLOAT(spread, "Spread", M_PI_F);
SOCKET_INT(map_resolution, "Map Resolution", 0); SOCKET_INT(map_resolution, "Map Resolution", 0);
@@ -859,15 +858,6 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f; float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
float3 dir = light->dir; float3 dir = light->dir;
/* Convert from spread angle 0..180 to 90..0, clamping to a minimum
* angle to avoid excessive noise. */
const float min_spread_angle = 1.0f * M_PI_F / 180.0f;
const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle));
/* Normalization computed using:
* integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */
const float tan_spread = tanf(spread_angle);
const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread);
dir = safe_normalize(dir); dir = safe_normalize(dir);
if (light->use_mis && area != 0.0f) if (light->use_mis && area != 0.0f)
@@ -887,8 +877,6 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].area.dir[0] = dir.x; klights[light_index].area.dir[0] = dir.x;
klights[light_index].area.dir[1] = dir.y; klights[light_index].area.dir[1] = dir.y;
klights[light_index].area.dir[2] = dir.z; klights[light_index].area.dir[2] = dir.z;
klights[light_index].area.tan_spread = tan_spread;
klights[light_index].area.normalize_spread = normalize_spread;
} }
else if (light->light_type == LIGHT_SPOT) { else if (light->light_type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT; shader_id &= ~SHADER_AREA_LIGHT;

View File

@@ -58,7 +58,6 @@ class Light : public Node {
NODE_SOCKET_API(float3, axisv) NODE_SOCKET_API(float3, axisv)
NODE_SOCKET_API(float, sizev) NODE_SOCKET_API(float, sizev)
NODE_SOCKET_API(bool, round) NODE_SOCKET_API(bool, round)
NODE_SOCKET_API(float, spread)
NODE_SOCKET_API(Transform, tfm) NODE_SOCKET_API(Transform, tfm)

View File

@@ -6091,9 +6091,6 @@ NODE_DEFINE(VectorMathNode)
type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT); type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
type_enum.insert("project", NODE_VECTOR_MATH_PROJECT); type_enum.insert("project", NODE_VECTOR_MATH_PROJECT);
type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT); type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT); type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE); type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE);
@@ -6154,24 +6151,24 @@ void VectorMathNode::compile(SVMCompiler &compiler)
{ {
ShaderInput *vector1_in = input("Vector1"); ShaderInput *vector1_in = input("Vector1");
ShaderInput *vector2_in = input("Vector2"); ShaderInput *vector2_in = input("Vector2");
ShaderInput *param1_in = input("Scale"); ShaderInput *scale_in = input("Scale");
ShaderOutput *value_out = output("Value"); ShaderOutput *value_out = output("Value");
ShaderOutput *vector_out = output("Vector"); ShaderOutput *vector_out = output("Vector");
int vector1_stack_offset = compiler.stack_assign(vector1_in); int vector1_stack_offset = compiler.stack_assign(vector1_in);
int vector2_stack_offset = compiler.stack_assign(vector2_in); int vector2_stack_offset = compiler.stack_assign(vector2_in);
int param1_stack_offset = compiler.stack_assign(param1_in); int scale_stack_offset = compiler.stack_assign(scale_in);
int value_stack_offset = compiler.stack_assign_if_linked(value_out); int value_stack_offset = compiler.stack_assign_if_linked(value_out);
int vector_stack_offset = compiler.stack_assign_if_linked(vector_out); int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
/* 3 Vector Operators */ /* 3 Vector Operators */
if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD) { if (math_type == NODE_VECTOR_MATH_WRAP) {
ShaderInput *vector3_in = input("Vector3"); ShaderInput *vector3_in = input("Vector3");
int vector3_stack_offset = compiler.stack_assign(vector3_in); int vector3_stack_offset = compiler.stack_assign(vector3_in);
compiler.add_node( compiler.add_node(
NODE_VECTOR_MATH, NODE_VECTOR_MATH,
math_type, math_type,
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset), compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
compiler.encode_uchar4(value_stack_offset, vector_stack_offset)); compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
compiler.add_node(vector3_stack_offset); compiler.add_node(vector3_stack_offset);
} }
@@ -6179,7 +6176,7 @@ void VectorMathNode::compile(SVMCompiler &compiler)
compiler.add_node( compiler.add_node(
NODE_VECTOR_MATH, NODE_VECTOR_MATH,
math_type, math_type,
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset), compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
compiler.encode_uchar4(value_stack_offset, vector_stack_offset)); compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
} }
} }

View File

@@ -153,6 +153,10 @@ void Object::update_motion()
void Object::compute_bounds(bool motion_blur) void Object::compute_bounds(bool motion_blur)
{ {
if (!is_modified() && !geometry->is_modified()) {
return;
}
BoundBox mbounds = geometry->bounds; BoundBox mbounds = geometry->bounds;
if (motion_blur && use_motion()) { if (motion_blur && use_motion()) {
@@ -217,7 +221,16 @@ void Object::tag_update(Scene *scene)
if (geometry) { if (geometry) {
if (tfm_is_modified()) { if (tfm_is_modified()) {
flag |= ObjectManager::TRANSFORM_MODIFIED; /* tag the geometry as modified so the BVH is updated, but do not tag everything as modified
*/
if (geometry->is_mesh() || geometry->is_volume()) {
Mesh *mesh = static_cast<Mesh *>(geometry);
mesh->tag_verts_modified();
}
else if (geometry->is_hair()) {
Hair *hair = static_cast<Hair *>(geometry);
hair->tag_curve_keys_modified();
}
} }
foreach (Node *node, geometry->get_used_shaders()) { foreach (Node *node, geometry->get_used_shaders()) {
@@ -910,10 +923,6 @@ void ObjectManager::tag_update(Scene *scene, uint32_t flag)
geometry_flag |= (GeometryManager::GEOMETRY_ADDED | GeometryManager::GEOMETRY_REMOVED); geometry_flag |= (GeometryManager::GEOMETRY_ADDED | GeometryManager::GEOMETRY_REMOVED);
} }
if ((flag & TRANSFORM_MODIFIED) != 0) {
geometry_flag |= GeometryManager::TRANSFORM_MODIFIED;
}
scene->geometry_manager->tag_update(scene, geometry_flag); scene->geometry_manager->tag_update(scene, geometry_flag);
} }

View File

@@ -133,7 +133,6 @@ class ObjectManager {
OBJECT_REMOVED = (1 << 4), OBJECT_REMOVED = (1 << 4),
OBJECT_MODIFIED = (1 << 5), OBJECT_MODIFIED = (1 << 5),
HOLDOUT_MODIFIED = (1 << 6), HOLDOUT_MODIFIED = (1 << 6),
TRANSFORM_MODIFIED = (1 << 7),
/* tag everything in the manager for an update */ /* tag everything in the manager for an update */
UPDATE_ALL = ~0u, UPDATE_ALL = ~0u,

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