1
1

Compare commits

..

5 Commits

1446 changed files with 18662 additions and 40133 deletions

View File

@@ -2,7 +2,7 @@
# 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.
#
@@ -255,6 +255,7 @@ ForEachMacros:
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
- SEQ_ALL_BEGIN
- SEQ_CURRENT_BEGIN
- SURFACE_QUAD_ITER_BEGIN
- foreach
- ED_screen_areas_iter
@@ -263,5 +264,8 @@ ForEachMacros:
- MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN
StatementMacros:
- PyObject_VAR_HEAD
# Use once we bump the minimum version to version 8.
# # 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-trailing-return-type,
-modernize-avoid-c-arrays,
-modernize-use-equals-default,
-modernize-use-nodiscard,
-modernize-loop-convert,
-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:
- key: modernize-use-default-member-init.UseAssignment
value: 1

3
.gitignore vendored
View File

@@ -46,6 +46,3 @@ Desktop.ini
# smoke simulation noise tile (generated)
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_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)
if(UNIX AND NOT APPLE)
@@ -520,10 +522,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
mark_as_advanced(WITH_LINKER_LLD)
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")
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)
set(_asan_defaults "\
-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")
endif()
set_and_warn_dependency(WITH_PYTHON WITH_CYCLES OFF)
set_and_warn_dependency(WITH_PYTHON WITH_DRACO OFF)
if(NOT WITH_PYTHON)
set(WITH_CYCLES OFF)
set(WITH_DRACO OFF)
endif()
if(WITH_DRACO AND NOT WITH_PYTHON_INSTALL)
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()
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_X11 OFF)
set(WITH_X11_XINPUT OFF)
@@ -806,7 +809,7 @@ endif()
if(NOT WITH_CUDA_DYNLOAD)
find_package(CUDA)
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)
endif()
endif()
@@ -1232,7 +1235,6 @@ if(WITH_OPENMP)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
else()
# Typically avoid adding flags as defines but we can't
# 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})
endif()
else()
message(STATUS "OpenMP not found, disabling WITH_OPENMP")
set(WITH_OPENMP OFF)
endif()
@@ -1319,7 +1320,6 @@ list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
find_package(Bullet)
if(NOT BULLET_FOUND)
message(STATUS "Bullet not found, disabling WITH_BULLET")
set(WITH_BULLET OFF)
endif()
else()
@@ -1955,10 +1955,10 @@ if(FIRST_RUN)
info_cfg_option(WITH_JACK)
info_cfg_option(WITH_JACK_DYNLOAD)
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_DYNLOAD)
info_cfg_option(WITH_PULSEAUDIO)
info_cfg_option(WITH_PULSEAUDIO_DYNLOAD)
info_cfg_option(WITH_WASAPI)
info_cfg_text("Compression:")

View File

@@ -128,14 +128,8 @@ Utilities
* source_archive:
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:
Updates git and all submodules and svn.
* update_code:
Updates git and all submodules but not svn.
updates git and all submodules
* format:
Format source code using clang (uses PATHS if passed in). For example::
@@ -480,9 +474,6 @@ check_smatch: .FORCE
cd "$(BUILD_DIR)" ; \
$(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
cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \
@@ -517,13 +508,6 @@ check_descriptions: .FORCE
source_archive: .FORCE
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"
icons: .FORCE
BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \
@@ -538,9 +522,6 @@ icons_geom: .FORCE
update: .FORCE
$(PYTHON) ./build_files/utils/make_update.py
update_code: .FORCE
$(PYTHON) ./build_files/utils/make_update.py --no-libraries
format: .FORCE
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)

View File

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

View File

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

View File

@@ -21,8 +21,7 @@ if(WIN32)
endif()
option(WITH_WEBP "Enable building of oiio with webp 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 ${NUM_CORES} CACHE STRING "Number of threads to run make with")
set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
if(NOT BUILD_MODE)
set(BUILD_MODE "Release")
@@ -37,8 +36,14 @@ else(BUILD_MODE STREQUAL "Debug")
endif()
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:
set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages")
# look in blenders source folder for packages directory, if that exists
# 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)
file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)

View File

@@ -85,8 +85,8 @@ class VersionInfo:
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_numbers = (version_number // 100, version_number % 100, version_number_patch)
self.short_version = "%d.%d" % (version_numbers[0], version_numbers[1])
self.version = "%d.%d.%d" % version_numbers
self.short_version = "%d.%02d" % (version_numbers[0], version_numbers[1])
self.version = "%d.%02d.%d" % version_numbers
self.version_cycle = self._parse_header_file(blender_h, 'BLENDER_VERSION_CYCLE')
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/include/OSL/
PATH_SUFFIXES
share/OSL/shaders
shaders
)
# 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.exit(1)
import os
from os.path import (
dirname,
join,
normpath,
splitext,
)
from cmake_consistency_check_config import (
IGNORE_SOURCE,
IGNORE_SOURCE_MISSING,
@@ -45,35 +37,32 @@ from cmake_consistency_check_config import (
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_c = set()
global_refs: Dict[str, List[Tuple[str, int]]] = {}
global_refs = {}
# 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
for ignore_path in ig_list
]
# Ignore cmake file, path pairs.
global_ignore_source_missing: Dict[str, List[str]] = {}
for k, v in IGNORE_SOURCE_MISSING_FLAT:
global_ignore_source_missing = {}
for k, v in IGNORE_SOURCE_MISSING:
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')
data = file_handle.readlines()
file_handle.close()
@@ -88,10 +77,7 @@ def replace_line(f: str, i: int, text: str, keep_indent: bool = True) -> None:
file_handle.close()
def source_list(
path: str,
filename_check: Optional[Callable[[str], bool]] = None,
) -> Generator[str, None, None]:
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
# skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
@@ -102,37 +88,37 @@ def source_list(
# extension checking
def is_cmake(filename: str) -> bool:
def is_cmake(filename):
ext = splitext(filename)[1]
return (ext == ".cmake") or (filename == "CMakeLists.txt")
def is_c_header(filename: str) -> bool:
def is_c_header(filename):
ext = splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename: str) -> bool:
def is_c(filename):
ext = splitext(filename)[1]
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)
def cmake_get_src(f: str) -> None:
def cmake_get_src(f):
sources_h = []
sources_c = []
filen = open(f, "r", encoding="utf8")
it: Optional[Iterator[str]] = iter(filen)
it = iter(filen)
found = False
i = 0
# 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("):
return False
@@ -145,7 +131,6 @@ def cmake_get_src(f: str) -> None:
if l.endswith(")"):
raise Exception("strict formatting not kept 'list(APPEND %s...)' on 1 line %s:%d" % (name, f, i))
return True
return False
while it is not None:
context_name = ""
@@ -284,7 +269,7 @@ def cmake_get_src(f: str) -> None:
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):
if ignore_path in f:
ignore_used[index] = True
@@ -292,7 +277,7 @@ def is_ignore_source(f: str, ignore_used: List[bool]) -> bool:
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):
if ignore_path in f:
ignore_used[index] = True
@@ -300,7 +285,7 @@ def is_ignore_cmake(f: str, ignore_used: List[bool]) -> bool:
return False
def main() -> None:
def main():
print("Scanning:", SOURCE_DIR)
@@ -374,7 +359,7 @@ def main() -> None:
if "extern" not in f:
i = 1
try:
for _ in open(f, "r", encoding="utf8"):
for l in open(f, "r", encoding="utf8"):
i += 1
except UnicodeDecodeError:
print("Non utf8: %s:%d" % (f, i))

