Compare commits
92 Commits
tmp-gpu-sh
...
blender-v3
Author | SHA1 | Date | |
---|---|---|---|
dc2d180181 | |||
![]() |
ddf92d719b | ||
add07576a0 | |||
63b9e5378b | |||
822501d86d | |||
b3fe135854 | |||
0039432cfc | |||
![]() |
9600f36cfc | ||
688713db24 | |||
5079a460a7 | |||
bcca7bf975 | |||
d7a1fc0868 | |||
40c5786df3 | |||
71bc9d4760 | |||
1d462e1729 | |||
44ac03785c | |||
aafbd74646 | |||
edc85e182e | |||
![]() |
9d6680e7f9 | ||
15e4d0f25d | |||
e53f3954a4 | |||
3b686b8233 | |||
![]() |
4c8740a452 | ||
9a7b1d2245 | |||
72aefef9d2 | |||
ed397ff507 | |||
7d26cf01f7 | |||
c3457af23f | |||
3707a78471 | |||
e84625dcbc | |||
29c4c78a38 | |||
cd804fb2e9 | |||
69c56d2819 | |||
7339663bbc | |||
6bd924c748 | |||
![]() |
e8a8e953b3 | ||
784c04bcbd | |||
50c39ff8fe | |||
512014f042 | |||
3d5dbc1c44 | |||
5d80b64d28 | |||
![]() |
08226693cf | ||
b2e15cb19d | |||
6514e4c418 | |||
![]() |
66addab27a | ||
606f6e73b0 | |||
56d45a2974 | |||
fa0173f728 | |||
52905c02ae | |||
50ecf9dcf5 | |||
0564b19ff4 | |||
ff5630b7fa | |||
0a6b6eb13b | |||
b9f5e6c0b4 | |||
62ce0c60cd | |||
58ee4852b6 | |||
ad4d66580e | |||
21f02dd85d | |||
7d5fa51666 | |||
61fe0d6264 | |||
![]() |
99efb95441 | ||
dc7ff75ef8 | |||
e83df74008 | |||
55ecdf3195 | |||
5beadc31d6 | |||
a8a9a08bf7 | |||
88f8b01e66 | |||
10d65b821b | |||
56bd7adce7 | |||
b4c9f8da88 | |||
0b7dbff04a | |||
![]() |
b93127c57b | ||
d009056b01 | |||
![]() |
669577a973 | ||
e29026bb4b | |||
1fd824345d | |||
fd4c343dcd | |||
46f5b305e4 | |||
4c8b93c5c2 | |||
256c1b82f6 | |||
580c603df0 | |||
![]() |
c37cd35469 | ||
490f1648a7 | |||
256a2d1e98 | |||
77694b571f | |||
![]() |
8b44b756d8 | ||
24a79289b0 | |||
2af6cb9dce | |||
8ca4d20878 | |||
e78a21afb6 | |||
d02eecc0ca | |||
f17593ff26 |
@@ -12,8 +12,6 @@ Checks: >
|
|||||||
-readability-avoid-const-params-in-decls,
|
-readability-avoid-const-params-in-decls,
|
||||||
-readability-simplify-boolean-expr,
|
-readability-simplify-boolean-expr,
|
||||||
-readability-make-member-function-const,
|
-readability-make-member-function-const,
|
||||||
-readability-suspicious-call-argument,
|
|
||||||
-readability-redundant-member-init,
|
|
||||||
|
|
||||||
-readability-misleading-indentation,
|
-readability-misleading-indentation,
|
||||||
|
|
||||||
@@ -27,8 +25,6 @@ Checks: >
|
|||||||
-bugprone-branch-clone,
|
-bugprone-branch-clone,
|
||||||
-bugprone-macro-parentheses,
|
-bugprone-macro-parentheses,
|
||||||
-bugprone-reserved-identifier,
|
-bugprone-reserved-identifier,
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-bugprone-implicit-widening-of-multiplication-result,
|
|
||||||
|
|
||||||
-bugprone-sizeof-expression,
|
-bugprone-sizeof-expression,
|
||||||
-bugprone-integer-division,
|
-bugprone-integer-division,
|
||||||
@@ -44,8 +40,7 @@ Checks: >
|
|||||||
-modernize-pass-by-value,
|
-modernize-pass-by-value,
|
||||||
# Cannot be enabled yet, because using raw string literals in tests breaks
|
# Cannot be enabled yet, because using raw string literals in tests breaks
|
||||||
# the windows compiler currently.
|
# the windows compiler currently.
|
||||||
-modernize-raw-string-literal,
|
-modernize-raw-string-literal
|
||||||
-modernize-return-braced-init-list
|
|
||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: modernize-use-default-member-init.UseAssignment
|
- key: modernize-use-default-member-init.UseAssignment
|
||||||
|
@@ -187,13 +187,6 @@ mark_as_advanced(CPACK_OVERRIDE_PACKAGENAME)
|
|||||||
mark_as_advanced(BUILDINFO_OVERRIDE_DATE)
|
mark_as_advanced(BUILDINFO_OVERRIDE_DATE)
|
||||||
mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
|
mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
|
||||||
|
|
||||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16")
|
|
||||||
option(WITH_UNITY_BUILD "Enable unity build for modules that support it to improve compile times" ON)
|
|
||||||
mark_as_advanced(WITH_UNITY_BUILD)
|
|
||||||
else()
|
|
||||||
set(WITH_UNITY_BUILD OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
|
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
|
||||||
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
|
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
|
||||||
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ON)
|
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ON)
|
||||||
@@ -418,7 +411,6 @@ option(WITH_CYCLES "Enable Cycles Render Engine" ON)
|
|||||||
option(WITH_CYCLES_OSL "Build Cycles with OpenShadingLanguage support" ON)
|
option(WITH_CYCLES_OSL "Build Cycles with OpenShadingLanguage support" ON)
|
||||||
option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
|
option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
|
||||||
option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
|
option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
|
||||||
option(WITH_CYCLES_DEBUG "Build Cycles with options useful for debugging (e.g., MIS)" OFF)
|
|
||||||
|
|
||||||
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
|
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
|
||||||
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
|
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
|
||||||
@@ -433,40 +425,30 @@ mark_as_advanced(WITH_CYCLES_DEBUG_NAN)
|
|||||||
mark_as_advanced(WITH_CYCLES_NATIVE_ONLY)
|
mark_as_advanced(WITH_CYCLES_NATIVE_ONLY)
|
||||||
|
|
||||||
# NVIDIA CUDA & OptiX
|
# NVIDIA CUDA & OptiX
|
||||||
if(NOT APPLE)
|
option(WITH_CYCLES_DEVICE_CUDA "Enable Cycles NVIDIA CUDA compute support" ON)
|
||||||
option(WITH_CYCLES_DEVICE_CUDA "Enable Cycles NVIDIA CUDA compute support" ON)
|
option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles NVIDIA OptiX support" ON)
|
||||||
option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles NVIDIA OptiX support" ON)
|
mark_as_advanced(WITH_CYCLES_DEVICE_CUDA)
|
||||||
mark_as_advanced(WITH_CYCLES_DEVICE_CUDA)
|
|
||||||
|
|
||||||
option(WITH_CYCLES_CUDA_BINARIES "Build Cycles NVIDIA CUDA binaries" OFF)
|
option(WITH_CYCLES_CUDA_BINARIES "Build Cycles NVIDIA CUDA binaries" OFF)
|
||||||
set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
|
set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
|
||||||
option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
|
option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
|
||||||
option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
|
option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
|
||||||
option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime (for developers, makes cuda-gdb work)" ON)
|
option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime (for developers, makes cuda-gdb work)" ON)
|
||||||
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
|
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
|
||||||
mark_as_advanced(WITH_CYCLES_CUBIN_COMPILER)
|
mark_as_advanced(WITH_CYCLES_CUBIN_COMPILER)
|
||||||
mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
|
mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
|
||||||
mark_as_advanced(WITH_CUDA_DYNLOAD)
|
mark_as_advanced(WITH_CUDA_DYNLOAD)
|
||||||
endif()
|
|
||||||
|
|
||||||
# AMD HIP
|
# AMD HIP
|
||||||
if(NOT APPLE)
|
if(WIN32)
|
||||||
if(WIN32)
|
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
|
||||||
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
|
else()
|
||||||
else()
|
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" OFF)
|
||||||
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
|
|
||||||
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
|
|
||||||
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
|
|
||||||
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Apple Metal
|
|
||||||
if(APPLE)
|
|
||||||
option(WITH_CYCLES_DEVICE_METAL "Enable Cycles Apple Metal compute support" ON)
|
|
||||||
endif()
|
endif()
|
||||||
|
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
|
||||||
|
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||||
|
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
|
||||||
|
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
|
||||||
|
|
||||||
# Draw Manager
|
# Draw Manager
|
||||||
option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF)
|
option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF)
|
||||||
@@ -511,10 +493,12 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This should be turned off when Blender enter beta/rc/release
|
# This should be turned off when Blender enter beta/rc/release
|
||||||
if("${BLENDER_VERSION_CYCLE}" STREQUAL "alpha")
|
if("${BLENDER_VERSION_CYCLE}" STREQUAL "release" OR
|
||||||
set(WITH_EXPERIMENTAL_FEATURES ON)
|
"${BLENDER_VERSION_CYCLE}" STREQUAL "rc" OR
|
||||||
else()
|
"${BLENDER_VERSION_CYCLE}" STREQUAL "beta")
|
||||||
set(WITH_EXPERIMENTAL_FEATURES OFF)
|
set(WITH_EXPERIMENTAL_FEATURES OFF)
|
||||||
|
else()
|
||||||
|
set(WITH_EXPERIMENTAL_FEATURES ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Unit testsing
|
# Unit testsing
|
||||||
@@ -536,14 +520,12 @@ option(WITH_OPENGL "When off limits visibility of the opengl header
|
|||||||
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
|
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
|
||||||
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
|
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
|
||||||
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
|
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
|
||||||
option(WITH_GPU_SHADER_BUILDER "Shader builder is a developer option enabling linting on GLSL during compilation" OFF)
|
|
||||||
|
|
||||||
mark_as_advanced(
|
mark_as_advanced(
|
||||||
WITH_OPENGL
|
WITH_OPENGL
|
||||||
WITH_GLEW_ES
|
WITH_GLEW_ES
|
||||||
WITH_GL_EGL
|
WITH_GL_EGL
|
||||||
WITH_GL_PROFILE_ES20
|
WITH_GL_PROFILE_ES20
|
||||||
WITH_GPU_SHADER_BUILDER
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@@ -561,14 +543,12 @@ if(WIN32)
|
|||||||
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
|
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compiler tool-chain.
|
# Compiler toolchain
|
||||||
if(UNIX AND NOT APPLE)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
|
||||||
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
|
mark_as_advanced(WITH_LINKER_GOLD)
|
||||||
mark_as_advanced(WITH_LINKER_GOLD)
|
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
|
||||||
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
|
mark_as_advanced(WITH_LINKER_LLD)
|
||||||
mark_as_advanced(WITH_LINKER_LLD)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
||||||
@@ -860,7 +840,7 @@ if(WITH_AUDASPACE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Auto-enable CUDA dynload if toolkit is not found.
|
# Auto-enable CUDA dynload if toolkit is not found.
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_CUDA AND NOT WITH_CUDA_DYNLOAD)
|
if(NOT WITH_CUDA_DYNLOAD)
|
||||||
find_package(CUDA)
|
find_package(CUDA)
|
||||||
if(NOT CUDA_FOUND)
|
if(NOT CUDA_FOUND)
|
||||||
message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead")
|
message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead")
|
||||||
@@ -1090,7 +1070,7 @@ if(MSVC)
|
|||||||
add_definitions(-D__LITTLE_ENDIAN__)
|
add_definitions(-D__LITTLE_ENDIAN__)
|
||||||
|
|
||||||
# OSX-Note: as we do cross-compiling with specific set architecture,
|
# OSX-Note: as we do cross-compiling with specific set architecture,
|
||||||
# endianness-detection and auto-setting is counterproductive
|
# endianess-detection and auto-setting is counterproductive
|
||||||
# so we just set endianness according CMAKE_OSX_ARCHITECTURES
|
# so we just set endianness according CMAKE_OSX_ARCHITECTURES
|
||||||
|
|
||||||
elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR CMAKE_OSX_ARCHITECTURES MATCHES arm64)
|
elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR CMAKE_OSX_ARCHITECTURES MATCHES arm64)
|
||||||
@@ -1780,7 +1760,7 @@ endif()
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
# If C++17 is not available, downgrading to an earlier standard is NOT OK.
|
# If C++17 is not available, downgrading to an earlier standard is NOT OK.
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
# Do not enable compiler specific language extensions.
|
# Do not enable compiler specific language extentions.
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
# Make MSVC properly report the value of the __cplusplus preprocessor macro
|
# Make MSVC properly report the value of the __cplusplus preprocessor macro
|
||||||
|
@@ -51,7 +51,7 @@ Other Convenience Targets
|
|||||||
* config: Run cmake configuration tool to set build options.
|
* config: Run cmake configuration tool to set build options.
|
||||||
* deps: Build library dependencies (intended only for platform maintainers).
|
* deps: Build library dependencies (intended only for platform maintainers).
|
||||||
|
|
||||||
The existance of locally build dependencies overrides the pre-built dependencies from subversion.
|
The existance of locally build dependancies overrides the pre-built dependencies from subversion.
|
||||||
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
|
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
|
||||||
|
|
||||||
Project Files
|
Project Files
|
||||||
|
@@ -38,6 +38,13 @@ elseif(UNIX AND NOT APPLE)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BLENDER_PLATFORM_ARM)
|
||||||
|
set(GMP_OPTIONS
|
||||||
|
${GMP_OPTIONS}
|
||||||
|
--disable-assembly
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
ExternalProject_Add(external_gmp
|
ExternalProject_Add(external_gmp
|
||||||
URL file://${PACKAGE_DIR}/${GMP_FILE}
|
URL file://${PACKAGE_DIR}/${GMP_FILE}
|
||||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
# ***** END GPL LICENSE BLOCK *****
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Copy all generated files to the proper structure as blender prefers
|
# Copy all generated files to the proper strucure as blender prefers
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
if(NOT DEFINED HARVEST_TARGET)
|
if(NOT DEFINED HARVEST_TARGET)
|
||||||
|
@@ -39,7 +39,7 @@ endif()
|
|||||||
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")
|
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")
|
||||||
# This path must be hard-coded like this, so that the GNUmakefile knows where it is and can pass it to make_source_archive.py:
|
# 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")
|
set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages")
|
||||||
option(PACKAGE_USE_UPSTREAM_SOURCES "Use sources upstream to download the package sources, when OFF the blender mirror will be used" ON)
|
option(PACKAGE_USE_UPSTREAM_SOURCES "Use soures upstream to download the package sources, when OFF the blender mirror will be used" ON)
|
||||||
|
|
||||||
file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)
|
file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)
|
||||||
file(TO_CMAKE_PATH ${PACKAGE_DIR} PACKAGE_DIR)
|
file(TO_CMAKE_PATH ${PACKAGE_DIR} PACKAGE_DIR)
|
||||||
|
@@ -24,7 +24,7 @@ if(MSVC)
|
|||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
OUTPUT ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
||||||
COMMAND echo packaging python
|
COMMAND echo packaging python
|
||||||
COMMAND echo this should output at ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
COMMAND echo this should ouput at ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTARGET}/libs
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTARGET}/libs
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}.lib ${PYTARGET}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}.lib ${PYTARGET}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/python.exe ${PYTARGET}/bin/python.exe
|
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/python.exe ${PYTARGET}/bin/python.exe
|
||||||
@@ -43,7 +43,7 @@ if(MSVC)
|
|||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
OUTPUT ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
||||||
COMMAND echo packaging python
|
COMMAND echo packaging python
|
||||||
COMMAND echo this should output at ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
COMMAND echo this should ouput at ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTARGET}/libs
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTARGET}/libs
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib ${PYTARGET}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib ${PYTARGET}/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/python${PYTHON_POSTFIX}.exe ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
COMMAND ${CMAKE_COMMAND} -E copy ${PYSRC}/python${PYTHON_POSTFIX}.exe ${PYTARGET}/bin/python${PYTHON_POSTFIX}.exe
|
||||||
|
@@ -474,9 +474,9 @@ set(ISPC_HASH 2e3abedbc0ea9aaec17d6562c632454d)
|
|||||||
set(ISPC_HASH_TYPE MD5)
|
set(ISPC_HASH_TYPE MD5)
|
||||||
set(ISPC_FILE ispc-${ISPC_VERSION}.tar.gz)
|
set(ISPC_FILE ispc-${ISPC_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(GMP_VERSION 6.2.1)
|
set(GMP_VERSION 6.2.0)
|
||||||
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
|
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
|
||||||
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
|
set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1)
|
||||||
set(GMP_HASH_TYPE MD5)
|
set(GMP_HASH_TYPE MD5)
|
||||||
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
||||||
|
|
||||||
|
@@ -1826,7 +1826,7 @@ compile_OCIO() {
|
|||||||
# Force linking against static libs
|
# Force linking against static libs
|
||||||
#rm -f $_inst/lib/*.so*
|
#rm -f $_inst/lib/*.so*
|
||||||
|
|
||||||
# Additional dependencies
|
# Additional depencencies
|
||||||
#cp ext/dist/lib/libtinyxml.a $_inst/lib
|
#cp ext/dist/lib/libtinyxml.a $_inst/lib
|
||||||
#cp ext/dist/lib/libyaml-cpp.a $_inst/lib
|
#cp ext/dist/lib/libyaml-cpp.a $_inst/lib
|
||||||
|
|
||||||
@@ -2083,9 +2083,9 @@ compile_OIIO() {
|
|||||||
cmake_d="$cmake_d -D OPENEXR_VERSION=$OPENEXR_VERSION"
|
cmake_d="$cmake_d -D OPENEXR_VERSION=$OPENEXR_VERSION"
|
||||||
|
|
||||||
if [ "$_with_built_openexr" = true ]; then
|
if [ "$_with_built_openexr" = true ]; then
|
||||||
cmake_d="$cmake_d -D ILMBASE_ROOT=$INST/openexr"
|
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
|
||||||
cmake_d="$cmake_d -D OPENEXR_ROOT=$INST/openexr"
|
cmake_d="$cmake_d -D OPENEXR_HOME=$INST/openexr"
|
||||||
INFO "Ilmbase_ROOT=$INST/openexr"
|
INFO "ILMBASE_HOME=$INST/openexr"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ptex is only needed when nicholas bishop is ready
|
# ptex is only needed when nicholas bishop is ready
|
||||||
@@ -2374,9 +2374,9 @@ compile_OSL() {
|
|||||||
#~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
|
#~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
|
||||||
|
|
||||||
if [ "$_with_built_openexr" = true ]; then
|
if [ "$_with_built_openexr" = true ]; then
|
||||||
cmake_d="$cmake_d -D ILMBASE_ROOT=$INST/openexr"
|
INFO "ILMBASE_HOME=$INST/openexr"
|
||||||
cmake_d="$cmake_d -D OPENEXR_ROOT=$INST/openexr"
|
cmake_d="$cmake_d -D OPENEXR_ROOT_DIR=$INST/openexr"
|
||||||
INFO "Ilmbase_ROOT=$INST/openexr"
|
cmake_d="$cmake_d -D ILMBASE_ROOT_DIR=$INST/openexr"
|
||||||
# XXX Temp workaround... sigh, ILMBase really messed the things up by defining their custom names ON by default :(
|
# XXX Temp workaround... sigh, ILMBase really messed the things up by defining their custom names ON by default :(
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -5801,7 +5801,7 @@ print_info() {
|
|||||||
PRINT "If you're using CMake add this to your configuration flags:"
|
PRINT "If you're using CMake add this to your configuration flags:"
|
||||||
|
|
||||||
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
|
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
|
||||||
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CLANG* -U *CYCLES*"
|
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
|
||||||
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
|
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
|
||||||
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR*"
|
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR*"
|
||||||
|
|
||||||
|
@@ -197,38 +197,3 @@ index 67ec0d15f..6dc3e85a0 100644
|
|||||||
#else
|
#else
|
||||||
#error Unknown architecture.
|
#error Unknown architecture.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
diff --git a/pxr/base/arch/demangle.cpp b/pxr/base/arch/demangle.cpp
|
|
||||||
index 67ec0d15f..6dc3e85a0 100644
|
|
||||||
--- a/pxr/base/arch/demangle.cpp
|
|
||||||
+++ b/pxr/base/arch/demangle.cpp
|
|
||||||
@@ -36,6 +36,7 @@
|
|
||||||
#if (ARCH_COMPILER_GCC_MAJOR == 3 && ARCH_COMPILER_GCC_MINOR >= 1) || \
|
|
||||||
ARCH_COMPILER_GCC_MAJOR > 3 || defined(ARCH_COMPILER_CLANG)
|
|
||||||
#define _AT_LEAST_GCC_THREE_ONE_OR_CLANG
|
|
||||||
+#include <cxxabi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PXR_NAMESPACE_OPEN_SCOPE
|
|
||||||
@@ -138,7 +139,6 @@
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_AT_LEAST_GCC_THREE_ONE_OR_CLANG)
|
|
||||||
-#include <cxxabi.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This routine doesn't work when you get to gcc3.4.
|
|
||||||
|
|
||||||
diff --git a/pxr/base/work/singularTask.h b/pxr/base/work/singularTask.h
|
|
||||||
index 67ec0d15f..6dc3e85a0 100644
|
|
||||||
--- a/pxr/base/work/singularTask.h
|
|
||||||
+++ b/pxr/base/work/singularTask.h
|
|
||||||
@@ -120,7 +120,7 @@
|
|
||||||
// case we go again to ensure the task can do whatever it
|
|
||||||
// was awakened to do. Once we successfully take the count
|
|
||||||
// to zero, we stop.
|
|
||||||
- size_t old = count;
|
|
||||||
+ std::size_t old = count;
|
|
||||||
do { _fn(); } while (
|
|
||||||
!count.compare_exchange_strong(old, 0));
|
|
||||||
});
|
|
||||||
|
@@ -21,7 +21,7 @@ ENDIF()
|
|||||||
|
|
||||||
SET(_optix_SEARCH_DIRS
|
SET(_optix_SEARCH_DIRS
|
||||||
${OPTIX_ROOT_DIR}
|
${OPTIX_ROOT_DIR}
|
||||||
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0"
|
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_PATH(OPTIX_INCLUDE_DIR
|
FIND_PATH(OPTIX_INCLUDE_DIR
|
||||||
|
@@ -114,7 +114,7 @@ def is_c_header(filename: str) -> bool:
|
|||||||
|
|
||||||
def is_c(filename: str) -> bool:
|
def is_c(filename: str) -> bool:
|
||||||
ext = splitext(filename)[1]
|
ext = splitext(filename)[1]
|
||||||
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".metal"})
|
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
|
||||||
|
|
||||||
|
|
||||||
def is_c_any(filename: str) -> bool:
|
def is_c_any(filename: str) -> bool:
|
||||||
|
@@ -180,7 +180,7 @@ def create_nb_project_main():
|
|||||||
f.write(' </logicalFolder>\n')
|
f.write(' </logicalFolder>\n')
|
||||||
|
|
||||||
f.write(' </logicalFolder>\n')
|
f.write(' </logicalFolder>\n')
|
||||||
# default, but this dir is in fact not in blender dir so we can ignore it
|
# default, but this dir is infact not in blender dir so we can ignore it
|
||||||
# f.write(' <sourceFolderFilter>^(nbproject)$</sourceFolderFilter>\n')
|
# f.write(' <sourceFolderFilter>^(nbproject)$</sourceFolderFilter>\n')
|
||||||
f.write(r' <sourceFolderFilter>^(nbproject|__pycache__|.*\.py|.*\.html|.*\.blend)$</sourceFolderFilter>\n')
|
f.write(r' <sourceFolderFilter>^(nbproject|__pycache__|.*\.py|.*\.html|.*\.blend)$</sourceFolderFilter>\n')
|
||||||
|
|
||||||
|
@@ -19,6 +19,9 @@ set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
|||||||
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
|
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE)
|
set(WITH_COREAUDIO OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
|
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_CYCLES_EMBREE OFF CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_DRACO OFF CACHE BOOL "" FORCE)
|
set(WITH_DRACO OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
|
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
|
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
|
||||||
|
@@ -61,7 +61,6 @@ set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
|
|||||||
# platform dependent options
|
# platform dependent options
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
|
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_CYCLES_DEVICE_METAL ON CACHE BOOL "" FORCE)
|
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||||
|
@@ -529,7 +529,7 @@ function(SETUP_LIBDIRS)
|
|||||||
|
|
||||||
# NOTE: For all new libraries, use absolute library paths.
|
# NOTE: For all new libraries, use absolute library paths.
|
||||||
# This should eventually be phased out.
|
# This should eventually be phased out.
|
||||||
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
|
# APPLE plaform uses full paths for linking libraries, and avoids link_directories.
|
||||||
if(NOT MSVC AND NOT APPLE)
|
if(NOT MSVC AND NOT APPLE)
|
||||||
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
|
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
|
||||||
|
|
||||||
@@ -1292,6 +1292,29 @@ macro(openmp_delayload
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(blender_precompile_headers target cpp header)
|
||||||
|
if(MSVC)
|
||||||
|
# get the name for the pch output file
|
||||||
|
get_filename_component(pchbase ${cpp} NAME_WE)
|
||||||
|
set(pchfinal "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${pchbase}.pch")
|
||||||
|
|
||||||
|
# mark the cpp as the one outputting the pch
|
||||||
|
set_property(SOURCE ${cpp} APPEND PROPERTY OBJECT_OUTPUTS "${pchfinal}")
|
||||||
|
|
||||||
|
# get all sources for the target
|
||||||
|
get_target_property(sources ${target} SOURCES)
|
||||||
|
|
||||||
|
# make all sources depend on the pch to enforce the build order
|
||||||
|
foreach(src ${sources})
|
||||||
|
set_property(SOURCE ${src} APPEND PROPERTY OBJECT_DEPENDS "${pchfinal}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
target_sources(${target} PRIVATE ${cpp} ${header})
|
||||||
|
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "/Yu${header} /Fp${pchfinal} /FI${header}")
|
||||||
|
set_source_files_properties(${cpp} PROPERTIES COMPILE_FLAGS "/Yc${header} /Fp${pchfinal}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro(set_and_warn_dependency
|
macro(set_and_warn_dependency
|
||||||
_dependency _setting _val)
|
_dependency _setting _val)
|
||||||
# when $_dependency is disabled, forces $_setting = $_val
|
# when $_dependency is disabled, forces $_setting = $_val
|
||||||
|
@@ -257,6 +257,9 @@ if(WITH_BOOST)
|
|||||||
if(WITH_INTERNATIONAL)
|
if(WITH_INTERNATIONAL)
|
||||||
list(APPEND _boost_FIND_COMPONENTS locale)
|
list(APPEND _boost_FIND_COMPONENTS locale)
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_CYCLES_NETWORK)
|
||||||
|
list(APPEND _boost_FIND_COMPONENTS serialization)
|
||||||
|
endif()
|
||||||
if(WITH_OPENVDB)
|
if(WITH_OPENVDB)
|
||||||
list(APPEND _boost_FIND_COMPONENTS iostreams)
|
list(APPEND _boost_FIND_COMPONENTS iostreams)
|
||||||
endif()
|
endif()
|
||||||
@@ -336,7 +339,7 @@ if(WITH_LLVM)
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
set(CYCLES_OSL ${LIBDIR}/osl)
|
set(CYCLES_OSL ${LIBDIR}/osl)
|
||||||
|
|
||||||
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
|
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
|
||||||
@@ -356,7 +359,7 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
if(WITH_CYCLES_EMBREE)
|
||||||
find_package(Embree 3.8.0 REQUIRED)
|
find_package(Embree 3.8.0 REQUIRED)
|
||||||
# Increase stack size for Embree, only works for executables.
|
# Increase stack size for Embree, only works for executables.
|
||||||
if(NOT WITH_PYTHON_MODULE)
|
if(NOT WITH_PYTHON_MODULE)
|
||||||
|
@@ -96,7 +96,7 @@ else()
|
|||||||
# Detect SDK version to use.
|
# Detect SDK version to use.
|
||||||
if(NOT DEFINED OSX_SYSTEM)
|
if(NOT DEFINED OSX_SYSTEM)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND xcrun --sdk macosx --show-sdk-version
|
COMMAND xcrun --show-sdk-version
|
||||||
OUTPUT_VARIABLE OSX_SYSTEM
|
OUTPUT_VARIABLE OSX_SYSTEM
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
# ***** END GPL LICENSE BLOCK *****
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
# Libraries configuration for any *nix system including Linux and Unix (excluding APPLE).
|
# Libraries configuration for any *nix system including Linux and Unix.
|
||||||
|
|
||||||
# Detect precompiled library directory
|
# Detect precompiled library directory
|
||||||
if(NOT DEFINED LIBDIR)
|
if(NOT DEFINED LIBDIR)
|
||||||
@@ -241,7 +241,7 @@ if(WITH_INPUT_NDOF)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
||||||
if(EXISTS ${CYCLES_OSL} AND NOT OSL_ROOT)
|
if(EXISTS ${CYCLES_OSL} AND NOT OSL_ROOT)
|
||||||
set(OSL_ROOT ${CYCLES_OSL})
|
set(OSL_ROOT ${CYCLES_OSL})
|
||||||
@@ -314,7 +314,7 @@ if(WITH_BOOST)
|
|||||||
endif()
|
endif()
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
set(__boost_packages filesystem regex thread date_time)
|
set(__boost_packages filesystem regex thread date_time)
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
|
if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
|
||||||
list(APPEND __boost_packages wave)
|
list(APPEND __boost_packages wave)
|
||||||
else()
|
else()
|
||||||
@@ -323,6 +323,9 @@ if(WITH_BOOST)
|
|||||||
if(WITH_INTERNATIONAL)
|
if(WITH_INTERNATIONAL)
|
||||||
list(APPEND __boost_packages locale)
|
list(APPEND __boost_packages locale)
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_CYCLES_NETWORK)
|
||||||
|
list(APPEND __boost_packages serialization)
|
||||||
|
endif()
|
||||||
if(WITH_OPENVDB)
|
if(WITH_OPENVDB)
|
||||||
list(APPEND __boost_packages iostreams)
|
list(APPEND __boost_packages iostreams)
|
||||||
endif()
|
endif()
|
||||||
@@ -400,7 +403,7 @@ if(WITH_OPENCOLORIO)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
if(WITH_CYCLES_EMBREE)
|
||||||
find_package(Embree 3.8.0 REQUIRED)
|
find_package(Embree 3.8.0 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -477,7 +477,7 @@ if(WITH_PYTHON)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_BOOST)
|
if(WITH_BOOST)
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
set(boost_extra_libs wave)
|
set(boost_extra_libs wave)
|
||||||
endif()
|
endif()
|
||||||
if(WITH_INTERNATIONAL)
|
if(WITH_INTERNATIONAL)
|
||||||
@@ -520,7 +520,7 @@ if(WITH_BOOST)
|
|||||||
debug ${BOOST_LIBPATH}/libboost_thread-${BOOST_DEBUG_POSTFIX}
|
debug ${BOOST_LIBPATH}/libboost_thread-${BOOST_DEBUG_POSTFIX}
|
||||||
debug ${BOOST_LIBPATH}/libboost_chrono-${BOOST_DEBUG_POSTFIX}
|
debug ${BOOST_LIBPATH}/libboost_chrono-${BOOST_DEBUG_POSTFIX}
|
||||||
)
|
)
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||||
optimized ${BOOST_LIBPATH}/libboost_wave-${BOOST_POSTFIX}
|
optimized ${BOOST_LIBPATH}/libboost_wave-${BOOST_POSTFIX}
|
||||||
debug ${BOOST_LIBPATH}/libboost_wave-${BOOST_DEBUG_POSTFIX})
|
debug ${BOOST_LIBPATH}/libboost_wave-${BOOST_DEBUG_POSTFIX})
|
||||||
@@ -708,7 +708,7 @@ if(WITH_CODEC_SNDFILE)
|
|||||||
set(LIBSNDFILE_LIBRARIES ${LIBSNDFILE_LIBPATH}/libsndfile-1.lib)
|
set(LIBSNDFILE_LIBRARIES ${LIBSNDFILE_LIBPATH}/libsndfile-1.lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
if(WITH_CYCLES_OSL)
|
||||||
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
||||||
set(OSL_SHADER_DIR ${CYCLES_OSL}/shaders)
|
set(OSL_SHADER_DIR ${CYCLES_OSL}/shaders)
|
||||||
# Shaders have moved around a bit between OSL versions, check multiple locations
|
# Shaders have moved around a bit between OSL versions, check multiple locations
|
||||||
@@ -741,7 +741,7 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
if(WITH_CYCLES_EMBREE)
|
||||||
windows_find_package(Embree)
|
windows_find_package(Embree)
|
||||||
if(NOT EMBREE_FOUND)
|
if(NOT EMBREE_FOUND)
|
||||||
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
|
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
|
||||||
|
@@ -27,7 +27,7 @@ if(WITH_WINDOWS_BUNDLE_CRT)
|
|||||||
# Install the CRT to the blender.crt Sub folder.
|
# Install the CRT to the blender.crt Sub folder.
|
||||||
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ./blender.crt COMPONENT Libraries)
|
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ./blender.crt COMPONENT Libraries)
|
||||||
|
|
||||||
# Generating the manifest is a relatively expensive operation since
|
# Generating the manifest is a relativly expensive operation since
|
||||||
# it is collecting an sha1 hash for every file required. so only do
|
# it is collecting an sha1 hash for every file required. so only do
|
||||||
# this work when the libs have either changed or the manifest does
|
# this work when the libs have either changed or the manifest does
|
||||||
# not exist yet.
|
# not exist yet.
|
||||||
|
@@ -5,38 +5,38 @@
|
|||||||
update-code:
|
update-code:
|
||||||
git:
|
git:
|
||||||
submodules:
|
submodules:
|
||||||
- branch: master
|
- branch: blender-v3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/scripts/addons
|
path: release/scripts/addons
|
||||||
- branch: master
|
- branch: blender-v3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/scripts/addons_contrib
|
path: release/scripts/addons_contrib
|
||||||
- branch: master
|
- branch: blender-v3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/datafiles/locale
|
path: release/datafiles/locale
|
||||||
- branch: master
|
- branch: blender-v3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: source/tools
|
path: source/tools
|
||||||
svn:
|
svn:
|
||||||
libraries:
|
libraries:
|
||||||
darwin-arm64:
|
darwin-arm64:
|
||||||
branch: trunk
|
branch: tags/blender-3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/darwin_arm64
|
path: lib/darwin_arm64
|
||||||
darwin-x86_64:
|
darwin-x86_64:
|
||||||
branch: trunk
|
branch: tags/blender-3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/darwin
|
path: lib/darwin
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
branch: trunk
|
branch: tags/blender-3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/linux_centos7_x86_64
|
path: lib/linux_centos7_x86_64
|
||||||
windows-amd64:
|
windows-amd64:
|
||||||
branch: trunk
|
branch: tags/blender-3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/win64_vc15
|
path: lib/win64_vc15
|
||||||
tests:
|
tests:
|
||||||
branch: trunk
|
branch: tags/blender-3.0-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/tests
|
path: lib/tests
|
||||||
benchmarks:
|
benchmarks:
|
||||||
|
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = V3.1
|
PROJECT_NUMBER = V3.0
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
@@ -6,87 +6,91 @@
|
|||||||
* as part of the normal development process.
|
* as part of the normal development process.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: other modules.
|
/** \defgroup MEM Guarded memory (de)allocation
|
||||||
* - `libmv`
|
* \ingroup intern
|
||||||
* - `cycles`
|
|
||||||
* - `opencolorio`
|
|
||||||
* - `opensubdiv`
|
|
||||||
* - `openvdb`
|
|
||||||
* - `quadriflow`
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_atomic Atomic Operations
|
/** \defgroup clog C-Logging (CLOG)
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_clog C-Logging (CLOG)
|
/** \defgroup ctr container
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_eigen Eigen
|
/** \defgroup iksolver iksolver
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_glew-mx GLEW with Multiple Rendering Context's
|
/** \defgroup itasc itasc
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_iksolver Inverse Kinematics (Solver)
|
/** \defgroup memutil memutil
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_itasc Inverse Kinematics (ITASC)
|
/** \defgroup mikktspace mikktspace
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_libc_compat libc Compatibility For Linux
|
/** \defgroup moto moto
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_locale Locale
|
/** \defgroup eigen eigen
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_mantaflow Manta-Flow Fluid Simulation
|
/** \defgroup smoke smoke
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup intern_mem Guarded Memory (de)allocation
|
/** \defgroup string string
|
||||||
* \ingroup intern */
|
* \ingroup intern
|
||||||
|
*/
|
||||||
/** \defgroup intern_memutil Memory Utilities (memutil)
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup intern_mikktspace MikktSpace
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup intern_rigidbody Rigid-Body C-API
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup intern_sky_model Sky Model
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup intern_utf_conv UTF-8/16 Conversion (utfconv)
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup audaspace Audaspace
|
/** \defgroup audaspace Audaspace
|
||||||
* \ingroup intern undoc
|
* \ingroup intern undoc
|
||||||
* \todo add to doxygen */
|
* \todo add to doxygen
|
||||||
|
*/
|
||||||
/** \defgroup audcoreaudio Audaspace CoreAudio
|
/** \defgroup audcoreaudio Audaspace CoreAudio
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audfx Audaspace FX
|
/** \defgroup audfx Audaspace FX
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audopenal Audaspace OpenAL
|
/** \defgroup audopenal Audaspace OpenAL
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audpulseaudio Audaspace PulseAudio
|
/** \defgroup audpulseaudio Audaspace PulseAudio
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audwasapi Audaspace WASAPI
|
/** \defgroup audwasapi Audaspace WASAPI
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audpython Audaspace Python
|
/** \defgroup audpython Audaspace Python
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audsdl Audaspace SDL
|
/** \defgroup audsdl Audaspace SDL
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audsrc Audaspace SRC
|
/** \defgroup audsrc Audaspace SRC
|
||||||
* \ingroup audaspace */
|
*
|
||||||
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audffmpeg Audaspace FFMpeg
|
/** \defgroup audffmpeg Audaspace FFMpeg
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audfftw Audaspace FFTW
|
/** \defgroup audfftw Audaspace FFTW
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audjack Audaspace Jack
|
/** \defgroup audjack Audaspace Jack
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
/** \defgroup audsndfile Audaspace sndfile
|
/** \defgroup audsndfile Audaspace sndfile
|
||||||
* \ingroup audaspace */
|
* \ingroup audaspace
|
||||||
|
*/
|
||||||
|
|
||||||
/** \defgroup GHOST GHOST API
|
/** \defgroup GHOST GHOST API
|
||||||
* \ingroup intern GUI
|
* \ingroup intern GUI
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
/** \defgroup bmesh BMesh
|
/** \defgroup bmesh BMesh
|
||||||
* \ingroup blender
|
* \ingroup blender
|
||||||
*/
|
*/
|
||||||
/** \defgroup compositor Compositing
|
/** \defgroup compositor Compositing */
|
||||||
* \ingroup blender */
|
|
||||||
|
|
||||||
/** \defgroup python Python
|
/** \defgroup python Python
|
||||||
* \ingroup blender
|
* \ingroup blender
|
||||||
@@ -79,8 +78,7 @@
|
|||||||
* \ingroup blender
|
* \ingroup blender
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \defgroup data DNA, RNA and .blend access
|
/** \defgroup data DNA, RNA and .blend access*/
|
||||||
* \ingroup blender */
|
|
||||||
|
|
||||||
/** \defgroup gpu GPU
|
/** \defgroup gpu GPU
|
||||||
* \ingroup blender
|
* \ingroup blender
|
||||||
@@ -103,12 +101,11 @@
|
|||||||
* merged in docs.
|
* merged in docs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/** \defgroup gui GUI */
|
||||||
* \defgroup gui GUI
|
|
||||||
* \ingroup blender */
|
|
||||||
|
|
||||||
/** \defgroup wm Window Manager
|
/** \defgroup wm Window Manager
|
||||||
* \ingroup gui */
|
* \ingroup blender gui
|
||||||
|
*/
|
||||||
|
|
||||||
/* ================================ */
|
/* ================================ */
|
||||||
|
|
||||||
@@ -282,8 +279,7 @@
|
|||||||
* \ingroup gui
|
* \ingroup gui
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \defgroup externformats External Formats
|
/** \defgroup externformats External Formats */
|
||||||
* \ingroup blender */
|
|
||||||
|
|
||||||
/** \defgroup collada COLLADA
|
/** \defgroup collada COLLADA
|
||||||
* \ingroup externformats
|
* \ingroup externformats
|
||||||
@@ -312,7 +308,4 @@
|
|||||||
/* ================================ */
|
/* ================================ */
|
||||||
|
|
||||||
/** \defgroup undoc Undocumented
|
/** \defgroup undoc Undocumented
|
||||||
*
|
* \brief Modules and libraries that are still undocumented, or lacking proper integration into the doxygen system, are marked in this group. */
|
||||||
* \brief Modules and libraries that are still undocumented,
|
|
||||||
* or lacking proper integration into the doxygen system, are marked in this group.
|
|
||||||
*/
|
|
||||||
|
@@ -61,7 +61,7 @@ def blender_extract_info(blender_bin: str) -> Dict[str, str]:
|
|||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
).stdout.decode(encoding="utf-8")
|
).stdout.decode(encoding="utf-8")
|
||||||
|
|
||||||
blender_version_output = subprocess.run(
|
blender_version_ouput = subprocess.run(
|
||||||
[blender_bin, "--version"],
|
[blender_bin, "--version"],
|
||||||
env=blender_env,
|
env=blender_env,
|
||||||
check=True,
|
check=True,
|
||||||
@@ -73,7 +73,7 @@ def blender_extract_info(blender_bin: str) -> Dict[str, str]:
|
|||||||
# check for each lines prefix to ensure these aren't included.
|
# check for each lines prefix to ensure these aren't included.
|
||||||
blender_version = ""
|
blender_version = ""
|
||||||
blender_date = ""
|
blender_date = ""
|
||||||
for l in blender_version_output.split("\n"):
|
for l in blender_version_ouput.split("\n"):
|
||||||
if l.startswith("Blender "):
|
if l.startswith("Blender "):
|
||||||
# Remove 'Blender' prefix.
|
# Remove 'Blender' prefix.
|
||||||
blender_version = l.split(" ", 1)[1].strip()
|
blender_version = l.split(" ", 1)[1].strip()
|
||||||
|
@@ -11,7 +11,7 @@ import queue
|
|||||||
|
|
||||||
execution_queue = queue.Queue()
|
execution_queue = queue.Queue()
|
||||||
|
|
||||||
# This function can safely be called in another thread.
|
# This function can savely be called in another thread.
|
||||||
# The function will be executed when the timer runs the next time.
|
# The function will be executed when the timer runs the next time.
|
||||||
def run_in_main_thread(function):
|
def run_in_main_thread(function):
|
||||||
execution_queue.put(function)
|
execution_queue.put(function)
|
||||||
|
@@ -728,7 +728,7 @@ Abusing RNA property callbacks
|
|||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
Python-defined RNA properties can have custom callbacks. Trying to perform complex operations
|
Python-defined RNA properties can have custom callbacks. Trying to perform complex operations
|
||||||
from there, like calling an operator, may work, but is not officially recommended nor supported.
|
from there, like calling an operator, may work, but is not officialy recommended nor supported.
|
||||||
|
|
||||||
Main reason is that those callback should be very fast, but additionally, it may for example
|
Main reason is that those callback should be very fast, but additionally, it may for example
|
||||||
create issues with undo/redo system (most operators store an history step, and editing an RNA
|
create issues with undo/redo system (most operators store an history step, and editing an RNA
|
||||||
|
@@ -1103,7 +1103,6 @@ context_type_map = {
|
|||||||
"selectable_objects": ("Object", True),
|
"selectable_objects": ("Object", True),
|
||||||
"selected_asset_files": ("FileSelectEntry", True),
|
"selected_asset_files": ("FileSelectEntry", True),
|
||||||
"selected_bones": ("EditBone", True),
|
"selected_bones": ("EditBone", True),
|
||||||
"selected_editable_actions": ("Action", True),
|
|
||||||
"selected_editable_bones": ("EditBone", True),
|
"selected_editable_bones": ("EditBone", True),
|
||||||
"selected_editable_fcurves": ("FCurve", True),
|
"selected_editable_fcurves": ("FCurve", True),
|
||||||
"selected_editable_keyframes": ("Keyframe", True),
|
"selected_editable_keyframes": ("Keyframe", True),
|
||||||
@@ -1119,7 +1118,6 @@ context_type_map = {
|
|||||||
"selected_pose_bones": ("PoseBone", True),
|
"selected_pose_bones": ("PoseBone", True),
|
||||||
"selected_pose_bones_from_active_object": ("PoseBone", True),
|
"selected_pose_bones_from_active_object": ("PoseBone", True),
|
||||||
"selected_sequences": ("Sequence", True),
|
"selected_sequences": ("Sequence", True),
|
||||||
"selected_visible_actions": ("Action", True),
|
|
||||||
"selected_visible_fcurves": ("FCurve", True),
|
"selected_visible_fcurves": ("FCurve", True),
|
||||||
"sequences": ("Sequence", True),
|
"sequences": ("Sequence", True),
|
||||||
"soft_body": ("SoftBodyModifier", False),
|
"soft_body": ("SoftBodyModifier", False),
|
||||||
@@ -1226,10 +1224,7 @@ def pycontext2sphinx(basepath):
|
|||||||
while char_array[i] is not None:
|
while char_array[i] is not None:
|
||||||
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
|
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
|
||||||
fw(".. data:: %s\n\n" % member)
|
fw(".. data:: %s\n\n" % member)
|
||||||
try:
|
member_type, is_seq = context_type_map[member]
|
||||||
member_type, is_seq = context_type_map[member]
|
|
||||||
except KeyError:
|
|
||||||
raise SystemExit("Error: context key %r not found in context_type_map; update %s" % (member, __file__)) from None
|
|
||||||
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
|
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
|
||||||
unique.add(member)
|
unique.add(member)
|
||||||
i += 1
|
i += 1
|
||||||
@@ -2256,7 +2251,7 @@ def main():
|
|||||||
# First monkey patch to load in fake members.
|
# First monkey patch to load in fake members.
|
||||||
setup_monkey_patch()
|
setup_monkey_patch()
|
||||||
|
|
||||||
# Perform changes to Blender itself.
|
# Perform changes to Blender it's self.
|
||||||
setup_data = setup_blender()
|
setup_data = setup_blender()
|
||||||
|
|
||||||
# eventually, create the dirs
|
# eventually, create the dirs
|
||||||
|
4
extern/hipew/src/hipew.c
vendored
4
extern/hipew/src/hipew.c
vendored
@@ -257,7 +257,7 @@ static int hipewHipInit(void) {
|
|||||||
#endif
|
#endif
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
static int result = 0;
|
static int result = 0;
|
||||||
int error;
|
int error, driver_version;
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
return result;
|
return result;
|
||||||
@@ -565,6 +565,8 @@ int hipewCompilerVersion(void) {
|
|||||||
const char *path = hipewCompilerPath();
|
const char *path = hipewCompilerPath();
|
||||||
const char *marker = "Hip compilation tools, release ";
|
const char *marker = "Hip compilation tools, release ";
|
||||||
FILE *pipe;
|
FILE *pipe;
|
||||||
|
int major, minor;
|
||||||
|
char *versionstr;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
char output[65536] = "\0";
|
char output[65536] = "\0";
|
||||||
char command[65536] = "\0";
|
char command[65536] = "\0";
|
||||||
|
@@ -25,6 +25,7 @@ add_subdirectory(ghost)
|
|||||||
add_subdirectory(guardedalloc)
|
add_subdirectory(guardedalloc)
|
||||||
add_subdirectory(libmv)
|
add_subdirectory(libmv)
|
||||||
add_subdirectory(memutil)
|
add_subdirectory(memutil)
|
||||||
|
add_subdirectory(numaapi)
|
||||||
add_subdirectory(opencolorio)
|
add_subdirectory(opencolorio)
|
||||||
add_subdirectory(opensubdiv)
|
add_subdirectory(opensubdiv)
|
||||||
add_subdirectory(mikktspace)
|
add_subdirectory(mikktspace)
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* \ingroup intern_atomic
|
* \ingroup Atomic
|
||||||
*
|
*
|
||||||
* \brief Provides wrapper around system-specific atomic primitives,
|
* \brief Provides wrapper around system-specific atomic primitives,
|
||||||
* and some extensions (faked-atomic operations over float numbers).
|
* and some extensions (faked-atomic operations over float numbers).
|
||||||
|
@@ -44,10 +44,6 @@
|
|||||||
* The Original Code is: adapted from jemalloc.
|
* The Original Code is: adapted from jemalloc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup intern_atomic
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ATOMIC_OPS_EXT_H__
|
#ifndef __ATOMIC_OPS_EXT_H__
|
||||||
#define __ATOMIC_OPS_EXT_H__
|
#define __ATOMIC_OPS_EXT_H__
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
* Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
|
* Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
|
||||||
* Copyright (C) 2009-2013 Facebook, Inc. All rights reserved.
|
* Copyright (C) 2009-2013 Facebook, Inc. All rights reserved.
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* 1. Redistributions of source code must retain the above copyright notice(s),
|
* 1. Redistributions of source code must retain the above copyright notice(s),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* 2. Redistributions in binary form must reproduce the above copyright notice(s),
|
* 2. Redistributions in binary form must reproduce the above copyright notice(s),
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
|
||||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
@@ -26,10 +26,6 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup intern_atomic
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ATOMIC_OPS_MSVC_H__
|
#ifndef __ATOMIC_OPS_MSVC_H__
|
||||||
#define __ATOMIC_OPS_MSVC_H__
|
#define __ATOMIC_OPS_MSVC_H__
|
||||||
|
|
||||||
|
@@ -44,10 +44,6 @@
|
|||||||
* The Original Code is: adapted from jemalloc.
|
* The Original Code is: adapted from jemalloc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup intern_atomic
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ATOMIC_OPS_UNIX_H__
|
#ifndef __ATOMIC_OPS_UNIX_H__
|
||||||
#define __ATOMIC_OPS_UNIX_H__
|
#define __ATOMIC_OPS_UNIX_H__
|
||||||
|
|
||||||
|
@@ -44,10 +44,6 @@
|
|||||||
* The Original Code is: adapted from jemalloc.
|
* The Original Code is: adapted from jemalloc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup intern_atomic
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ATOMIC_OPS_UTILS_H__
|
#ifndef __ATOMIC_OPS_UTILS_H__
|
||||||
#define __ATOMIC_OPS_UTILS_H__
|
#define __ATOMIC_OPS_UTILS_H__
|
||||||
|
|
||||||
|
@@ -14,8 +14,11 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLG_LOG_H__
|
||||||
|
#define __CLG_LOG_H__
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* \ingroup intern_clog
|
* \ingroup clog
|
||||||
*
|
*
|
||||||
* C Logging Library (clog)
|
* C Logging Library (clog)
|
||||||
* ========================
|
* ========================
|
||||||
@@ -65,9 +68,6 @@
|
|||||||
* - 4+: May be used for more details than 3, should be avoided but not prevented.
|
* - 4+: May be used for more details than 3, should be avoided but not prevented.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CLG_LOG_H__
|
|
||||||
#define __CLG_LOG_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* \ingroup intern_clog
|
* \ingroup clog
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -388,7 +388,7 @@ static void clg_ctx_fatal_action(CLogContext *ctx)
|
|||||||
|
|
||||||
static void clg_ctx_backtrace(CLogContext *ctx)
|
static void clg_ctx_backtrace(CLogContext *ctx)
|
||||||
{
|
{
|
||||||
/* NOTE: we avoid writing to 'FILE', for back-trace we make an exception,
|
/* Note: we avoid writing to 'FILE', for back-trace we make an exception,
|
||||||
* if necessary we could have a version of the callback that writes to file
|
* if necessary we could have a version of the callback that writes to file
|
||||||
* descriptor all at once. */
|
* descriptor all at once. */
|
||||||
ctx->callbacks.backtrace_fn(ctx->output_file);
|
ctx->callbacks.backtrace_fn(ctx->output_file);
|
||||||
|
@@ -226,9 +226,6 @@ add_definitions(
|
|||||||
-DCCL_NAMESPACE_END=}
|
-DCCL_NAMESPACE_END=}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_CYCLES_DEBUG)
|
|
||||||
add_definitions(-DWITH_CYCLES_DEBUG)
|
|
||||||
endif()
|
|
||||||
if(WITH_CYCLES_STANDALONE_GUI)
|
if(WITH_CYCLES_STANDALONE_GUI)
|
||||||
add_definitions(-DWITH_CYCLES_STANDALONE_GUI)
|
add_definitions(-DWITH_CYCLES_STANDALONE_GUI)
|
||||||
endif()
|
endif()
|
||||||
@@ -337,7 +334,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
|
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
|
||||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
|
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
|
||||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
|
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
|
||||||
|
@@ -40,7 +40,6 @@ set(SRC
|
|||||||
object_cull.cpp
|
object_cull.cpp
|
||||||
output_driver.cpp
|
output_driver.cpp
|
||||||
particles.cpp
|
particles.cpp
|
||||||
pointcloud.cpp
|
|
||||||
curves.cpp
|
curves.cpp
|
||||||
logging.cpp
|
logging.cpp
|
||||||
python.cpp
|
python.cpp
|
||||||
@@ -88,7 +87,6 @@ endif()
|
|||||||
|
|
||||||
set(ADDON_FILES
|
set(ADDON_FILES
|
||||||
addon/__init__.py
|
addon/__init__.py
|
||||||
addon/camera.py
|
|
||||||
addon/engine.py
|
addon/engine.py
|
||||||
addon/operators.py
|
addon/operators.py
|
||||||
addon/osl.py
|
addon/osl.py
|
||||||
@@ -103,11 +101,6 @@ add_definitions(${GL_DEFINITIONS})
|
|||||||
if(WITH_CYCLES_DEVICE_HIP)
|
if(WITH_CYCLES_DEVICE_HIP)
|
||||||
add_definitions(-DWITH_HIP)
|
add_definitions(-DWITH_HIP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES_DEVICE_METAL)
|
|
||||||
add_definitions(-DWITH_METAL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_MOD_FLUID)
|
if(WITH_MOD_FLUID)
|
||||||
add_definitions(-DWITH_FLUID)
|
add_definitions(-DWITH_FLUID)
|
||||||
endif()
|
endif()
|
||||||
@@ -145,6 +138,11 @@ endif()
|
|||||||
|
|
||||||
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||||
|
|
||||||
|
# avoid link failure with clang 3.4 debug
|
||||||
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gline-tables-only")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_dependencies(bf_intern_cycles bf_rna)
|
add_dependencies(bf_intern_cycles bf_rna)
|
||||||
|
|
||||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${ADDON_FILES}" ${CYCLES_INSTALL_PATH})
|
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${ADDON_FILES}" ${CYCLES_INSTALL_PATH})
|
||||||
|
@@ -1,84 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2011-2021 Blender Foundation
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
# <pep8 compliant>
|
|
||||||
|
|
||||||
# Fit to match default projective camera with focal_length 50 and sensor_width 36.
|
|
||||||
default_fisheye_polynomial = [-1.1735143712967577e-05,
|
|
||||||
-0.019988736953434998,
|
|
||||||
-3.3525322965709175e-06,
|
|
||||||
3.099275275886036e-06,
|
|
||||||
-2.6064646454854524e-08]
|
|
||||||
|
|
||||||
# Utilities to generate lens polynomials to match built-in camera types, only here
|
|
||||||
# for reference at the moment, not used by the code.
|
|
||||||
def create_grid(sensor_height, sensor_width):
|
|
||||||
import numpy as np
|
|
||||||
if sensor_height is None:
|
|
||||||
sensor_height = sensor_width / (16 / 9) # Default aspect ration 16:9
|
|
||||||
uu, vv = np.meshgrid(np.linspace(0, 1, 100), np.linspace(0, 1, 100))
|
|
||||||
uu = (uu - 0.5) * sensor_width
|
|
||||||
vv = (vv - 0.5) * sensor_height
|
|
||||||
rr = np.sqrt(uu ** 2 + vv ** 2)
|
|
||||||
return rr
|
|
||||||
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_projective(focal_length=50, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
rr = create_grid(sensor_height, sensor_width)
|
|
||||||
polynomial = np.polyfit(rr.flat, (-np.arctan(rr / focal_length)).flat, 4)
|
|
||||||
return list(reversed(polynomial))
|
|
||||||
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_projective_fov(fov, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
f = sensor_width / 2 / np.tan(fov / 2)
|
|
||||||
return fisheye_lens_polynomial_from_projective(f, sensor_width, sensor_height)
|
|
||||||
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_equisolid(lens=10.5, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
rr = create_grid(sensor_height, sensor_width)
|
|
||||||
x = rr.reshape(-1)
|
|
||||||
x = np.stack([x**i for i in [1, 2, 3, 4]])
|
|
||||||
y = (-2 * np.arcsin(rr / (2 * lens))).reshape(-1)
|
|
||||||
polynomial = np.linalg.lstsq(x.T, y.T, rcond=None)[0]
|
|
||||||
return [0] + list(polynomial)
|
|
||||||
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_equidistant(fov=180, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
return [0, -np.radians(fov) / sensor_width, 0, 0, 0]
|
|
||||||
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_distorted_projective_polynomial(k1, k2, k3, focal_length=50, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
rr = create_grid(sensor_height, sensor_width)
|
|
||||||
r2 = (rr / focal_length) ** 2
|
|
||||||
r4 = r2 * r2
|
|
||||||
r6 = r4 * r2
|
|
||||||
r_coeff = 1 + k1 * r2 + k2 * r4 + k3 * r6
|
|
||||||
polynomial = np.polyfit(rr.flat, (-np.arctan(rr / focal_length * r_coeff)).flat, 4)
|
|
||||||
return list(reversed(polynomial))
|
|
||||||
|
|
||||||
def fisheye_lens_polynomial_from_distorted_projective_divisions(k1, k2, focal_length=50, sensor_width=36, sensor_height=None):
|
|
||||||
import numpy as np
|
|
||||||
rr = create_grid(sensor_height, sensor_width)
|
|
||||||
r2 = (rr / focal_length) ** 2
|
|
||||||
r4 = r2 * r2
|
|
||||||
r_coeff = 1 + k1 * r2 + k2 * r4
|
|
||||||
polynomial = np.polyfit(rr.flat, (-np.arctan(rr / focal_length / r_coeff)).flat, 4)
|
|
||||||
return list(reversed(polynomial))
|
|
@@ -28,7 +28,7 @@ def _configure_argument_parser():
|
|||||||
action='store_true')
|
action='store_true')
|
||||||
parser.add_argument("--cycles-device",
|
parser.add_argument("--cycles-device",
|
||||||
help="Set the device to use for Cycles, overriding user preferences and the scene setting."
|
help="Set the device to use for Cycles, overriding user preferences and the scene setting."
|
||||||
"Valid options are 'CPU', 'CUDA', 'OPTIX', 'HIP' or 'METAL'."
|
"Valid options are 'CPU', 'CUDA', 'OPTIX', or 'HIP'"
|
||||||
"Additionally, you can append '+CPU' to any GPU type for hybrid rendering.",
|
"Additionally, you can append '+CPU' to any GPU type for hybrid rendering.",
|
||||||
default=None)
|
default=None)
|
||||||
return parser
|
return parser
|
||||||
@@ -60,8 +60,9 @@ def init():
|
|||||||
|
|
||||||
path = os.path.dirname(__file__)
|
path = os.path.dirname(__file__)
|
||||||
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
|
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
|
||||||
|
temp_path = bpy.app.tempdir
|
||||||
|
|
||||||
_cycles.init(path, user_path, bpy.app.background)
|
_cycles.init(path, user_path, temp_path, bpy.app.background)
|
||||||
_parse_command_line()
|
_parse_command_line()
|
||||||
|
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@ from math import pi
|
|||||||
# enums
|
# enums
|
||||||
|
|
||||||
from . import engine
|
from . import engine
|
||||||
from . import camera
|
|
||||||
|
|
||||||
enum_devices = (
|
enum_devices = (
|
||||||
('CPU', "CPU", "Use CPU for rendering"),
|
('CPU', "CPU", "Use CPU for rendering"),
|
||||||
@@ -73,8 +72,6 @@ enum_panorama_types = (
|
|||||||
('FISHEYE_EQUISOLID', "Fisheye Equisolid",
|
('FISHEYE_EQUISOLID', "Fisheye Equisolid",
|
||||||
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
||||||
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
|
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
|
||||||
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
|
|
||||||
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked."),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
enum_curve_shape = (
|
enum_curve_shape = (
|
||||||
@@ -114,8 +111,7 @@ enum_device_type = (
|
|||||||
('CPU', "CPU", "CPU", 0),
|
('CPU', "CPU", "CPU", 0),
|
||||||
('CUDA', "CUDA", "CUDA", 1),
|
('CUDA', "CUDA", "CUDA", 1),
|
||||||
('OPTIX', "OptiX", "OptiX", 3),
|
('OPTIX', "OptiX", "OptiX", 3),
|
||||||
('HIP', "HIP", "HIP", 4),
|
("HIP", "HIP", "HIP", 4)
|
||||||
('METAL', "Metal", "Metal", 5)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
enum_texture_limit = (
|
enum_texture_limit = (
|
||||||
@@ -222,12 +218,6 @@ enum_denoising_prefilter = (
|
|||||||
('ACCURATE', "Accurate", "Prefilter noisy guiding passes before denoising color. Improves quality when guiding passes are noisy using extra processing time", 3),
|
('ACCURATE', "Accurate", "Prefilter noisy guiding passes before denoising color. Improves quality when guiding passes are noisy using extra processing time", 3),
|
||||||
)
|
)
|
||||||
|
|
||||||
enum_direct_light_sampling_type = (
|
|
||||||
('MULTIPLE_IMPORTANCE_SAMPLING', "Multiple Importance Sampling", "Multiple importance sampling is used to combine direct light contributions from next-event estimation and forward path tracing", 0),
|
|
||||||
('FORWARD_PATH_TRACING', "Forward Path Tracing", "Direct light contributions are only sampled using forward path tracing", 1),
|
|
||||||
('NEXT_EVENT_ESTIMATION', "Next-Event Estimation", "Direct light contributions are only sampled using next-event estimation", 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_render_passes(self, context):
|
def update_render_passes(self, context):
|
||||||
scene = context.scene
|
scene = context.scene
|
||||||
view_layer = context.view_layer
|
view_layer = context.view_layer
|
||||||
@@ -335,13 +325,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
default=1024,
|
default=1024,
|
||||||
)
|
)
|
||||||
|
|
||||||
sample_offset: IntProperty(
|
|
||||||
name="Sample Offset",
|
|
||||||
description="Number of samples to skip when starting render",
|
|
||||||
min=0, max=(1 << 24),
|
|
||||||
default=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
time_limit: FloatProperty(
|
time_limit: FloatProperty(
|
||||||
name="Time Limit",
|
name="Time Limit",
|
||||||
description="Limit the render time (excluding synchronization time)."
|
description="Limit the render time (excluding synchronization time)."
|
||||||
@@ -432,13 +415,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
direct_light_sampling_type: EnumProperty(
|
|
||||||
name="Direct Light Sampling",
|
|
||||||
description="The type of strategy used for sampling direct light contributions",
|
|
||||||
items=enum_direct_light_sampling_type,
|
|
||||||
default='MULTIPLE_IMPORTANCE_SAMPLING',
|
|
||||||
)
|
|
||||||
|
|
||||||
min_light_bounces: IntProperty(
|
min_light_bounces: IntProperty(
|
||||||
name="Min Light Bounces",
|
name="Min Light Bounces",
|
||||||
description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
|
description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
|
||||||
@@ -802,7 +778,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
name="Tile Size",
|
name="Tile Size",
|
||||||
default=2048,
|
default=2048,
|
||||||
description="",
|
description="",
|
||||||
min=8, max=8192,
|
min=8, max=16384,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Various fine-tuning debug flags
|
# Various fine-tuning debug flags
|
||||||
@@ -894,32 +870,6 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
|
|||||||
default=pi,
|
default=pi,
|
||||||
)
|
)
|
||||||
|
|
||||||
fisheye_polynomial_k0: FloatProperty(
|
|
||||||
name="Fisheye Polynomial K0",
|
|
||||||
description="Coefficient K0 of the lens polinomial",
|
|
||||||
default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE',
|
|
||||||
)
|
|
||||||
fisheye_polynomial_k1: FloatProperty(
|
|
||||||
name="Fisheye Polynomial K1",
|
|
||||||
description="Coefficient K1 of the lens polinomial",
|
|
||||||
default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE',
|
|
||||||
)
|
|
||||||
fisheye_polynomial_k2: FloatProperty(
|
|
||||||
name="Fisheye Polynomial K2",
|
|
||||||
description="Coefficient K2 of the lens polinomial",
|
|
||||||
default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE',
|
|
||||||
)
|
|
||||||
fisheye_polynomial_k3: FloatProperty(
|
|
||||||
name="Fisheye Polynomial K3",
|
|
||||||
description="Coefficient K3 of the lens polinomial",
|
|
||||||
default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE',
|
|
||||||
)
|
|
||||||
fisheye_polynomial_k4: FloatProperty(
|
|
||||||
name="Fisheye Polynomial K4",
|
|
||||||
description="Coefficient K4 of the lens polinomial",
|
|
||||||
default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE',
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.Camera.cycles = PointerProperty(
|
bpy.types.Camera.cycles = PointerProperty(
|
||||||
@@ -1342,7 +1292,8 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
|
|
||||||
def get_device_types(self, context):
|
def get_device_types(self, context):
|
||||||
import _cycles
|
import _cycles
|
||||||
has_cuda, has_optix, has_hip, has_metal = _cycles.get_device_types()
|
has_cuda, has_optix, has_hip = _cycles.get_device_types()
|
||||||
|
|
||||||
list = [('NONE', "None", "Don't use compute device", 0)]
|
list = [('NONE', "None", "Don't use compute device", 0)]
|
||||||
if has_cuda:
|
if has_cuda:
|
||||||
list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
|
list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
|
||||||
@@ -1350,8 +1301,6 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
list.append(('OPTIX', "OptiX", "Use OptiX for GPU acceleration", 3))
|
list.append(('OPTIX', "OptiX", "Use OptiX for GPU acceleration", 3))
|
||||||
if has_hip:
|
if has_hip:
|
||||||
list.append(('HIP', "HIP", "Use HIP for GPU acceleration", 4))
|
list.append(('HIP', "HIP", "Use HIP for GPU acceleration", 4))
|
||||||
if has_metal:
|
|
||||||
list.append(('METAL', "Metal", "Use Metal for GPU acceleration", 5))
|
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
@@ -1377,7 +1326,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
|
|
||||||
def update_device_entries(self, device_list):
|
def update_device_entries(self, device_list):
|
||||||
for device in device_list:
|
for device in device_list:
|
||||||
if not device[1] in {'CUDA', 'OPTIX', 'CPU', 'HIP', 'METAL'}:
|
if not device[1] in {'CUDA', 'OPTIX', 'CPU', 'HIP'}:
|
||||||
continue
|
continue
|
||||||
# Try to find existing Device entry
|
# Try to find existing Device entry
|
||||||
entry = self.find_existing_device_entry(device)
|
entry = self.find_existing_device_entry(device)
|
||||||
@@ -1421,7 +1370,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
import _cycles
|
import _cycles
|
||||||
# Ensure `self.devices` is not re-allocated when the second call to
|
# Ensure `self.devices` is not re-allocated when the second call to
|
||||||
# get_devices_for_type is made, freeing items from the first list.
|
# get_devices_for_type is made, freeing items from the first list.
|
||||||
for device_type in ('CUDA', 'OPTIX', 'HIP', 'METAL'):
|
for device_type in ('CUDA', 'OPTIX', 'HIP'):
|
||||||
self.update_device_entries(_cycles.available_devices(device_type))
|
self.update_device_entries(_cycles.available_devices(device_type))
|
||||||
|
|
||||||
# Deprecated: use refresh_devices instead.
|
# Deprecated: use refresh_devices instead.
|
||||||
@@ -1473,8 +1422,6 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
col.label(text="Requires discrete AMD GPU with RDNA architecture", icon='BLANK1')
|
col.label(text="Requires discrete AMD GPU with RDNA architecture", icon='BLANK1')
|
||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
||||||
elif device_type == 'METAL':
|
|
||||||
col.label(text="Requires Apple Silicon and macOS 12.0 or newer", icon='BLANK1')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
|
@@ -97,11 +97,6 @@ def use_cpu(context):
|
|||||||
return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
|
return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
|
||||||
|
|
||||||
|
|
||||||
def use_metal(context):
|
|
||||||
cscene = context.scene.cycles
|
|
||||||
|
|
||||||
return (get_device_type(context) == 'METAL' and cscene.device == 'GPU')
|
|
||||||
|
|
||||||
def use_cuda(context):
|
def use_cuda(context):
|
||||||
cscene = context.scene.cycles
|
cscene = context.scene.cycles
|
||||||
|
|
||||||
@@ -295,9 +290,6 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
|
|||||||
col.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
|
col.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
|
||||||
col.prop(cscene, "sampling_pattern", text="Pattern")
|
col.prop(cscene, "sampling_pattern", text="Pattern")
|
||||||
|
|
||||||
col = layout.column(align=True)
|
|
||||||
col.prop(cscene, "sample_offset")
|
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
heading = layout.column(align=True, heading="Scrambling Distance")
|
heading = layout.column(align=True, heading="Scrambling Distance")
|
||||||
@@ -1020,7 +1012,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
ob = context.object
|
ob = context.object
|
||||||
if CyclesButtonsPanel.poll(context) and ob:
|
if CyclesButtonsPanel.poll(context) and ob:
|
||||||
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'HAIR', 'POINTCLOUD'}:
|
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}:
|
||||||
return True
|
return True
|
||||||
if ob.instance_type == 'COLLECTION' and ob.instance_collection:
|
if ob.instance_type == 'COLLECTION' and ob.instance_collection:
|
||||||
return True
|
return True
|
||||||
@@ -1824,38 +1816,37 @@ class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.use_property_split = True
|
|
||||||
layout.use_property_decorate = False # No animation.
|
|
||||||
|
|
||||||
scene = context.scene
|
scene = context.scene
|
||||||
cscene = scene.cycles
|
cscene = scene.cycles
|
||||||
|
|
||||||
col = layout.column(heading="CPU")
|
col = layout.column()
|
||||||
|
|
||||||
|
col.label(text="CPU Flags:")
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
|
row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
|
||||||
row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
|
row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
|
||||||
row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
|
row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
|
||||||
row.prop(cscene, "debug_use_cpu_avx", toggle=True)
|
row.prop(cscene, "debug_use_cpu_avx", toggle=True)
|
||||||
row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
|
row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
|
||||||
col.prop(cscene, "debug_bvh_layout", text="BVH")
|
col.prop(cscene, "debug_bvh_layout")
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
col = layout.column(heading="CUDA")
|
col = layout.column()
|
||||||
|
col.label(text="CUDA Flags:")
|
||||||
col.prop(cscene, "debug_use_cuda_adaptive_compile")
|
col.prop(cscene, "debug_use_cuda_adaptive_compile")
|
||||||
col = layout.column(heading="OptiX")
|
|
||||||
col.prop(cscene, "debug_use_optix_debug", text="Module Debug")
|
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
col.prop(cscene, "debug_bvh_type", text="Viewport BVH")
|
col = layout.column()
|
||||||
|
col.label(text="OptiX Flags:")
|
||||||
|
col.prop(cscene, "debug_use_optix_debug")
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
import _cycles
|
col = layout.column()
|
||||||
if _cycles.with_debug:
|
col.prop(cscene, "debug_bvh_type")
|
||||||
col.prop(cscene, "direct_light_sampling_type")
|
|
||||||
|
|
||||||
|
|
||||||
class CYCLES_RENDER_PT_simplify(CyclesButtonsPanel, Panel):
|
class CYCLES_RENDER_PT_simplify(CyclesButtonsPanel, Panel):
|
||||||
|
@@ -69,12 +69,6 @@ struct BlenderCamera {
|
|||||||
float pole_merge_angle_from;
|
float pole_merge_angle_from;
|
||||||
float pole_merge_angle_to;
|
float pole_merge_angle_to;
|
||||||
|
|
||||||
float fisheye_polynomial_k0;
|
|
||||||
float fisheye_polynomial_k1;
|
|
||||||
float fisheye_polynomial_k2;
|
|
||||||
float fisheye_polynomial_k3;
|
|
||||||
float fisheye_polynomial_k4;
|
|
||||||
|
|
||||||
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
|
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
|
||||||
float sensor_width;
|
float sensor_width;
|
||||||
float sensor_height;
|
float sensor_height;
|
||||||
@@ -206,12 +200,6 @@ static void blender_camera_from_object(BlenderCamera *bcam,
|
|||||||
bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
|
bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
|
||||||
bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
|
bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
|
||||||
|
|
||||||
bcam->fisheye_polynomial_k0 = RNA_float_get(&ccamera, "fisheye_polynomial_k0");
|
|
||||||
bcam->fisheye_polynomial_k1 = RNA_float_get(&ccamera, "fisheye_polynomial_k1");
|
|
||||||
bcam->fisheye_polynomial_k2 = RNA_float_get(&ccamera, "fisheye_polynomial_k2");
|
|
||||||
bcam->fisheye_polynomial_k3 = RNA_float_get(&ccamera, "fisheye_polynomial_k3");
|
|
||||||
bcam->fisheye_polynomial_k4 = RNA_float_get(&ccamera, "fisheye_polynomial_k4");
|
|
||||||
|
|
||||||
bcam->interocular_distance = b_camera.stereo().interocular_distance();
|
bcam->interocular_distance = b_camera.stereo().interocular_distance();
|
||||||
if (b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) {
|
if (b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) {
|
||||||
bcam->convergence_distance = FLT_MAX;
|
bcam->convergence_distance = FLT_MAX;
|
||||||
@@ -434,8 +422,7 @@ static void blender_camera_sync(Camera *cam,
|
|||||||
cam->set_full_height(height);
|
cam->set_full_height(height);
|
||||||
|
|
||||||
/* panorama sensor */
|
/* panorama sensor */
|
||||||
if (bcam->type == CAMERA_PANORAMA && (bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID ||
|
if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
|
||||||
bcam->panorama_type == PANORAMA_FISHEYE_LENS_POLYNOMIAL)) {
|
|
||||||
float fit_xratio = (float)bcam->render_width * bcam->pixelaspect.x;
|
float fit_xratio = (float)bcam->render_width * bcam->pixelaspect.x;
|
||||||
float fit_yratio = (float)bcam->render_height * bcam->pixelaspect.y;
|
float fit_yratio = (float)bcam->render_height * bcam->pixelaspect.y;
|
||||||
bool horizontal_fit;
|
bool horizontal_fit;
|
||||||
@@ -478,12 +465,6 @@ static void blender_camera_sync(Camera *cam,
|
|||||||
cam->set_latitude_min(bcam->latitude_min);
|
cam->set_latitude_min(bcam->latitude_min);
|
||||||
cam->set_latitude_max(bcam->latitude_max);
|
cam->set_latitude_max(bcam->latitude_max);
|
||||||
|
|
||||||
cam->set_fisheye_polynomial_k0(bcam->fisheye_polynomial_k0);
|
|
||||||
cam->set_fisheye_polynomial_k1(bcam->fisheye_polynomial_k1);
|
|
||||||
cam->set_fisheye_polynomial_k2(bcam->fisheye_polynomial_k2);
|
|
||||||
cam->set_fisheye_polynomial_k3(bcam->fisheye_polynomial_k3);
|
|
||||||
cam->set_fisheye_polynomial_k4(bcam->fisheye_polynomial_k4);
|
|
||||||
|
|
||||||
cam->set_longitude_min(bcam->longitude_min);
|
cam->set_longitude_min(bcam->longitude_min);
|
||||||
cam->set_longitude_max(bcam->longitude_max);
|
cam->set_longitude_max(bcam->longitude_max);
|
||||||
|
|
||||||
|
@@ -199,7 +199,7 @@ static bool ObtainCacheParticleUV(Hair *hair,
|
|||||||
b_mesh->uv_layers.begin(l);
|
b_mesh->uv_layers.begin(l);
|
||||||
|
|
||||||
float2 uv = zero_float2();
|
float2 uv = zero_float2();
|
||||||
if (!b_mesh->uv_layers.empty())
|
if (b_mesh->uv_layers.length())
|
||||||
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
|
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
|
||||||
CData->curve_uv.push_back_slow(uv);
|
CData->curve_uv.push_back_slow(uv);
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ static bool ObtainCacheParticleVcol(Hair *hair,
|
|||||||
b_mesh->vertex_colors.begin(l);
|
b_mesh->vertex_colors.begin(l);
|
||||||
|
|
||||||
float4 vcol = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
|
float4 vcol = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
if (!b_mesh->vertex_colors.empty())
|
if (b_mesh->vertex_colors.length())
|
||||||
b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
|
b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
|
||||||
CData->curve_vcol.push_back_slow(vcol);
|
CData->curve_vcol.push_back_slow(vcol);
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@ enum ComputeDevice {
|
|||||||
COMPUTE_DEVICE_CUDA = 1,
|
COMPUTE_DEVICE_CUDA = 1,
|
||||||
COMPUTE_DEVICE_OPTIX = 3,
|
COMPUTE_DEVICE_OPTIX = 3,
|
||||||
COMPUTE_DEVICE_HIP = 4,
|
COMPUTE_DEVICE_HIP = 4,
|
||||||
COMPUTE_DEVICE_METAL = 5,
|
|
||||||
|
|
||||||
COMPUTE_DEVICE_NUM
|
COMPUTE_DEVICE_NUM
|
||||||
};
|
};
|
||||||
@@ -86,9 +85,6 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
|
|||||||
else if (compute_device == COMPUTE_DEVICE_HIP) {
|
else if (compute_device == COMPUTE_DEVICE_HIP) {
|
||||||
mask |= DEVICE_MASK_HIP;
|
mask |= DEVICE_MASK_HIP;
|
||||||
}
|
}
|
||||||
else if (compute_device == COMPUTE_DEVICE_METAL) {
|
|
||||||
mask |= DEVICE_MASK_METAL;
|
|
||||||
}
|
|
||||||
vector<DeviceInfo> devices = Device::available_devices(mask);
|
vector<DeviceInfo> devices = Device::available_devices(mask);
|
||||||
|
|
||||||
/* Match device preferences and available devices. */
|
/* Match device preferences and available devices. */
|
||||||
|
@@ -272,300 +272,12 @@ uint BlenderDisplaySpaceShader::get_shader_program()
|
|||||||
return shader_program_;
|
return shader_program_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
|
||||||
* DrawTile.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Higher level representation of a texture from the graphics library. */
|
|
||||||
class GLTexture {
|
|
||||||
public:
|
|
||||||
/* Global counter for all allocated OpenGL textures used by instances of this class. */
|
|
||||||
static inline std::atomic<int> num_used = 0;
|
|
||||||
|
|
||||||
GLTexture() = default;
|
|
||||||
|
|
||||||
~GLTexture()
|
|
||||||
{
|
|
||||||
assert(gl_id == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture(const GLTexture &other) = delete;
|
|
||||||
GLTexture &operator=(GLTexture &other) = delete;
|
|
||||||
|
|
||||||
GLTexture(GLTexture &&other) noexcept
|
|
||||||
: gl_id(other.gl_id), width(other.width), height(other.height)
|
|
||||||
{
|
|
||||||
other.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture &operator=(GLTexture &&other)
|
|
||||||
{
|
|
||||||
if (this == &other) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_id = other.gl_id;
|
|
||||||
width = other.width;
|
|
||||||
height = other.height;
|
|
||||||
|
|
||||||
other.reset();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gl_resources_ensure()
|
|
||||||
{
|
|
||||||
if (gl_id) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create texture. */
|
|
||||||
glGenTextures(1, &gl_id);
|
|
||||||
if (!gl_id) {
|
|
||||||
LOG(ERROR) << "Error creating texture.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the texture. */
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, gl_id);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
/* Clamp to edge so that precision issues when zoomed out (which forces linear interpolation)
|
|
||||||
* does not cause unwanted repetition. */
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
++num_used;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_resources_destroy()
|
|
||||||
{
|
|
||||||
if (!gl_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glDeleteTextures(1, &gl_id);
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
--num_used;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OpenGL resource IDs of the texture.
|
|
||||||
*
|
|
||||||
* NOTE: Allocated on the render engine's context. */
|
|
||||||
uint gl_id = 0;
|
|
||||||
|
|
||||||
/* Dimensions of the texture in pixels. */
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
gl_id = 0;
|
|
||||||
width = 0;
|
|
||||||
height = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
|
|
||||||
class GLPixelBufferObject {
|
|
||||||
public:
|
|
||||||
/* Global counter for all allocated OpenGL PBOs used by instances of this class. */
|
|
||||||
static inline std::atomic<int> num_used = 0;
|
|
||||||
|
|
||||||
GLPixelBufferObject() = default;
|
|
||||||
|
|
||||||
~GLPixelBufferObject()
|
|
||||||
{
|
|
||||||
assert(gl_id == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLPixelBufferObject(const GLPixelBufferObject &other) = delete;
|
|
||||||
GLPixelBufferObject &operator=(GLPixelBufferObject &other) = delete;
|
|
||||||
|
|
||||||
GLPixelBufferObject(GLPixelBufferObject &&other) noexcept
|
|
||||||
: gl_id(other.gl_id), width(other.width), height(other.height)
|
|
||||||
{
|
|
||||||
other.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLPixelBufferObject &operator=(GLPixelBufferObject &&other)
|
|
||||||
{
|
|
||||||
if (this == &other) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_id = other.gl_id;
|
|
||||||
width = other.width;
|
|
||||||
height = other.height;
|
|
||||||
|
|
||||||
other.reset();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gl_resources_ensure()
|
|
||||||
{
|
|
||||||
if (gl_id) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenBuffers(1, &gl_id);
|
|
||||||
if (!gl_id) {
|
|
||||||
LOG(ERROR) << "Error creating texture pixel buffer object.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
++num_used;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_resources_destroy()
|
|
||||||
{
|
|
||||||
if (!gl_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glDeleteBuffers(1, &gl_id);
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
--num_used;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OpenGL resource IDs of the PBO.
|
|
||||||
*
|
|
||||||
* NOTE: Allocated on the render engine's context. */
|
|
||||||
uint gl_id = 0;
|
|
||||||
|
|
||||||
/* Dimensions of the PBO. */
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
gl_id = 0;
|
|
||||||
width = 0;
|
|
||||||
height = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DrawTile {
|
|
||||||
public:
|
|
||||||
DrawTile() = default;
|
|
||||||
~DrawTile() = default;
|
|
||||||
|
|
||||||
DrawTile(const DrawTile &other) = delete;
|
|
||||||
DrawTile &operator=(const DrawTile &other) = delete;
|
|
||||||
|
|
||||||
DrawTile(DrawTile &&other) noexcept = default;
|
|
||||||
|
|
||||||
DrawTile &operator=(DrawTile &&other) = default;
|
|
||||||
|
|
||||||
bool gl_resources_ensure()
|
|
||||||
{
|
|
||||||
if (!texture.gl_resources_ensure()) {
|
|
||||||
gl_resources_destroy();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gl_vertex_buffer) {
|
|
||||||
glGenBuffers(1, &gl_vertex_buffer);
|
|
||||||
if (!gl_vertex_buffer) {
|
|
||||||
LOG(ERROR) << "Error allocating tile VBO.";
|
|
||||||
gl_resources_destroy();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_resources_destroy()
|
|
||||||
{
|
|
||||||
texture.gl_resources_destroy();
|
|
||||||
|
|
||||||
if (gl_vertex_buffer) {
|
|
||||||
glDeleteBuffers(1, &gl_vertex_buffer);
|
|
||||||
gl_vertex_buffer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ready_to_draw() const
|
|
||||||
{
|
|
||||||
return texture.gl_id != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Texture which contains pixels of the tile. */
|
|
||||||
GLTexture texture;
|
|
||||||
|
|
||||||
/* Display parameters the texture of this tile has been updated for. */
|
|
||||||
BlenderDisplayDriver::Params params;
|
|
||||||
|
|
||||||
/* OpenGL resources needed for drawing. */
|
|
||||||
uint gl_vertex_buffer = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DrawTileAndPBO {
|
|
||||||
public:
|
|
||||||
bool gl_resources_ensure()
|
|
||||||
{
|
|
||||||
if (!tile.gl_resources_ensure() || !buffer_object.gl_resources_ensure()) {
|
|
||||||
gl_resources_destroy();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gl_resources_destroy()
|
|
||||||
{
|
|
||||||
tile.gl_resources_destroy();
|
|
||||||
buffer_object.gl_resources_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawTile tile;
|
|
||||||
GLPixelBufferObject buffer_object;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* BlenderDisplayDriver.
|
* BlenderDisplayDriver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct BlenderDisplayDriver::Tiles {
|
|
||||||
/* Resources of a tile which is being currently rendered. */
|
|
||||||
DrawTileAndPBO current_tile;
|
|
||||||
|
|
||||||
/* All tiles which rendering is finished and which content will not be changed. */
|
|
||||||
struct {
|
|
||||||
vector<DrawTile> tiles;
|
|
||||||
|
|
||||||
void gl_resources_destroy_and_clear()
|
|
||||||
{
|
|
||||||
for (DrawTile &tile : tiles) {
|
|
||||||
tile.gl_resources_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
tiles.clear();
|
|
||||||
}
|
|
||||||
} finished_tiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene)
|
BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene)
|
||||||
: b_engine_(b_engine),
|
: b_engine_(b_engine), display_shader_(BlenderDisplayShader::create(b_engine, b_scene))
|
||||||
display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
|
|
||||||
tiles_(make_unique<Tiles>())
|
|
||||||
{
|
{
|
||||||
/* Create context while on the main thread. */
|
/* Create context while on the main thread. */
|
||||||
gl_context_create();
|
gl_context_create();
|
||||||
@@ -580,21 +292,6 @@ BlenderDisplayDriver::~BlenderDisplayDriver()
|
|||||||
* Update procedure.
|
* Update procedure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void BlenderDisplayDriver::next_tile_begin()
|
|
||||||
{
|
|
||||||
if (!tiles_->current_tile.tile.ready_to_draw()) {
|
|
||||||
LOG(ERROR)
|
|
||||||
<< "Unexpectedly moving to the next tile without any data provided for current tile.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Moving to the next tile without giving render data for the current tile is not an expected
|
|
||||||
* situation. */
|
|
||||||
DCHECK(!need_clear_);
|
|
||||||
|
|
||||||
tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
||||||
int texture_width,
|
int texture_width,
|
||||||
int texture_height)
|
int texture_height)
|
||||||
@@ -615,96 +312,58 @@ bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
|||||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTile ¤t_tile = tiles_->current_tile.tile;
|
if (!gl_texture_resources_ensure()) {
|
||||||
GLPixelBufferObject ¤t_tile_buffer_object = tiles_->current_tile.buffer_object;
|
|
||||||
|
|
||||||
/* Clear storage of all finished tiles when display clear is requested.
|
|
||||||
* Do it when new tile data is provided to handle the display clear flag in a single place.
|
|
||||||
* It also makes the logic reliable from the whether drawing did happen or not point of view. */
|
|
||||||
if (need_clear_) {
|
|
||||||
tiles_->finished_tiles.gl_resources_destroy_and_clear();
|
|
||||||
need_clear_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tiles_->current_tile.gl_resources_ensure()) {
|
|
||||||
tiles_->current_tile.gl_resources_destroy();
|
|
||||||
gl_context_disable();
|
gl_context_disable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update texture dimensions if needed. */
|
/* Update texture dimensions if needed. */
|
||||||
if (current_tile.texture.width != texture_width ||
|
if (texture_.width != texture_width || texture_.height != texture_height) {
|
||||||
current_tile.texture.height != texture_height) {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, current_tile.texture.gl_id);
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
glTexImage2D(
|
glTexImage2D(
|
||||||
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
current_tile.texture.width = texture_width;
|
texture_.width = texture_width;
|
||||||
current_tile.texture.height = texture_height;
|
texture_.height = texture_height;
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
/* Texture did change, and no pixel storage was provided. Tag for an explicit zeroing out to
|
||||||
|
* avoid undefined content. */
|
||||||
|
texture_.need_clear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update PBO dimensions if needed.
|
/* Update PBO dimensions if needed.
|
||||||
*
|
*
|
||||||
* NOTE: Allocate the PBO for the size which will fit the final render resolution (as in,
|
* NOTE: Allocate the PBO for the the size which will fit the final render resolution (as in,
|
||||||
* at a resolution divider 1. This was we don't need to recreate graphics interoperability
|
* at a resolution divider 1. This was we don't need to recreate graphics interoperability
|
||||||
* objects which are costly and which are tied to the specific underlying buffer size.
|
* objects which are costly and which are tied to the specific underlying buffer size.
|
||||||
* The downside of this approach is that when graphics interoperability is not used we are
|
* The downside of this approach is that when graphics interoperability is not used we are
|
||||||
* sending too much data to GPU when resolution divider is not 1. */
|
* sending too much data to GPU when resolution divider is not 1. */
|
||||||
/* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
|
/* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
|
||||||
* mode faster. */
|
* mode faster. */
|
||||||
const int buffer_width = params.size.x;
|
const int buffer_width = params.full_size.x;
|
||||||
const int buffer_height = params.size.y;
|
const int buffer_height = params.full_size.y;
|
||||||
if (current_tile_buffer_object.width != buffer_width ||
|
if (texture_.buffer_width != buffer_width || texture_.buffer_height != buffer_height) {
|
||||||
current_tile_buffer_object.height != buffer_height) {
|
|
||||||
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
|
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, current_tile_buffer_object.gl_id);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
current_tile_buffer_object.width = buffer_width;
|
texture_.buffer_width = buffer_width;
|
||||||
current_tile_buffer_object.height = buffer_height;
|
texture_.buffer_height = buffer_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store an updated parameters of the current tile.
|
/* New content will be provided to the texture in one way or another, so mark this in a
|
||||||
* In theory it is only needed once per update of the tile, but doing it on every update is
|
* centralized place. */
|
||||||
* the easiest and is not expensive. */
|
texture_.need_update = true;
|
||||||
tiles_->current_tile.tile.params = params;
|
|
||||||
|
texture_.params = params;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
|
|
||||||
{
|
|
||||||
const GLTexture &texture = tile.tile.texture;
|
|
||||||
|
|
||||||
DCHECK_NE(tile.buffer_object.gl_id, 0);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tile.buffer_object.gl_id);
|
|
||||||
|
|
||||||
glTexSubImage2D(
|
|
||||||
GL_TEXTURE_2D, 0, 0, 0, texture.width, texture.height, GL_RGBA, GL_HALF_FLOAT, 0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::update_end()
|
void BlenderDisplayDriver::update_end()
|
||||||
{
|
{
|
||||||
/* Unpack the PBO into the texture as soon as the new content is provided.
|
|
||||||
*
|
|
||||||
* This allows to ensure that the unpacking happens while resources like graphics interop (which
|
|
||||||
* lifetime is outside of control of the display driver) are still valid, as well as allows to
|
|
||||||
* move the tile from being current to finished immediately after this call.
|
|
||||||
*
|
|
||||||
* One concern with this approach is that if the update happens more often than drawing then
|
|
||||||
* doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
|
|
||||||
* takes care of ensuring updates don't happen that often. In regular applications redraw will
|
|
||||||
* happen much more often than this update. */
|
|
||||||
update_tile_texture_pixels(tiles_->current_tile);
|
|
||||||
|
|
||||||
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
@@ -717,11 +376,7 @@ void BlenderDisplayDriver::update_end()
|
|||||||
|
|
||||||
half4 *BlenderDisplayDriver::map_texture_buffer()
|
half4 *BlenderDisplayDriver::map_texture_buffer()
|
||||||
{
|
{
|
||||||
const uint pbo_gl_id = tiles_->current_tile.buffer_object.gl_id;
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
|
|
||||||
DCHECK_NE(pbo_gl_id, 0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_gl_id);
|
|
||||||
|
|
||||||
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
|
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
|
||||||
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
||||||
@@ -729,6 +384,15 @@ half4 *BlenderDisplayDriver::map_texture_buffer()
|
|||||||
LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
|
LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture_.need_clear) {
|
||||||
|
const int64_t texture_width = texture_.width;
|
||||||
|
const int64_t texture_height = texture_.height;
|
||||||
|
memset(reinterpret_cast<void *>(mapped_rgba_pixels),
|
||||||
|
0,
|
||||||
|
texture_width * texture_height * sizeof(half4));
|
||||||
|
texture_.need_clear = false;
|
||||||
|
}
|
||||||
|
|
||||||
return mapped_rgba_pixels;
|
return mapped_rgba_pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,9 +411,12 @@ BlenderDisplayDriver::GraphicsInterop BlenderDisplayDriver::graphics_interop_get
|
|||||||
{
|
{
|
||||||
GraphicsInterop interop_dst;
|
GraphicsInterop interop_dst;
|
||||||
|
|
||||||
interop_dst.buffer_width = tiles_->current_tile.buffer_object.width;
|
interop_dst.buffer_width = texture_.buffer_width;
|
||||||
interop_dst.buffer_height = tiles_->current_tile.buffer_object.height;
|
interop_dst.buffer_height = texture_.buffer_height;
|
||||||
interop_dst.opengl_pbo_id = tiles_->current_tile.buffer_object.gl_id;
|
interop_dst.opengl_pbo_id = texture_.gl_pbo_id;
|
||||||
|
|
||||||
|
interop_dst.need_clear = texture_.need_clear;
|
||||||
|
texture_.need_clear = false;
|
||||||
|
|
||||||
return interop_dst;
|
return interop_dst;
|
||||||
}
|
}
|
||||||
@@ -770,7 +437,7 @@ void BlenderDisplayDriver::graphics_interop_deactivate()
|
|||||||
|
|
||||||
void BlenderDisplayDriver::clear()
|
void BlenderDisplayDriver::clear()
|
||||||
{
|
{
|
||||||
need_clear_ = true;
|
texture_.need_clear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
||||||
@@ -778,155 +445,26 @@ void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
|||||||
zoom_ = make_float2(zoom_x, zoom_y);
|
zoom_ = make_float2(zoom_x, zoom_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
|
|
||||||
* This buffer is used to render texture in the viewport.
|
|
||||||
*
|
|
||||||
* NOTE: The buffer needs to be bound. */
|
|
||||||
static void vertex_buffer_update(const DisplayDriver::Params ¶ms)
|
|
||||||
{
|
|
||||||
const int x = params.full_offset.x;
|
|
||||||
const int y = params.full_offset.y;
|
|
||||||
|
|
||||||
const int width = params.size.x;
|
|
||||||
const int height = params.size.y;
|
|
||||||
|
|
||||||
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
|
|
||||||
* rendered. */
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
|
||||||
if (!vpointer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpointer[0] = 0.0f;
|
|
||||||
vpointer[1] = 0.0f;
|
|
||||||
vpointer[2] = x;
|
|
||||||
vpointer[3] = y;
|
|
||||||
|
|
||||||
vpointer[4] = 1.0f;
|
|
||||||
vpointer[5] = 0.0f;
|
|
||||||
vpointer[6] = x + width;
|
|
||||||
vpointer[7] = y;
|
|
||||||
|
|
||||||
vpointer[8] = 1.0f;
|
|
||||||
vpointer[9] = 1.0f;
|
|
||||||
vpointer[10] = x + width;
|
|
||||||
vpointer[11] = y + height;
|
|
||||||
|
|
||||||
vpointer[12] = 0.0f;
|
|
||||||
vpointer[13] = 1.0f;
|
|
||||||
vpointer[14] = x;
|
|
||||||
vpointer[15] = y + height;
|
|
||||||
|
|
||||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_tile(const float2 &zoom,
|
|
||||||
const int texcoord_attribute,
|
|
||||||
const int position_attribute,
|
|
||||||
const DrawTile &draw_tile)
|
|
||||||
{
|
|
||||||
if (!draw_tile.ready_to_draw()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GLTexture &texture = draw_tile.texture;
|
|
||||||
|
|
||||||
DCHECK_NE(texture.gl_id, 0);
|
|
||||||
DCHECK_NE(draw_tile.gl_vertex_buffer, 0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, draw_tile.gl_vertex_buffer);
|
|
||||||
|
|
||||||
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
|
|
||||||
* texture during bordered-rendered camera view without flickering. The validness of the display
|
|
||||||
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
|
|
||||||
* have an early output.
|
|
||||||
*
|
|
||||||
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
|
|
||||||
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
|
|
||||||
* the texture draw parameters and the latest updated draw parameters (although, complexity of
|
|
||||||
* doing it might not worth it. */
|
|
||||||
vertex_buffer_update(draw_tile.params);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
|
|
||||||
|
|
||||||
/* Trick to keep sharp rendering without jagged edges on all GPUs.
|
|
||||||
*
|
|
||||||
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
|
|
||||||
* in.
|
|
||||||
* For the render result with a resolution divider in effect we always use nearest interpolation.
|
|
||||||
*
|
|
||||||
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
|
|
||||||
* the zoom level 1. The MAG filter is always NEAREST. */
|
|
||||||
const float zoomed_width = draw_tile.params.size.x * zoom.x;
|
|
||||||
const float zoomed_height = draw_tile.params.size.y * zoom.y;
|
|
||||||
if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
|
|
||||||
/* Resolution divider is different from 1, force nearest interpolation. */
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
else if (zoomed_width - draw_tile.params.size.x > 0.5f ||
|
|
||||||
zoomed_height - draw_tile.params.size.y > 0.5f) {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
glVertexAttribPointer(
|
|
||||||
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
|
|
||||||
glVertexAttribPointer(position_attribute,
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
4 * sizeof(float),
|
|
||||||
(const GLvoid *)(sizeof(float) * 2));
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::flush()
|
|
||||||
{
|
|
||||||
/* This is called from the render thread that also calls update_begin/end, right before ending
|
|
||||||
* the render loop. We wait for any queued PBO and render commands to be done, before destroying
|
|
||||||
* the render thread and activating the context in the main thread to destroy resources.
|
|
||||||
*
|
|
||||||
* If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
|
|
||||||
* rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
|
|
||||||
* RTX 6000 on Linux. */
|
|
||||||
if (!gl_context_enable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gl_upload_sync_) {
|
|
||||||
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gl_render_sync_) {
|
|
||||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_context_disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::draw(const Params ¶ms)
|
void BlenderDisplayDriver::draw(const Params ¶ms)
|
||||||
{
|
{
|
||||||
/* See do_update_begin() for why no locking is required here. */
|
/* See do_update_begin() for why no locking is required here. */
|
||||||
const bool transparent = true; // TODO(sergey): Derive this from Film.
|
const bool transparent = true; // TODO(sergey): Derive this from Film.
|
||||||
|
|
||||||
|
if (!gl_draw_resources_ensure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_gl_context_) {
|
if (use_gl_context_) {
|
||||||
gl_context_mutex_.lock();
|
gl_context_mutex_.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_clear_) {
|
if (texture_.need_clear) {
|
||||||
/* Texture is requested to be cleared and was not yet cleared.
|
/* Texture is requested to be cleared and was not yet cleared.
|
||||||
*
|
*
|
||||||
* Do early return which should be equivalent of drawing all-zero texture.
|
* Do early return which should be equivalent of drawing all-zero texture.
|
||||||
* Watch out for the lock though so that the clear happening during update is properly
|
* Watch out for the lock though so that the clear happening during update is properly
|
||||||
* synchronized here. */
|
* synchronized here. */
|
||||||
if (use_gl_context_) {
|
gl_context_mutex_.unlock();
|
||||||
gl_context_mutex_.unlock();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -939,37 +477,66 @@ void BlenderDisplayDriver::draw(const Params ¶ms)
|
|||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
display_shader_->bind(params.full_size.x, params.full_size.y);
|
||||||
|
|
||||||
/* NOTE: The VAO is to be allocated on the drawing context as it is not shared across contexts.
|
glActiveTexture(GL_TEXTURE0);
|
||||||
* Simplest is to allocate it on every redraw so that it is possible to destroy it from a
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
* correct context. */
|
|
||||||
|
/* Trick to keep sharp rendering without jagged edges on all GPUs.
|
||||||
|
*
|
||||||
|
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
|
||||||
|
* in.
|
||||||
|
* For the render result with a resolution divider in effect we always use nearest interpolation.
|
||||||
|
*
|
||||||
|
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
|
||||||
|
* the zoom level 1. The MAG filter is always NEAREST. */
|
||||||
|
const float zoomed_width = params.size.x * zoom_.x;
|
||||||
|
const float zoomed_height = params.size.y * zoom_.y;
|
||||||
|
if (texture_.width != params.size.x || texture_.height != params.size.y) {
|
||||||
|
/* Resolution divider is different from 1, force nearest interpolation. */
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else if (zoomed_width - params.size.x > 0.5f || zoomed_height - params.size.y > 0.5f) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
|
||||||
|
|
||||||
|
texture_update_if_needed();
|
||||||
|
vertex_buffer_update(params);
|
||||||
|
|
||||||
|
/* TODO(sergey): Does it make sense/possible to cache/reuse the VAO? */
|
||||||
GLuint vertex_array_object;
|
GLuint vertex_array_object;
|
||||||
glGenVertexArrays(1, &vertex_array_object);
|
glGenVertexArrays(1, &vertex_array_object);
|
||||||
glBindVertexArray(vertex_array_object);
|
glBindVertexArray(vertex_array_object);
|
||||||
|
|
||||||
display_shader_->bind(params.full_size.x, params.full_size.y);
|
|
||||||
|
|
||||||
const int texcoord_attribute = display_shader_->get_tex_coord_attrib_location();
|
const int texcoord_attribute = display_shader_->get_tex_coord_attrib_location();
|
||||||
const int position_attribute = display_shader_->get_position_attrib_location();
|
const int position_attribute = display_shader_->get_position_attrib_location();
|
||||||
|
|
||||||
glEnableVertexAttribArray(texcoord_attribute);
|
glEnableVertexAttribArray(texcoord_attribute);
|
||||||
glEnableVertexAttribArray(position_attribute);
|
glEnableVertexAttribArray(position_attribute);
|
||||||
|
|
||||||
draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
|
glVertexAttribPointer(
|
||||||
|
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
|
||||||
|
glVertexAttribPointer(position_attribute,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
4 * sizeof(float),
|
||||||
|
(const GLvoid *)(sizeof(float) * 2));
|
||||||
|
|
||||||
for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
draw_tile(zoom_, texcoord_attribute, position_attribute, tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
display_shader_->unbind();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
glDeleteVertexArrays(1, &vertex_array_object);
|
glDeleteVertexArrays(1, &vertex_array_object);
|
||||||
|
|
||||||
|
display_shader_->unbind();
|
||||||
|
|
||||||
if (transparent) {
|
if (transparent) {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
@@ -977,11 +544,6 @@ void BlenderDisplayDriver::draw(const Params ¶ms)
|
|||||||
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
if (VLOG_IS_ON(5)) {
|
|
||||||
VLOG(5) << "Number of textures: " << GLTexture::num_used;
|
|
||||||
VLOG(5) << "Number of PBOs: " << GLPixelBufferObject::num_used;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_gl_context_) {
|
if (use_gl_context_) {
|
||||||
gl_context_mutex_.unlock();
|
gl_context_mutex_.unlock();
|
||||||
}
|
}
|
||||||
@@ -1056,16 +618,154 @@ void BlenderDisplayDriver::gl_context_dispose()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlenderDisplayDriver::gl_draw_resources_ensure()
|
||||||
|
{
|
||||||
|
if (!texture_.gl_id) {
|
||||||
|
/* If there is no texture allocated, there is nothing to draw. Inform the draw call that it can
|
||||||
|
* can not continue. Note that this is not an unrecoverable error, so once the texture is known
|
||||||
|
* we will come back here and create all the GPU resources needed for draw. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_draw_resource_creation_attempted_) {
|
||||||
|
return gl_draw_resources_created_;
|
||||||
|
}
|
||||||
|
gl_draw_resource_creation_attempted_ = true;
|
||||||
|
|
||||||
|
if (!vertex_buffer_) {
|
||||||
|
glGenBuffers(1, &vertex_buffer_);
|
||||||
|
if (!vertex_buffer_) {
|
||||||
|
LOG(ERROR) << "Error creating vertex buffer.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_draw_resources_created_ = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void BlenderDisplayDriver::gl_resources_destroy()
|
void BlenderDisplayDriver::gl_resources_destroy()
|
||||||
{
|
{
|
||||||
gl_context_enable();
|
gl_context_enable();
|
||||||
|
|
||||||
tiles_->current_tile.gl_resources_destroy();
|
if (vertex_buffer_ != 0) {
|
||||||
tiles_->finished_tiles.gl_resources_destroy_and_clear();
|
glDeleteBuffers(1, &vertex_buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_.gl_pbo_id) {
|
||||||
|
glDeleteBuffers(1, &texture_.gl_pbo_id);
|
||||||
|
texture_.gl_pbo_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_.gl_id) {
|
||||||
|
glDeleteTextures(1, &texture_.gl_id);
|
||||||
|
texture_.gl_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
gl_context_disable();
|
gl_context_disable();
|
||||||
|
|
||||||
gl_context_dispose();
|
gl_context_dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlenderDisplayDriver::gl_texture_resources_ensure()
|
||||||
|
{
|
||||||
|
if (texture_.creation_attempted) {
|
||||||
|
return texture_.is_created;
|
||||||
|
}
|
||||||
|
texture_.creation_attempted = true;
|
||||||
|
|
||||||
|
DCHECK(!texture_.gl_id);
|
||||||
|
DCHECK(!texture_.gl_pbo_id);
|
||||||
|
|
||||||
|
/* Create texture. */
|
||||||
|
glGenTextures(1, &texture_.gl_id);
|
||||||
|
if (!texture_.gl_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the texture. */
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
/* Create PBO for the texture. */
|
||||||
|
glGenBuffers(1, &texture_.gl_pbo_id);
|
||||||
|
if (!texture_.gl_pbo_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture pixel buffer object.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creation finished with a success. */
|
||||||
|
texture_.is_created = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlenderDisplayDriver::texture_update_if_needed()
|
||||||
|
{
|
||||||
|
if (!texture_.need_update) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
|
glTexSubImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, 0, 0, texture_.width, texture_.height, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
texture_.need_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlenderDisplayDriver::vertex_buffer_update(const Params & /*params*/)
|
||||||
|
{
|
||||||
|
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
|
||||||
|
* texture during bordered-rendered camera view without flickering. The validness of the display
|
||||||
|
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
|
||||||
|
* have an early output.
|
||||||
|
*
|
||||||
|
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
|
||||||
|
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
|
||||||
|
* the texture draw parameters and the latest updated draw parameters (although, complexity of
|
||||||
|
* doing it might not worth it. */
|
||||||
|
const int x = texture_.params.full_offset.x;
|
||||||
|
const int y = texture_.params.full_offset.y;
|
||||||
|
|
||||||
|
const int width = texture_.params.size.x;
|
||||||
|
const int height = texture_.params.size.y;
|
||||||
|
|
||||||
|
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
|
||||||
|
* rendered. */
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
||||||
|
if (!vpointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpointer[0] = 0.0f;
|
||||||
|
vpointer[1] = 0.0f;
|
||||||
|
vpointer[2] = x;
|
||||||
|
vpointer[3] = y;
|
||||||
|
|
||||||
|
vpointer[4] = 1.0f;
|
||||||
|
vpointer[5] = 0.0f;
|
||||||
|
vpointer[6] = x + width;
|
||||||
|
vpointer[7] = y;
|
||||||
|
|
||||||
|
vpointer[8] = 1.0f;
|
||||||
|
vpointer[9] = 1.0f;
|
||||||
|
vpointer[10] = x + width;
|
||||||
|
vpointer[11] = y + height;
|
||||||
|
|
||||||
|
vpointer[12] = 0.0f;
|
||||||
|
vpointer[13] = 1.0f;
|
||||||
|
vpointer[14] = x;
|
||||||
|
vpointer[15] = y + height;
|
||||||
|
|
||||||
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/unique_ptr.h"
|
#include "util/unique_ptr.h"
|
||||||
#include "util/vector.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@@ -113,8 +112,6 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
void set_zoom(float zoom_x, float zoom_y);
|
void set_zoom(float zoom_x, float zoom_y);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void next_tile_begin() override;
|
|
||||||
|
|
||||||
virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||||
virtual void update_end() override;
|
virtual void update_end() override;
|
||||||
|
|
||||||
@@ -125,17 +122,33 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
|
|
||||||
virtual void draw(const Params ¶ms) override;
|
virtual void draw(const Params ¶ms) override;
|
||||||
|
|
||||||
virtual void flush() override;
|
|
||||||
|
|
||||||
/* Helper function which allocates new GPU context. */
|
/* Helper function which allocates new GPU context. */
|
||||||
void gl_context_create();
|
void gl_context_create();
|
||||||
bool gl_context_enable();
|
bool gl_context_enable();
|
||||||
void gl_context_disable();
|
void gl_context_disable();
|
||||||
void gl_context_dispose();
|
void gl_context_dispose();
|
||||||
|
|
||||||
|
/* Make sure texture is allocated and its initial configuration is performed. */
|
||||||
|
bool gl_texture_resources_ensure();
|
||||||
|
|
||||||
|
/* Ensure all runtime GPU resources needed for drawing are allocated.
|
||||||
|
* Returns true if all resources needed for drawing are available. */
|
||||||
|
bool gl_draw_resources_ensure();
|
||||||
|
|
||||||
/* Destroy all GPU resources which are being used by this object. */
|
/* Destroy all GPU resources which are being used by this object. */
|
||||||
void gl_resources_destroy();
|
void gl_resources_destroy();
|
||||||
|
|
||||||
|
/* Update GPU texture dimensions and content if needed (new pixel data was provided).
|
||||||
|
*
|
||||||
|
* NOTE: The texture needs to be bound. */
|
||||||
|
void texture_update_if_needed();
|
||||||
|
|
||||||
|
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
|
||||||
|
* This buffer is used to render texture in the viewport.
|
||||||
|
*
|
||||||
|
* NOTE: The buffer needs to be bound. */
|
||||||
|
void vertex_buffer_update(const Params ¶ms);
|
||||||
|
|
||||||
BL::RenderEngine b_engine_;
|
BL::RenderEngine b_engine_;
|
||||||
|
|
||||||
/* OpenGL context which is used the render engine doesn't have its own. */
|
/* OpenGL context which is used the render engine doesn't have its own. */
|
||||||
@@ -146,14 +159,50 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
/* Mutex used to guard the `gl_context_`. */
|
/* Mutex used to guard the `gl_context_`. */
|
||||||
thread_mutex gl_context_mutex_;
|
thread_mutex gl_context_mutex_;
|
||||||
|
|
||||||
/* Content of the display is to be filled with zeroes. */
|
/* Texture which contains pixels of the render result. */
|
||||||
std::atomic<bool> need_clear_ = true;
|
struct {
|
||||||
|
/* Indicates whether texture creation was attempted and succeeded.
|
||||||
|
* Used to avoid multiple attempts of texture creation on GPU issues or GPU context
|
||||||
|
* misconfiguration. */
|
||||||
|
bool creation_attempted = false;
|
||||||
|
bool is_created = false;
|
||||||
|
|
||||||
|
/* OpenGL resource IDs of the texture itself and Pixel Buffer Object (PBO) used to write
|
||||||
|
* pixels to it.
|
||||||
|
*
|
||||||
|
* NOTE: Allocated on the engine's context. */
|
||||||
|
uint gl_id = 0;
|
||||||
|
uint gl_pbo_id = 0;
|
||||||
|
|
||||||
|
/* Is true when new data was written to the PBO, meaning, the texture might need to be resized
|
||||||
|
* and new data is to be uploaded to the GPU. */
|
||||||
|
bool need_update = false;
|
||||||
|
|
||||||
|
/* Content of the texture is to be filled with zeroes. */
|
||||||
|
std::atomic<bool> need_clear = true;
|
||||||
|
|
||||||
|
/* Dimensions of the texture in pixels. */
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
/* Dimensions of the underlying PBO. */
|
||||||
|
int buffer_width = 0;
|
||||||
|
int buffer_height = 0;
|
||||||
|
|
||||||
|
/* Display parameters the texture has been updated for. */
|
||||||
|
Params params;
|
||||||
|
} texture_;
|
||||||
|
|
||||||
unique_ptr<BlenderDisplayShader> display_shader_;
|
unique_ptr<BlenderDisplayShader> display_shader_;
|
||||||
|
|
||||||
/* Opaque storage for an internal state and data for tiles. */
|
/* Special track of whether GPU resources were attempted to be created, to avoid attempts of
|
||||||
struct Tiles;
|
* their re-creation on failure on every redraw. */
|
||||||
unique_ptr<Tiles> tiles_;
|
bool gl_draw_resource_creation_attempted_ = false;
|
||||||
|
bool gl_draw_resources_created_ = false;
|
||||||
|
|
||||||
|
/* Vertex buffer which hold vertices of a triangle fan which is textures with the texture
|
||||||
|
* holding the render result. */
|
||||||
|
uint vertex_buffer_ = 0;
|
||||||
|
|
||||||
void *gl_render_sync_ = nullptr;
|
void *gl_render_sync_ = nullptr;
|
||||||
void *gl_upload_sync_ = nullptr;
|
void *gl_upload_sync_ = nullptr;
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
#include "scene/hair.h"
|
#include "scene/hair.h"
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
#include "scene/object.h"
|
#include "scene/object.h"
|
||||||
#include "scene/pointcloud.h"
|
|
||||||
#include "scene/volume.h"
|
#include "scene/volume.h"
|
||||||
|
|
||||||
#include "blender/sync.h"
|
#include "blender/sync.h"
|
||||||
@@ -40,10 +39,6 @@ static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_parti
|
|||||||
return Geometry::HAIR;
|
return Geometry::HAIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b_ob_info.object_data.is_a(&RNA_PointCloud)) {
|
|
||||||
return Geometry::POINTCLOUD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b_ob_info.object_data.is_a(&RNA_Volume) ||
|
if (b_ob_info.object_data.is_a(&RNA_Volume) ||
|
||||||
(b_ob_info.object_data == b_ob_info.real_object.data() &&
|
(b_ob_info.object_data == b_ob_info.real_object.data() &&
|
||||||
object_fluid_gas_domain_find(b_ob_info.real_object))) {
|
object_fluid_gas_domain_find(b_ob_info.real_object))) {
|
||||||
@@ -116,9 +111,6 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
|
|||||||
else if (geom_type == Geometry::VOLUME) {
|
else if (geom_type == Geometry::VOLUME) {
|
||||||
geom = scene->create_node<Volume>();
|
geom = scene->create_node<Volume>();
|
||||||
}
|
}
|
||||||
else if (geom_type == Geometry::POINTCLOUD) {
|
|
||||||
geom = scene->create_node<PointCloud>();
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
geom = scene->create_node<Mesh>();
|
geom = scene->create_node<Mesh>();
|
||||||
}
|
}
|
||||||
@@ -178,10 +170,6 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
|
|||||||
Volume *volume = static_cast<Volume *>(geom);
|
Volume *volume = static_cast<Volume *>(geom);
|
||||||
sync_volume(b_ob_info, volume);
|
sync_volume(b_ob_info, volume);
|
||||||
}
|
}
|
||||||
else if (geom_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
sync_pointcloud(pointcloud, b_ob_info);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||||
sync_mesh(b_depsgraph, b_ob_info, mesh);
|
sync_mesh(b_depsgraph, b_ob_info, mesh);
|
||||||
@@ -243,10 +231,6 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
|
|||||||
object_fluid_gas_domain_find(b_ob_info.real_object)) {
|
object_fluid_gas_domain_find(b_ob_info.real_object)) {
|
||||||
/* No volume motion blur support yet. */
|
/* No volume motion blur support yet. */
|
||||||
}
|
}
|
||||||
else if (b_ob_info.object_data.is_a(&RNA_PointCloud)) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
sync_pointcloud_motion(pointcloud, b_ob_info, motion_step);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||||
sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step);
|
sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step);
|
||||||
|
@@ -555,7 +555,7 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
|||||||
/* Create uv map attributes. */
|
/* Create uv map attributes. */
|
||||||
static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
||||||
{
|
{
|
||||||
if (!b_mesh.uv_layers.empty()) {
|
if (b_mesh.uv_layers.length() != 0) {
|
||||||
for (BL::MeshUVLoopLayer &l : b_mesh.uv_layers) {
|
for (BL::MeshUVLoopLayer &l : b_mesh.uv_layers) {
|
||||||
const bool active_render = l.active_render();
|
const bool active_render = l.active_render();
|
||||||
AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
|
AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
|
||||||
@@ -619,7 +619,7 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
|||||||
|
|
||||||
static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
|
static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
|
||||||
{
|
{
|
||||||
if (!b_mesh.uv_layers.empty()) {
|
if (b_mesh.uv_layers.length() != 0) {
|
||||||
BL::Mesh::uv_layers_iterator l;
|
BL::Mesh::uv_layers_iterator l;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@@ -951,7 +951,7 @@ static void create_mesh(Scene *scene,
|
|||||||
N = attr_N->data_float3();
|
N = attr_N->data_float3();
|
||||||
|
|
||||||
/* create generated coordinates from undeformed coordinates */
|
/* create generated coordinates from undeformed coordinates */
|
||||||
const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.empty()) &&
|
const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.length() == 0) &&
|
||||||
(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
|
(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
|
||||||
if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) {
|
if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) {
|
||||||
Attribute *attr = attributes.add(ATTR_STD_GENERATED);
|
Attribute *attr = attributes.add(ATTR_STD_GENERATED);
|
||||||
@@ -1086,6 +1086,40 @@ static void create_subd_mesh(Scene *scene,
|
|||||||
|
|
||||||
/* Sync */
|
/* Sync */
|
||||||
|
|
||||||
|
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
|
||||||
|
* things like velocity from cache modifier, fluid simulation).
|
||||||
|
*
|
||||||
|
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
|
||||||
|
* set by `sync_object_motion_init()`. */
|
||||||
|
static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
|
||||||
|
{
|
||||||
|
const Scene::MotionType need_motion = scene->need_motion();
|
||||||
|
if (need_motion == Scene::MOTION_NONE) {
|
||||||
|
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
|
||||||
|
* attributes. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_motion == Scene::MOTION_BLUR) {
|
||||||
|
/* A bit tricky and implicit case:
|
||||||
|
* - Motion blur is enabled in the scene, which implies specific number of time steps for
|
||||||
|
* objects.
|
||||||
|
* - If the object has motion blur disabled on it, it will have 0 time steps.
|
||||||
|
* - Motion attribute expects non-zero time steps.
|
||||||
|
*
|
||||||
|
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
|
||||||
|
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
|
||||||
|
const bool use_motion = get_boolean(cobject, "use_motion_blur");
|
||||||
|
if (!use_motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
|
||||||
|
* level. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
|
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
|
||||||
{
|
{
|
||||||
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
|
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
|
||||||
@@ -1110,7 +1144,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
|
|||||||
|
|
||||||
if (b_mesh) {
|
if (b_mesh) {
|
||||||
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
||||||
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
const bool need_motion = mesh_need_motion_attribute(b_ob_info, scene);
|
||||||
const float motion_scale = (need_motion) ?
|
const float motion_scale = (need_motion) ?
|
||||||
scene->motion_shutter_time() /
|
scene->motion_shutter_time() /
|
||||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||||
|
@@ -72,8 +72,7 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
|
|||||||
|
|
||||||
BL::Object::type_enum type = b_ob_info.iter_object.type();
|
BL::Object::type_enum type = b_ob_info.iter_object.type();
|
||||||
|
|
||||||
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR ||
|
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) {
|
||||||
type == BL::Object::type_POINTCLOUD) {
|
|
||||||
/* Will be exported attached to mesh. */
|
/* Will be exported attached to mesh. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -207,7 +206,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only interested in object that we can create geometry from */
|
/* only interested in object that we can create meshes from */
|
||||||
if (!object_is_geometry(b_ob_info)) {
|
if (!object_is_geometry(b_ob_info)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,7 @@ bool BlenderOutputDriver::read_render_tile(const Tile &tile)
|
|||||||
|
|
||||||
bool BlenderOutputDriver::update_render_tile(const Tile &tile)
|
bool BlenderOutputDriver::update_render_tile(const Tile &tile)
|
||||||
{
|
{
|
||||||
/* Use final write for preview renders, otherwise render result wouldn't be updated
|
/* Use final write for preview renders, otherwise render result wouldn't be be updated
|
||||||
* quickly on Blender side. For all other cases we use the display driver. */
|
* quickly on Blender side. For all other cases we use the display driver. */
|
||||||
if (b_engine_.is_preview()) {
|
if (b_engine_.is_preview()) {
|
||||||
write_render_tile(tile);
|
write_render_tile(tile);
|
||||||
|
@@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011-2013 Blender Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scene/pointcloud.h"
|
|
||||||
#include "scene/attribute.h"
|
|
||||||
#include "scene/scene.h"
|
|
||||||
|
|
||||||
#include "blender/sync.h"
|
|
||||||
#include "blender/util.h"
|
|
||||||
|
|
||||||
#include "util/foreach.h"
|
|
||||||
#include "util/hash.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
template<typename TypeInCycles, typename GetValueAtIndex>
|
|
||||||
static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
|
|
||||||
TypeInCycles *data,
|
|
||||||
const GetValueAtIndex &get_value_at_index)
|
|
||||||
{
|
|
||||||
const int num_points = b_pointcloud.points.length();
|
|
||||||
for (int i = 0; i < num_points; i++) {
|
|
||||||
data[i] = get_value_at_index(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void attr_create_motion(PointCloud *pointcloud,
|
|
||||||
BL::Attribute &b_attribute,
|
|
||||||
const float motion_scale)
|
|
||||||
{
|
|
||||||
if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
|
|
||||||
(b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
|
|
||||||
const int num_points = pointcloud->get_points().size();
|
|
||||||
|
|
||||||
/* Find or add attribute */
|
|
||||||
float3 *P = &pointcloud->get_points()[0];
|
|
||||||
Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
|
|
||||||
if (!attr_mP) {
|
|
||||||
attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only export previous and next frame, we don't have any in between data. */
|
|
||||||
float motion_times[2] = {-1.0f, 1.0f};
|
|
||||||
for (int step = 0; step < 2; step++) {
|
|
||||||
const float relative_time = motion_times[step] * 0.5f * motion_scale;
|
|
||||||
float3 *mP = attr_mP->data_float3() + step * num_points;
|
|
||||||
|
|
||||||
for (int i = 0; i < num_points; i++) {
|
|
||||||
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void copy_attributes(PointCloud *pointcloud,
|
|
||||||
BL::PointCloud b_pointcloud,
|
|
||||||
const bool need_motion,
|
|
||||||
const float motion_scale)
|
|
||||||
{
|
|
||||||
AttributeSet &attributes = pointcloud->attributes;
|
|
||||||
static const ustring u_velocity("velocity");
|
|
||||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
|
||||||
const ustring name{b_attribute.name().c_str()};
|
|
||||||
|
|
||||||
if (need_motion && name == u_velocity) {
|
|
||||||
attr_create_motion(pointcloud, b_attribute, motion_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.find(name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AttributeElement element = ATTR_ELEMENT_VERTEX;
|
|
||||||
const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type();
|
|
||||||
switch (b_data_type) {
|
|
||||||
case BL::Attribute::data_type_FLOAT: {
|
|
||||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
|
||||||
float *data = attr->data_float();
|
|
||||||
fill_generic_attribute(
|
|
||||||
b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BL::Attribute::data_type_BOOLEAN: {
|
|
||||||
BL::BoolAttribute b_bool_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
|
||||||
float *data = attr->data_float();
|
|
||||||
fill_generic_attribute(
|
|
||||||
b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BL::Attribute::data_type_INT: {
|
|
||||||
BL::IntAttribute b_int_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
|
||||||
float *data = attr->data_float();
|
|
||||||
fill_generic_attribute(
|
|
||||||
b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
|
||||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeVector, element);
|
|
||||||
float3 *data = attr->data_float3();
|
|
||||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
|
||||||
BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
|
|
||||||
return make_float3(v[0], v[1], v[2]);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BL::Attribute::data_type_FLOAT_COLOR: {
|
|
||||||
BL::FloatColorAttribute b_color_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
|
||||||
float4 *data = attr->data_float4();
|
|
||||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
|
||||||
BL::Array<float, 4> v = b_color_attribute.data[i].color();
|
|
||||||
return make_float4(v[0], v[1], v[2], v[3]);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BL::Attribute::data_type_FLOAT2: {
|
|
||||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
|
||||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
|
||||||
float2 *data = attr->data_float2();
|
|
||||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
|
||||||
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
|
|
||||||
return make_float2(v[0], v[1]);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
/* Not supported. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void export_pointcloud(Scene *scene,
|
|
||||||
PointCloud *pointcloud,
|
|
||||||
BL::PointCloud b_pointcloud,
|
|
||||||
const bool need_motion,
|
|
||||||
const float motion_scale)
|
|
||||||
{
|
|
||||||
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
|
||||||
|
|
||||||
/* Add requested attributes. */
|
|
||||||
Attribute *attr_random = NULL;
|
|
||||||
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
|
|
||||||
attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reserve memory. */
|
|
||||||
const int num_points = b_pointcloud.points.length();
|
|
||||||
pointcloud->reserve(num_points);
|
|
||||||
|
|
||||||
/* Export points. */
|
|
||||||
BL::PointCloud::points_iterator b_point_iter;
|
|
||||||
for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end();
|
|
||||||
++b_point_iter) {
|
|
||||||
BL::Point b_point = *b_point_iter;
|
|
||||||
const float3 co = get_float3(b_point.co());
|
|
||||||
const float radius = b_point.radius();
|
|
||||||
pointcloud->add_point(co, radius);
|
|
||||||
|
|
||||||
/* Random number per point. */
|
|
||||||
if (attr_random != NULL) {
|
|
||||||
attr_random->add(hash_uint2_to_float(b_point.index(), 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export attributes */
|
|
||||||
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void export_pointcloud_motion(PointCloud *pointcloud,
|
|
||||||
BL::PointCloud b_pointcloud,
|
|
||||||
int motion_step)
|
|
||||||
{
|
|
||||||
/* Find or add attribute. */
|
|
||||||
Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
bool new_attribute = false;
|
|
||||||
|
|
||||||
if (!attr_mP) {
|
|
||||||
attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
new_attribute = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export motion points. */
|
|
||||||
const int num_points = pointcloud->num_points();
|
|
||||||
float3 *mP = attr_mP->data_float3() + motion_step * num_points;
|
|
||||||
bool have_motion = false;
|
|
||||||
int num_motion_points = 0;
|
|
||||||
const array<float3> &pointcloud_points = pointcloud->get_points();
|
|
||||||
|
|
||||||
BL::PointCloud::points_iterator b_point_iter;
|
|
||||||
for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end();
|
|
||||||
++b_point_iter) {
|
|
||||||
BL::Point b_point = *b_point_iter;
|
|
||||||
|
|
||||||
if (num_motion_points < num_points) {
|
|
||||||
float3 P = get_float3(b_point.co());
|
|
||||||
P.w = b_point.radius();
|
|
||||||
mP[num_motion_points] = P;
|
|
||||||
have_motion = have_motion || (P != pointcloud_points[num_motion_points]);
|
|
||||||
num_motion_points++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In case of new attribute, we verify if there really was any motion. */
|
|
||||||
if (new_attribute) {
|
|
||||||
if (num_motion_points != num_points || !have_motion) {
|
|
||||||
pointcloud->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
}
|
|
||||||
else if (motion_step > 0) {
|
|
||||||
/* Motion, fill up previous steps that we might have skipped because
|
|
||||||
* they had no motion, but we need them anyway now. */
|
|
||||||
for (int step = 0; step < motion_step; step++) {
|
|
||||||
pointcloud->copy_center_to_motion_step(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export attributes */
|
|
||||||
copy_attributes(pointcloud, b_pointcloud, false, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info)
|
|
||||||
{
|
|
||||||
size_t old_numpoints = pointcloud->num_points();
|
|
||||||
|
|
||||||
array<Node *> used_shaders = pointcloud->get_used_shaders();
|
|
||||||
|
|
||||||
PointCloud new_pointcloud;
|
|
||||||
new_pointcloud.set_used_shaders(used_shaders);
|
|
||||||
|
|
||||||
/* TODO: add option to filter out points in the view layer. */
|
|
||||||
BL::PointCloud b_pointcloud(b_ob_info.object_data);
|
|
||||||
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
|
||||||
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
|
||||||
const float motion_scale = (need_motion) ?
|
|
||||||
scene->motion_shutter_time() /
|
|
||||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
|
||||||
0.0f;
|
|
||||||
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
|
|
||||||
|
|
||||||
/* update original sockets */
|
|
||||||
for (const SocketType &socket : new_pointcloud.type->inputs) {
|
|
||||||
/* Those sockets are updated in sync_object, so do not modify them. */
|
|
||||||
if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
|
|
||||||
socket.name == "used_shaders") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pointcloud->set_value(socket, new_pointcloud, socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointcloud->attributes.clear();
|
|
||||||
foreach (Attribute &attr, new_pointcloud.attributes.attributes) {
|
|
||||||
pointcloud->attributes.attributes.push_back(std::move(attr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tag update */
|
|
||||||
const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points());
|
|
||||||
pointcloud->tag_update(scene, rebuild);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSync::sync_pointcloud_motion(PointCloud *pointcloud,
|
|
||||||
BObjectInfo &b_ob_info,
|
|
||||||
int motion_step)
|
|
||||||
{
|
|
||||||
/* Skip if nothing exported. */
|
|
||||||
if (pointcloud->num_points() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export deformed coordinates. */
|
|
||||||
if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
|
|
||||||
/* PointCloud object. */
|
|
||||||
BL::PointCloud b_pointcloud(b_ob_info.object_data);
|
|
||||||
export_pointcloud_motion(pointcloud, b_pointcloud, motion_step);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* No deformation on this frame, copy coordinates if other frames did have it. */
|
|
||||||
pointcloud->copy_center_to_motion_step(motion_step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
@@ -138,18 +138,20 @@ static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
|
|||||||
|
|
||||||
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
|
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *path, *user_path;
|
PyObject *path, *user_path, *temp_path;
|
||||||
int headless;
|
int headless;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
|
if (!PyArg_ParseTuple(args, "OOOi", &path, &user_path, &temp_path, &headless)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
|
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr, *temp_path_coerce = nullptr;
|
||||||
path_init(PyC_UnicodeAsByte(path, &path_coerce),
|
path_init(PyC_UnicodeAsByte(path, &path_coerce),
|
||||||
PyC_UnicodeAsByte(user_path, &user_path_coerce));
|
PyC_UnicodeAsByte(user_path, &user_path_coerce),
|
||||||
|
PyC_UnicodeAsByte(temp_path, &temp_path_coerce));
|
||||||
Py_XDECREF(path_coerce);
|
Py_XDECREF(path_coerce);
|
||||||
Py_XDECREF(user_path_coerce);
|
Py_XDECREF(user_path_coerce);
|
||||||
|
Py_XDECREF(temp_path_coerce);
|
||||||
|
|
||||||
BlenderSession::headless = headless;
|
BlenderSession::headless = headless;
|
||||||
|
|
||||||
@@ -733,20 +735,27 @@ static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepat
|
|||||||
|
|
||||||
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
|
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
(void)args;
|
||||||
|
(void)keywords;
|
||||||
|
#else
|
||||||
static const char *keyword_list[] = {
|
static const char *keyword_list[] = {
|
||||||
"preferences", "scene", "view_layer", "input", "output", NULL};
|
"preferences", "scene", "view_layer", "input", "output", "tile_size", "samples", NULL};
|
||||||
PyObject *pypreferences, *pyscene, *pyviewlayer;
|
PyObject *pypreferences, *pyscene, *pyviewlayer;
|
||||||
PyObject *pyinput, *pyoutput = NULL;
|
PyObject *pyinput, *pyoutput = NULL;
|
||||||
|
int tile_size = 0, samples = 0;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args,
|
if (!PyArg_ParseTupleAndKeywords(args,
|
||||||
keywords,
|
keywords,
|
||||||
"OOOO|O",
|
"OOOO|Oii",
|
||||||
(char **)keyword_list,
|
(char **)keyword_list,
|
||||||
&pypreferences,
|
&pypreferences,
|
||||||
&pyscene,
|
&pyscene,
|
||||||
&pyviewlayer,
|
&pyviewlayer,
|
||||||
&pyinput,
|
&pyinput,
|
||||||
&pyoutput)) {
|
&pyoutput,
|
||||||
|
&tile_size,
|
||||||
|
&samples)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,10 +777,14 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
|
|||||||
&RNA_ViewLayer,
|
&RNA_ViewLayer,
|
||||||
PyLong_AsVoidPtr(pyviewlayer),
|
PyLong_AsVoidPtr(pyviewlayer),
|
||||||
&viewlayerptr);
|
&viewlayerptr);
|
||||||
BL::ViewLayer b_view_layer(viewlayerptr);
|
PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
|
||||||
|
|
||||||
DenoiseParams params = BlenderSync::get_denoise_params(b_scene, b_view_layer, true);
|
DenoiseParams params;
|
||||||
params.use = true;
|
params.radius = get_int(cviewlayer, "denoising_radius");
|
||||||
|
params.strength = get_float(cviewlayer, "denoising_strength");
|
||||||
|
params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
|
||||||
|
params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
|
||||||
|
params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
|
||||||
|
|
||||||
/* Parse file paths list. */
|
/* Parse file paths list. */
|
||||||
vector<string> input, output;
|
vector<string> input, output;
|
||||||
@@ -799,15 +812,24 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create denoiser. */
|
/* Create denoiser. */
|
||||||
DenoiserPipeline denoiser(device, params);
|
DenoiserPipeline denoiser(device);
|
||||||
|
denoiser.params = params;
|
||||||
denoiser.input = input;
|
denoiser.input = input;
|
||||||
denoiser.output = output;
|
denoiser.output = output;
|
||||||
|
|
||||||
|
if (tile_size > 0) {
|
||||||
|
denoiser.tile_size = make_int2(tile_size, tile_size);
|
||||||
|
}
|
||||||
|
if (samples > 0) {
|
||||||
|
denoiser.samples_override = samples;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run denoiser. */
|
/* Run denoiser. */
|
||||||
if (!denoiser.run()) {
|
if (!denoiser.run()) {
|
||||||
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
|
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
@@ -884,18 +906,16 @@ static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*
|
|||||||
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
|
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
|
||||||
{
|
{
|
||||||
vector<DeviceType> device_types = Device::available_types();
|
vector<DeviceType> device_types = Device::available_types();
|
||||||
bool has_cuda = false, has_optix = false, has_hip = false, has_metal = false;
|
bool has_cuda = false, has_optix = false, has_hip = false;
|
||||||
foreach (DeviceType device_type, device_types) {
|
foreach (DeviceType device_type, device_types) {
|
||||||
has_cuda |= (device_type == DEVICE_CUDA);
|
has_cuda |= (device_type == DEVICE_CUDA);
|
||||||
has_optix |= (device_type == DEVICE_OPTIX);
|
has_optix |= (device_type == DEVICE_OPTIX);
|
||||||
has_hip |= (device_type == DEVICE_HIP);
|
has_hip |= (device_type == DEVICE_HIP);
|
||||||
has_metal |= (device_type == DEVICE_METAL);
|
|
||||||
}
|
}
|
||||||
PyObject *list = PyTuple_New(4);
|
PyObject *list = PyTuple_New(3);
|
||||||
PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
|
PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
|
||||||
PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_optix));
|
PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_optix));
|
||||||
PyTuple_SET_ITEM(list, 2, PyBool_FromLong(has_hip));
|
PyTuple_SET_ITEM(list, 2, PyBool_FromLong(has_hip));
|
||||||
PyTuple_SET_ITEM(list, 3, PyBool_FromLong(has_metal));
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,9 +944,6 @@ static PyObject *set_device_override_func(PyObject * /*self*/, PyObject *arg)
|
|||||||
else if (override == "HIP") {
|
else if (override == "HIP") {
|
||||||
BlenderSession::device_override = DEVICE_MASK_HIP;
|
BlenderSession::device_override = DEVICE_MASK_HIP;
|
||||||
}
|
}
|
||||||
else if (override == "METAL") {
|
|
||||||
BlenderSession::device_override = DEVICE_MASK_METAL;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
printf("\nError: %s is not a valid Cycles device.\n", override.c_str());
|
printf("\nError: %s is not a valid Cycles device.\n", override.c_str());
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
@@ -1037,13 +1054,5 @@ void *CCL_python_module_init()
|
|||||||
Py_INCREF(Py_False);
|
Py_INCREF(Py_False);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_CYCLES_DEBUG
|
|
||||||
PyModule_AddObject(mod, "with_debug", Py_True);
|
|
||||||
Py_INCREF(Py_True);
|
|
||||||
#else /* WITH_CYCLES_DEBUG */
|
|
||||||
PyModule_AddObject(mod, "with_debug", Py_False);
|
|
||||||
Py_INCREF(Py_False);
|
|
||||||
#endif /* WITH_CYCLES_DEBUG */
|
|
||||||
|
|
||||||
return (void *)mod;
|
return (void *)mod;
|
||||||
}
|
}
|
||||||
|
@@ -396,13 +396,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
|
|||||||
/* set the current view */
|
/* set the current view */
|
||||||
b_engine.active_view_set(b_rview_name.c_str());
|
b_engine.active_view_set(b_rview_name.c_str());
|
||||||
|
|
||||||
/* Force update in this case, since the camera transform on each frame changes
|
|
||||||
* in different views. This could be optimized by somehow storing the animated
|
|
||||||
* camera transforms separate from the fixed stereo transform. */
|
|
||||||
if ((scene->need_motion() != Scene::MOTION_NONE) && view_index > 0) {
|
|
||||||
sync->tag_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update scene */
|
/* update scene */
|
||||||
BL::Object b_camera_override(b_engine.camera_override());
|
BL::Object b_camera_override(b_engine.camera_override());
|
||||||
sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
|
sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
|
||||||
@@ -502,15 +495,10 @@ void BlenderSession::render_frame_finish()
|
|||||||
path_remove(filename);
|
path_remove(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear output driver. */
|
/* Clear driver. */
|
||||||
session->set_output_driver(nullptr);
|
session->set_output_driver(nullptr);
|
||||||
session->full_buffer_written_cb = function_null;
|
session->full_buffer_written_cb = function_null;
|
||||||
|
|
||||||
/* The display driver holds OpenGL resources which belong to an OpenGL context held by the render
|
|
||||||
* engine on Blender side. Force destruction of those resources. */
|
|
||||||
display_driver_ = nullptr;
|
|
||||||
session->set_display_driver(nullptr);
|
|
||||||
|
|
||||||
/* All the files are handled.
|
/* All the files are handled.
|
||||||
* Clear the list so that this session can be re-used by Persistent Data. */
|
* Clear the list so that this session can be re-used by Persistent Data. */
|
||||||
full_buffer_files_.clear();
|
full_buffer_files_.clear();
|
||||||
@@ -641,7 +629,7 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
|
|||||||
integrator->set_use_emission((bake_filter & BL::BakeSettings::pass_filter_EMIT) != 0);
|
integrator->set_use_emission((bake_filter & BL::BakeSettings::pass_filter_EMIT) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always use transparent background for baking. */
|
/* Always use transpanent background for baking. */
|
||||||
scene->background->set_transparent(true);
|
scene->background->set_transparent(true);
|
||||||
|
|
||||||
/* Load built-in images from Blender. */
|
/* Load built-in images from Blender. */
|
||||||
|
@@ -378,19 +378,10 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
}
|
}
|
||||||
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
|
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
|
||||||
BL::ShaderNodeMapRange b_map_range_node(b_node);
|
BL::ShaderNodeMapRange b_map_range_node(b_node);
|
||||||
if (b_map_range_node.data_type() == BL::ShaderNodeMapRange::data_type_FLOAT_VECTOR) {
|
MapRangeNode *map_range_node = graph->create_node<MapRangeNode>();
|
||||||
VectorMapRangeNode *vector_map_range_node = graph->create_node<VectorMapRangeNode>();
|
map_range_node->set_clamp(b_map_range_node.clamp());
|
||||||
vector_map_range_node->set_use_clamp(b_map_range_node.clamp());
|
map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type());
|
||||||
vector_map_range_node->set_range_type(
|
node = map_range_node;
|
||||||
(NodeMapRangeType)b_map_range_node.interpolation_type());
|
|
||||||
node = vector_map_range_node;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MapRangeNode *map_range_node = graph->create_node<MapRangeNode>();
|
|
||||||
map_range_node->set_clamp(b_map_range_node.clamp());
|
|
||||||
map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type());
|
|
||||||
node = map_range_node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
|
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
|
||||||
BL::ShaderNodeClamp b_clamp_node(b_node);
|
BL::ShaderNodeClamp b_clamp_node(b_node);
|
||||||
@@ -776,7 +767,7 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ustring filename = ustring(
|
ustring filename = ustring(
|
||||||
image_user_file_path(b_image_user, b_image, b_scene.frame_current()));
|
image_user_file_path(b_image_user, b_image, b_scene.frame_current(), true));
|
||||||
image->set_filename(filename);
|
image->set_filename(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -813,7 +804,7 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
env->set_filename(
|
env->set_filename(
|
||||||
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current())));
|
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current(), false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = env;
|
node = env;
|
||||||
|
@@ -95,11 +95,6 @@ void BlenderSync::reset(BL::BlendData &b_data, BL::Scene &b_scene)
|
|||||||
this->b_scene = b_scene;
|
this->b_scene = b_scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSync::tag_update()
|
|
||||||
{
|
|
||||||
has_updates_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sync */
|
/* Sync */
|
||||||
|
|
||||||
void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
|
void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
|
||||||
@@ -397,12 +392,6 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
|
|||||||
integrator->set_ao_bounces(0);
|
integrator->set_ao_bounces(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_CYCLES_DEBUG
|
|
||||||
DirectLightSamplingType direct_light_sampling_type = (DirectLightSamplingType)get_enum(
|
|
||||||
cscene, "direct_light_sampling_type", DIRECT_LIGHT_SAMPLING_NUM, DIRECT_LIGHT_SAMPLING_MIS);
|
|
||||||
integrator->set_direct_light_sampling_type(direct_light_sampling_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const DenoiseParams denoise_params = get_denoise_params(b_scene, b_view_layer, background);
|
const DenoiseParams denoise_params = get_denoise_params(b_scene, b_view_layer, background);
|
||||||
integrator->set_use_denoise(denoise_params.use);
|
integrator->set_use_denoise(denoise_params.use);
|
||||||
|
|
||||||
@@ -832,14 +821,6 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
|||||||
SessionParams params;
|
SessionParams params;
|
||||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||||
|
|
||||||
if (background && !b_engine.is_preview()) {
|
|
||||||
/* Viewport and preview renders do not require temp directory and do request session
|
|
||||||
* parameters more often than the background render.
|
|
||||||
* Optimize RNA-C++ usage and memory allocation a bit by saving string access which we know is
|
|
||||||
* not needed for viewport render. */
|
|
||||||
params.temp_dir = b_engine.temporary_directory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* feature set */
|
/* feature set */
|
||||||
params.experimental = (get_enum(cscene, "feature_set") != 0);
|
params.experimental = (get_enum(cscene, "feature_set") != 0);
|
||||||
|
|
||||||
@@ -854,25 +835,18 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
|||||||
/* samples */
|
/* samples */
|
||||||
int samples = get_int(cscene, "samples");
|
int samples = get_int(cscene, "samples");
|
||||||
int preview_samples = get_int(cscene, "preview_samples");
|
int preview_samples = get_int(cscene, "preview_samples");
|
||||||
int sample_offset = get_int(cscene, "sample_offset");
|
|
||||||
|
|
||||||
if (background) {
|
if (background) {
|
||||||
params.samples = samples;
|
params.samples = samples;
|
||||||
params.sample_offset = sample_offset;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
params.samples = preview_samples;
|
params.samples = preview_samples;
|
||||||
if (params.samples == 0) {
|
if (params.samples == 0)
|
||||||
params.samples = INT_MAX;
|
params.samples = INT_MAX;
|
||||||
}
|
|
||||||
params.sample_offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clamp sample offset. */
|
|
||||||
params.sample_offset = clamp(params.sample_offset, 0, Integrator::MAX_SAMPLES);
|
|
||||||
|
|
||||||
/* Clamp samples. */
|
/* Clamp samples. */
|
||||||
params.samples = clamp(params.samples, 0, Integrator::MAX_SAMPLES - params.sample_offset);
|
params.samples = min(params.samples, Integrator::MAX_SAMPLES);
|
||||||
|
|
||||||
/* Viewport Performance */
|
/* Viewport Performance */
|
||||||
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
|
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
|
||||||
@@ -891,7 +865,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
|||||||
|
|
||||||
/* Time limit. */
|
/* Time limit. */
|
||||||
if (background) {
|
if (background) {
|
||||||
params.time_limit = (double)get_float(cscene, "time_limit");
|
params.time_limit = get_float(cscene, "time_limit");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* For the viewport it kind of makes more sense to think in terms of the noise floor, which is
|
/* For the viewport it kind of makes more sense to think in terms of the noise floor, which is
|
||||||
|
@@ -66,8 +66,6 @@ class BlenderSync {
|
|||||||
|
|
||||||
void reset(BL::BlendData &b_data, BL::Scene &b_scene);
|
void reset(BL::BlendData &b_data, BL::Scene &b_scene);
|
||||||
|
|
||||||
void tag_update();
|
|
||||||
|
|
||||||
/* sync */
|
/* sync */
|
||||||
void sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
|
void sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
|
||||||
void sync_data(BL::RenderSettings &b_render,
|
void sync_data(BL::RenderSettings &b_render,
|
||||||
@@ -105,11 +103,11 @@ class BlenderSync {
|
|||||||
static BufferParams get_buffer_params(
|
static BufferParams get_buffer_params(
|
||||||
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
|
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
|
||||||
|
|
||||||
|
private:
|
||||||
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
|
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
|
||||||
BL::ViewLayer &b_view_layer,
|
BL::ViewLayer &b_view_layer,
|
||||||
bool background);
|
bool background);
|
||||||
|
|
||||||
private:
|
|
||||||
/* sync */
|
/* sync */
|
||||||
void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
|
void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
|
||||||
void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);
|
void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);
|
||||||
@@ -169,16 +167,12 @@ class BlenderSync {
|
|||||||
Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
|
Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
|
||||||
bool object_has_particle_hair(BL::Object b_ob);
|
bool object_has_particle_hair(BL::Object b_ob);
|
||||||
|
|
||||||
/* Point Cloud */
|
|
||||||
void sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info);
|
|
||||||
void sync_pointcloud_motion(PointCloud *pointcloud, BObjectInfo &b_ob_info, int motion_step = 0);
|
|
||||||
|
|
||||||
/* Camera */
|
/* Camera */
|
||||||
void sync_camera_motion(
|
void sync_camera_motion(
|
||||||
BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time);
|
BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time);
|
||||||
|
|
||||||
/* Geometry */
|
/* Geometry */
|
||||||
Geometry *sync_geometry(BL::Depsgraph &b_depsgraph,
|
Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah,
|
||||||
BObjectInfo &b_ob_info,
|
BObjectInfo &b_ob_info,
|
||||||
bool object_updated,
|
bool object_updated,
|
||||||
bool use_particle_hair,
|
bool use_particle_hair,
|
||||||
@@ -273,6 +267,7 @@ class BlenderSync {
|
|||||||
|
|
||||||
Progress &progress;
|
Progress &progress;
|
||||||
|
|
||||||
|
protected:
|
||||||
/* Indicates that `sync_recalc()` detected changes in the scene.
|
/* Indicates that `sync_recalc()` detected changes in the scene.
|
||||||
* If this flag is false then the data is considered to be up-to-date and will not be
|
* If this flag is false then the data is considered to be up-to-date and will not be
|
||||||
* synchronized at all. */
|
* synchronized at all. */
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
#define __BLENDER_UTIL_H__
|
#define __BLENDER_UTIL_H__
|
||||||
|
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
#include "scene/scene.h"
|
|
||||||
|
|
||||||
#include "util/algorithm.h"
|
#include "util/algorithm.h"
|
||||||
#include "util/array.h"
|
#include "util/array.h"
|
||||||
@@ -34,7 +33,7 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
|
void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
|
||||||
void BKE_image_user_file_path_ex(void *iuser, void *ima, char *path, bool resolve_udim);
|
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
|
||||||
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
|
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
|
||||||
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
|
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
|
||||||
}
|
}
|
||||||
@@ -291,14 +290,25 @@ static inline int render_resolution_y(BL::RenderSettings &b_render)
|
|||||||
return b_render.resolution_y() * b_render.resolution_percentage() / 100;
|
return b_render.resolution_y() * b_render.resolution_percentage() / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline string image_user_file_path(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
static inline string image_user_file_path(BL::ImageUser &iuser,
|
||||||
|
BL::Image &ima,
|
||||||
|
int cfra,
|
||||||
|
bool load_tiled)
|
||||||
{
|
{
|
||||||
char filepath[1024];
|
char filepath[1024];
|
||||||
iuser.tile(0);
|
iuser.tile(0);
|
||||||
BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
|
BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
|
||||||
BKE_image_user_file_path_ex(iuser.ptr.data, ima.ptr.data, filepath, false);
|
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
|
||||||
|
|
||||||
return string(filepath);
|
string filepath_str = string(filepath);
|
||||||
|
if (load_tiled && ima.source() == BL::Image::source_TILED) {
|
||||||
|
string udim;
|
||||||
|
if (ima.tiles.length() > 0) {
|
||||||
|
udim = to_string(ima.tiles[0].number());
|
||||||
|
}
|
||||||
|
string_replace(filepath_str, udim, "<UDIM>");
|
||||||
|
}
|
||||||
|
return filepath_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
||||||
@@ -637,7 +647,7 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob,
|
|||||||
{
|
{
|
||||||
PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
|
PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
|
||||||
|
|
||||||
if (cobj.data && !b_ob.modifiers.empty() && experimental) {
|
if (cobj.data && b_ob.modifiers.length() > 0 && experimental) {
|
||||||
BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length() - 1];
|
BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length() - 1];
|
||||||
bool enabled = preview ? mod.show_viewport() : mod.show_render();
|
bool enabled = preview ? mod.show_viewport() : mod.show_render();
|
||||||
|
|
||||||
@@ -671,40 +681,6 @@ static inline uint object_ray_visibility(BL::Object &b_ob)
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
|
|
||||||
* things like velocity from cache modifier, fluid simulation).
|
|
||||||
*
|
|
||||||
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
|
|
||||||
* set by `sync_object_motion_init()`. */
|
|
||||||
static inline bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
|
|
||||||
{
|
|
||||||
const Scene::MotionType need_motion = scene->need_motion();
|
|
||||||
if (need_motion == Scene::MOTION_NONE) {
|
|
||||||
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
|
|
||||||
* attributes. */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_motion == Scene::MOTION_BLUR) {
|
|
||||||
/* A bit tricky and implicit case:
|
|
||||||
* - Motion blur is enabled in the scene, which implies specific number of time steps for
|
|
||||||
* objects.
|
|
||||||
* - If the object has motion blur disabled on it, it will have 0 time steps.
|
|
||||||
* - Motion attribute expects non-zero time steps.
|
|
||||||
*
|
|
||||||
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
|
|
||||||
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
|
|
||||||
const bool use_motion = get_boolean(cobject, "use_motion_blur");
|
|
||||||
if (!use_motion) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
|
|
||||||
* level. */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EdgeMap {
|
class EdgeMap {
|
||||||
public:
|
public:
|
||||||
EdgeMap()
|
EdgeMap()
|
||||||
|
@@ -33,17 +33,6 @@ set(SRC
|
|||||||
unaligned.cpp
|
unaligned.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SRC_METAL
|
|
||||||
metal.mm
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WITH_CYCLES_DEVICE_METAL)
|
|
||||||
list(APPEND SRC
|
|
||||||
${SRC_METAL}
|
|
||||||
)
|
|
||||||
add_definitions(-DWITH_METAL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(SRC_HEADERS
|
set(SRC_HEADERS
|
||||||
bvh.h
|
bvh.h
|
||||||
bvh2.h
|
bvh2.h
|
||||||
@@ -57,7 +46,6 @@ set(SRC_HEADERS
|
|||||||
sort.h
|
sort.h
|
||||||
split.h
|
split.h
|
||||||
unaligned.h
|
unaligned.h
|
||||||
metal.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB
|
set(LIB
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
#include "scene/hair.h"
|
#include "scene/hair.h"
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
#include "scene/object.h"
|
#include "scene/object.h"
|
||||||
#include "scene/pointcloud.h"
|
|
||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
|
|
||||||
#include "util/algorithm.h"
|
#include "util/algorithm.h"
|
||||||
@@ -114,9 +113,9 @@ void BVHBuild::add_reference_triangles(BoundBox &root,
|
|||||||
else {
|
else {
|
||||||
/* Motion triangles, trace optimized case: we split triangle
|
/* Motion triangles, trace optimized case: we split triangle
|
||||||
* primitives into separate nodes for each of the time steps.
|
* primitives into separate nodes for each of the time steps.
|
||||||
* This way we minimize overlap of neighbor triangle primitives.
|
* This way we minimize overlap of neighbor curve primitives.
|
||||||
*/
|
*/
|
||||||
const int num_bvh_steps = params.num_motion_triangle_steps * 2 + 1;
|
const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
|
||||||
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
|
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
|
||||||
const size_t num_verts = mesh->verts.size();
|
const size_t num_verts = mesh->verts.size();
|
||||||
const size_t num_steps = mesh->motion_steps;
|
const size_t num_steps = mesh->motion_steps;
|
||||||
@@ -270,101 +269,6 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHBuild::add_reference_points(BoundBox &root,
|
|
||||||
BoundBox ¢er,
|
|
||||||
PointCloud *pointcloud,
|
|
||||||
int i)
|
|
||||||
{
|
|
||||||
const Attribute *point_attr_mP = NULL;
|
|
||||||
if (pointcloud->has_motion_blur()) {
|
|
||||||
point_attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float3 *points_data = &pointcloud->points[0];
|
|
||||||
const float *radius_data = &pointcloud->radius[0];
|
|
||||||
const size_t num_points = pointcloud->num_points();
|
|
||||||
const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL;
|
|
||||||
const size_t num_steps = pointcloud->get_motion_steps();
|
|
||||||
|
|
||||||
if (point_attr_mP == NULL) {
|
|
||||||
/* Really simple logic for static points. */
|
|
||||||
for (uint j = 0; j < num_points; j++) {
|
|
||||||
const PointCloud::Point point = pointcloud->get_point(j);
|
|
||||||
BoundBox bounds = BoundBox::empty;
|
|
||||||
point.bounds_grow(points_data, radius_data, bounds);
|
|
||||||
if (bounds.valid()) {
|
|
||||||
references.push_back(BVHReference(bounds, j, i, PRIMITIVE_POINT));
|
|
||||||
root.grow(bounds);
|
|
||||||
center.grow(bounds.center2());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (params.num_motion_point_steps == 0 || params.use_spatial_split) {
|
|
||||||
/* Simple case of motion points: single node for the whole
|
|
||||||
* shutter time. Lowest memory usage but less optimal
|
|
||||||
* rendering.
|
|
||||||
*/
|
|
||||||
/* TODO(sergey): Support motion steps for spatially split BVH. */
|
|
||||||
for (uint j = 0; j < num_points; j++) {
|
|
||||||
const PointCloud::Point point = pointcloud->get_point(j);
|
|
||||||
BoundBox bounds = BoundBox::empty;
|
|
||||||
point.bounds_grow(points_data, radius_data, bounds);
|
|
||||||
for (size_t step = 0; step < num_steps - 1; step++) {
|
|
||||||
point.bounds_grow(motion_data + step * num_points, radius_data, bounds);
|
|
||||||
}
|
|
||||||
if (bounds.valid()) {
|
|
||||||
references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT));
|
|
||||||
root.grow(bounds);
|
|
||||||
center.grow(bounds.center2());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Motion points, trace optimized case: we split point
|
|
||||||
* primitives into separate nodes for each of the time steps.
|
|
||||||
* This way we minimize overlap of neighbor point primitives.
|
|
||||||
*/
|
|
||||||
const int num_bvh_steps = params.num_motion_point_steps * 2 + 1;
|
|
||||||
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
|
|
||||||
|
|
||||||
for (uint j = 0; j < num_points; j++) {
|
|
||||||
const PointCloud::Point point = pointcloud->get_point(j);
|
|
||||||
const size_t num_steps = pointcloud->get_motion_steps();
|
|
||||||
const float3 *point_steps = point_attr_mP->data_float3();
|
|
||||||
|
|
||||||
/* Calculate bounding box of the previous time step.
|
|
||||||
* Will be reused later to avoid duplicated work on
|
|
||||||
* calculating BVH time step boundbox.
|
|
||||||
*/
|
|
||||||
float4 prev_key = point.motion_key(
|
|
||||||
points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j);
|
|
||||||
BoundBox prev_bounds = BoundBox::empty;
|
|
||||||
point.bounds_grow(prev_key, prev_bounds);
|
|
||||||
/* Create all primitive time steps, */
|
|
||||||
for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
|
|
||||||
const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
|
|
||||||
float4 curr_key = point.motion_key(
|
|
||||||
points_data, radius_data, point_steps, num_points, num_steps, curr_time, j);
|
|
||||||
BoundBox curr_bounds = BoundBox::empty;
|
|
||||||
point.bounds_grow(curr_key, curr_bounds);
|
|
||||||
BoundBox bounds = prev_bounds;
|
|
||||||
bounds.grow(curr_bounds);
|
|
||||||
if (bounds.valid()) {
|
|
||||||
const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
|
|
||||||
references.push_back(
|
|
||||||
BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT, prev_time, curr_time));
|
|
||||||
root.grow(bounds);
|
|
||||||
center.grow(bounds.center2());
|
|
||||||
}
|
|
||||||
/* Current time boundbox becomes previous one for the
|
|
||||||
* next time step.
|
|
||||||
*/
|
|
||||||
prev_bounds = curr_bounds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BVHBuild::add_reference_geometry(BoundBox &root,
|
void BVHBuild::add_reference_geometry(BoundBox &root,
|
||||||
BoundBox ¢er,
|
BoundBox ¢er,
|
||||||
Geometry *geom,
|
Geometry *geom,
|
||||||
@@ -378,10 +282,6 @@ void BVHBuild::add_reference_geometry(BoundBox &root,
|
|||||||
Hair *hair = static_cast<Hair *>(geom);
|
Hair *hair = static_cast<Hair *>(geom);
|
||||||
add_reference_curves(root, center, hair, object_index);
|
add_reference_curves(root, center, hair, object_index);
|
||||||
}
|
}
|
||||||
else if (geom->geometry_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
add_reference_points(root, center, pointcloud, object_index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHBuild::add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i)
|
void BVHBuild::add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i)
|
||||||
@@ -411,10 +311,6 @@ static size_t count_primitives(Geometry *geom)
|
|||||||
Hair *hair = static_cast<Hair *>(geom);
|
Hair *hair = static_cast<Hair *>(geom);
|
||||||
return count_curve_segments(hair);
|
return count_curve_segments(hair);
|
||||||
}
|
}
|
||||||
else if (geom->geometry_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
return pointcloud->num_points();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -432,9 +328,8 @@ void BVHBuild::add_references(BVHRange &root)
|
|||||||
if (!ob->get_geometry()->is_instanced()) {
|
if (!ob->get_geometry()->is_instanced()) {
|
||||||
num_alloc_references += count_primitives(ob->get_geometry());
|
num_alloc_references += count_primitives(ob->get_geometry());
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
num_alloc_references++;
|
num_alloc_references++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
num_alloc_references += count_primitives(ob->get_geometry());
|
num_alloc_references += count_primitives(ob->get_geometry());
|
||||||
@@ -499,7 +394,7 @@ BVHNode *BVHBuild::run()
|
|||||||
spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
|
spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
|
||||||
spatial_free_index = 0;
|
spatial_free_index = 0;
|
||||||
|
|
||||||
need_prim_time = params.use_motion_steps();
|
need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0;
|
||||||
|
|
||||||
/* init progress updates */
|
/* init progress updates */
|
||||||
double build_start_time;
|
double build_start_time;
|
||||||
@@ -640,8 +535,7 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
|
|||||||
const vector<BVHReference> &references) const
|
const vector<BVHReference> &references) const
|
||||||
{
|
{
|
||||||
size_t size = range.size();
|
size_t size = range.size();
|
||||||
size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size),
|
size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size);
|
||||||
params.max_point_leaf_size);
|
|
||||||
|
|
||||||
if (size > max_leaf_size)
|
if (size > max_leaf_size)
|
||||||
return false;
|
return false;
|
||||||
@@ -650,44 +544,32 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
|
|||||||
size_t num_motion_triangles = 0;
|
size_t num_motion_triangles = 0;
|
||||||
size_t num_curves = 0;
|
size_t num_curves = 0;
|
||||||
size_t num_motion_curves = 0;
|
size_t num_motion_curves = 0;
|
||||||
size_t num_points = 0;
|
|
||||||
size_t num_motion_points = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
const BVHReference &ref = references[range.start() + i];
|
const BVHReference &ref = references[range.start() + i];
|
||||||
|
|
||||||
if (ref.prim_type() & PRIMITIVE_CURVE) {
|
if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
|
||||||
if (ref.prim_type() & PRIMITIVE_MOTION) {
|
if (ref.prim_type() & PRIMITIVE_ALL_MOTION) {
|
||||||
num_motion_curves++;
|
num_motion_curves++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
num_curves++;
|
num_curves++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ref.prim_type() & PRIMITIVE_TRIANGLE) {
|
else if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
|
||||||
if (ref.prim_type() & PRIMITIVE_MOTION) {
|
if (ref.prim_type() & PRIMITIVE_ALL_MOTION) {
|
||||||
num_motion_triangles++;
|
num_motion_triangles++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
num_triangles++;
|
num_triangles++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ref.prim_type() & PRIMITIVE_POINT) {
|
|
||||||
if (ref.prim_type() & PRIMITIVE_MOTION) {
|
|
||||||
num_motion_points++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
num_points++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (num_triangles <= params.max_triangle_leaf_size) &&
|
return (num_triangles <= params.max_triangle_leaf_size) &&
|
||||||
(num_motion_triangles <= params.max_motion_triangle_leaf_size) &&
|
(num_motion_triangles <= params.max_motion_triangle_leaf_size) &&
|
||||||
(num_curves <= params.max_curve_leaf_size) &&
|
(num_curves <= params.max_curve_leaf_size) &&
|
||||||
(num_motion_curves <= params.max_motion_curve_leaf_size) &&
|
(num_motion_curves <= params.max_motion_curve_leaf_size);
|
||||||
(num_points <= params.max_point_leaf_size) &&
|
|
||||||
(num_motion_points <= params.max_motion_point_leaf_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multithreaded binning builder */
|
/* multithreaded binning builder */
|
||||||
@@ -973,7 +855,7 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer
|
|||||||
for (int i = 0; i < range.size(); i++) {
|
for (int i = 0; i < range.size(); i++) {
|
||||||
const BVHReference &ref = references[range.start() + i];
|
const BVHReference &ref = references[range.start() + i];
|
||||||
if (ref.prim_index() != -1) {
|
if (ref.prim_index() != -1) {
|
||||||
uint32_t type_index = PRIMITIVE_INDEX(ref.prim_type() & PRIMITIVE_ALL);
|
uint32_t type_index = bitscan((uint32_t)(ref.prim_type() & PRIMITIVE_ALL));
|
||||||
p_ref[type_index].push_back(ref);
|
p_ref[type_index].push_back(ref);
|
||||||
p_type[type_index].push_back(ref.prim_type());
|
p_type[type_index].push_back(ref.prim_type());
|
||||||
p_index[type_index].push_back(ref.prim_index());
|
p_index[type_index].push_back(ref.prim_index());
|
||||||
|
@@ -39,7 +39,6 @@ class Geometry;
|
|||||||
class Hair;
|
class Hair;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class Object;
|
class Object;
|
||||||
class PointCloud;
|
|
||||||
class Progress;
|
class Progress;
|
||||||
|
|
||||||
/* BVH Builder */
|
/* BVH Builder */
|
||||||
@@ -69,7 +68,6 @@ class BVHBuild {
|
|||||||
/* Adding references. */
|
/* Adding references. */
|
||||||
void add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i);
|
void add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i);
|
||||||
void add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i);
|
void add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i);
|
||||||
void add_reference_points(BoundBox &root, BoundBox ¢er, PointCloud *pointcloud, int i);
|
|
||||||
void add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i);
|
void add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i);
|
||||||
void add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i);
|
void add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i);
|
||||||
void add_references(BVHRange &root);
|
void add_references(BVHRange &root);
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "bvh/bvh2.h"
|
#include "bvh/bvh2.h"
|
||||||
#include "bvh/embree.h"
|
#include "bvh/embree.h"
|
||||||
#include "bvh/metal.h"
|
|
||||||
#include "bvh/multi.h"
|
#include "bvh/multi.h"
|
||||||
#include "bvh/optix.h"
|
#include "bvh/optix.h"
|
||||||
|
|
||||||
@@ -41,12 +40,8 @@ const char *bvh_layout_name(BVHLayout layout)
|
|||||||
return "EMBREE";
|
return "EMBREE";
|
||||||
case BVH_LAYOUT_OPTIX:
|
case BVH_LAYOUT_OPTIX:
|
||||||
return "OPTIX";
|
return "OPTIX";
|
||||||
case BVH_LAYOUT_METAL:
|
|
||||||
return "METAL";
|
|
||||||
case BVH_LAYOUT_MULTI_OPTIX:
|
case BVH_LAYOUT_MULTI_OPTIX:
|
||||||
case BVH_LAYOUT_MULTI_METAL:
|
|
||||||
case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
|
case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
|
||||||
case BVH_LAYOUT_MULTI_METAL_EMBREE:
|
|
||||||
return "MULTI";
|
return "MULTI";
|
||||||
case BVH_LAYOUT_ALL:
|
case BVH_LAYOUT_ALL:
|
||||||
return "ALL";
|
return "ALL";
|
||||||
@@ -107,18 +102,9 @@ BVH *BVH::create(const BVHParams ¶ms,
|
|||||||
#else
|
#else
|
||||||
(void)device;
|
(void)device;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case BVH_LAYOUT_METAL:
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
return bvh_metal_create(params, geometry, objects, device);
|
|
||||||
#else
|
|
||||||
(void)device;
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case BVH_LAYOUT_MULTI_OPTIX:
|
case BVH_LAYOUT_MULTI_OPTIX:
|
||||||
case BVH_LAYOUT_MULTI_METAL:
|
|
||||||
case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
|
case BVH_LAYOUT_MULTI_OPTIX_EMBREE:
|
||||||
case BVH_LAYOUT_MULTI_METAL_EMBREE:
|
|
||||||
return new BVHMulti(params, geometry, objects);
|
return new BVHMulti(params, geometry, objects);
|
||||||
case BVH_LAYOUT_NONE:
|
case BVH_LAYOUT_NONE:
|
||||||
case BVH_LAYOUT_ALL:
|
case BVH_LAYOUT_ALL:
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include "scene/hair.h"
|
#include "scene/hair.h"
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
#include "scene/object.h"
|
#include "scene/object.h"
|
||||||
#include "scene/pointcloud.h"
|
|
||||||
|
|
||||||
#include "bvh/build.h"
|
#include "bvh/build.h"
|
||||||
#include "bvh/node.h"
|
#include "bvh/node.h"
|
||||||
@@ -387,7 +386,7 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Primitives. */
|
/* Primitives. */
|
||||||
if (pack.prim_type[prim] & PRIMITIVE_CURVE) {
|
if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
|
||||||
/* Curves. */
|
/* Curves. */
|
||||||
const Hair *hair = static_cast<const Hair *>(ob->get_geometry());
|
const Hair *hair = static_cast<const Hair *>(ob->get_geometry());
|
||||||
int prim_offset = (params.top_level) ? hair->prim_offset : 0;
|
int prim_offset = (params.top_level) ? hair->prim_offset : 0;
|
||||||
@@ -410,30 +409,6 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pack.prim_type[prim] & PRIMITIVE_POINT) {
|
|
||||||
/* Points. */
|
|
||||||
const PointCloud *pointcloud = static_cast<const PointCloud *>(ob->get_geometry());
|
|
||||||
int prim_offset = (params.top_level) ? pointcloud->prim_offset : 0;
|
|
||||||
const float3 *points = &pointcloud->points[0];
|
|
||||||
const float *radius = &pointcloud->radius[0];
|
|
||||||
PointCloud::Point point = pointcloud->get_point(pidx - prim_offset);
|
|
||||||
|
|
||||||
point.bounds_grow(points, radius, bbox);
|
|
||||||
|
|
||||||
/* Motion points. */
|
|
||||||
if (pointcloud->get_use_motion_blur()) {
|
|
||||||
Attribute *attr = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
|
|
||||||
if (attr) {
|
|
||||||
size_t pointcloud_size = pointcloud->points.size();
|
|
||||||
size_t steps = pointcloud->get_motion_steps() - 1;
|
|
||||||
float3 *point_steps = attr->data_float3();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < steps; i++)
|
|
||||||
point.bounds_grow(point_steps + i * pointcloud_size, radius, bbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
/* Triangles. */
|
/* Triangles. */
|
||||||
const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
|
const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
|
||||||
@@ -530,8 +505,7 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
|
|||||||
pack.leaf_nodes.resize(leaf_nodes_size);
|
pack.leaf_nodes.resize(leaf_nodes_size);
|
||||||
pack.object_node.resize(objects.size());
|
pack.object_node.resize(objects.size());
|
||||||
|
|
||||||
if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0 ||
|
if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
|
||||||
params.num_motion_point_steps > 0) {
|
|
||||||
pack.prim_time.resize(prim_index_size);
|
pack.prim_time.resize(prim_index_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +564,13 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
|
|||||||
float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL;
|
float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL;
|
||||||
|
|
||||||
for (size_t i = 0; i < bvh_prim_index_size; i++) {
|
for (size_t i = 0; i < bvh_prim_index_size; i++) {
|
||||||
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
|
if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
|
||||||
|
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
|
||||||
|
}
|
||||||
|
|
||||||
pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
|
pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
|
||||||
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
|
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
|
||||||
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
|
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
|
||||||
|
@@ -45,7 +45,6 @@
|
|||||||
# include "scene/hair.h"
|
# include "scene/hair.h"
|
||||||
# include "scene/mesh.h"
|
# include "scene/mesh.h"
|
||||||
# include "scene/object.h"
|
# include "scene/object.h"
|
||||||
# include "scene/pointcloud.h"
|
|
||||||
|
|
||||||
# include "util/foreach.h"
|
# include "util/foreach.h"
|
||||||
# include "util/log.h"
|
# include "util/log.h"
|
||||||
@@ -91,7 +90,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
++ctx->num_hits;
|
++ctx->num_hits;
|
||||||
|
|
||||||
/* Always use baked shadow transparency for curves. */
|
/* Always use baked shadow transparency for curves. */
|
||||||
if (current_isect.type & PRIMITIVE_CURVE) {
|
if (current_isect.type & PRIMITIVE_ALL_CURVE) {
|
||||||
ctx->throughput *= intersection_curve_shadow_transparency(
|
ctx->throughput *= intersection_curve_shadow_transparency(
|
||||||
kg, current_isect.object, current_isect.prim, current_isect.u);
|
kg, current_isect.object, current_isect.prim, current_isect.u);
|
||||||
|
|
||||||
@@ -246,7 +245,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_filter_func_backface_cull(const RTCFilterFunctionNArguments *args)
|
static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args)
|
||||||
{
|
{
|
||||||
const RTCRay *ray = (RTCRay *)args->ray;
|
const RTCRay *ray = (RTCRay *)args->ray;
|
||||||
RTCHit *hit = (RTCHit *)args->hit;
|
RTCHit *hit = (RTCHit *)args->hit;
|
||||||
@@ -259,7 +258,7 @@ static void rtc_filter_func_backface_cull(const RTCFilterFunctionNArguments *arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_filter_occluded_func_backface_cull(const RTCFilterFunctionNArguments *args)
|
static void rtc_filter_occluded_func_thick_curve(const RTCFilterFunctionNArguments *args)
|
||||||
{
|
{
|
||||||
const RTCRay *ray = (RTCRay *)args->ray;
|
const RTCRay *ray = (RTCRay *)args->ray;
|
||||||
RTCHit *hit = (RTCHit *)args->hit;
|
RTCHit *hit = (RTCHit *)args->hit;
|
||||||
@@ -304,7 +303,7 @@ static void rtc_error_func(void *, enum RTCError, const char *str)
|
|||||||
VLOG(1) << str;
|
VLOG(1) << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double progress_start_time = 0.0;
|
static double progress_start_time = 0.0f;
|
||||||
|
|
||||||
static bool rtc_progress_func(void *user_ptr, const double n)
|
static bool rtc_progress_func(void *user_ptr, const double n)
|
||||||
{
|
{
|
||||||
@@ -411,12 +410,6 @@ void BVHEmbree::add_object(Object *ob, int i)
|
|||||||
add_curves(ob, hair, i);
|
add_curves(ob, hair, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (geom->geometry_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
if (pointcloud->num_points() > 0) {
|
|
||||||
add_points(ob, pointcloud, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHEmbree::add_instance(Object *ob, int i)
|
void BVHEmbree::add_instance(Object *ob, int i)
|
||||||
@@ -631,89 +624,6 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHEmbree::set_point_vertex_buffer(RTCGeometry geom_id,
|
|
||||||
const PointCloud *pointcloud,
|
|
||||||
const bool update)
|
|
||||||
{
|
|
||||||
const Attribute *attr_mP = NULL;
|
|
||||||
size_t num_motion_steps = 1;
|
|
||||||
if (pointcloud->has_motion_blur()) {
|
|
||||||
attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
if (attr_mP) {
|
|
||||||
num_motion_steps = pointcloud->get_motion_steps();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t num_points = pointcloud->num_points();
|
|
||||||
|
|
||||||
/* Copy the point data to Embree */
|
|
||||||
const int t_mid = (num_motion_steps - 1) / 2;
|
|
||||||
const float *radius = pointcloud->get_radius().data();
|
|
||||||
for (int t = 0; t < num_motion_steps; ++t) {
|
|
||||||
const float3 *verts;
|
|
||||||
if (t == t_mid || attr_mP == NULL) {
|
|
||||||
verts = pointcloud->get_points().data();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int t_ = (t > t_mid) ? (t - 1) : t;
|
|
||||||
verts = &attr_mP->data_float3()[t_ * num_points];
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 *rtc_verts = (update) ? (float4 *)rtcGetGeometryBufferData(
|
|
||||||
geom_id, RTC_BUFFER_TYPE_VERTEX, t) :
|
|
||||||
(float4 *)rtcSetNewGeometryBuffer(geom_id,
|
|
||||||
RTC_BUFFER_TYPE_VERTEX,
|
|
||||||
t,
|
|
||||||
RTC_FORMAT_FLOAT4,
|
|
||||||
sizeof(float) * 4,
|
|
||||||
num_points);
|
|
||||||
|
|
||||||
assert(rtc_verts);
|
|
||||||
if (rtc_verts) {
|
|
||||||
for (size_t j = 0; j < num_points; ++j) {
|
|
||||||
rtc_verts[j] = float3_to_float4(verts[j]);
|
|
||||||
rtc_verts[j].w = radius[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update) {
|
|
||||||
rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BVHEmbree::add_points(const Object *ob, const PointCloud *pointcloud, int i)
|
|
||||||
{
|
|
||||||
size_t prim_offset = pointcloud->prim_offset;
|
|
||||||
|
|
||||||
const Attribute *attr_mP = NULL;
|
|
||||||
size_t num_motion_steps = 1;
|
|
||||||
if (pointcloud->has_motion_blur()) {
|
|
||||||
attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
|
||||||
if (attr_mP) {
|
|
||||||
num_motion_steps = pointcloud->get_motion_steps();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum RTCGeometryType type = RTC_GEOMETRY_TYPE_SPHERE_POINT;
|
|
||||||
|
|
||||||
RTCGeometry geom_id = rtcNewGeometry(rtc_device, type);
|
|
||||||
|
|
||||||
rtcSetGeometryBuildQuality(geom_id, build_quality);
|
|
||||||
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
|
|
||||||
|
|
||||||
set_point_vertex_buffer(geom_id, pointcloud, false);
|
|
||||||
|
|
||||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
|
||||||
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_backface_cull);
|
|
||||||
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_backface_cull);
|
|
||||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
|
||||||
|
|
||||||
rtcCommitGeometry(geom_id);
|
|
||||||
rtcAttachGeometryByID(scene, geom_id, i * 2);
|
|
||||||
rtcReleaseGeometry(geom_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
||||||
{
|
{
|
||||||
size_t prim_offset = hair->curve_segment_offset;
|
size_t prim_offset = hair->curve_segment_offset;
|
||||||
@@ -768,8 +678,8 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
|||||||
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_backface_cull);
|
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve);
|
||||||
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_backface_cull);
|
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve);
|
||||||
}
|
}
|
||||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||||
|
|
||||||
@@ -806,14 +716,6 @@ void BVHEmbree::refit(Progress &progress)
|
|||||||
rtcCommitGeometry(geom);
|
rtcCommitGeometry(geom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (geom->geometry_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
if (pointcloud->num_points() > 0) {
|
|
||||||
RTCGeometry geom = rtcGetGeometry(scene, geom_id);
|
|
||||||
set_point_vertex_buffer(geom, pointcloud, true);
|
|
||||||
rtcCommitGeometry(geom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
geom_id += 2;
|
geom_id += 2;
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
class Hair;
|
class Hair;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class PointCloud;
|
|
||||||
|
|
||||||
class BVHEmbree : public BVH {
|
class BVHEmbree : public BVH {
|
||||||
public:
|
public:
|
||||||
@@ -52,15 +51,11 @@ class BVHEmbree : public BVH {
|
|||||||
void add_object(Object *ob, int i);
|
void add_object(Object *ob, int i);
|
||||||
void add_instance(Object *ob, int i);
|
void add_instance(Object *ob, int i);
|
||||||
void add_curves(const Object *ob, const Hair *hair, int i);
|
void add_curves(const Object *ob, const Hair *hair, int i);
|
||||||
void add_points(const Object *ob, const PointCloud *pointcloud, int i);
|
|
||||||
void add_triangles(const Object *ob, const Mesh *mesh, int i);
|
void add_triangles(const Object *ob, const Mesh *mesh, int i);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update);
|
void set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update);
|
||||||
void set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update);
|
void set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update);
|
||||||
void set_point_vertex_buffer(RTCGeometry geom_id,
|
|
||||||
const PointCloud *pointcloud,
|
|
||||||
const bool update);
|
|
||||||
|
|
||||||
RTCDevice rtc_device;
|
RTCDevice rtc_device;
|
||||||
enum RTCBuildQuality build_quality;
|
enum RTCBuildQuality build_quality;
|
||||||
|
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Blender Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __BVH_METAL_H__
|
|
||||||
#define __BVH_METAL_H__
|
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
|
|
||||||
# include "bvh/bvh.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
BVH *bvh_metal_create(const BVHParams ¶ms,
|
|
||||||
const vector<Geometry *> &geometry,
|
|
||||||
const vector<Object *> &objects,
|
|
||||||
Device *device);
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
||||||
|
|
||||||
#endif /* WITH_METAL */
|
|
||||||
|
|
||||||
#endif /* __BVH_METAL_H__ */
|
|
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Blender Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
|
|
||||||
# include "device/metal/bvh.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
BVH *bvh_metal_create(const BVHParams ¶ms,
|
|
||||||
const vector<Geometry *> &geometry,
|
|
||||||
const vector<Object *> &objects,
|
|
||||||
Device *device)
|
|
||||||
{
|
|
||||||
return new BVHMetal(params, geometry, objects, device);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
||||||
|
|
||||||
#endif /* WITH_METAL */
|
|
@@ -153,7 +153,7 @@ void BVHNode::update_time()
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct DumpTraversalContext {
|
struct DumpTraversalContext {
|
||||||
/* Descriptor of while where writing is happening. */
|
/* Descriptor of wile where writing is happening. */
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
/* Unique identifier of the node current. */
|
/* Unique identifier of the node current. */
|
||||||
int id;
|
int id;
|
||||||
|
@@ -178,7 +178,7 @@ class InnerNode : public BVHNode {
|
|||||||
reset_unused_children();
|
reset_unused_children();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: This function is only used during binary BVH builder, and it's
|
/* NOTE: This function is only used during binary BVH builder, and it
|
||||||
* supposed to be configured to have 2 children which will be filled-in in a
|
* supposed to be configured to have 2 children which will be filled-in in a
|
||||||
* bit. But this is important to have children reset to NULL. */
|
* bit. But this is important to have children reset to NULL. */
|
||||||
explicit InnerNode(const BoundBox &bounds) : BVHNode(bounds), num_children_(0)
|
explicit InnerNode(const BoundBox &bounds) : BVHNode(bounds), num_children_(0)
|
||||||
|
@@ -83,8 +83,6 @@ class BVHParams {
|
|||||||
int max_motion_triangle_leaf_size;
|
int max_motion_triangle_leaf_size;
|
||||||
int max_curve_leaf_size;
|
int max_curve_leaf_size;
|
||||||
int max_motion_curve_leaf_size;
|
int max_motion_curve_leaf_size;
|
||||||
int max_point_leaf_size;
|
|
||||||
int max_motion_point_leaf_size;
|
|
||||||
|
|
||||||
/* object or mesh level bvh */
|
/* object or mesh level bvh */
|
||||||
bool top_level;
|
bool top_level;
|
||||||
@@ -100,13 +98,13 @@ class BVHParams {
|
|||||||
/* Split time range to this number of steps and create leaf node for each
|
/* Split time range to this number of steps and create leaf node for each
|
||||||
* of this time steps.
|
* of this time steps.
|
||||||
*
|
*
|
||||||
* Speeds up rendering of motion primitives in the cost of higher memory usage.
|
* Speeds up rendering of motion curve primitives in the cost of higher
|
||||||
|
* memory usage.
|
||||||
*/
|
*/
|
||||||
|
int num_motion_curve_steps;
|
||||||
|
|
||||||
/* Same as above, but for triangle primitives. */
|
/* Same as above, but for triangle primitives. */
|
||||||
int num_motion_triangle_steps;
|
int num_motion_triangle_steps;
|
||||||
int num_motion_curve_steps;
|
|
||||||
int num_motion_point_steps;
|
|
||||||
|
|
||||||
/* Same as in SceneParams. */
|
/* Same as in SceneParams. */
|
||||||
int bvh_type;
|
int bvh_type;
|
||||||
@@ -134,8 +132,6 @@ class BVHParams {
|
|||||||
max_motion_triangle_leaf_size = 8;
|
max_motion_triangle_leaf_size = 8;
|
||||||
max_curve_leaf_size = 1;
|
max_curve_leaf_size = 1;
|
||||||
max_motion_curve_leaf_size = 4;
|
max_motion_curve_leaf_size = 4;
|
||||||
max_point_leaf_size = 8;
|
|
||||||
max_motion_point_leaf_size = 8;
|
|
||||||
|
|
||||||
top_level = false;
|
top_level = false;
|
||||||
bvh_layout = BVH_LAYOUT_BVH2;
|
bvh_layout = BVH_LAYOUT_BVH2;
|
||||||
@@ -143,7 +139,6 @@ class BVHParams {
|
|||||||
|
|
||||||
num_motion_curve_steps = 0;
|
num_motion_curve_steps = 0;
|
||||||
num_motion_triangle_steps = 0;
|
num_motion_triangle_steps = 0;
|
||||||
num_motion_point_steps = 0;
|
|
||||||
|
|
||||||
bvh_type = 0;
|
bvh_type = 0;
|
||||||
|
|
||||||
@@ -171,12 +166,6 @@ class BVHParams {
|
|||||||
return (size <= min_leaf_size || level >= MAX_DEPTH);
|
return (size <= min_leaf_size || level >= MAX_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_motion_steps()
|
|
||||||
{
|
|
||||||
return num_motion_curve_steps > 0 || num_motion_triangle_steps > 0 ||
|
|
||||||
num_motion_point_steps > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Gets best matching BVH.
|
/* Gets best matching BVH.
|
||||||
*
|
*
|
||||||
* If the requested layout is supported by the device, it will be used.
|
* If the requested layout is supported by the device, it will be used.
|
||||||
|
@@ -23,7 +23,6 @@
|
|||||||
#include "scene/hair.h"
|
#include "scene/hair.h"
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
#include "scene/object.h"
|
#include "scene/object.h"
|
||||||
#include "scene/pointcloud.h"
|
|
||||||
|
|
||||||
#include "util/algorithm.h"
|
#include "util/algorithm.h"
|
||||||
|
|
||||||
@@ -427,32 +426,6 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHSpatialSplit::split_point_primitive(const PointCloud *pointcloud,
|
|
||||||
const Transform *tfm,
|
|
||||||
int prim_index,
|
|
||||||
int dim,
|
|
||||||
float pos,
|
|
||||||
BoundBox &left_bounds,
|
|
||||||
BoundBox &right_bounds)
|
|
||||||
{
|
|
||||||
/* No real splitting support for points, assume they are small enough for it
|
|
||||||
* not to matter. */
|
|
||||||
float3 point = pointcloud->get_points()[prim_index];
|
|
||||||
|
|
||||||
if (tfm != NULL) {
|
|
||||||
point = transform_point(tfm, point);
|
|
||||||
}
|
|
||||||
point = get_unaligned_point(point);
|
|
||||||
|
|
||||||
if (point[dim] <= pos) {
|
|
||||||
left_bounds.grow(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (point[dim] >= pos) {
|
|
||||||
right_bounds.grow(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref,
|
void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref,
|
||||||
const Mesh *mesh,
|
const Mesh *mesh,
|
||||||
int dim,
|
int dim,
|
||||||
@@ -480,16 +453,6 @@ void BVHSpatialSplit::split_curve_reference(const BVHReference &ref,
|
|||||||
right_bounds);
|
right_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHSpatialSplit::split_point_reference(const BVHReference &ref,
|
|
||||||
const PointCloud *pointcloud,
|
|
||||||
int dim,
|
|
||||||
float pos,
|
|
||||||
BoundBox &left_bounds,
|
|
||||||
BoundBox &right_bounds)
|
|
||||||
{
|
|
||||||
split_point_primitive(pointcloud, NULL, ref.prim_index(), dim, pos, left_bounds, right_bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BVHSpatialSplit::split_object_reference(
|
void BVHSpatialSplit::split_object_reference(
|
||||||
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds)
|
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds)
|
||||||
{
|
{
|
||||||
@@ -512,13 +475,6 @@ void BVHSpatialSplit::split_object_reference(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (geom->geometry_type == Geometry::POINTCLOUD) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
|
||||||
for (int point_idx = 0; point_idx < pointcloud->num_points(); ++point_idx) {
|
|
||||||
split_point_primitive(
|
|
||||||
pointcloud, &object->get_tfm(), point_idx, dim, pos, left_bounds, right_bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BVHSpatialSplit::split_reference(const BVHBuild &builder,
|
void BVHSpatialSplit::split_reference(const BVHBuild &builder,
|
||||||
@@ -535,18 +491,14 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder,
|
|||||||
/* loop over vertices/edges. */
|
/* loop over vertices/edges. */
|
||||||
const Object *ob = builder.objects[ref.prim_object()];
|
const Object *ob = builder.objects[ref.prim_object()];
|
||||||
|
|
||||||
if (ref.prim_type() & PRIMITIVE_TRIANGLE) {
|
if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
|
||||||
Mesh *mesh = static_cast<Mesh *>(ob->get_geometry());
|
Mesh *mesh = static_cast<Mesh *>(ob->get_geometry());
|
||||||
split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
|
split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
|
||||||
}
|
}
|
||||||
else if (ref.prim_type() & PRIMITIVE_CURVE) {
|
else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
|
||||||
Hair *hair = static_cast<Hair *>(ob->get_geometry());
|
Hair *hair = static_cast<Hair *>(ob->get_geometry());
|
||||||
split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds);
|
split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds);
|
||||||
}
|
}
|
||||||
else if (ref.prim_type() & PRIMITIVE_POINT) {
|
|
||||||
PointCloud *pointcloud = static_cast<PointCloud *>(ob->get_geometry());
|
|
||||||
split_point_reference(ref, pointcloud, dim, pos, left_bounds, right_bounds);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
split_object_reference(ob, dim, pos, left_bounds, right_bounds);
|
split_object_reference(ob, dim, pos, left_bounds, right_bounds);
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,6 @@ CCL_NAMESPACE_BEGIN
|
|||||||
class BVHBuild;
|
class BVHBuild;
|
||||||
class Hair;
|
class Hair;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class PointCloud;
|
|
||||||
struct Transform;
|
struct Transform;
|
||||||
|
|
||||||
/* Object Split */
|
/* Object Split */
|
||||||
@@ -124,13 +123,6 @@ class BVHSpatialSplit {
|
|||||||
float pos,
|
float pos,
|
||||||
BoundBox &left_bounds,
|
BoundBox &left_bounds,
|
||||||
BoundBox &right_bounds);
|
BoundBox &right_bounds);
|
||||||
void split_point_primitive(const PointCloud *pointcloud,
|
|
||||||
const Transform *tfm,
|
|
||||||
int prim_index,
|
|
||||||
int dim,
|
|
||||||
float pos,
|
|
||||||
BoundBox &left_bounds,
|
|
||||||
BoundBox &right_bounds);
|
|
||||||
|
|
||||||
/* Lower-level functions which calculates boundaries of left and right nodes
|
/* Lower-level functions which calculates boundaries of left and right nodes
|
||||||
* needed for spatial split.
|
* needed for spatial split.
|
||||||
@@ -149,12 +141,6 @@ class BVHSpatialSplit {
|
|||||||
float pos,
|
float pos,
|
||||||
BoundBox &left_bounds,
|
BoundBox &left_bounds,
|
||||||
BoundBox &right_bounds);
|
BoundBox &right_bounds);
|
||||||
void split_point_reference(const BVHReference &ref,
|
|
||||||
const PointCloud *pointcloud,
|
|
||||||
int dim,
|
|
||||||
float pos,
|
|
||||||
BoundBox &left_bounds,
|
|
||||||
BoundBox &right_bounds);
|
|
||||||
void split_object_reference(
|
void split_object_reference(
|
||||||
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds);
|
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds);
|
||||||
|
|
||||||
|
@@ -69,7 +69,7 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali
|
|||||||
const int packed_type = ref.prim_type();
|
const int packed_type = ref.prim_type();
|
||||||
const int type = (packed_type & PRIMITIVE_ALL);
|
const int type = (packed_type & PRIMITIVE_ALL);
|
||||||
/* No motion blur curves here, we can't fit them to aligned boxes well. */
|
/* No motion blur curves here, we can't fit them to aligned boxes well. */
|
||||||
if ((type & PRIMITIVE_CURVE) && !(type & PRIMITIVE_MOTION)) {
|
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
|
||||||
const int curve_index = ref.prim_index();
|
const int curve_index = ref.prim_index();
|
||||||
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
|
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
|
||||||
const Hair *hair = static_cast<const Hair *>(object->get_geometry());
|
const Hair *hair = static_cast<const Hair *>(object->get_geometry());
|
||||||
@@ -95,7 +95,7 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim,
|
|||||||
const int packed_type = prim.prim_type();
|
const int packed_type = prim.prim_type();
|
||||||
const int type = (packed_type & PRIMITIVE_ALL);
|
const int type = (packed_type & PRIMITIVE_ALL);
|
||||||
/* No motion blur curves here, we can't fit them to aligned boxes well. */
|
/* No motion blur curves here, we can't fit them to aligned boxes well. */
|
||||||
if ((type & PRIMITIVE_CURVE) && !(type & PRIMITIVE_MOTION)) {
|
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
|
||||||
const int curve_index = prim.prim_index();
|
const int curve_index = prim.prim_index();
|
||||||
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
|
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
|
||||||
const Hair *hair = static_cast<const Hair *>(object->get_geometry());
|
const Hair *hair = static_cast<const Hair *>(object->get_geometry());
|
||||||
|
@@ -551,23 +551,4 @@ if(NOT WITH_HIP_DYNLOAD)
|
|||||||
set(WITH_HIP_DYNLOAD ON)
|
set(WITH_HIP_DYNLOAD ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
###########################################################################
|
|
||||||
# Metal
|
|
||||||
###########################################################################
|
|
||||||
|
|
||||||
if(WITH_CYCLES_DEVICE_METAL)
|
|
||||||
find_library(METAL_LIBRARY Metal)
|
|
||||||
|
|
||||||
# This file was added in the 12.0 SDK, use it as a way to detect the version.
|
|
||||||
if (METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
|
|
||||||
message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL")
|
|
||||||
set(WITH_CYCLES_DEVICE_METAL OFF)
|
|
||||||
elseif (NOT METAL_LIBRARY)
|
|
||||||
message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL")
|
|
||||||
set(WITH_CYCLES_DEVICE_METAL OFF)
|
|
||||||
else()
|
|
||||||
message(STATUS "Found Metal: ${METAL_LIBRARY}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
unset(_cycles_lib_dir)
|
unset(_cycles_lib_dir)
|
||||||
|
@@ -88,7 +88,7 @@ endmacro()
|
|||||||
|
|
||||||
function(cycles_link_directories)
|
function(cycles_link_directories)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
|
# APPLE plaform uses full paths for linking libraries, and avoids link_directories.
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -168,6 +168,12 @@ macro(cycles_target_link_libraries target)
|
|||||||
target_link_libraries(${target} extern_hipew)
|
target_link_libraries(${target} extern_hipew)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CYCLES_STANDALONE_REPOSITORY)
|
||||||
|
target_link_libraries(${target} extern_numaapi)
|
||||||
|
else()
|
||||||
|
target_link_libraries(${target} bf_intern_numaapi)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
if(CYCLES_STANDALONE_REPOSITORY)
|
if(CYCLES_STANDALONE_REPOSITORY)
|
||||||
target_link_libraries(${target} extern_libc_compat)
|
target_link_libraries(${target} extern_libc_compat)
|
||||||
|
@@ -43,7 +43,7 @@ if(WITH_CYCLES_DEVICE_HIP AND WITH_HIP_DYNLOAD)
|
|||||||
add_definitions(-DWITH_HIP_DYNLOAD)
|
add_definitions(-DWITH_HIP_DYNLOAD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SRC_BASE
|
set(SRC
|
||||||
device.cpp
|
device.cpp
|
||||||
denoise.cpp
|
denoise.cpp
|
||||||
graphics_interop.cpp
|
graphics_interop.cpp
|
||||||
@@ -104,21 +104,6 @@ set(SRC_MULTI
|
|||||||
multi/device.h
|
multi/device.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SRC_METAL
|
|
||||||
metal/bvh.mm
|
|
||||||
metal/bvh.h
|
|
||||||
metal/device.mm
|
|
||||||
metal/device.h
|
|
||||||
metal/device_impl.mm
|
|
||||||
metal/device_impl.h
|
|
||||||
metal/kernel.mm
|
|
||||||
metal/kernel.h
|
|
||||||
metal/queue.mm
|
|
||||||
metal/queue.h
|
|
||||||
metal/util.mm
|
|
||||||
metal/util.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(SRC_OPTIX
|
set(SRC_OPTIX
|
||||||
optix/device.cpp
|
optix/device.cpp
|
||||||
optix/device.h
|
optix/device.h
|
||||||
@@ -138,17 +123,6 @@ set(SRC_HEADERS
|
|||||||
queue.h
|
queue.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
|
||||||
${SRC_BASE}
|
|
||||||
${SRC_CPU}
|
|
||||||
${SRC_CUDA}
|
|
||||||
${SRC_HIP}
|
|
||||||
${SRC_DUMMY}
|
|
||||||
${SRC_MULTI}
|
|
||||||
${SRC_OPTIX}
|
|
||||||
${SRC_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
set(LIB
|
set(LIB
|
||||||
cycles_kernel
|
cycles_kernel
|
||||||
cycles_util
|
cycles_util
|
||||||
@@ -184,15 +158,6 @@ endif()
|
|||||||
if(WITH_CYCLES_DEVICE_OPTIX)
|
if(WITH_CYCLES_DEVICE_OPTIX)
|
||||||
add_definitions(-DWITH_OPTIX)
|
add_definitions(-DWITH_OPTIX)
|
||||||
endif()
|
endif()
|
||||||
if(WITH_CYCLES_DEVICE_METAL)
|
|
||||||
list(APPEND LIB
|
|
||||||
${METAL_LIBRARY}
|
|
||||||
)
|
|
||||||
add_definitions(-DWITH_METAL)
|
|
||||||
list(APPEND SRC
|
|
||||||
${SRC_METAL}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_OPENIMAGEDENOISE)
|
if(WITH_OPENIMAGEDENOISE)
|
||||||
list(APPEND LIB
|
list(APPEND LIB
|
||||||
@@ -203,12 +168,20 @@ endif()
|
|||||||
include_directories(${INC})
|
include_directories(${INC})
|
||||||
include_directories(SYSTEM ${INC_SYS})
|
include_directories(SYSTEM ${INC_SYS})
|
||||||
|
|
||||||
cycles_add_library(cycles_device "${LIB}" ${SRC})
|
cycles_add_library(cycles_device "${LIB}"
|
||||||
|
${SRC}
|
||||||
|
${SRC_CPU}
|
||||||
|
${SRC_CUDA}
|
||||||
|
${SRC_HIP}
|
||||||
|
${SRC_DUMMY}
|
||||||
|
${SRC_MULTI}
|
||||||
|
${SRC_OPTIX}
|
||||||
|
${SRC_HEADERS}
|
||||||
|
)
|
||||||
|
|
||||||
source_group("cpu" FILES ${SRC_CPU})
|
source_group("cpu" FILES ${SRC_CPU})
|
||||||
source_group("cuda" FILES ${SRC_CUDA})
|
source_group("cuda" FILES ${SRC_CUDA})
|
||||||
source_group("dummy" FILES ${SRC_DUMMY})
|
source_group("dummy" FILES ${SRC_DUMMY})
|
||||||
source_group("multi" FILES ${SRC_MULTI})
|
source_group("multi" FILES ${SRC_MULTI})
|
||||||
source_group("metal" FILES ${SRC_METAL})
|
|
||||||
source_group("optix" FILES ${SRC_OPTIX})
|
source_group("optix" FILES ${SRC_OPTIX})
|
||||||
source_group("common" FILES ${SRC} ${SRC_HEADERS})
|
source_group("common" FILES ${SRC} ${SRC_HEADERS})
|
||||||
|
@@ -38,6 +38,7 @@ void device_cpu_info(vector<DeviceInfo> &devices)
|
|||||||
info.id = "CPU";
|
info.id = "CPU";
|
||||||
info.num = 0;
|
info.num = 0;
|
||||||
info.has_osl = true;
|
info.has_osl = true;
|
||||||
|
info.has_half_images = true;
|
||||||
info.has_nanovdb = true;
|
info.has_nanovdb = true;
|
||||||
info.has_profiling = true;
|
info.has_profiling = true;
|
||||||
if (openimagedenoise_supported()) {
|
if (openimagedenoise_supported()) {
|
||||||
|
@@ -93,6 +93,11 @@ CPUDevice::~CPUDevice()
|
|||||||
texture_info.free();
|
texture_info.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPUDevice::show_samples() const
|
||||||
|
{
|
||||||
|
return (info.cpu_threads == 1);
|
||||||
|
}
|
||||||
|
|
||||||
BVHLayoutMask CPUDevice::get_bvh_layout_mask() const
|
BVHLayoutMask CPUDevice::get_bvh_layout_mask() const
|
||||||
{
|
{
|
||||||
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
|
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
|
||||||
@@ -273,8 +278,7 @@ void CPUDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
|
|||||||
{
|
{
|
||||||
#ifdef WITH_EMBREE
|
#ifdef WITH_EMBREE
|
||||||
if (bvh->params.bvh_layout == BVH_LAYOUT_EMBREE ||
|
if (bvh->params.bvh_layout == BVH_LAYOUT_EMBREE ||
|
||||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE ||
|
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE) {
|
||||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL_EMBREE) {
|
|
||||||
BVHEmbree *const bvh_embree = static_cast<BVHEmbree *>(bvh);
|
BVHEmbree *const bvh_embree = static_cast<BVHEmbree *>(bvh);
|
||||||
if (refit) {
|
if (refit) {
|
||||||
bvh_embree->refit(progress);
|
bvh_embree->refit(progress);
|
||||||
|
@@ -60,6 +60,8 @@ class CPUDevice : public Device {
|
|||||||
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_);
|
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_);
|
||||||
~CPUDevice();
|
~CPUDevice();
|
||||||
|
|
||||||
|
virtual bool show_samples() const override;
|
||||||
|
|
||||||
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
||||||
|
|
||||||
/* Returns true if the texture info was copied to the device (meaning, some more
|
/* Returns true if the texture info was copied to the device (meaning, some more
|
||||||
|
@@ -144,6 +144,7 @@ void device_cuda_info(vector<DeviceInfo> &devices)
|
|||||||
info.description = string(name);
|
info.description = string(name);
|
||||||
info.num = num;
|
info.num = num;
|
||||||
|
|
||||||
|
info.has_half_images = (major >= 3);
|
||||||
info.has_nanovdb = true;
|
info.has_nanovdb = true;
|
||||||
info.denoisers = 0;
|
info.denoisers = 0;
|
||||||
|
|
||||||
|
@@ -46,6 +46,12 @@ bool CUDADevice::have_precompiled_kernels()
|
|||||||
return path_exists(cubins_path);
|
return path_exists(cubins_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CUDADevice::show_samples() const
|
||||||
|
{
|
||||||
|
/* The CUDADevice only processes one tile at a time, so showing samples is fine. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BVHLayoutMask CUDADevice::get_bvh_layout_mask() const
|
BVHLayoutMask CUDADevice::get_bvh_layout_mask() const
|
||||||
{
|
{
|
||||||
return BVH_LAYOUT_BVH2;
|
return BVH_LAYOUT_BVH2;
|
||||||
@@ -236,10 +242,6 @@ string CUDADevice::compile_kernel_get_common_cflags(const uint kernel_features)
|
|||||||
cflags += " -DWITH_NANOVDB";
|
cflags += " -DWITH_NANOVDB";
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef WITH_CYCLES_DEBUG
|
|
||||||
cflags += " -DWITH_CYCLES_DEBUG";
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return cflags;
|
return cflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,10 +479,10 @@ void CUDADevice::reserve_local_memory(const uint kernel_features)
|
|||||||
* still to make it faster. */
|
* still to make it faster. */
|
||||||
CUDADeviceQueue queue(this);
|
CUDADeviceQueue queue(this);
|
||||||
|
|
||||||
device_ptr d_path_index = 0;
|
void *d_path_index = nullptr;
|
||||||
device_ptr d_render_buffer = 0;
|
void *d_render_buffer = nullptr;
|
||||||
int d_work_size = 0;
|
int d_work_size = 0;
|
||||||
DeviceKernelArguments args(&d_path_index, &d_render_buffer, &d_work_size);
|
void *args[] = {&d_path_index, &d_render_buffer, &d_work_size};
|
||||||
|
|
||||||
queue.init_execution();
|
queue.init_execution();
|
||||||
queue.enqueue(test_kernel, 1, args);
|
queue.enqueue(test_kernel, 1, args);
|
||||||
@@ -936,6 +938,7 @@ void CUDADevice::tex_alloc(device_texture &mem)
|
|||||||
{
|
{
|
||||||
CUDAContextScope scope(this);
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
|
/* General variables for both architectures */
|
||||||
string bind_name = mem.name;
|
string bind_name = mem.name;
|
||||||
size_t dsize = datatype_size(mem.data_type);
|
size_t dsize = datatype_size(mem.data_type);
|
||||||
size_t size = mem.memory_size();
|
size_t size = mem.memory_size();
|
||||||
@@ -1098,6 +1101,7 @@ void CUDADevice::tex_alloc(device_texture &mem)
|
|||||||
|
|
||||||
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
|
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
|
||||||
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
|
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
|
||||||
|
/* Kepler+, bindless textures. */
|
||||||
CUDA_RESOURCE_DESC resDesc;
|
CUDA_RESOURCE_DESC resDesc;
|
||||||
memset(&resDesc, 0, sizeof(resDesc));
|
memset(&resDesc, 0, sizeof(resDesc));
|
||||||
|
|
||||||
|
@@ -76,6 +76,8 @@ class CUDADevice : public Device {
|
|||||||
|
|
||||||
static bool have_precompiled_kernels();
|
static bool have_precompiled_kernels();
|
||||||
|
|
||||||
|
virtual bool show_samples() const override;
|
||||||
|
|
||||||
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
||||||
|
|
||||||
void set_error(const string &error) override;
|
void set_error(const string &error) override;
|
||||||
|
@@ -45,10 +45,8 @@ void CUDADeviceGraphicsInterop::set_display_interop(
|
|||||||
|
|
||||||
need_clear_ = display_interop.need_clear;
|
need_clear_ = display_interop.need_clear;
|
||||||
|
|
||||||
if (!display_interop.need_recreate) {
|
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
|
||||||
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CUDAContextScope scope(device_);
|
CUDAContextScope scope(device_);
|
||||||
|
@@ -89,9 +89,7 @@ bool CUDADeviceQueue::kernel_available(DeviceKernel kernel) const
|
|||||||
return cuda_device_->kernels.available(kernel);
|
return cuda_device_->kernels.available(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUDADeviceQueue::enqueue(DeviceKernel kernel,
|
bool CUDADeviceQueue::enqueue(DeviceKernel kernel, const int work_size, void *args[])
|
||||||
const int work_size,
|
|
||||||
DeviceKernelArguments const &args)
|
|
||||||
{
|
{
|
||||||
if (cuda_device_->have_error()) {
|
if (cuda_device_->have_error()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -135,7 +133,7 @@ bool CUDADeviceQueue::enqueue(DeviceKernel kernel,
|
|||||||
1,
|
1,
|
||||||
shared_mem_bytes,
|
shared_mem_bytes,
|
||||||
cuda_stream_,
|
cuda_stream_,
|
||||||
const_cast<void **>(args.values),
|
args,
|
||||||
0),
|
0),
|
||||||
"enqueue");
|
"enqueue");
|
||||||
|
|
||||||
|
@@ -42,9 +42,7 @@ class CUDADeviceQueue : public DeviceQueue {
|
|||||||
|
|
||||||
virtual bool kernel_available(DeviceKernel kernel) const override;
|
virtual bool kernel_available(DeviceKernel kernel) const override;
|
||||||
|
|
||||||
virtual bool enqueue(DeviceKernel kernel,
|
virtual bool enqueue(DeviceKernel kernel, const int work_size, void *args[]) override;
|
||||||
const int work_size,
|
|
||||||
DeviceKernelArguments const &args) override;
|
|
||||||
|
|
||||||
virtual bool synchronize() override;
|
virtual bool synchronize() override;
|
||||||
|
|
||||||
|
@@ -76,8 +76,6 @@ NODE_DEFINE(DenoiseParams)
|
|||||||
SOCKET_BOOLEAN(use_pass_albedo, "Use Pass Albedo", true);
|
SOCKET_BOOLEAN(use_pass_albedo, "Use Pass Albedo", true);
|
||||||
SOCKET_BOOLEAN(use_pass_normal, "Use Pass Normal", false);
|
SOCKET_BOOLEAN(use_pass_normal, "Use Pass Normal", false);
|
||||||
|
|
||||||
SOCKET_BOOLEAN(temporally_stable, "Temporally Stable", false);
|
|
||||||
|
|
||||||
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
|
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
|
@@ -72,9 +72,6 @@ class DenoiseParams : public Node {
|
|||||||
bool use_pass_albedo = true;
|
bool use_pass_albedo = true;
|
||||||
bool use_pass_normal = true;
|
bool use_pass_normal = true;
|
||||||
|
|
||||||
/* Configure the denoiser to use motion vectors, previous image and a temporally stable model. */
|
|
||||||
bool temporally_stable = false;
|
|
||||||
|
|
||||||
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
|
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
|
||||||
|
|
||||||
static const NodeEnum *get_type_enum();
|
static const NodeEnum *get_type_enum();
|
||||||
@@ -86,8 +83,7 @@ class DenoiseParams : public Node {
|
|||||||
{
|
{
|
||||||
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
|
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
|
||||||
use_pass_albedo == other.use_pass_albedo &&
|
use_pass_albedo == other.use_pass_albedo &&
|
||||||
use_pass_normal == other.use_pass_normal &&
|
use_pass_normal == other.use_pass_normal && prefilter == other.prefilter);
|
||||||
temporally_stable == other.temporally_stable && prefilter == other.prefilter);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
#include "device/cuda/device.h"
|
#include "device/cuda/device.h"
|
||||||
#include "device/dummy/device.h"
|
#include "device/dummy/device.h"
|
||||||
#include "device/hip/device.h"
|
#include "device/hip/device.h"
|
||||||
#include "device/metal/device.h"
|
|
||||||
#include "device/multi/device.h"
|
#include "device/multi/device.h"
|
||||||
#include "device/optix/device.h"
|
#include "device/optix/device.h"
|
||||||
|
|
||||||
@@ -37,7 +36,6 @@
|
|||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/system.h"
|
#include "util/system.h"
|
||||||
#include "util/task.h"
|
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
#include "util/types.h"
|
#include "util/types.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
@@ -51,7 +49,6 @@ vector<DeviceInfo> Device::cuda_devices;
|
|||||||
vector<DeviceInfo> Device::optix_devices;
|
vector<DeviceInfo> Device::optix_devices;
|
||||||
vector<DeviceInfo> Device::cpu_devices;
|
vector<DeviceInfo> Device::cpu_devices;
|
||||||
vector<DeviceInfo> Device::hip_devices;
|
vector<DeviceInfo> Device::hip_devices;
|
||||||
vector<DeviceInfo> Device::metal_devices;
|
|
||||||
uint Device::devices_initialized_mask = 0;
|
uint Device::devices_initialized_mask = 0;
|
||||||
|
|
||||||
/* Device */
|
/* Device */
|
||||||
@@ -108,12 +105,6 @@ Device *Device::create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
case DEVICE_METAL:
|
|
||||||
if (device_metal_init())
|
|
||||||
device = device_metal_create(info, stats, profiler);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -137,8 +128,6 @@ DeviceType Device::type_from_string(const char *name)
|
|||||||
return DEVICE_MULTI;
|
return DEVICE_MULTI;
|
||||||
else if (strcmp(name, "HIP") == 0)
|
else if (strcmp(name, "HIP") == 0)
|
||||||
return DEVICE_HIP;
|
return DEVICE_HIP;
|
||||||
else if (strcmp(name, "METAL") == 0)
|
|
||||||
return DEVICE_METAL;
|
|
||||||
|
|
||||||
return DEVICE_NONE;
|
return DEVICE_NONE;
|
||||||
}
|
}
|
||||||
@@ -155,8 +144,6 @@ string Device::string_from_type(DeviceType type)
|
|||||||
return "MULTI";
|
return "MULTI";
|
||||||
else if (type == DEVICE_HIP)
|
else if (type == DEVICE_HIP)
|
||||||
return "HIP";
|
return "HIP";
|
||||||
else if (type == DEVICE_METAL)
|
|
||||||
return "METAL";
|
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -174,9 +161,7 @@ vector<DeviceType> Device::available_types()
|
|||||||
#ifdef WITH_HIP
|
#ifdef WITH_HIP
|
||||||
types.push_back(DEVICE_HIP);
|
types.push_back(DEVICE_HIP);
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_METAL
|
|
||||||
types.push_back(DEVICE_METAL);
|
|
||||||
#endif
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,20 +227,6 @@ vector<DeviceInfo> Device::available_devices(uint mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
if (mask & DEVICE_MASK_METAL) {
|
|
||||||
if (!(devices_initialized_mask & DEVICE_MASK_METAL)) {
|
|
||||||
if (device_metal_init()) {
|
|
||||||
device_metal_info(metal_devices);
|
|
||||||
}
|
|
||||||
devices_initialized_mask |= DEVICE_MASK_METAL;
|
|
||||||
}
|
|
||||||
foreach (DeviceInfo &info, metal_devices) {
|
|
||||||
devices.push_back(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,15 +266,6 @@ string Device::device_capabilities(uint mask)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
if (mask & DEVICE_MASK_METAL) {
|
|
||||||
if (device_metal_init()) {
|
|
||||||
capabilities += "\nMetal device capabilities:\n";
|
|
||||||
capabilities += device_metal_capabilities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +286,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
|||||||
info.description = "Multi Device";
|
info.description = "Multi Device";
|
||||||
info.num = 0;
|
info.num = 0;
|
||||||
|
|
||||||
|
info.has_half_images = true;
|
||||||
info.has_nanovdb = true;
|
info.has_nanovdb = true;
|
||||||
info.has_osl = true;
|
info.has_osl = true;
|
||||||
info.has_profiling = true;
|
info.has_profiling = true;
|
||||||
@@ -334,7 +297,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
|||||||
/* Ensure CPU device does not slow down GPU. */
|
/* Ensure CPU device does not slow down GPU. */
|
||||||
if (device.type == DEVICE_CPU && subdevices.size() > 1) {
|
if (device.type == DEVICE_CPU && subdevices.size() > 1) {
|
||||||
if (background) {
|
if (background) {
|
||||||
int orig_cpu_threads = (threads) ? threads : TaskScheduler::num_threads();
|
int orig_cpu_threads = (threads) ? threads : system_cpu_thread_count();
|
||||||
int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
|
int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
|
||||||
|
|
||||||
VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads
|
VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads
|
||||||
@@ -370,6 +333,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Accumulate device info. */
|
/* Accumulate device info. */
|
||||||
|
info.has_half_images &= device.has_half_images;
|
||||||
info.has_nanovdb &= device.has_nanovdb;
|
info.has_nanovdb &= device.has_nanovdb;
|
||||||
info.has_osl &= device.has_osl;
|
info.has_osl &= device.has_osl;
|
||||||
info.has_profiling &= device.has_profiling;
|
info.has_profiling &= device.has_profiling;
|
||||||
@@ -392,7 +356,6 @@ void Device::free_memory()
|
|||||||
optix_devices.free_memory();
|
optix_devices.free_memory();
|
||||||
hip_devices.free_memory();
|
hip_devices.free_memory();
|
||||||
cpu_devices.free_memory();
|
cpu_devices.free_memory();
|
||||||
metal_devices.free_memory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<DeviceQueue> Device::gpu_queue_create()
|
unique_ptr<DeviceQueue> Device::gpu_queue_create()
|
||||||
|
@@ -52,7 +52,6 @@ enum DeviceType {
|
|||||||
DEVICE_MULTI,
|
DEVICE_MULTI,
|
||||||
DEVICE_OPTIX,
|
DEVICE_OPTIX,
|
||||||
DEVICE_HIP,
|
DEVICE_HIP,
|
||||||
DEVICE_METAL,
|
|
||||||
DEVICE_DUMMY,
|
DEVICE_DUMMY,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +60,6 @@ enum DeviceTypeMask {
|
|||||||
DEVICE_MASK_CUDA = (1 << DEVICE_CUDA),
|
DEVICE_MASK_CUDA = (1 << DEVICE_CUDA),
|
||||||
DEVICE_MASK_OPTIX = (1 << DEVICE_OPTIX),
|
DEVICE_MASK_OPTIX = (1 << DEVICE_OPTIX),
|
||||||
DEVICE_MASK_HIP = (1 << DEVICE_HIP),
|
DEVICE_MASK_HIP = (1 << DEVICE_HIP),
|
||||||
DEVICE_MASK_METAL = (1 << DEVICE_METAL),
|
|
||||||
DEVICE_MASK_ALL = ~0
|
DEVICE_MASK_ALL = ~0
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,6 +73,7 @@ class DeviceInfo {
|
|||||||
int num;
|
int num;
|
||||||
bool display_device; /* GPU is used as a display device. */
|
bool display_device; /* GPU is used as a display device. */
|
||||||
bool has_nanovdb; /* Support NanoVDB volumes. */
|
bool has_nanovdb; /* Support NanoVDB volumes. */
|
||||||
|
bool has_half_images; /* Support half-float textures. */
|
||||||
bool has_osl; /* Support Open Shading Language. */
|
bool has_osl; /* Support Open Shading Language. */
|
||||||
bool has_profiling; /* Supports runtime collection of profiling info. */
|
bool has_profiling; /* Supports runtime collection of profiling info. */
|
||||||
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
|
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
|
||||||
@@ -91,6 +90,7 @@ class DeviceInfo {
|
|||||||
num = 0;
|
num = 0;
|
||||||
cpu_threads = 0;
|
cpu_threads = 0;
|
||||||
display_device = false;
|
display_device = false;
|
||||||
|
has_half_images = false;
|
||||||
has_nanovdb = false;
|
has_nanovdb = false;
|
||||||
has_osl = false;
|
has_osl = false;
|
||||||
has_profiling = false;
|
has_profiling = false;
|
||||||
@@ -151,6 +151,10 @@ class Device {
|
|||||||
fprintf(stderr, "%s\n", error.c_str());
|
fprintf(stderr, "%s\n", error.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
virtual bool show_samples() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
|
virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
@@ -283,7 +287,6 @@ class Device {
|
|||||||
static vector<DeviceInfo> optix_devices;
|
static vector<DeviceInfo> optix_devices;
|
||||||
static vector<DeviceInfo> cpu_devices;
|
static vector<DeviceInfo> cpu_devices;
|
||||||
static vector<DeviceInfo> hip_devices;
|
static vector<DeviceInfo> hip_devices;
|
||||||
static vector<DeviceInfo> metal_devices;
|
|
||||||
static uint devices_initialized_mask;
|
static uint devices_initialized_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -148,6 +148,7 @@ void device_hip_info(vector<DeviceInfo> &devices)
|
|||||||
info.description = string(name);
|
info.description = string(name);
|
||||||
info.num = num;
|
info.num = num;
|
||||||
|
|
||||||
|
info.has_half_images = true;
|
||||||
info.has_nanovdb = true;
|
info.has_nanovdb = true;
|
||||||
info.denoisers = 0;
|
info.denoisers = 0;
|
||||||
|
|
||||||
|
@@ -47,6 +47,12 @@ bool HIPDevice::have_precompiled_kernels()
|
|||||||
return path_exists(fatbins_path);
|
return path_exists(fatbins_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HIPDevice::show_samples() const
|
||||||
|
{
|
||||||
|
/* The HIPDevice only processes one tile at a time, so showing samples is fine. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BVHLayoutMask HIPDevice::get_bvh_layout_mask() const
|
BVHLayoutMask HIPDevice::get_bvh_layout_mask() const
|
||||||
{
|
{
|
||||||
return BVH_LAYOUT_BVH2;
|
return BVH_LAYOUT_BVH2;
|
||||||
@@ -237,7 +243,7 @@ string HIPDevice::compile_kernel(const uint kernel_features, const char *name, c
|
|||||||
hipGetDeviceProperties(&props, hipDevId);
|
hipGetDeviceProperties(&props, hipDevId);
|
||||||
|
|
||||||
/* gcnArchName can contain tokens after the arch name with features, ie.
|
/* gcnArchName can contain tokens after the arch name with features, ie.
|
||||||
* `gfx1010:sramecc-:xnack-` so we tokenize it to get the first part. */
|
"gfx1010:sramecc-:xnack-" so we tokenize it to get the first part. */
|
||||||
char *arch = strtok(props.gcnArchName, ":");
|
char *arch = strtok(props.gcnArchName, ":");
|
||||||
if (arch == NULL) {
|
if (arch == NULL) {
|
||||||
arch = props.gcnArchName;
|
arch = props.gcnArchName;
|
||||||
@@ -368,9 +374,10 @@ string HIPDevice::compile_kernel(const uint kernel_features, const char *name, c
|
|||||||
|
|
||||||
bool HIPDevice::load_kernels(const uint kernel_features)
|
bool HIPDevice::load_kernels(const uint kernel_features)
|
||||||
{
|
{
|
||||||
/* TODO(sergey): Support kernels re-load for HIP devices adaptive compile.
|
/* TODO(sergey): Support kernels re-load for CUDA devices adaptive compile.
|
||||||
*
|
*
|
||||||
* Currently re-loading kernels will invalidate memory pointers.
|
* Currently re-loading kernel will invalidate memory pointers,
|
||||||
|
* causing problems in cuCtxSynchronize.
|
||||||
*/
|
*/
|
||||||
if (hipModule) {
|
if (hipModule) {
|
||||||
if (use_adaptive_compilation()) {
|
if (use_adaptive_compilation()) {
|
||||||
@@ -440,10 +447,10 @@ void HIPDevice::reserve_local_memory(const uint kernel_features)
|
|||||||
* still to make it faster. */
|
* still to make it faster. */
|
||||||
HIPDeviceQueue queue(this);
|
HIPDeviceQueue queue(this);
|
||||||
|
|
||||||
device_ptr d_path_index = 0;
|
void *d_path_index = nullptr;
|
||||||
device_ptr d_render_buffer = 0;
|
void *d_render_buffer = nullptr;
|
||||||
int d_work_size = 0;
|
int d_work_size = 0;
|
||||||
DeviceKernelArguments args(&d_path_index, &d_render_buffer, &d_work_size);
|
void *args[] = {&d_path_index, &d_render_buffer, &d_work_size};
|
||||||
|
|
||||||
queue.init_execution();
|
queue.init_execution();
|
||||||
queue.enqueue(test_kernel, 1, args);
|
queue.enqueue(test_kernel, 1, args);
|
||||||
@@ -892,6 +899,7 @@ void HIPDevice::tex_alloc(device_texture &mem)
|
|||||||
{
|
{
|
||||||
HIPContextScope scope(this);
|
HIPContextScope scope(this);
|
||||||
|
|
||||||
|
/* General variables for both architectures */
|
||||||
string bind_name = mem.name;
|
string bind_name = mem.name;
|
||||||
size_t dsize = datatype_size(mem.data_type);
|
size_t dsize = datatype_size(mem.data_type);
|
||||||
size_t size = mem.memory_size();
|
size_t size = mem.memory_size();
|
||||||
|
@@ -75,6 +75,8 @@ class HIPDevice : public Device {
|
|||||||
|
|
||||||
static bool have_precompiled_kernels();
|
static bool have_precompiled_kernels();
|
||||||
|
|
||||||
|
virtual bool show_samples() const override;
|
||||||
|
|
||||||
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
virtual BVHLayoutMask get_bvh_layout_mask() const override;
|
||||||
|
|
||||||
void set_error(const string &error) override;
|
void set_error(const string &error) override;
|
||||||
@@ -91,7 +93,9 @@ class HIPDevice : public Device {
|
|||||||
|
|
||||||
virtual string compile_kernel_get_common_cflags(const uint kernel_features);
|
virtual string compile_kernel_get_common_cflags(const uint kernel_features);
|
||||||
|
|
||||||
string compile_kernel(const uint kernel_features, const char *name, const char *base = "hip");
|
string compile_kernel(const uint kernel_features,
|
||||||
|
const char *name,
|
||||||
|
const char *base = "hip");
|
||||||
|
|
||||||
virtual bool load_kernels(const uint kernel_features) override;
|
virtual bool load_kernels(const uint kernel_features) override;
|
||||||
void reserve_local_memory(const uint kernel_features);
|
void reserve_local_memory(const uint kernel_features);
|
||||||
|
@@ -48,7 +48,7 @@ class HIPDeviceGraphicsInterop : public DeviceGraphicsInterop {
|
|||||||
HIPDeviceQueue *queue_ = nullptr;
|
HIPDeviceQueue *queue_ = nullptr;
|
||||||
HIPDevice *device_ = nullptr;
|
HIPDevice *device_ = nullptr;
|
||||||
|
|
||||||
/* OpenGL PBO which is currently registered as the destination for the HIP buffer. */
|
/* OpenGL PBO which is currently registered as the destination for the CUDA buffer. */
|
||||||
uint opengl_pbo_id_ = 0;
|
uint opengl_pbo_id_ = 0;
|
||||||
/* Buffer area in pixels of the corresponding PBO. */
|
/* Buffer area in pixels of the corresponding PBO. */
|
||||||
int64_t buffer_area_ = 0;
|
int64_t buffer_area_ = 0;
|
||||||
|
@@ -89,9 +89,7 @@ bool HIPDeviceQueue::kernel_available(DeviceKernel kernel) const
|
|||||||
return hip_device_->kernels.available(kernel);
|
return hip_device_->kernels.available(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
|
bool HIPDeviceQueue::enqueue(DeviceKernel kernel, const int work_size, void *args[])
|
||||||
const int work_size,
|
|
||||||
DeviceKernelArguments const &args)
|
|
||||||
{
|
{
|
||||||
if (hip_device_->have_error()) {
|
if (hip_device_->have_error()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -134,7 +132,7 @@ bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
|
|||||||
1,
|
1,
|
||||||
shared_mem_bytes,
|
shared_mem_bytes,
|
||||||
hip_stream_,
|
hip_stream_,
|
||||||
const_cast<void **>(args.values),
|
args,
|
||||||
0),
|
0),
|
||||||
"enqueue");
|
"enqueue");
|
||||||
|
|
||||||
|
@@ -42,9 +42,7 @@ class HIPDeviceQueue : public DeviceQueue {
|
|||||||
|
|
||||||
virtual bool kernel_available(DeviceKernel kernel) const override;
|
virtual bool kernel_available(DeviceKernel kernel) const override;
|
||||||
|
|
||||||
virtual bool enqueue(DeviceKernel kernel,
|
virtual bool enqueue(DeviceKernel kernel, const int work_size, void *args[]) override;
|
||||||
const int work_size,
|
|
||||||
DeviceKernelArguments const &args) override;
|
|
||||||
|
|
||||||
virtual bool synchronize() override;
|
virtual bool synchronize() override;
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
device_memory::device_memory(Device *device, const char *name, MemoryType type)
|
device_memory::device_memory(Device *device, const char *name, MemoryType type)
|
||||||
: data_type(device_type_traits<uchar>::data_type),
|
: data_type(device_type_traits<uchar>::data_type),
|
||||||
data_elements(device_type_traits<uchar>::num_elements),
|
data_elements(device_type_traits<uchar>::num_elements_cpu),
|
||||||
data_size(0),
|
data_size(0),
|
||||||
device_size(0),
|
device_size(0),
|
||||||
data_width(0),
|
data_width(0),
|
||||||
|
@@ -81,140 +81,155 @@ static constexpr size_t datatype_size(DataType datatype)
|
|||||||
|
|
||||||
template<typename T> struct device_type_traits {
|
template<typename T> struct device_type_traits {
|
||||||
static const DataType data_type = TYPE_UNKNOWN;
|
static const DataType data_type = TYPE_UNKNOWN;
|
||||||
static const size_t num_elements = sizeof(T);
|
static const size_t num_elements_cpu = sizeof(T);
|
||||||
|
static const size_t num_elements_gpu = sizeof(T);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uchar> {
|
template<> struct device_type_traits<uchar> {
|
||||||
static const DataType data_type = TYPE_UCHAR;
|
static const DataType data_type = TYPE_UCHAR;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(uchar) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(uchar) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uchar2> {
|
template<> struct device_type_traits<uchar2> {
|
||||||
static const DataType data_type = TYPE_UCHAR;
|
static const DataType data_type = TYPE_UCHAR;
|
||||||
static const size_t num_elements = 2;
|
static const size_t num_elements_cpu = 2;
|
||||||
static_assert(sizeof(uchar2) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 2;
|
||||||
|
static_assert(sizeof(uchar2) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uchar3> {
|
template<> struct device_type_traits<uchar3> {
|
||||||
static const DataType data_type = TYPE_UCHAR;
|
static const DataType data_type = TYPE_UCHAR;
|
||||||
static const size_t num_elements = 3;
|
static const size_t num_elements_cpu = 3;
|
||||||
static_assert(sizeof(uchar3) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 3;
|
||||||
|
static_assert(sizeof(uchar3) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uchar4> {
|
template<> struct device_type_traits<uchar4> {
|
||||||
static const DataType data_type = TYPE_UCHAR;
|
static const DataType data_type = TYPE_UCHAR;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(uchar4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(uchar4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint> {
|
template<> struct device_type_traits<uint> {
|
||||||
static const DataType data_type = TYPE_UINT;
|
static const DataType data_type = TYPE_UINT;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(uint) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(uint) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint2> {
|
template<> struct device_type_traits<uint2> {
|
||||||
static const DataType data_type = TYPE_UINT;
|
static const DataType data_type = TYPE_UINT;
|
||||||
static const size_t num_elements = 2;
|
static const size_t num_elements_cpu = 2;
|
||||||
static_assert(sizeof(uint2) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 2;
|
||||||
|
static_assert(sizeof(uint2) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint3> {
|
template<> struct device_type_traits<uint3> {
|
||||||
static const DataType data_type = TYPE_UINT;
|
static const DataType data_type = TYPE_UINT;
|
||||||
static const size_t num_elements = 3;
|
static const size_t num_elements_cpu = 3;
|
||||||
static_assert(sizeof(uint3) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 3;
|
||||||
|
static_assert(sizeof(uint3) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint4> {
|
template<> struct device_type_traits<uint4> {
|
||||||
static const DataType data_type = TYPE_UINT;
|
static const DataType data_type = TYPE_UINT;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(uint4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(uint4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<int> {
|
template<> struct device_type_traits<int> {
|
||||||
static const DataType data_type = TYPE_INT;
|
static const DataType data_type = TYPE_INT;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(int) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(int) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<int2> {
|
template<> struct device_type_traits<int2> {
|
||||||
static const DataType data_type = TYPE_INT;
|
static const DataType data_type = TYPE_INT;
|
||||||
static const size_t num_elements = 2;
|
static const size_t num_elements_cpu = 2;
|
||||||
static_assert(sizeof(int2) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 2;
|
||||||
|
static_assert(sizeof(int2) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<int3> {
|
template<> struct device_type_traits<int3> {
|
||||||
static const DataType data_type = TYPE_INT;
|
static const DataType data_type = TYPE_INT;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(int3) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 3;
|
||||||
|
static_assert(sizeof(int3) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<int4> {
|
template<> struct device_type_traits<int4> {
|
||||||
static const DataType data_type = TYPE_INT;
|
static const DataType data_type = TYPE_INT;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(int4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(int4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<float> {
|
template<> struct device_type_traits<float> {
|
||||||
static const DataType data_type = TYPE_FLOAT;
|
static const DataType data_type = TYPE_FLOAT;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(float) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(float) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<float2> {
|
template<> struct device_type_traits<float2> {
|
||||||
static const DataType data_type = TYPE_FLOAT;
|
static const DataType data_type = TYPE_FLOAT;
|
||||||
static const size_t num_elements = 2;
|
static const size_t num_elements_cpu = 2;
|
||||||
static_assert(sizeof(float2) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 2;
|
||||||
|
static_assert(sizeof(float2) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<float3> {
|
template<> struct device_type_traits<float3> {
|
||||||
/* float3 has different size depending on the device, can't use it for interchanging
|
|
||||||
* memory between CPU and GPU.
|
|
||||||
*
|
|
||||||
* Leave body empty to trigger a compile error if used. */
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct device_type_traits<packed_float3> {
|
|
||||||
static const DataType data_type = TYPE_FLOAT;
|
static const DataType data_type = TYPE_FLOAT;
|
||||||
static const size_t num_elements = 3;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(packed_float3) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 3;
|
||||||
|
static_assert(sizeof(float3) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<float4> {
|
template<> struct device_type_traits<float4> {
|
||||||
static const DataType data_type = TYPE_FLOAT;
|
static const DataType data_type = TYPE_FLOAT;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(float4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(float4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<half> {
|
template<> struct device_type_traits<half> {
|
||||||
static const DataType data_type = TYPE_HALF;
|
static const DataType data_type = TYPE_HALF;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(half) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(half) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<ushort4> {
|
template<> struct device_type_traits<ushort4> {
|
||||||
static const DataType data_type = TYPE_UINT16;
|
static const DataType data_type = TYPE_UINT16;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(ushort4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(ushort4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint16_t> {
|
template<> struct device_type_traits<uint16_t> {
|
||||||
static const DataType data_type = TYPE_UINT16;
|
static const DataType data_type = TYPE_UINT16;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(uint16_t) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(uint16_t) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<half4> {
|
template<> struct device_type_traits<half4> {
|
||||||
static const DataType data_type = TYPE_HALF;
|
static const DataType data_type = TYPE_HALF;
|
||||||
static const size_t num_elements = 4;
|
static const size_t num_elements_cpu = 4;
|
||||||
static_assert(sizeof(half4) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 4;
|
||||||
|
static_assert(sizeof(half4) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct device_type_traits<uint64_t> {
|
template<> struct device_type_traits<uint64_t> {
|
||||||
static const DataType data_type = TYPE_UINT64;
|
static const DataType data_type = TYPE_UINT64;
|
||||||
static const size_t num_elements = 1;
|
static const size_t num_elements_cpu = 1;
|
||||||
static_assert(sizeof(uint64_t) == num_elements * datatype_size(data_type));
|
static const size_t num_elements_gpu = 1;
|
||||||
|
static_assert(sizeof(uint64_t) == num_elements_cpu * datatype_size(data_type));
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device Memory
|
/* Device Memory
|
||||||
@@ -263,7 +278,6 @@ class device_memory {
|
|||||||
friend class CUDADevice;
|
friend class CUDADevice;
|
||||||
friend class OptiXDevice;
|
friend class OptiXDevice;
|
||||||
friend class HIPDevice;
|
friend class HIPDevice;
|
||||||
friend class MetalDevice;
|
|
||||||
|
|
||||||
/* Only create through subclasses. */
|
/* Only create through subclasses. */
|
||||||
device_memory(Device *device, const char *name, MemoryType type);
|
device_memory(Device *device, const char *name, MemoryType type);
|
||||||
@@ -311,7 +325,9 @@ template<typename T> class device_only_memory : public device_memory {
|
|||||||
: device_memory(device, name, allow_host_memory_fallback ? MEM_READ_WRITE : MEM_DEVICE_ONLY)
|
: device_memory(device, name, allow_host_memory_fallback ? MEM_READ_WRITE : MEM_DEVICE_ONLY)
|
||||||
{
|
{
|
||||||
data_type = device_type_traits<T>::data_type;
|
data_type = device_type_traits<T>::data_type;
|
||||||
data_elements = max(device_type_traits<T>::num_elements, 1);
|
data_elements = max(device_is_cpu() ? device_type_traits<T>::num_elements_cpu :
|
||||||
|
device_type_traits<T>::num_elements_gpu,
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
|
device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
|
||||||
@@ -367,11 +383,15 @@ template<typename T> class device_only_memory : public device_memory {
|
|||||||
|
|
||||||
template<typename T> class device_vector : public device_memory {
|
template<typename T> class device_vector : public device_memory {
|
||||||
public:
|
public:
|
||||||
|
/* Can only use this for types that have the same size on CPU and GPU. */
|
||||||
|
static_assert(device_type_traits<T>::num_elements_cpu ==
|
||||||
|
device_type_traits<T>::num_elements_gpu);
|
||||||
|
|
||||||
device_vector(Device *device, const char *name, MemoryType type)
|
device_vector(Device *device, const char *name, MemoryType type)
|
||||||
: device_memory(device, name, type)
|
: device_memory(device, name, type)
|
||||||
{
|
{
|
||||||
data_type = device_type_traits<T>::data_type;
|
data_type = device_type_traits<T>::data_type;
|
||||||
data_elements = device_type_traits<T>::num_elements;
|
data_elements = device_type_traits<T>::num_elements_cpu;
|
||||||
modified = true;
|
modified = true;
|
||||||
need_realloc_ = true;
|
need_realloc_ = true;
|
||||||
|
|
||||||
@@ -582,7 +602,7 @@ template<typename T> class device_vector : public device_memory {
|
|||||||
* from an already allocated base memory. It is freed automatically when it
|
* from an already allocated base memory. It is freed automatically when it
|
||||||
* goes out of scope, which should happen before base memory is freed.
|
* goes out of scope, which should happen before base memory is freed.
|
||||||
*
|
*
|
||||||
* NOTE: some devices require offset and size of the sub_ptr to be properly
|
* Note: some devices require offset and size of the sub_ptr to be properly
|
||||||
* aligned to device->mem_address_alingment(). */
|
* aligned to device->mem_address_alingment(). */
|
||||||
|
|
||||||
class device_sub_ptr {
|
class device_sub_ptr {
|
||||||
|
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Blender Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef WITH_METAL
|
|
||||||
|
|
||||||
# include "bvh/bvh.h"
|
|
||||||
# include "bvh/params.h"
|
|
||||||
# include "device/memory.h"
|
|
||||||
|
|
||||||
# include <Metal/Metal.h>
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
class BVHMetal : public BVH {
|
|
||||||
public:
|
|
||||||
API_AVAILABLE(macos(11.0))
|
|
||||||
id<MTLAccelerationStructure> accel_struct = nil;
|
|
||||||
bool accel_struct_building = false;
|
|
||||||
|
|
||||||
API_AVAILABLE(macos(11.0))
|
|
||||||
vector<id<MTLAccelerationStructure>> blas_array;
|
|
||||||
|
|
||||||
bool motion_blur = false;
|
|
||||||
|
|
||||||
Stats &stats;
|
|
||||||
|
|
||||||
bool build(Progress &progress, id<MTLDevice> device, id<MTLCommandQueue> queue, bool refit);
|
|
||||||
|
|
||||||
BVHMetal(const BVHParams ¶ms,
|
|
||||||
const vector<Geometry *> &geometry,
|
|
||||||
const vector<Object *> &objects,
|
|
||||||
Device *device);
|
|
||||||
virtual ~BVHMetal();
|
|
||||||
|
|
||||||
bool build_BLAS(Progress &progress, id<MTLDevice> device, id<MTLCommandQueue> queue, bool refit);
|
|
||||||
bool build_BLAS_mesh(Progress &progress,
|
|
||||||
id<MTLDevice> device,
|
|
||||||
id<MTLCommandQueue> queue,
|
|
||||||
Geometry *const geom,
|
|
||||||
bool refit);
|
|
||||||
bool build_BLAS_hair(Progress &progress,
|
|
||||||
id<MTLDevice> device,
|
|
||||||
id<MTLCommandQueue> queue,
|
|
||||||
Geometry *const geom,
|
|
||||||
bool refit);
|
|
||||||
bool build_TLAS(Progress &progress, id<MTLDevice> device, id<MTLCommandQueue> queue, bool refit);
|
|
||||||
};
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
|
||||||
|
|
||||||
#endif /* WITH_METAL */
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user