View File

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

View File

@@ -25,12 +25,6 @@ import subprocess
import sys
import os
from typing import (
Any,
List,
)
USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [
@@ -53,26 +47,25 @@ if USE_QUIET:
CHECKER_ARGS.append("--quiet")
def main() -> None:
def main():
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
source_defines = project_source_info.build_defines_as_args()
check_commands = []
for c, inc_dirs, defs in source_info:
cmd = (
[CHECKER_BIN] +
CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs] +
source_defines
)
cmd = ([CHECKER_BIN] +
CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs] +
source_defines
)
check_commands.append((c, cmd))
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:
percent = 100.0 * (i / len(check_commands))
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_CYCLES_DEBUG 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_LIBMV_SCHUR_SPECIALIZATIONS OFF CACHE BOOL "" FORCE)
set(WITH_PYTHON_SAFETY ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
if(WIN32)
set(WITH_WINDOWS_BUNDLE_CRT OFF CACHE BOOL "" FORCE)
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_OCEANSIM 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_OPENCOLLADA 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_POTRACE 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_QUADRIFLOW 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
# so the python module doesn't hold the audio device and loads quickly.
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_JACK OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO 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_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
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)

View File

@@ -7,8 +7,8 @@
set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC 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_BUILDINFO 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_COREAUDIO 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_OSL OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
set(WITH_DRACO OFF CACHE BOOL "" FORCE)
set(WITH_FFTW3 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_OCEANSIM 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_WASAPI OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO 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_OPENMP 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_PUGIXML 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_SDL OFF CACHE BOOL "" FORCE)
set(WITH_TBB 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)
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
#
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC ON 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_BULLET 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_GMP 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_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS 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_OCEANSIM 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_OPENCOLLADA 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_POTRACE 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_QUADRIFLOW 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
# so the python module doesn't hold the audio device and loads quickly.
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_JACK OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO 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_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
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_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.
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)
find_package(OpenAL)
if(NOT OPENAL_FOUND)
message(WARNING "OpenAL not found, disabling WITH_OPENAL")
set(WITH_OPENAL OFF)
endif()
endif()
@@ -66,7 +65,6 @@ if(WITH_JACK)
NAMES jackmp
)
if(NOT JACK_FRAMEWORK)
message(STATUS "JACK not found, disabling WITH_JACK")
set(WITH_JACK OFF)
else()
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
@@ -104,7 +102,6 @@ endif()
if(WITH_USD)
find_package(USD)
if(NOT USD_FOUND)
message(STATUS "USD not found, disabling WITH_USD")
set(WITH_USD OFF)
endif()
endif()
@@ -149,7 +146,7 @@ if(WITH_PYTHON)
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/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_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
@@ -311,7 +308,7 @@ if(WITH_OPENCOLORIO)
if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF)
message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO")
message(STATUS "OpenColorIO not found")
endif()
endif()
@@ -360,7 +357,7 @@ if(WITH_CYCLES_OSL)
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
set(OSL_FOUND TRUE)
else()
message(WARNING "OSL not found, disabling WITH_CYCLES_OSL")
message(STATUS "OSL not found")
set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -388,7 +385,7 @@ if(WITH_OPENIMAGEDENOISE)
if(NOT OPENIMAGEDENOISE_FOUND)
set(WITH_OPENIMAGEDENOISE OFF)
message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE")
message(STATUS "OpenImageDenoise not found")
endif()
endif()
@@ -416,7 +413,7 @@ if(WITH_OPENMP)
set(OpenMP_LINKER_FLAGS "-L'${LIBDIR}/openmp/lib' -lomp")
# 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.
execute_process(
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)
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
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")
@@ -157,21 +162,6 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj")
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
if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS " /permissive-")
@@ -184,41 +174,14 @@ if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
set(WITH_WINDOWS_SCCACHE Off)
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)
set(CMAKE_C_COMPILER_LAUNCHER sccache)
set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
set(SYMBOL_FORMAT /Z7)
set(SYMBOL_FORMAT_RELEASE /Z7)
else()
unset(CMAKE_C_COMPILER_LAUNCHER)
unset(CMAKE_CXX_COMPILER_LAUNCHER)
if(MSVC_ASAN)
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")
set(SYMBOL_FORMAT /ZI)
endif()
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_CXX_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_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
unset(SYMBOL_FORMAT)
unset(SYMBOL_FORMAT_RELEASE)
# JMC is available on msvc 15.8 (1915) and up
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC")

View File

@@ -44,15 +44,6 @@ __all__ = (
"init",
)
from typing import (
Callable,
Generator,
List,
Optional,
Union,
Tuple,
)
import sys
if sys.version_info.major < 3:
@@ -79,11 +70,10 @@ SOURCE_DIR = abspath(SOURCE_DIR)
SIMPLE_PROJECTFILE = False
# must initialize from 'init'
CMAKE_DIR = ""
PROJECT_DIR = ""
CMAKE_DIR = None
def init(cmake_path: str) -> bool:
def init(cmake_path):
global CMAKE_DIR, PROJECT_DIR
# get cmake path
@@ -101,10 +91,7 @@ def init(cmake_path: str) -> bool:
return True
def source_list(
path: str,
filename_check: Optional[Callable[[str], bool]] = None,
) -> Generator[str, None, None]:
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
# skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
@@ -116,57 +103,53 @@ def source_list(
# extension checking
def is_cmake(filename: str) -> bool:
def is_cmake(filename):
ext = splitext(filename)[1]
return (ext == ".cmake") or (filename.endswith("CMakeLists.txt"))
def is_c_header(filename: str) -> bool:
def is_c_header(filename):
ext = splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_py(filename: str) -> bool:
def is_py(filename):
ext = splitext(filename)[1]
return (ext == ".py")
def is_glsl(filename: str) -> bool:
def is_glsl(filename):
ext = splitext(filename)[1]
return (ext == ".glsl")
def is_c(filename: str) -> bool:
def is_c(filename):
ext = splitext(filename)[1]
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)
def is_svn_file(filename: str) -> bool:
def is_svn_file(filename):
dn, fn = os.path.split(filename)
filename_svn = join(dn, ".svn", "text-base", "%s.svn-base" % fn)
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)
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.
"""
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)
def create_eclipse_project() -> str:
def create_eclipse_project():
print("CMAKE_DIR %r" % CMAKE_DIR)
if sys.platform == "win32":
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
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:
lines = [
l_strip for l in cache_file
@@ -250,12 +233,12 @@ def cmake_cache_var(var: str) -> Optional[str]:
return None
def cmake_compiler_defines() -> Optional[List[str]]:
def cmake_compiler_defines():
compiler = cmake_cache_var("CMAKE_C_COMPILER") # could do CXX too
if compiler is None:
print("Couldn't find the compiler, os defines will be omitted...")
return None
return
import tempfile
temp_c = tempfile.mkstemp(suffix=".c")[1]
@@ -272,5 +255,5 @@ def cmake_compiler_defines() -> Optional[List[str]]:
return lines
def project_name_get() -> Optional[str]:
def project_name_get():
return cmake_cache_var("CMAKE_PROJECT_NAME")

View File

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

View File

@@ -1,12 +1,11 @@
#!/usr/bin/env python3
import argparse
import dataclasses
import os
import re
import subprocess
from pathlib import Path
from typing import Iterable, TextIO, Optional, Any, Union
from typing import Iterable, TextIO
# This script can run from any location,
# output is created in the $CWD
@@ -19,43 +18,21 @@ SKIP_NAMES = {
".gitignore",
".gitmodules",
".arcconfig",
".svn",
}
def main() -> None:
output_dir = Path(".").absolute()
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}")
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)
tarball = tarball_path(curdir, version, cli_args)
manifest = manifest_path(tarball)
packages_dir = packages_path(curdir, cli_args)
manifest = output_dir / f"blender-{version}-manifest.txt"
tarball = output_dir / f"blender-{version}.tar.xz"
create_manifest(version, manifest, blender_srcdir, packages_dir)
create_tarball(version, tarball, manifest, blender_srcdir, packages_dir)
os.chdir(blender_srcdir)
create_manifest(version, manifest)
create_tarball(version, tarball, manifest)
create_checksum_file(tarball)
cleanup(manifest)
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
def create_manifest(
version: BlenderVersion,
outpath: Path,
blender_srcdir: Path,
packages_dir: Optional[Path],
) -> None:
def create_manifest(version: BlenderVersion, outpath: Path) -> None:
print(f'Building manifest of files: "{outpath}"...', end="", flush=True)
with outpath.open("w", encoding="utf-8") as outfile:
main_files_to_manifest(blender_srcdir, outfile)
submodules_to_manifest(blender_srcdir, version, outfile)
if packages_dir:
packages_to_manifest(outfile, packages_dir)
main_files_to_manifest(outfile)
submodules_to_manifest(version, outfile)
print("OK")
def main_files_to_manifest(blender_srcdir: Path, outfile: TextIO) -> None:
assert not blender_srcdir.is_absolute()
for path in git_ls_files(blender_srcdir):
def main_files_to_manifest(outfile: TextIO) -> None:
for path in git_ls_files():
print(path, file=outfile)
def submodules_to_manifest(
blender_srcdir: Path, version: BlenderVersion, outfile: TextIO
) -> None:
def submodules_to_manifest(version: BlenderVersion, outfile: TextIO) -> None:
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]
# Don't use native slashes as GIT for MS-Windows outputs forward slashes.
if skip_addon_contrib and submodule == "release/scripts/addons_contrib":
continue
for path in git_ls_files(blender_srcdir / submodule):
for path in git_ls_files(Path(submodule)):
print(path, file=outfile)
def packages_to_manifest(outfile: TextIO, packages_dir: 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:
def create_tarball(version: BlenderVersion, tarball: Path, manifest: Path) -> None:
print(f'Creating archive: "{tarball}" ...', end="", flush=True)
command = ["tar"]
# Requires GNU `tar`, since `--transform` is used.
if packages_dir:
command += ["--transform", f"s,{packages_dir}/,packages/,g"]
command += [
command = [
"tar",
"--transform",
f"s,^{blender_srcdir.name}/,blender-{version}/,g",
f"s,^,blender-{version}/,g",
"--use-compress-program=xz -9",
"--create",
f"--file={tarball}",
@@ -219,8 +130,7 @@ def create_tarball(
"--owner=0",
"--group=0",
]
subprocess.run(command, check=True, timeout=3600)
subprocess.run(command, check=True, timeout=300)
print("OK")
@@ -264,7 +174,7 @@ def git_ls_files(directory: Path = Path(".")) -> Iterable[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."""
command = ("git", *cli_args)

View File

@@ -9,10 +9,14 @@ if "%BUILD_WITH_SCCACHE%"=="1" (
if "%WITH_CLANG%"=="1" (
set CLANG_CMAKE_ARGS=-T"llvm"
)
if "%WITH_ASAN%"=="1" (
if "%WITH_ASAN%"=="1" (
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" (

View File

@@ -46,10 +46,16 @@ set LLVM_DIR=
set CFLAGS=-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" (
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%" == "" (

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# 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
# 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
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,
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>
import argparse
import os
import subprocess
import sys
import time
from typing import (
Dict,
TextIO,
)
def man_format(data: str) -> str:
def man_format(data):
data = data.replace("-", "\\-")
data = data.replace("\t", " ")
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 = {
"ASAN_OPTIONS": "exitcode=0:" + os.environ.get("ASAN_OPTIONS", ""),
}
blender_bin = sys.argv[1]
outfilename = sys.argv[2]
blender_help = subprocess.run(
[blender_bin, "--help"],
env=blender_env,
check=True,
stdout=subprocess.PIPE,
).stdout.decode(encoding="utf-8")
cmd = [blender_bin, "--help"]
print(" executing:", " ".join(cmd))
ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "")
blender_help = subprocess.run(
cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).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(
[blender_bin, "--version"],
env=blender_env,
check=True,
stdout=subprocess.PIPE,
).stdout.decode(encoding="utf-8")
outfile = open(outfilename, "w")
fw = outfile.write
# Extract information from the version string.
# 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
fw('.TH "BLENDER" "1" "%s" "Blender %s"\n' % (date_string, blender_version.replace(".", "\\&.")))
if not blender_date:
# 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'''
fw('''
.SH NAME
blender \- a full-featured 3D application''')
fh.write(r'''
fw('''
.SH SYNOPSIS
.B blender [args ...] [file] [args ...]''')
fh.write(r'''
fw('''
.br
.SH DESCRIPTION
.PP
.B blender
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.
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.
Use Blender to create 3D images and animations, films and commercials, content for games, '''
r'''architectural and industrial visualizatons, and scientific visualizations.
Use Blender to create 3D images and animations, films and commercials, content for games, architectural and industrial visualizatons, and scientific visualizations.
https://www.blender.org''')
fh.write(r'''
fw('''
.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:
l = lines.pop(0)
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))
fw('.TP\n')
fw('.B %s\n' % man_format(l))
while lines:
# line with no
if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # No white space.
break
while lines:
# line with no
if lines[0].strip() and len(lines[0].lstrip()) == len(lines[0]): # no white space
break
if not l: # Second blank line.
fh.write('.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')
if not l: # second blank line
fw('.IP\n')
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
.SH SEE ALSO
.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>.
''')
def create_argparse() -> argparse.ArgumentParser:
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()
outfile.close()
print("written:", outfilename)

View File

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

View File

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

View File

@@ -553,7 +553,7 @@ def example_extract_docstring(filepath):
line_no += 1
else:
file.close()
return "", 0, False
return "", 0
for line in file:
line_no += 1
@@ -563,17 +563,15 @@ def example_extract_docstring(filepath):
text.append(line.rstrip())
line_no += 1
line_no_has_content = False
# Skip over blank lines so the Python code doesn't have blank lines at the top.
for line in file:
if line.strip():
line_no_has_content = True
break
line_no += 1
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):
@@ -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_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"):
fw("%s\n" % (ident + line).rstrip())
fw("\n")
# Some files only contain a doc-string.
if line_no_has_content:
fw("%s.. literalinclude:: %s\n" % (ident, filepath))
if line_no > 0:
fw("%s :lines: %d-\n" % (ident, line_no))
fw("\n")
fw("%s.. literalinclude:: %s\n" % (ident, filepath))
if line_no > 0:
fw("%s :lines: %d-\n" % (ident, line_no))
fw("\n")
EXAMPLE_SET_USED.add(example_id)
else:
if bpy.app.debug:
@@ -1412,8 +1408,7 @@ def pyrna2sphinx(basepath):
else:
fw(" .. attribute:: %s\n\n" % prop.identifier)
if prop.description:
write_indented_lines(" ", fw, prop.description, False)
fw("\n")
fw(" %s\n\n" % prop.description)
# special exception, can't use generic code here for enums
if prop.type == "enum":

View File

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

View File

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

View File

@@ -255,7 +255,6 @@ protected:
/**
* This function tells the device, to start or pause 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;

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;
std::lock_guard<ILockable> lock(*device);
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)
@@ -68,40 +68,29 @@ void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
}
}
void PulseAudioDevice::runMixingThread()
void PulseAudioDevice::playing(bool playing)
{
for(;;)
{
{
std::lock_guard<ILockable> lock(*this);
m_playback = playing;
if(shouldStop())
{
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);
}
AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
}
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
m_playback(false),
m_state(PA_CONTEXT_UNCONNECTED),
m_buffersize(buffersize),
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)
{
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.");
}
@@ -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_threaded_mainloop_start(m_mainloop);
while(m_state != PA_CONTEXT_READY)
{
switch(m_state)
{
case PA_CONTEXT_FAILED:
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_unref(m_context);
AUD_pa_mainloop_free(m_mainloop);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
break;
default:
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
AUD_pa_threaded_mainloop_wait(m_mainloop);
break;
}
}
@@ -172,10 +166,13 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
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_unref(m_context);
AUD_pa_mainloop_free(m_mainloop);
AUD_pa_threaded_mainloop_free(m_mainloop);
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.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_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_pa_threaded_mainloop_unlock(m_mainloop);
create();
}
PulseAudioDevice::~PulseAudioDevice()
{
stopMixingThread();
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
AUD_pa_mainloop_free(m_mainloop);
AUD_pa_threaded_mainloop_free(m_mainloop);
destroy();
}

View File

@@ -26,7 +26,7 @@
* The PulseAudioDevice class.
*/
#include "devices/ThreadedDevice.h"
#include "devices/SoftwareDevice.h"
#include <pulse/pulseaudio.h>
@@ -35,10 +35,15 @@ AUD_NAMESPACE_BEGIN
/**
* 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:
pa_mainloop* m_mainloop;
/**
* Whether there is currently playback.
*/
volatile bool m_playback;
pa_threaded_mainloop* m_mainloop;
pa_context* m_context;
pa_stream* m_stream;
pa_context_state_t m_state;
@@ -69,15 +74,13 @@ private:
*/
AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
// delete copy constructor and operator=
PulseAudioDevice(const PulseAudioDevice&) = delete;
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
protected:
virtual void playing(bool playing);
public:
/**
* 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_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork);
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback);
PULSEAUDIO_SYMBOL(pa_stream_set_write_callback);
PULSEAUDIO_SYMBOL(pa_stream_write);
PULSEAUDIO_SYMBOL(pa_mainloop_free);
PULSEAUDIO_SYMBOL(pa_mainloop_get_api);
PULSEAUDIO_SYMBOL(pa_mainloop_new);
PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
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 padding;
UINT32 length;
data_t* buffer;
if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
return;
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)))
goto init_error;
if(FAILED(render_client->GetBuffer(length, &buffer)))
{
SafeRelease(&render_client);
return;
}
if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
goto init_error;
lock();
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
goto init_error;
mix((data_t*)buffer, length);
length = buffer_size - padding;
unlock();
if(FAILED(render_client->GetBuffer(length, &buffer)))
goto init_error;
mix((data_t*)buffer, length);
if(FAILED(render_client->ReleaseBuffer(length, 0)))
{
init_error:
SafeRelease(&render_client);
doStop();
return;
}
if(FAILED(render_client->ReleaseBuffer(length, 0)))
{
SafeRelease(&render_client);
return;
}
m_audio_client->Start();
@@ -76,38 +96,58 @@ void WASAPIDevice::runMixingThread()
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)))
goto stop_thread;
length = buffer_size - padding;
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)))
goto stop_thread;
lock();
mix((data_t*)buffer, length);
mix((data_t*)buffer, length);
if(FAILED(render_client->ReleaseBuffer(length, 0)))
goto stop_thread;
unlock();
// stop thread
if(shouldStop())
{
stop_thread:
m_audio_client->Stop();
SafeRelease(&render_client);
doStop();
return;
}
if(FAILED(render_client->ReleaseBuffer(length, 0)))
{
m_audio_client->Stop();
SafeRelease(&render_client);
return;
}
// stop thread
if(!m_playing)
{
m_audio_client->Stop();
SafeRelease(&render_client);
return;
}
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) :
m_playing(false),
m_imm_device_enumerator(nullptr),
m_imm_device(nullptr),
m_audio_client(nullptr),
@@ -285,7 +325,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
WASAPIDevice::~WASAPIDevice()
{
stopMixingThread();
lock();
stopAll();
unlock();
if(m_thread.joinable())
m_thread.join();
SafeRelease(&m_audio_client);
SafeRelease(&m_imm_device);

View File

@@ -26,7 +26,7 @@
* The WASAPIDevice class.
*/
#include "devices/ThreadedDevice.h"
#include "devices/SoftwareDevice.h"
#include <thread>
@@ -40,23 +40,41 @@ AUD_NAMESPACE_BEGIN
/**
* 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:
/**
* Whether there is currently playback.
*/
bool m_playing;
IMMDeviceEnumerator* m_imm_device_enumerator;
IMMDevice* m_imm_device;
IAudioClient* m_audio_client;
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
/**
* The streaming thread.
*/
std::thread m_thread;
/**
* Starts the streaming thread.
*/
AUD_LOCAL void start();
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
AUD_LOCAL void updateStream();
// delete copy constructor and operator=
WASAPIDevice(const WASAPIDevice&) = delete;
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
protected:
virtual void playing(bool playing);
public:
/**
* 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));
std::lock_guard<ILockable> lock(*this);
std::lock_guard<std::recursive_mutex> lock(m_mutex);
{
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound;
@@ -880,7 +880,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<IReader> reader, b
// play sound
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);
@@ -897,7 +897,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<ISound> sound, boo
void SoftwareDevice::stopAll()
{
std::lock_guard<ILockable> lock(*this);
std::lock_guard<std::recursive_mutex> lock(m_mutex);
while(!m_playingSounds.empty())
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 <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

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

View File

@@ -801,22 +801,17 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
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(
name="AO Bounces",
default=1,
description="After this number of light bounces, use approximate global illumination. 0 disables this feature",
default=0,
description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
min=0, max=1024,
)
ao_bounces_render: IntProperty(
name="AO Bounces Render",
default=1,
description="After this number of light bounces, use approximate global illumination. 0 disables this feature",
default=0,
description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
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")
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):
bl_label = "Motion Blur"
bl_options = {'DEFAULT_CLOSED'}
@@ -775,7 +746,7 @@ class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
col = layout.column()
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):
@@ -1438,15 +1409,15 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
bl_label = "Beam Shape"
class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
bl_label = "Spot Shape"
bl_parent_id = "CYCLES_LIGHT_PT_light"
bl_context = "data"
@classmethod
def poll(cls, context):
if context.light.type in {'SPOT', 'AREA'}:
return context.light and CyclesButtonsPanel.poll(context)
light = context.light
return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1454,12 +1425,9 @@ class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
layout.use_property_split = True
col = layout.column()
if light.type == 'SPOT':
col.prop(light, "spot_size", text="Spot Size")
col.prop(light, "spot_blend", text="Blend", slider=True)
col.prop(light, "show_cone")
elif light.type == 'AREA':
col.prop(light, "spread", text="Spread")
col.prop(light, "spot_size", text="Size")
col.prop(light, "spot_blend", text="Blend", slider=True)
col.prop(light, "show_cone")
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_child_particles", text="Child Particles")
col.prop(cscene, "texture_limit", text="Texture Limit")
col.prop(cscene, "ao_bounces", text="AO Bounces")
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_child_particles_render", text="Child Particles")
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):
@@ -2272,7 +2242,6 @@ classes = (
CYCLES_RENDER_PT_light_paths_max_bounces,
CYCLES_RENDER_PT_light_paths_clamping,
CYCLES_RENDER_PT_light_paths_caustics,
CYCLES_RENDER_PT_light_paths_fast_gi,
CYCLES_RENDER_PT_volumes,
CYCLES_RENDER_PT_subdivision,
CYCLES_RENDER_PT_hair,
@@ -2315,7 +2284,7 @@ classes = (
CYCLES_LIGHT_PT_preview,
CYCLES_LIGHT_PT_light,
CYCLES_LIGHT_PT_nodes,
CYCLES_LIGHT_PT_beam_shape,
CYCLES_LIGHT_PT_spot,
CYCLES_WORLD_PT_preview,
CYCLES_WORLD_PT_surface,
CYCLES_WORLD_PT_volume,
@@ -2345,7 +2314,7 @@ classes = (
node_panel(CYCLES_WORLD_PT_settings_surface),
node_panel(CYCLES_WORLD_PT_settings_volume),
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.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
for light in bpy.data.lights:
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.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.width = b_node.resolution();

View File

@@ -27,7 +27,7 @@ class BlenderImageLoader : public ImageLoader {
public:
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,
void *pixels,
const size_t pixels_size,
@@ -44,7 +44,7 @@ class BlenderPointDensityLoader : public ImageLoader {
public:
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,
void *pixels,
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_axisv(transform_get_column(&tfm, 1));
light->set_sizeu(b_area_light.size());
light->set_spread(b_area_light.spread());
switch (b_area_light.shape()) {
case BL::AreaLight::shape_SQUARE:
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:
element = ATTR_ELEMENT_VERTEX;
break;
case BL::Attribute::domain_FACE:
case BL::Attribute::domain_POLYGON:
element = ATTR_ELEMENT_FACE;
break;
default:

View File

@@ -143,6 +143,12 @@ void BlenderSession::create_session()
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 */
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
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);
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
* 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();
scene->reset();
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;
if (is_new_session) {
/* Sync object should be re-created for new scene. */
delete sync;
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
}
else {
/* Sync recalculations to do just the required updates. */
sync->sync_recalc(b_depsgraph, b_v3d);
}
/* There is no single depsgraph to use for the entire render.
* See note on create_session().
*/
/* sync object should be re-created */
delete sync;
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
BL::SpaceView3D b_null_space_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. */
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. */
buffer_params.passes = passes;
@@ -594,6 +598,18 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* clear callback */
session->write_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)

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);
if (viewport_parameters.modified(new_viewport_parameters)) {
world_recalc = true;
}
BlenderViewportParameters new_viewport_parameters(b_v3d);
if (viewport_parameters.modified(new_viewport_parameters)) {
world_recalc = true;
}
}
@@ -360,7 +358,7 @@ void BlenderSync::sync_integrator()
integrator->set_adaptive_min_samples(adaptive_min_samples);
if (get_boolean(cscene, "use_fast_gi")) {
if (b_scene.render().use_simplify()) {
if (preview) {
integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
}
@@ -569,8 +567,7 @@ int BlenderSync::get_denoising_pass(BL::RenderPass &b_pass)
return -1;
}
vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene,
BL::RenderLayer &b_rlay,
vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
BL::ViewLayer &b_view_layer,
bool adaptive_sampling,
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) {
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;
if (pass_type != PASS_NONE)
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)
{
BL::RenderSettings r = b_scene.render();
SceneParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
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(
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;
if (background) {
texture_limit = RNA_enum_get(&cscene, "texture_limit_render");

View File

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

View File

@@ -26,7 +26,7 @@
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume,
const struct VolumeGrid *grid);
struct VolumeGrid *grid);
#endif
CCL_NAMESPACE_BEGIN
@@ -41,7 +41,7 @@ class BlenderSmokeLoader : public ImageLoader {
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) {
return false;
@@ -227,7 +227,7 @@ class BlenderVolumeLoader : public VDBImageLoader {
const bool unload = !b_volume_grid.is_loaded();
::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);
if (unload) {

View File

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

View File

@@ -78,7 +78,6 @@ class DeviceInfo {
int num;
bool display_device; /* GPU is used as a display device. */
bool has_half_images; /* Support half-float textures. */
bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_volume_decoupled; /* Decoupled volume shading. */
bool has_branched_path; /* Supports branched path tracing. */
bool has_adaptive_stop_per_sample; /* Per-sample adaptive sampling stopping. */
@@ -100,7 +99,6 @@ class DeviceInfo {
cpu_threads = 0;
display_device = false;
has_half_images = false;
has_nanovdb = false;
has_volume_decoupled = false;
has_branched_path = true;
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_osl = true;
info.has_half_images = true;
info.has_nanovdb = true;
info.has_profiling = true;
info.denoisers = DENOISER_NLM;
if (openimagedenoise_supported()) {

View File

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

View File

@@ -46,13 +46,10 @@ class MultiDevice : public Device {
list<SubDevice> devices, denoising_devices;
device_ptr unique_key;
vector<vector<SubDevice *>> peer_islands;
bool use_denoising;
bool matching_rendering_and_denoising_devices;
MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
: Device(info, stats, profiler, background_),
unique_key(1),
use_denoising(!info.denoising_devices.empty())
: Device(info, stats, profiler, background_), unique_key(1)
{
foreach (DeviceInfo &subinfo, info.multi_devices) {
/* 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))
return false;
use_denoising = requested_features.use_denoising;
if (requested_features.use_denoising) {
/* Only need denoising feature, everything else is unused. */
DeviceRequestedFeatures denoising_features;
@@ -404,7 +400,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size;
/* 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) {
mem.device = sub.device;
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
* 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 */
if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) {
if (strcmp(mem.name, "RenderBuffers") == 0) {
vector<device_ptr> device_pointers;
device_pointers.reserve(devices.size());
@@ -522,7 +518,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size;
/* 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) {
mem.device = sub.device;
mem.device_pointer = sub.ptr_map[key];

View File

@@ -126,9 +126,6 @@ void device_opencl_info(vector<DeviceInfo> &devices)
/* Check OpenCL extensions */
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);
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
# ifdef WITH_CYCLES_DEBUG
module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0;
@@ -377,7 +377,7 @@ class OptiXDevice : public CUDADevice {
module_options.numBoundValues = 0;
# endif
OptixPipelineCompileOptions pipeline_options = {};
OptixPipelineCompileOptions pipeline_options;
// Default to no motion blur and two-level graph, since it is the fastest option
pipeline_options.usesMotionBlur = false;
pipeline_options.traversableGraphFlags =
@@ -477,7 +477,7 @@ class OptiXDevice : public CUDADevice {
# if OPTIX_ABI_VERSION >= 36
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.usesMotionBlur = false;
@@ -571,7 +571,7 @@ class OptiXDevice : public CUDADevice {
stack_size[PG_HITS_MOTION].cssIS + stack_size[PG_HITS_MOTION].cssAH);
# endif
OptixPipelineLinkOptions link_options = {};
OptixPipelineLinkOptions link_options;
link_options.maxTraceDepth = 1;
# ifdef WITH_CYCLES_DEBUG
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
OptixDenoiserOptions denoiser_options = {};
OptixDenoiserOptions denoiser_options;
assert(task.denoising.input_passes >= 1 && task.denoising.input_passes <= 3);
denoiser_options.inputKind = static_cast<OptixDenoiserInputKind>(
OPTIX_DENOISER_INPUT_RGB + (task.denoising.input_passes - 1));
@@ -1157,7 +1157,7 @@ class OptiXDevice : public CUDADevice {
// Compute memory usage
OptixAccelBufferSizes sizes = {};
OptixAccelBuildOptions options = {};
OptixAccelBuildOptions options;
options.operation = operation;
if (background) {
// Prefer best performance and lowest memory consumption in background
@@ -1195,7 +1195,7 @@ class OptiXDevice : public CUDADevice {
}
// Finally build the acceleration structure
OptixAccelEmitDesc compacted_size_prop = {};
OptixAccelEmitDesc compacted_size_prop;
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
// Make sure this pointer is 8-byte aligned

View File

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

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]);
float3 axisv = make_float3(
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);
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;
}
@@ -136,37 +136,19 @@ ccl_device_inline bool lamp_light_sample(
}
else {
inplane = ls->P;
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);
ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true);
inplane = ls->P - inplane;
}
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->Ng = Ng;
ls->Ng = D;
ls->D = normalize_len(ls->P - P, &ls->t);
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) {
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);
}
else {
float3 sample_axisu = axisu;
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->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
}
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 {
return false;

View File

@@ -146,70 +146,6 @@ ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot
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)
{
float cos_pi = dot(Ng, I);

View File

@@ -1501,9 +1501,9 @@ typedef struct KernelAreaLight {
float axisu[3];
float invarea;
float axisv[3];
float tan_spread;
float pad1;
float dir[3];
float normalize_spread;
float pad2;
} KernelAreaLight;
typedef struct KernelDistantLight {

View File

@@ -88,13 +88,6 @@ point wrap(point value, point max, point min)
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)
{
float cx = cos(euler[0]);

View File

@@ -46,12 +46,6 @@ shader node_vector_math(string math_type = "add",
else if (math_type == "reflect") {
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") {
Value = dot(Vector1, Vector2);
}

View File

@@ -44,26 +44,26 @@ ccl_device void svm_node_vector_math(KernelGlobals *kg,
int *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(
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);
float3 a = stack_load_float3(stack, a_stack_offset);
float3 b = stack_load_float3(stack, b_stack_offset);
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;
float3 vector;
/* 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);
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))
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 b,
float3 c,
float param1)
float scale)
{
switch (type) {
case NODE_VECTOR_MATH_ADD:
@@ -46,12 +46,6 @@ ccl_device void svm_vector_math(float *value,
case NODE_VECTOR_MATH_REFLECT:
*vector = reflect(a, b);
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:
*value = dot(a, b);
break;
@@ -62,7 +56,7 @@ ccl_device void svm_vector_math(float *value,
*value = len(a);
break;
case NODE_VECTOR_MATH_SCALE:
*vector = a * param1;
*vector = a * scale;
break;
case NODE_VECTOR_MATH_NORMALIZE:
*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));
break;
default:
*vector = zero_float3();
*vector = make_float3(0.0f, 0.0f, 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);
}
/* Manually align for readability. */
/* clang-format off */
int i = (t >= 6365.0f) ? 5 :
(t >= 3315.0f) ? 4 :
(t >= 1902.0f) ? 3 :
(t >= 1449.0f) ? 2 :
(t >= 1167.0f) ? 1 :
0;
/* clang-format on */
int i = (t >= 6365.0f) ?
5 :
(t >= 3315.0f) ? 4 :
(t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
ccl_constant float *r = blackbody_table_r[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_COSINE,
NODE_VECTOR_MATH_TANGENT,
NODE_VECTOR_MATH_REFRACT,
NODE_VECTOR_MATH_FACEFORWARD,
} NodeVectorMathType;
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());
/* 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) {
if (progress.get_cancel()) {
return;
@@ -426,32 +422,21 @@ static void add_uvs(AlembicProcedural *proc,
float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
const ArraySample::Key indices_key = uvsample.getIndices()->getKey();
const ArraySample::Key values_key = uvsample.getVals()->getKey();
const unsigned int *indices = uvsample.getIndices()->get();
const V2f *values = uvsample.getVals()->get();
if (indices_key == previous_indices_key && values_key == previous_values_key) {
attr.data.reuse_data_for_last_time(time);
}
else {
const unsigned int *indices = uvsample.getIndices()->get();
const V2f *values = uvsample.getVals()->get();
for (const int3 &loop : *triangles_loops) {
unsigned int v0 = indices[loop.x];
unsigned int v1 = indices[loop.y];
unsigned int v2 = indices[loop.z];
for (const int3 &loop : *triangles_loops) {
unsigned int v0 = indices[loop.x];
unsigned int v1 = indices[loop.y];
unsigned int v2 = indices[loop.z];
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);
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;
}
previous_indices_key = indices_key;
previous_values_key = values_key;
attr.data.add_data(data, time);
}
}
@@ -751,11 +736,6 @@ void AlembicObject::load_all_data(AlembicProcedural *proc,
ccl::set<chrono_t> times = get_relevant_sample_times(
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 */
foreach (chrono_t time, times) {
if (progress.get_cancel()) {
@@ -767,27 +747,22 @@ void AlembicObject::load_all_data(AlembicProcedural *proc,
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) {
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) {
cached_data.triangles.reuse_data_for_last_time(time);
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;
add_triangles(
sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader);
}
if (normals.valid()) {
@@ -1407,15 +1382,6 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
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). */
foreach (Node *shader_node, object->get_used_shaders()) {
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());
/* 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.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());
/* 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
* repass the data if something is animated (vertices most likely) to avoid buffer overflows. */
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());
/* 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_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;
};
/* 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 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. */
template<typename T> class CacheLookupResult {
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
* animation time in seconds using the TimeSampling from the Alembic property. */
template<typename T> class DataStore {
/* Holds information to map a cache entry for a given time to an index into the data array. */
struct TimeIndexPair {
/* Frame time for this entry. */
struct DataTimePair {
double time = 0;
/* Frame time for the data pointed to by `index`. */
double source_time = 0;
/* Index into the data array. */
size_t index = 0;
T data{};
};
/* This is the actual data that is stored. We deduplicate data across frames to avoid storing
* 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{};
vector<DataTimePair> data{};
Alembic::AbcCoreAbstract::TimeSampling time_sampling{};
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();
}
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) {
return CacheLookupResult<T>::no_data_found_for_time();
}
if (last_loaded_time == index.time || last_loaded_time == index.source_time) {
if (last_loaded_time == data_pair.time) {
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[index.index]);
return CacheLookupResult<T>::new_data(&data_pair.data);
}
/* 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();
}
const TimeIndexPair &index = get_index_for_time(time);
if (index.index == -1ul) {
return CacheLookupResult<T>::no_data_found_for_time();
}
assert(index.index < data.size());
return CacheLookupResult<T>::new_data(&data[index.index]);
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];
return CacheLookupResult<T>::new_data(&data_pair.data);
}
void add_data(T &data_, double time)
{
index_data_map.push_back({time, time, data.size()});
if constexpr (is_array<T>::value) {
data.emplace_back();
data.back().steal_data(data_);
data.back().data.steal_data(data_);
data.back().time = time;
return;
}
data.push_back(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});
data.push_back({time, data_});
}
bool is_constant() const
@@ -239,7 +210,6 @@ template<typename T> class DataStore {
{
invalidate_last_loaded_time();
data.clear();
index_data_map.clear();
}
void invalidate_last_loaded_time()
@@ -262,14 +232,6 @@ template<typename T> class DataStore {
T value = result.get_data();
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.
@@ -481,23 +443,16 @@ class AlembicProcedural : public Procedural {
* invocation, and updates the data on subsequent invocations if the frame changed. */
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. */
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. */
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)
{
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()) {
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_negative_scaled = false;
transform_normal = transform_identity();
tag_modified();
}
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.bvh_layout = bparams.bvh_layout;
dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions();
/* 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_vindex.tag_realloc();
dscene->tri_patch.tag_realloc();
dscene->tri_vnormal.tag_realloc();
dscene->tri_patch_uv.tag_realloc();
dscene->tri_shader.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,
* 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
* 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);
/* 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 */
bool need_update_scene_bvh = (scene->bvh == nullptr);
{
scoped_callback_timer timer([scene](double time) {
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});
}
});
vector<Object *> volume_objects;
foreach (Object *object, scene->objects) {
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) {
if (scene->update_stats) {

View File

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

View File

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

View File

@@ -97,13 +97,6 @@ class ImageMetaData {
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
* from custom sources (file, memory, procedurally generated, etc). */
class ImageLoader {
@@ -112,7 +105,7 @@ class ImageLoader {
virtual ~ImageLoader(){};
/* 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. */
virtual bool load_pixels(const ImageMetaData &metadata,
@@ -219,8 +212,7 @@ class ImageManager {
private:
bool need_update_;
ImageDeviceFeatures features;
bool has_half_images;
thread_mutex device_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. */
if (!path_exists(filepath.string())) {
@@ -76,7 +76,7 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMe
}
/* check if it's half float */
if (spec.format == TypeDesc::HALF && features.has_half_float) {
if (spec.format == TypeDesc::HALF) {
is_half = true;
}

View File

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

View File

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

View File

@@ -34,7 +34,7 @@ class SkyLoader : public ImageLoader {
float ozone_density);
~SkyLoader();
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_metadata(ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
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
if (!grid) {
@@ -56,71 +56,55 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
if (grid->isType<openvdb::FloatGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
}
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
# endif
}
else if (grid->isType<openvdb::Vec3fGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
}
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
# endif
}
else if (grid->isType<openvdb::BoolGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
# endif
}
else if (grid->isType<openvdb::DoubleGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
# endif
}
else if (grid->isType<openvdb::Int32Grid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
# endif
}
else if (grid->isType<openvdb::Int64Grid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
# endif
}
else if (grid->isType<openvdb::Vec3IGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
# endif
}
else if (grid->isType<openvdb::Vec3dGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
if (features.has_nanovdb) {
nanogrid = nanovdb::openToNanoVDB(
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
}
nanogrid = nanovdb::openToNanoVDB(
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
# endif
}
else if (grid->isType<openvdb::MaskGrid>()) {
@@ -134,25 +118,21 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
}
# ifdef WITH_NANOVDB
if (nanogrid) {
metadata.byte_size = nanogrid.size();
if (metadata.channels == 1) {
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
}
else {
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
}
metadata.byte_size = nanogrid.size();
if (metadata.channels == 1) {
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
}
else {
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
{
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. */
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
if (nanogrid) {
texture_to_index = transform_identity();
}
else
Transform texture_to_index = transform_identity();
# else
openvdb::Coord min = bbox.min();
Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
transform_scale(dim.x(), dim.y(), dim.z());
# 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.use_transform_3d = true;
# ifndef WITH_NANOVDB
(void)features;
# endif
return true;
#else
(void)metadata;
(void)features;
return false;
#endif
}
@@ -194,52 +165,48 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
{
#ifdef WITH_OPENVDB
# 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
{
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;
#else
(void)pixels;

View File

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

View File

@@ -129,7 +129,6 @@ NODE_DEFINE(Light)
SOCKET_VECTOR(axisv, "Axis V", zero_float3());
SOCKET_FLOAT(sizev, "Size V", 1.0f);
SOCKET_BOOLEAN(round, "Round", false);
SOCKET_FLOAT(spread, "Spread", M_PI_F);
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;
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);
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[1] = dir.y;
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) {
shader_id &= ~SHADER_AREA_LIGHT;

View File

@@ -58,7 +58,6 @@ class Light : public Node {
NODE_SOCKET_API(float3, axisv)
NODE_SOCKET_API(float, sizev)
NODE_SOCKET_API(bool, round)
NODE_SOCKET_API(float, spread)
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("project", NODE_VECTOR_MATH_PROJECT);
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("distance", NODE_VECTOR_MATH_DISTANCE);
@@ -6154,24 +6151,24 @@ void VectorMathNode::compile(SVMCompiler &compiler)
{
ShaderInput *vector1_in = input("Vector1");
ShaderInput *vector2_in = input("Vector2");
ShaderInput *param1_in = input("Scale");
ShaderInput *scale_in = input("Scale");
ShaderOutput *value_out = output("Value");
ShaderOutput *vector_out = output("Vector");
int vector1_stack_offset = compiler.stack_assign(vector1_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 vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
/* 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");
int vector3_stack_offset = compiler.stack_assign(vector3_in);
compiler.add_node(
NODE_VECTOR_MATH,
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.add_node(vector3_stack_offset);
}
@@ -6179,7 +6176,7 @@ void VectorMathNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_VECTOR_MATH,
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));
}
}

View File

@@ -153,6 +153,10 @@ void Object::update_motion()
void Object::compute_bounds(bool motion_blur)
{
if (!is_modified() && !geometry->is_modified()) {
return;
}
BoundBox mbounds = geometry->bounds;
if (motion_blur && use_motion()) {
@@ -217,7 +221,16 @@ void Object::tag_update(Scene *scene)
if (geometry) {
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()) {
@@ -910,10 +923,6 @@ void ObjectManager::tag_update(Scene *scene, uint32_t flag)
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);
}

View File

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

View File

@@ -179,7 +179,7 @@ void Scene::free_memory(bool final)
bake_manager->device_free(device, &dscene);
if (final)
if (!params.persistent_data || final)
image_manager->device_free(device);
else
image_manager->device_free_builtin(device);

View File

@@ -178,6 +178,7 @@ class SceneParams {
int num_bvh_time_steps;
int hair_subdivisions;
CurveShapeType hair_shape;
bool persistent_data;
int texture_limit;
bool background;
@@ -192,6 +193,7 @@ class SceneParams {
num_bvh_time_steps = 0;
hair_subdivisions = 3;
hair_shape = CURVE_RIBBON;
persistent_data = false;
texture_limit = 0;
background = true;
}
@@ -204,7 +206,7 @@ class SceneParams {
use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
num_bvh_time_steps == params.num_bvh_time_steps &&
hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape &&
texture_limit == params.texture_limit);
persistent_data == params.persistent_data && texture_limit == params.texture_limit);
}
int curve_subdivisions()

View File

@@ -18,7 +18,6 @@
#define TEST_CATEGORY_NAME util_avx2
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
defined(__AVX2__)
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# include "util_avxf_test.h"
#endif

View File

@@ -18,7 +18,6 @@
#define TEST_CATEGORY_NAME util_avx
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
defined(__AVX__)
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# include "util_avxf_test.h"
#endif

View File

@@ -788,7 +788,7 @@ ccl_device_inline float compare_floats(float a, float b, float abs_diff, int ulp
}
/* Calculate the angle between the two vectors a and b.
* The usual approach `acos(dot(a, b))` has severe precision issues for small angles,
* The usual approach acos(dot(a, b)) has severe precision issues for small angles,
* which are avoided by this method.
* Based on "Mangled Angles" from https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf
*/

View File

@@ -388,22 +388,6 @@ ccl_device_inline float3 reflect(const float3 incident, const float3 normal)
return incident - 2.0f * unit_normal * dot(incident, unit_normal);
}
ccl_device_inline float3 refract(const float3 incident, const float3 normal, const float eta)
{
float k = 1.0f - eta * eta * (1.0f - dot(normal, incident) * dot(normal, incident));
if (k < 0.0f)
return zero_float3();
else
return eta * incident - (eta * dot(normal, incident) + sqrt(k)) * normal;
}
ccl_device_inline float3 faceforward(const float3 vector,
const float3 incident,
const float3 reference)
{
return (dot(reference, incident) < 0.0f) ? vector : -vector;
}
ccl_device_inline float3 project(const float3 v, const float3 v_proj)
{
float len_squared = dot(v_proj, v_proj);

View File

@@ -178,8 +178,8 @@ DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *pDataObject)
{
/* Text
* NOTE: Unicode text is available as CF_TEXT too, the system can do the
* conversion, but we do the conversion our self with #WC_NO_BEST_FIT_CHARS.
* Note: Unicode text is available as CF_TEXT too, the system can do the
* conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
*/
FORMATETC fmtetc = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (pDataObject->QueryGetData(&fmtetc) == S_OK) {

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