Compare commits
6 Commits
tmp-new-gp
...
temp-3d-te
Author | SHA1 | Date | |
---|---|---|---|
01c1fdd30f | |||
489f334dd6 | |||
ea7edbd467 | |||
b319c2f63c | |||
9b6a4ce1c3 | |||
277c7d96ee |
@@ -205,7 +205,6 @@ ForEachMacros:
|
||||
- FOREACH_SCENE_COLLECTION_BEGIN
|
||||
- FOREACH_SCENE_OBJECT_BEGIN
|
||||
- FOREACH_SELECTED_BASE_BEGIN
|
||||
- FOREACH_SELECTED_BEZT_BEGIN
|
||||
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN
|
||||
- FOREACH_SELECTED_OBJECT_BEGIN
|
||||
- FOREACH_TRANS_DATA_CONTAINER
|
||||
@@ -269,7 +268,6 @@ ForEachMacros:
|
||||
StatementMacros:
|
||||
- PyObject_HEAD
|
||||
- PyObject_VAR_HEAD
|
||||
- ccl_gpu_kernel_postfix
|
||||
|
||||
MacroBlockBegin: "^BSDF_CLOSURE_CLASS_BEGIN$"
|
||||
MacroBlockEnd: "^BSDF_CLOSURE_CLASS_END$"
|
||||
|
@@ -256,7 +256,7 @@ endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
|
||||
else()
|
||||
# not an option for other OS's
|
||||
@@ -284,7 +284,6 @@ option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON)
|
||||
option(WITH_IMAGE_DDS "Enable DDS Image Support" ON)
|
||||
option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON)
|
||||
option(WITH_IMAGE_HDR "Enable HDR Image Support" ON)
|
||||
option(WITH_IMAGE_WEBP "Enable WebP Image Support" OFF)
|
||||
|
||||
# Audio/Video format support
|
||||
option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON)
|
||||
@@ -409,8 +408,6 @@ option(WITH_CYCLES_DEBUG "Build Cycles with options useful for debug
|
||||
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
|
||||
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
|
||||
|
||||
option(WITH_CYCLES_HYDRA_RENDER_DELEGATE "Build Cycles Hydra render delegate" OFF)
|
||||
|
||||
option(WITH_CYCLES_DEBUG_NAN "Build Cycles with additional asserts for detecting NaNs and invalid values" OFF)
|
||||
option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" OFF)
|
||||
option(WITH_CYCLES_KERNEL_ASAN "Build Cycles kernels with address sanitizer when WITH_COMPILER_ASAN is on, even if it's very slow" OFF)
|
||||
@@ -505,7 +502,7 @@ else()
|
||||
set(WITH_EXPERIMENTAL_FEATURES OFF)
|
||||
endif()
|
||||
|
||||
# Unit testing
|
||||
# Unit testsing
|
||||
option(WITH_GTESTS "Enable GTest unit testing" OFF)
|
||||
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
|
||||
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
|
||||
@@ -534,19 +531,6 @@ mark_as_advanced(
|
||||
WITH_GPU_SHADER_BUILDER
|
||||
)
|
||||
|
||||
# Metal
|
||||
|
||||
if (APPLE)
|
||||
option(WITH_METAL_BACKEND "Use Metal for graphics instead of (or as well as) OpenGL on macOS." OFF)
|
||||
mark_as_advanced(WITH_METAL_BACKEND)
|
||||
else()
|
||||
set(WITH_METAL_BACKEND OFF)
|
||||
endif()
|
||||
|
||||
if (WITH_METAL_BACKEND)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
|
||||
mark_as_advanced(WITH_GL_ANGLE)
|
||||
@@ -745,10 +729,9 @@ endif()
|
||||
#-----------------------------------------------------------------------------
|
||||
# Check for conflicting/unsupported configurations
|
||||
|
||||
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE)
|
||||
message(FATAL_ERROR
|
||||
"At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE "
|
||||
"or WITH_CYCLES_HYDRA_RENDER_DELEGATE "
|
||||
"must be enabled, nothing to do!"
|
||||
)
|
||||
endif()
|
||||
@@ -883,7 +866,7 @@ if(WITH_CYCLES_DEVICE_HIP)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Check if submodules are cloned.
|
||||
# Check check if submodules are cloned
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/datafiles/locale")
|
||||
@@ -1291,16 +1274,6 @@ else()
|
||||
list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure Metal.
|
||||
if (WITH_METAL_BACKEND)
|
||||
add_definitions(-DWITH_METAL_BACKEND)
|
||||
|
||||
# No need to add frameworks here, all the ones we need for Metal and
|
||||
# Metal-OpenGL Interop are already being added by
|
||||
# build_files/cmake/platform/platform_apple.cmake
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure OpenMP.
|
||||
if(WITH_OPENMP)
|
||||
@@ -1695,8 +1668,6 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_BUT_SET_VARIABLE -Wno-unused-but-set-variable)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
|
||||
@@ -1911,13 +1882,15 @@ if(WITH_BLENDER)
|
||||
# source after intern and extern to gather all
|
||||
# internal and external library information first, for test linking
|
||||
add_subdirectory(source)
|
||||
elseif(WITH_CYCLES_STANDALONE OR WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
elseif(WITH_CYCLES_STANDALONE)
|
||||
add_subdirectory(intern/glew-mx)
|
||||
add_subdirectory(intern/guardedalloc)
|
||||
add_subdirectory(intern/libc_compat)
|
||||
add_subdirectory(intern/numaapi)
|
||||
add_subdirectory(intern/sky)
|
||||
|
||||
add_subdirectory(intern/cycles)
|
||||
add_subdirectory(extern/clew)
|
||||
if(WITH_CYCLES_LOGGING)
|
||||
if(NOT WITH_SYSTEM_GFLAGS)
|
||||
add_subdirectory(extern/gflags)
|
||||
@@ -1974,7 +1947,7 @@ if(FIRST_RUN)
|
||||
|
||||
set(_msg " - ${_setting}")
|
||||
string(LENGTH "${_msg}" _len)
|
||||
while("36" GREATER "${_len}")
|
||||
while("32" GREATER "${_len}")
|
||||
string(APPEND _msg " ")
|
||||
math(EXPR _len "${_len} + 1")
|
||||
endwhile()
|
||||
|
41
GNUmakefile
41
GNUmakefile
@@ -32,7 +32,7 @@ Other Convenience Targets
|
||||
* config: Run cmake configuration tool to set build options.
|
||||
* deps: Build library dependencies (intended only for platform maintainers).
|
||||
|
||||
The existence of locally build dependencies overrides the pre-built dependencies from subversion.
|
||||
The existance of locally build dependencies overrides the pre-built dependencies from subversion.
|
||||
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
|
||||
|
||||
Project Files
|
||||
@@ -51,13 +51,20 @@ Testing Targets
|
||||
|
||||
* test:
|
||||
Run automated tests with ctest.
|
||||
* test_cmake:
|
||||
Runs our own cmake file checker
|
||||
which detects errors in the cmake file list definitions
|
||||
* test_pep8:
|
||||
Checks all python script are pep8
|
||||
which are tagged to use the stricter formatting
|
||||
* test_deprecated:
|
||||
Checks for deprecation tags in our code which may need to be removed
|
||||
|
||||
Static Source Code Checking
|
||||
Not associated with building Blender.
|
||||
|
||||
* check_cppcheck: Run blender source through cppcheck (C & C++).
|
||||
* check_clang_array: Run blender source through clang array checking script (C & C++).
|
||||
* check_deprecated: Check if there is any deprecated code to remove.
|
||||
* check_splint: Run blenders source through splint (C only).
|
||||
* check_sparse: Run blenders source through sparse (C only).
|
||||
* check_smatch: Run blenders source through smatch (C only).
|
||||
@@ -66,10 +73,6 @@ Static Source Code Checking
|
||||
using one of the accepted licenses in 'doc/license/SPDX-license-identifiers.txt'
|
||||
Append with 'SHOW_HEADERS=1' to show all unique headers
|
||||
which can be useful for spotting license irregularities.
|
||||
* check_cmake: Runs our own cmake file checker which detects errors in the cmake file list definitions.
|
||||
* check_pep8: Checks all Python script are pep8 which are tagged to use the stricter formatting.
|
||||
* check_mypy: Checks all Python scripts using mypy,
|
||||
see: source/tools/check_source/check_mypy_config.py scripts which are included.
|
||||
|
||||
Spell Checkers
|
||||
This runs the spell checker from the developer tools repositor.
|
||||
@@ -397,6 +400,20 @@ package_archive: .FORCE
|
||||
test: .FORCE
|
||||
@$(PYTHON) ./build_files/utils/make_test.py "$(BUILD_DIR)"
|
||||
|
||||
# run pep8 check check on scripts we distribute.
|
||||
test_pep8: .FORCE
|
||||
@$(PYTHON) tests/python/pep8.py > test_pep8.log 2>&1
|
||||
@echo "written: test_pep8.log"
|
||||
|
||||
# run some checks on our CMAKE files.
|
||||
test_cmake: .FORCE
|
||||
@$(PYTHON) build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1
|
||||
@echo "written: test_cmake_consistency.log"
|
||||
|
||||
# run deprecation tests, see if we have anything to remove.
|
||||
test_deprecated: .FORCE
|
||||
@$(PYTHON) tests/check_deprecated.py
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Project Files
|
||||
@@ -474,23 +491,11 @@ check_descriptions: .FORCE
|
||||
@$(BLENDER_BIN) --background -noaudio --factory-startup --python \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
|
||||
|
||||
check_deprecated: .FORCE
|
||||
@PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
source/tools/check_source/check_deprecated.py
|
||||
|
||||
check_licenses: .FORCE
|
||||
@PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_licenses.py" \
|
||||
"--show-headers=$(SHOW_HEADERS)"
|
||||
|
||||
check_pep8: .FORCE
|
||||
@PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
tests/python/pep8.py
|
||||
|
||||
check_cmake: .FORCE
|
||||
@PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
source/tools/check_source/check_cmake_consistency.py
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Utilities
|
||||
|
@@ -1,16 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
## Update and uncomment this in the release branch
|
||||
# set(BLENDER_VERSION 3.1)
|
||||
|
||||
function(download_source dep)
|
||||
set(TARGET_FILE ${${dep}_FILE})
|
||||
set(TARGET_HASH_TYPE ${${dep}_HASH_TYPE})
|
||||
set(TARGET_HASH ${${dep}_HASH})
|
||||
if(PACKAGE_USE_UPSTREAM_SOURCES)
|
||||
set(TARGET_URI ${${dep}_URI})
|
||||
elseif(BLENDER_VERSION)
|
||||
set(TARGET_URI https://svn.blender.org/svnroot/bf-blender/tags/blender-${BLENDER_VERSION}-release/lib/packages/${TARGET_FILE})
|
||||
else()
|
||||
set(TARGET_URI https://svn.blender.org/svnroot/bf-blender/trunk/lib/packages/${TARGET_FILE})
|
||||
endif()
|
||||
|
@@ -52,14 +52,6 @@ add_dependencies(
|
||||
external_boost
|
||||
)
|
||||
|
||||
# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a".
|
||||
# See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01
|
||||
if (USD_VERSION VERSION_LESS 21.11)
|
||||
set(PXR_LIB_PREFIX "")
|
||||
else()
|
||||
set(PXR_LIB_PREFIX "usd_")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# USD currently demands python be available at build time
|
||||
# and then proceeds not to use it, but still checks that the
|
||||
@@ -73,14 +65,14 @@ if(WIN32)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_usd after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/ ${HARVEST_TARGET}/usd
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/${PXR_LIB_PREFIX}usd_m.lib ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/usd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
if(BUILD_MODE STREQUAL Debug)
|
||||
ExternalProject_Add_Step(external_usd after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/lib ${HARVEST_TARGET}/usd/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/${PXR_LIB_PREFIX}usd_m_d.lib ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/usd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
@@ -92,7 +84,7 @@ else()
|
||||
# case (only the shared library). As a result, we need to grab the `libusd_m.a`
|
||||
# file from the build directory instead of from the install directory.
|
||||
ExternalProject_Add_Step(external_usd after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/lib${PXR_LIB_PREFIX}usd_m.a ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m.a
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/libusd_m.a ${HARVEST_TARGET}/usd/lib/libusd_m.a
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,12 +32,9 @@ FIND_PATH(USD_INCLUDE_DIR
|
||||
DOC "Universal Scene Description (USD) header files"
|
||||
)
|
||||
|
||||
# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a".
|
||||
# See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01
|
||||
FIND_LIBRARY(USD_LIBRARY
|
||||
NAMES
|
||||
usd_usd_m usd_usd_ms usd_m usd_ms
|
||||
${PXR_LIB_PREFIX}usd
|
||||
usd_m usd_ms
|
||||
NAMES_PER_DIR
|
||||
HINTS
|
||||
${_usd_SEARCH_DIRS}
|
||||
|
@@ -1,77 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright 2022 Blender Foundation.
|
||||
|
||||
# - Find WebP library
|
||||
# Find the native WebP includes and library
|
||||
# This module defines
|
||||
# WEBP_INCLUDE_DIRS, where to find WebP headers, Set when WebP is found.
|
||||
# WEBP_LIBRARIES, libraries to link against to use WebP.
|
||||
# WEBP_ROOT_DIR, The base directory to search for WebP.
|
||||
# This can also be an environment variable.
|
||||
# WEBP_FOUND, If false, do not try to use WebP.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
# WEBP_LIBRARY, where to find the WEBP library.
|
||||
|
||||
# If WEBP_ROOT_DIR was defined in the environment, use it.
|
||||
IF(NOT WEBP_ROOT_DIR AND NOT $ENV{WEBP_ROOT_DIR} STREQUAL "")
|
||||
SET(WEBP_ROOT_DIR $ENV{WEBP_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_webp_SEARCH_DIRS
|
||||
${WEBP_ROOT_DIR}
|
||||
/opt/lib/webp
|
||||
)
|
||||
|
||||
FIND_PATH(WEBP_INCLUDE_DIR
|
||||
NAMES
|
||||
webp/types.h
|
||||
HINTS
|
||||
${_webp_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
SET(_webp_FIND_COMPONENTS
|
||||
webp
|
||||
webpmux
|
||||
webpdemux
|
||||
)
|
||||
|
||||
SET(_webp_LIBRARIES)
|
||||
FOREACH(COMPONENT ${_webp_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
||||
FIND_LIBRARY(WEBP_${UPPERCOMPONENT}_LIBRARY
|
||||
NAMES
|
||||
${COMPONENT}
|
||||
NAMES_PER_DIR
|
||||
HINTS
|
||||
${_webp_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib lib/static
|
||||
)
|
||||
LIST(APPEND _webp_LIBRARIES "${WEBP_${UPPERCOMPONENT}_LIBRARY}")
|
||||
ENDFOREACH()
|
||||
|
||||
IF(${WEBP_WEBP_LIBRARY_NOTFOUND})
|
||||
set(WEBP_FOUND FALSE)
|
||||
ELSE()
|
||||
# handle the QUIETLY and REQUIRED arguments and set WEBP_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WebP DEFAULT_MSG _webp_LIBRARIES WEBP_INCLUDE_DIR)
|
||||
|
||||
IF(WEBP_FOUND)
|
||||
get_filename_component(WEBP_LIBRARY_DIR ${WEBP_WEBP_LIBRARY} DIRECTORY)
|
||||
SET(WEBP_INCLUDE_DIRS ${WEBP_INCLUDE_DIR})
|
||||
SET(WEBP_LIBRARIES ${_webp_LIBRARIES})
|
||||
ELSE()
|
||||
SET(WEBPL_PUGIXML_FOUND FALSE)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
WEBP_INCLUDE_DIR
|
||||
WEBP_LIBRARY_DIR
|
||||
)
|
387
build_files/cmake/cmake_consistency_check.py
Executable file
387
build_files/cmake/cmake_consistency_check.py
Executable file
@@ -0,0 +1,387 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# Note: this code should be cleaned up / refactored.
|
||||
|
||||
import sys
|
||||
if sys.version_info.major < 3:
|
||||
print("\nPython3.x needed, found %s.\nAborting!\n" %
|
||||
sys.version.partition(" ")[0])
|
||||
sys.exit(1)
|
||||
|
||||
import os
|
||||
from os.path import (
|
||||
dirname,
|
||||
join,
|
||||
normpath,
|
||||
splitext,
|
||||
)
|
||||
|
||||
from cmake_consistency_check_config import (
|
||||
IGNORE_SOURCE,
|
||||
IGNORE_SOURCE_MISSING,
|
||||
IGNORE_CMAKE,
|
||||
UTF8_CHECK,
|
||||
SOURCE_DIR,
|
||||
BUILD_DIR,
|
||||
)
|
||||
|
||||
from typing import (
|
||||
Callable,
|
||||
Dict,
|
||||
Generator,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
)
|
||||
|
||||
|
||||
global_h = set()
|
||||
global_c = set()
|
||||
global_refs: Dict[str, List[Tuple[str, int]]] = {}
|
||||
|
||||
# Flatten `IGNORE_SOURCE_MISSING` to avoid nested looping.
|
||||
IGNORE_SOURCE_MISSING_FLAT = [
|
||||
(k, ignore_path) for k, ig_list in IGNORE_SOURCE_MISSING
|
||||
for ignore_path in ig_list
|
||||
]
|
||||
|
||||
# Ignore cmake file, path pairs.
|
||||
global_ignore_source_missing: Dict[str, List[str]] = {}
|
||||
for k, v in IGNORE_SOURCE_MISSING_FLAT:
|
||||
global_ignore_source_missing.setdefault(k, []).append(v)
|
||||
del IGNORE_SOURCE_MISSING_FLAT
|
||||
|
||||
|
||||
def replace_line(f: str, i: int, text: str, keep_indent: bool = True) -> None:
|
||||
file_handle = open(f, 'r')
|
||||
data = file_handle.readlines()
|
||||
file_handle.close()
|
||||
|
||||
l = data[i]
|
||||
ws = l[:len(l) - len(l.lstrip())]
|
||||
|
||||
data[i] = "%s%s\n" % (ws, text)
|
||||
|
||||
file_handle = open(f, 'w')
|
||||
file_handle.writelines(data)
|
||||
file_handle.close()
|
||||
|
||||
|
||||
def source_list(
|
||||
path: str,
|
||||
filename_check: Optional[Callable[[str], bool]] = None,
|
||||
) -> Generator[str, None, None]:
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
# skip '.git'
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
|
||||
for filename in filenames:
|
||||
if filename_check is None or filename_check(filename):
|
||||
yield os.path.join(dirpath, filename)
|
||||
|
||||
|
||||
# extension checking
|
||||
def is_cmake(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext == ".cmake") or (filename == "CMakeLists.txt")
|
||||
|
||||
|
||||
def is_c_header(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext in {".h", ".hpp", ".hxx", ".hh"})
|
||||
|
||||
|
||||
def is_c(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".metal"})
|
||||
|
||||
|
||||
def is_c_any(filename: str) -> bool:
|
||||
return is_c(filename) or is_c_header(filename)
|
||||
|
||||
|
||||
def cmake_get_src(f: str) -> None:
|
||||
|
||||
sources_h = []
|
||||
sources_c = []
|
||||
|
||||
filen = open(f, "r", encoding="utf8")
|
||||
it: Optional[Iterator[str]] = iter(filen)
|
||||
found = False
|
||||
i = 0
|
||||
# print(f)
|
||||
|
||||
def is_definition(l: str, f: str, i: int, name: str) -> bool:
|
||||
if l.startswith("unset("):
|
||||
return False
|
||||
|
||||
if ('set(%s' % name) in l or ('set(' in l and l.endswith(name)):
|
||||
if len(l.split()) > 1:
|
||||
raise Exception("strict formatting not kept 'set(%s*' %s:%d" % (name, f, i))
|
||||
return True
|
||||
|
||||
if ("list(APPEND %s" % name) in l or ('list(APPEND ' in l and l.endswith(name)):
|
||||
if l.endswith(")"):
|
||||
raise Exception("strict formatting not kept 'list(APPEND %s...)' on 1 line %s:%d" % (name, f, i))
|
||||
return True
|
||||
return False
|
||||
|
||||
while it is not None:
|
||||
context_name = ""
|
||||
while it is not None:
|
||||
i += 1
|
||||
try:
|
||||
l = next(it)
|
||||
except StopIteration:
|
||||
it = None
|
||||
break
|
||||
l = l.strip()
|
||||
if not l.startswith("#"):
|
||||
found = is_definition(l, f, i, "SRC")
|
||||
if found:
|
||||
context_name = "SRC"
|
||||
break
|
||||
found = is_definition(l, f, i, "INC")
|
||||
if found:
|
||||
context_name = "INC"
|
||||
break
|
||||
|
||||
if found:
|
||||
cmake_base = dirname(f)
|
||||
cmake_base_bin = os.path.join(BUILD_DIR, os.path.relpath(cmake_base, SOURCE_DIR))
|
||||
|
||||
# Find known missing sources list (if we have one).
|
||||
f_rel = os.path.relpath(f, SOURCE_DIR)
|
||||
f_rel_key = f_rel
|
||||
if os.sep != "/":
|
||||
f_rel_key = f_rel_key.replace(os.sep, "/")
|
||||
local_ignore_source_missing = global_ignore_source_missing.get(f_rel_key, [])
|
||||
|
||||
while it is not None:
|
||||
i += 1
|
||||
try:
|
||||
l = next(it)
|
||||
except StopIteration:
|
||||
it = None
|
||||
break
|
||||
|
||||
l = l.strip()
|
||||
|
||||
if not l.startswith("#"):
|
||||
|
||||
# Remove in-line comments.
|
||||
l = l.split(" # ")[0].rstrip()
|
||||
|
||||
if ")" in l:
|
||||
if l.strip() != ")":
|
||||
raise Exception("strict formatting not kept '*)' %s:%d" % (f, i))
|
||||
break
|
||||
|
||||
# replace dirs
|
||||
l = l.replace("${CMAKE_SOURCE_DIR}", SOURCE_DIR)
|
||||
l = l.replace("${CMAKE_CURRENT_SOURCE_DIR}", cmake_base)
|
||||
l = l.replace("${CMAKE_CURRENT_BINARY_DIR}", cmake_base_bin)
|
||||
l = l.strip('"')
|
||||
|
||||
if not l:
|
||||
pass
|
||||
elif l in local_ignore_source_missing:
|
||||
local_ignore_source_missing.remove(l)
|
||||
elif l.startswith("$"):
|
||||
if context_name == "SRC":
|
||||
# assume if it ends with context_name we know about it
|
||||
if not l.split("}")[0].endswith(context_name):
|
||||
print("Can't use var '%s' %s:%d" % (l, f, i))
|
||||
elif len(l.split()) > 1:
|
||||
raise Exception("Multi-line define '%s' %s:%d" % (l, f, i))
|
||||
else:
|
||||
new_file = normpath(join(cmake_base, l))
|
||||
|
||||
if context_name == "SRC":
|
||||
if is_c_header(new_file):
|
||||
sources_h.append(new_file)
|
||||
global_refs.setdefault(new_file, []).append((f, i))
|
||||
elif is_c(new_file):
|
||||
sources_c.append(new_file)
|
||||
global_refs.setdefault(new_file, []).append((f, i))
|
||||
elif l in {"PARENT_SCOPE", }:
|
||||
# cmake var, ignore
|
||||
pass
|
||||
elif new_file.endswith(".list"):
|
||||
pass
|
||||
elif new_file.endswith(".def"):
|
||||
pass
|
||||
elif new_file.endswith(".cl"): # opencl
|
||||
pass
|
||||
elif new_file.endswith(".cu"): # cuda
|
||||
pass
|
||||
elif new_file.endswith(".osl"): # open shading language
|
||||
pass
|
||||
elif new_file.endswith(".glsl"):
|
||||
pass
|
||||
else:
|
||||
raise Exception("unknown file type - not c or h %s -> %s" % (f, new_file))
|
||||
|
||||
elif context_name == "INC":
|
||||
if new_file.startswith(BUILD_DIR):
|
||||
# assume generated path
|
||||
pass
|
||||
elif os.path.isdir(new_file):
|
||||
new_path_rel = os.path.relpath(new_file, cmake_base)
|
||||
|
||||
if new_path_rel != l:
|
||||
print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel))
|
||||
|
||||
# # Save time. just replace the line
|
||||
# replace_line(f, i - 1, new_path_rel)
|
||||
|
||||
else:
|
||||
raise Exception("non existent include %s:%d -> %s" % (f, i, new_file))
|
||||
|
||||
# print(new_file)
|
||||
|
||||
global_h.update(set(sources_h))
|
||||
global_c.update(set(sources_c))
|
||||
'''
|
||||
if not sources_h and not sources_c:
|
||||
raise Exception("No sources %s" % f)
|
||||
|
||||
sources_h_fs = list(source_list(cmake_base, is_c_header))
|
||||
sources_c_fs = list(source_list(cmake_base, is_c))
|
||||
'''
|
||||
# find missing C files:
|
||||
'''
|
||||
for ff in sources_c_fs:
|
||||
if ff not in sources_c:
|
||||
print(" missing: " + ff)
|
||||
'''
|
||||
|
||||
# reset
|
||||
del sources_h[:]
|
||||
del sources_c[:]
|
||||
|
||||
filen.close()
|
||||
|
||||
|
||||
def is_ignore_source(f: str, ignore_used: List[bool]) -> bool:
|
||||
for index, ignore_path in enumerate(IGNORE_SOURCE):
|
||||
if ignore_path in f:
|
||||
ignore_used[index] = True
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_ignore_cmake(f: str, ignore_used: List[bool]) -> bool:
|
||||
for index, ignore_path in enumerate(IGNORE_CMAKE):
|
||||
if ignore_path in f:
|
||||
ignore_used[index] = True
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
print("Scanning:", SOURCE_DIR)
|
||||
|
||||
ignore_used_source = [False] * len(IGNORE_SOURCE)
|
||||
ignore_used_cmake = [False] * len(IGNORE_CMAKE)
|
||||
|
||||
for cmake in source_list(SOURCE_DIR, is_cmake):
|
||||
if not is_ignore_cmake(cmake, ignore_used_cmake):
|
||||
cmake_get_src(cmake)
|
||||
|
||||
# First do stupid check, do these files exist?
|
||||
print("\nChecking for missing references:")
|
||||
is_err = False
|
||||
errs = []
|
||||
for f in (global_h | global_c):
|
||||
if f.startswith(BUILD_DIR):
|
||||
continue
|
||||
|
||||
if not os.path.exists(f):
|
||||
refs = global_refs[f]
|
||||
if refs:
|
||||
for cf, i in refs:
|
||||
errs.append((cf, i))
|
||||
else:
|
||||
raise Exception("CMake references missing, internal error, aborting!")
|
||||
is_err = True
|
||||
|
||||
errs.sort()
|
||||
errs.reverse()
|
||||
for cf, i in errs:
|
||||
print("%s:%d" % (cf, i))
|
||||
# Write a 'sed' script, useful if we get a lot of these
|
||||
# print("sed '%dd' '%s' > '%s.tmp' ; mv '%s.tmp' '%s'" % (i, cf, cf, cf, cf))
|
||||
|
||||
if is_err:
|
||||
raise Exception("CMake references missing files, aborting!")
|
||||
del is_err
|
||||
del errs
|
||||
|
||||
# now check on files not accounted for.
|
||||
print("\nC/C++ Files CMake does not know about...")
|
||||
for cf in sorted(source_list(SOURCE_DIR, is_c)):
|
||||
if not is_ignore_source(cf, ignore_used_source):
|
||||
if cf not in global_c:
|
||||
print("missing_c: ", cf)
|
||||
|
||||
# Check if automake builds a corresponding .o file.
|
||||
'''
|
||||
if cf in global_c:
|
||||
out1 = os.path.splitext(cf)[0] + ".o"
|
||||
out2 = os.path.splitext(cf)[0] + ".Po"
|
||||
out2_dir, out2_file = out2 = os.path.split(out2)
|
||||
out2 = os.path.join(out2_dir, ".deps", out2_file)
|
||||
if not os.path.exists(out1) and not os.path.exists(out2):
|
||||
print("bad_c: ", cf)
|
||||
'''
|
||||
|
||||
print("\nC/C++ Headers CMake does not know about...")
|
||||
for hf in sorted(source_list(SOURCE_DIR, is_c_header)):
|
||||
if not is_ignore_source(hf, ignore_used_source):
|
||||
if hf not in global_h:
|
||||
print("missing_h: ", hf)
|
||||
|
||||
if UTF8_CHECK:
|
||||
# test encoding
|
||||
import traceback
|
||||
for files in (global_c, global_h):
|
||||
for f in sorted(files):
|
||||
if os.path.exists(f):
|
||||
# ignore outside of our source tree
|
||||
if "extern" not in f:
|
||||
i = 1
|
||||
try:
|
||||
for _ in open(f, "r", encoding="utf8"):
|
||||
i += 1
|
||||
except UnicodeDecodeError:
|
||||
print("Non utf8: %s:%d" % (f, i))
|
||||
if i > 1:
|
||||
traceback.print_exc()
|
||||
|
||||
# Check ignores aren't stale
|
||||
print("\nCheck for unused 'IGNORE_SOURCE' paths...")
|
||||
for index, ignore_path in enumerate(IGNORE_SOURCE):
|
||||
if not ignore_used_source[index]:
|
||||
print("unused ignore: %r" % ignore_path)
|
||||
|
||||
# Check ignores aren't stale
|
||||
print("\nCheck for unused 'IGNORE_SOURCE_MISSING' paths...")
|
||||
for k, v in sorted(global_ignore_source_missing.items()):
|
||||
for ignore_path in v:
|
||||
print("unused ignore: %r -> %r" % (ignore_path, k))
|
||||
|
||||
# Check ignores aren't stale
|
||||
print("\nCheck for unused 'IGNORE_CMAKE' paths...")
|
||||
for index, ignore_path in enumerate(IGNORE_CMAKE):
|
||||
if not ignore_used_cmake[index]:
|
||||
print("unused ignore: %r" % ignore_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
64
build_files/cmake/cmake_consistency_check_config.py
Normal file
64
build_files/cmake/cmake_consistency_check_config.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import os
|
||||
|
||||
IGNORE_SOURCE = (
|
||||
"/test/",
|
||||
"/tests/gtests/",
|
||||
"/release/",
|
||||
|
||||
# specific source files
|
||||
"extern/audaspace/",
|
||||
|
||||
# Use for `WIN32` only.
|
||||
"source/creator/blender_launcher_win32.c",
|
||||
|
||||
# specific source files
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp",
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp",
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp",
|
||||
"extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.cpp",
|
||||
"extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp",
|
||||
"extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp",
|
||||
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp",
|
||||
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp",
|
||||
|
||||
"doc/doxygen/doxygen.extern.h",
|
||||
"doc/doxygen/doxygen.intern.h",
|
||||
"doc/doxygen/doxygen.main.h",
|
||||
"doc/doxygen/doxygen.source.h",
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h",
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h",
|
||||
"extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h",
|
||||
"extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h",
|
||||
"extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h",
|
||||
"extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h",
|
||||
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h",
|
||||
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h",
|
||||
)
|
||||
|
||||
# Ignore cmake file, path pairs.
|
||||
IGNORE_SOURCE_MISSING = (
|
||||
( # Use for cycles stand-alone.
|
||||
"intern/cycles/util/CMakeLists.txt", (
|
||||
"../../third_party/numaapi/include",
|
||||
)),
|
||||
( # Use for `WITH_NANOVDB`.
|
||||
"intern/cycles/kernel/CMakeLists.txt", (
|
||||
"nanovdb/util/CSampleFromVoxels.h",
|
||||
"nanovdb/util/SampleFromVoxels.h",
|
||||
"nanovdb/NanoVDB.h",
|
||||
"nanovdb/CNanoVDB.h",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
IGNORE_CMAKE = (
|
||||
"extern/audaspace/CMakeLists.txt",
|
||||
)
|
||||
|
||||
UTF8_CHECK = True
|
||||
|
||||
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(os.path.dirname(__file__), "..", ".."))))
|
||||
|
||||
# doesn't have to exist, just use as reference
|
||||
BUILD_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(SOURCE_DIR, "..", "build"))))
|
@@ -879,7 +879,7 @@ function(delayed_install
|
||||
destination)
|
||||
|
||||
foreach(f ${files})
|
||||
if(IS_ABSOLUTE ${f} OR "${base}" STREQUAL "")
|
||||
if(IS_ABSOLUTE ${f})
|
||||
set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${f})
|
||||
else()
|
||||
set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f})
|
||||
|
@@ -106,8 +106,8 @@ if(WIN32)
|
||||
set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:medium)
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "blender-launcher" "Blender")
|
||||
set(CPACK_CREATE_DESKTOP_LINKS "blender-launcher" "Blender")
|
||||
set(CPACK_PACKAGE_EXECUTABLES "blender-launcher" "blender")
|
||||
set(CPACK_CREATE_DESKTOP_LINKS "blender-launcher" "blender")
|
||||
|
||||
include(CPack)
|
||||
|
||||
|
@@ -232,15 +232,6 @@ if(WITH_IMAGE_TIFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_WEBP)
|
||||
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
|
||||
find_package(WebP)
|
||||
if(NOT WEBP_FOUND)
|
||||
message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
|
||||
set(WITH_IMAGE_WEBP OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_BOOST)
|
||||
set(Boost_NO_BOOST_CMAKE ON)
|
||||
set(BOOST_ROOT ${LIBDIR}/boost)
|
||||
|
@@ -368,14 +368,6 @@ if(WITH_PUGIXML)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_WEBP)
|
||||
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
|
||||
find_package_wrapper(WebP)
|
||||
if(NOT WEBP_FOUND)
|
||||
set(WITH_IMAGE_WEBP OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENIMAGEIO)
|
||||
find_package_wrapper(OpenImageIO)
|
||||
set(OPENIMAGEIO_LIBRARIES
|
||||
@@ -857,45 +849,3 @@ if(WITH_COMPILER_CCACHE)
|
||||
set(WITH_COMPILER_CCACHE OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# On some platforms certain atomic operations are not possible with assembly and/or intrinsics and
|
||||
# they are emulated in software with locks. For example, on armel there is no intrinsics to grant
|
||||
# 64 bit atomic operations and STL library uses libatomic to offload software emulation of atomics
|
||||
# to.
|
||||
# This function will check whether libatomic is required and if so will configure linker flags.
|
||||
# If atomic operations are possible without libatomic then linker flags are left as-is.
|
||||
function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
|
||||
# Source which is used to enforce situation when software emulation of atomics is required.
|
||||
# Assume that using 64bit integer gives a definitive answer (as in, if 64bit atomic operations
|
||||
# are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible.
|
||||
set(_source
|
||||
"#include <atomic>
|
||||
#include <cstdint>
|
||||
int main(int argc, char **argv) {
|
||||
std::atomic<uint64_t> uint64; uint64++;
|
||||
return 0;
|
||||
}")
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITHOUT_LIBATOMIC)
|
||||
|
||||
if(NOT ATOMIC_OPS_WITHOUT_LIBATOMIC)
|
||||
# Compilation of the test program has failed.
|
||||
# Try it again with -latomic to see if this is what is needed, or whether something else is
|
||||
# going on.
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES atomic)
|
||||
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITH_LIBATOMIC)
|
||||
|
||||
if(ATOMIC_OPS_WITH_LIBATOMIC)
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -latomic" PARENT_SCOPE)
|
||||
else()
|
||||
# Atomic operations are required part of Blender and it is not possible to process forward.
|
||||
# We expect that either standard library or libatomic will make atomics to work. If both
|
||||
# cases has failed something fishy o na bigger scope is going on.
|
||||
message(FATAL_ERROR "Failed to detect required configuration for atomic operations")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
CONFIGURE_ATOMIC_LIB_IF_NEEDED()
|
||||
|
@@ -39,12 +39,12 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(WITH_WINDOWS_STRIPPED_PDB OFF)
|
||||
endif()
|
||||
else()
|
||||
if(WITH_BLENDER AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.28.29921) # MSVC 2019 16.9.16
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.28.29921) # MSVC 2019 16.9.16
|
||||
message(FATAL_ERROR "Compiler is unsupported, MSVC 2019 16.9.16 or newer is required for building blender.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_BLENDER AND NOT WITH_PYTHON_MODULE)
|
||||
if(NOT WITH_PYTHON_MODULE)
|
||||
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT blender)
|
||||
endif()
|
||||
|
||||
@@ -238,6 +238,7 @@ else()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED LIBDIR)
|
||||
|
||||
# Setup 64bit and 64bit windows systems
|
||||
if(CMAKE_CL_64)
|
||||
message(STATUS "64 bit compiler detected.")
|
||||
@@ -251,9 +252,6 @@ if(NOT DEFINED LIBDIR)
|
||||
elseif(MSVC_VERSION GREATER 1919)
|
||||
message(STATUS "Visual Studio 2019 detected.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||
elseif(MSVC_VERSION GREATER 1909)
|
||||
message(STATUS "Visual Studio 2017 detected.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||
@@ -302,8 +300,9 @@ set(ZLIB_INCLUDE_DIR ${LIBDIR}/zlib/include)
|
||||
set(ZLIB_LIBRARY ${LIBDIR}/zlib/lib/libz_st.lib)
|
||||
set(ZLIB_DIR ${LIBDIR}/zlib)
|
||||
|
||||
windows_find_package(ZLIB) # we want to find before finding things that depend on it like png
|
||||
windows_find_package(PNG)
|
||||
windows_find_package(zlib) # we want to find before finding things that depend on it like png
|
||||
windows_find_package(png)
|
||||
|
||||
if(NOT PNG_FOUND)
|
||||
warn_hardcoded_paths(libpng)
|
||||
set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include)
|
||||
@@ -314,9 +313,9 @@ if(NOT PNG_FOUND)
|
||||
endif()
|
||||
|
||||
set(JPEG_NAMES ${JPEG_NAMES} libjpeg)
|
||||
windows_find_package(JPEG REQUIRED)
|
||||
windows_find_package(jpeg REQUIRED)
|
||||
if(NOT JPEG_FOUND)
|
||||
warn_hardcoded_paths(libjpeg)
|
||||
warn_hardcoded_paths(jpeg)
|
||||
set(JPEG_INCLUDE_DIR ${LIBDIR}/jpeg/include)
|
||||
set(JPEG_LIBRARIES ${LIBDIR}/jpeg/lib/libjpeg.lib)
|
||||
endif()
|
||||
@@ -334,7 +333,7 @@ set(FREETYPE_LIBRARIES
|
||||
${LIBDIR}/brotli/lib/brotlidec-static.lib
|
||||
${LIBDIR}/brotli/lib/brotlicommon-static.lib
|
||||
)
|
||||
windows_find_package(Freetype REQUIRED)
|
||||
windows_find_package(freetype REQUIRED)
|
||||
|
||||
if(WITH_FFTW3)
|
||||
set(FFTW3 ${LIBDIR}/fftw3)
|
||||
@@ -343,16 +342,6 @@ if(WITH_FFTW3)
|
||||
set(FFTW3_LIBPATH ${FFTW3}/lib)
|
||||
endif()
|
||||
|
||||
windows_find_package(WebP)
|
||||
if(NOT WEBP_FOUND)
|
||||
if(EXISTS ${LIBDIR}/webp)
|
||||
set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
|
||||
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
|
||||
set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
|
||||
set(WEBP_FOUND ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLLADA)
|
||||
set(OPENCOLLADA ${LIBDIR}/opencollada)
|
||||
|
||||
@@ -400,9 +389,9 @@ if(WITH_CODEC_FFMPEG)
|
||||
${LIBDIR}/ffmpeg/include
|
||||
${LIBDIR}/ffmpeg/include/msvc
|
||||
)
|
||||
windows_find_package(FFmpeg)
|
||||
if(NOT FFmpeg_FOUND)
|
||||
warn_hardcoded_paths(FFmpeg)
|
||||
windows_find_package(FFMPEG)
|
||||
if(NOT FFMPEG_FOUND)
|
||||
warn_hardcoded_paths(ffmpeg)
|
||||
set(FFMPEG_LIBRARIES
|
||||
${LIBDIR}/ffmpeg/lib/avcodec.lib
|
||||
${LIBDIR}/ffmpeg/lib/avformat.lib
|
||||
@@ -414,10 +403,10 @@ if(WITH_CODEC_FFMPEG)
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_OPENEXR)
|
||||
windows_find_package(OpenEXR REQUIRED)
|
||||
if(NOT OpenEXR_FOUND)
|
||||
set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_VERSION "2.1")
|
||||
set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_VERSION "2.1")
|
||||
windows_find_package(OPENEXR REQUIRED)
|
||||
if(NOT OPENEXR_FOUND)
|
||||
warn_hardcoded_paths(OpenEXR)
|
||||
set(OPENEXR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
|
||||
@@ -531,20 +520,17 @@ if(WITH_BOOST)
|
||||
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
|
||||
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
|
||||
endif()
|
||||
|
||||
if(WITH_OPENIMAGEIO)
|
||||
windows_find_package(OpenImageIO)
|
||||
if(NOT OpenImageIO_FOUND)
|
||||
set(OPENIMAGEIO ${LIBDIR}/OpenImageIO)
|
||||
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
|
||||
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
|
||||
set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib)
|
||||
set(OIIO_DEBUG debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_d.lib debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util_d.lib)
|
||||
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
|
||||
endif()
|
||||
set(OPENIMAGEIO ${LIBDIR}/OpenImageIO)
|
||||
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
|
||||
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
|
||||
set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib)
|
||||
set(OIIO_DEBUG debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_d.lib debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util_d.lib)
|
||||
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
|
||||
|
||||
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
|
||||
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
|
||||
@@ -575,38 +561,31 @@ if(WITH_LLVM)
|
||||
message(WARNING "LLVM debug libs not present on this system. Using release libs for debug builds.")
|
||||
set(LLVM_LIBRARY ${LLVM_LIBRARY_OPTIMIZED})
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
windows_find_package(OpenColorIO)
|
||||
if(NOT OpenColorIO_FOUND)
|
||||
set(OPENCOLORIO ${LIBDIR}/OpenColorIO)
|
||||
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
|
||||
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
|
||||
set(OPENCOLORIO_LIBRARIES
|
||||
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
set(OPENCOLORIO ${LIBDIR}/OpenColorIO)
|
||||
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
|
||||
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
|
||||
set(OPENCOLORIO_LIBRARIES
|
||||
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
|
||||
)
|
||||
set(OPENCOLORIO_DEFINITIONS "-DOpenColorIO_SKIP_IMPORTS")
|
||||
endif()
|
||||
|
||||
if(WITH_OPENVDB)
|
||||
windows_find_package(OpenVDB)
|
||||
if(NOT OpenVDB_FOUND)
|
||||
set(OPENVDB ${LIBDIR}/openVDB)
|
||||
set(OPENVDB_LIBPATH ${OPENVDB}/lib)
|
||||
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
|
||||
set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib)
|
||||
endif()
|
||||
|
||||
set(OPENVDB ${LIBDIR}/openVDB)
|
||||
set(OPENVDB_LIBPATH ${OPENVDB}/lib)
|
||||
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
|
||||
set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib )
|
||||
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
@@ -645,24 +624,21 @@ if(WITH_IMAGE_OPENJPEG)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV)
|
||||
set(OPENSUBDIV_INCLUDE_DIRS ${LIBDIR}/opensubdiv/include)
|
||||
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
|
||||
)
|
||||
set(OPENSUBDIV_HAS_OPENMP TRUE)
|
||||
set(OPENSUBDIV_HAS_TBB FALSE)
|
||||
set(OPENSUBDIV_HAS_OPENCL TRUE)
|
||||
set(OPENSUBDIV_HAS_CUDA FALSE)
|
||||
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
|
||||
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
|
||||
windows_find_package(OpenSubdiv)
|
||||
if(NOT OpenSubdiv_FOUND)
|
||||
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
|
||||
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV}/include)
|
||||
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
|
||||
)
|
||||
set(OPENSUBDIV_HAS_OPENMP TRUE)
|
||||
set(OPENSUBDIV_HAS_TBB FALSE)
|
||||
set(OPENSUBDIV_HAS_OPENCL TRUE)
|
||||
set(OPENSUBDIV_HAS_CUDA FALSE)
|
||||
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
|
||||
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_SDL)
|
||||
@@ -683,15 +659,12 @@ if(WITH_SYSTEM_AUDASPACE)
|
||||
endif()
|
||||
|
||||
if(WITH_TBB)
|
||||
windows_find_package(TBB)
|
||||
if(NOT TBB_FOUND)
|
||||
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
|
||||
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
|
||||
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
|
||||
if(WITH_TBB_MALLOC_PROXY)
|
||||
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
|
||||
add_definitions(-DWITH_TBB_MALLOC)
|
||||
endif()
|
||||
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
|
||||
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
|
||||
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
|
||||
if(WITH_TBB_MALLOC_PROXY)
|
||||
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
|
||||
add_definitions(-DWITH_TBB_MALLOC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -710,6 +683,7 @@ if(WITH_OPENAL)
|
||||
else()
|
||||
set(OPENAL_LIBRARY ${OPENAL_LIBPATH}/wrap_oal.lib)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(WITH_CODEC_SNDFILE)
|
||||
@@ -754,7 +728,7 @@ endif()
|
||||
|
||||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
||||
windows_find_package(Embree)
|
||||
if(NOT Embree_FOUND)
|
||||
if(NOT EMBREE_FOUND)
|
||||
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
|
||||
set(EMBREE_LIBRARIES
|
||||
optimized ${LIBDIR}/embree/lib/embree3.lib
|
||||
@@ -782,6 +756,7 @@ endif()
|
||||
if(WITH_USD)
|
||||
windows_find_package(USD)
|
||||
if(NOT USD_FOUND)
|
||||
set(USD_FOUND ON)
|
||||
set(USD_INCLUDE_DIRS ${LIBDIR}/usd/include)
|
||||
set(USD_RELEASE_LIB ${LIBDIR}/usd/lib/libusd_m.lib)
|
||||
set(USD_DEBUG_LIB ${LIBDIR}/usd/lib/libusd_m_d.lib)
|
||||
|
@@ -5,7 +5,7 @@ for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
|
||||
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
|
||||
REM For python, default on 39 but if that does not exist also check
|
||||
REM the 310,311 and 312 folders to see if those are there, it checks
|
||||
REM this far ahead to ensure good lib folder compatibility in the future.
|
||||
REM this far ahead to ensure good lib folder compatiblity in the future.
|
||||
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
||||
if EXIST %PYTHON% (
|
||||
goto detect_python_done
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.9.3
|
||||
# Doxyfile 1.9.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all generated output in the proper direction.
|
||||
# Possible values are: None, LTR, RTL and Context.
|
||||
# The default value is: None.
|
||||
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||
# descriptions after the members that are listed in the file and class
|
||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||
@@ -250,16 +258,16 @@ TAB_SIZE = 4
|
||||
# the documentation. An alias has the form:
|
||||
# name=value
|
||||
# For example adding
|
||||
# "sideeffect=@par Side Effects:^^"
|
||||
# "sideeffect=@par Side Effects:\n"
|
||||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||
# documentation, which will result in a user-defined paragraph with heading
|
||||
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
|
||||
# to insert newlines (in the resulting output). You can put ^^ in the value part
|
||||
# of an alias to insert a newline as if a physical newline was in the original
|
||||
# file. When you need a literal { or } or , in the value part of an alias you
|
||||
# have to escape them by means of a backslash (\), this can lead to conflicts
|
||||
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||
# @} or use a double escape (\\{ and \\})
|
||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
||||
# alias to insert a newline as if a physical newline was in the original file.
|
||||
# When you need a literal { or } or , in the value part of an alias you have to
|
||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
||||
# a double escape (\\{ and \\})
|
||||
|
||||
ALIASES =
|
||||
|
||||
@@ -304,8 +312,8 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
@@ -458,7 +466,7 @@ LOOKUP_CACHE_SIZE = 3
|
||||
# than 0 to get more control over the balance between CPU load and processing
|
||||
# speed. At this moment only the input processing can be done using multiple
|
||||
# threads. Since this is still an experimental feature the default is set to 1,
|
||||
# which effectively disables parallel processing. Please report any issues you
|
||||
# which efficively disables parallel processing. Please report any issues you
|
||||
# encounter. Generating dot graphs in parallel is controlled by the
|
||||
# DOT_NUM_THREADS setting.
|
||||
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||
@@ -602,12 +610,6 @@ HIDE_SCOPE_NAMES = NO
|
||||
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
|
||||
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
|
||||
# will show which file needs to be included to use the class.
|
||||
# The default value is: YES.
|
||||
|
||||
SHOW_HEADERFILE = YES
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
||||
# the files that are included by a file in the documentation of that file.
|
||||
# The default value is: YES.
|
||||
@@ -765,8 +767,7 @@ FILE_VERSION_FILTER =
|
||||
# output files in an output format independent way. To create the layout file
|
||||
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
||||
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
||||
# will be used as the name of the layout file. See also section "Changing the
|
||||
# layout of pages" for information.
|
||||
# will be used as the name of the layout file.
|
||||
#
|
||||
# Note that if you run doxygen from a directory containing a file called
|
||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||
@@ -812,26 +813,18 @@ WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
|
||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||
# potential errors in the documentation, such as documenting some parameters in
|
||||
# a documented function twice, or documenting parameters that don't exist or
|
||||
# using markup commands wrongly.
|
||||
# potential errors in the documentation, such as not documenting some parameters
|
||||
# in a documented function, or documenting parameters that don't exist or using
|
||||
# markup commands wrongly.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
|
||||
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
|
||||
# function parameter documentation. If set to NO, doxygen will accept that some
|
||||
# parameters have no documentation without warning.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_INCOMPLETE_DOC = YES
|
||||
|
||||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||
# are documented, but have no documentation for their parameters or return
|
||||
# value. If set to NO, doxygen will only warn about wrong parameter
|
||||
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
|
||||
# set to YES then this flag will automatically be disabled. See also
|
||||
# WARN_IF_INCOMPLETE_DOC
|
||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
||||
# parameter documentation, but not about the absence of documentation. If
|
||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_NO_PARAMDOC = NO
|
||||
@@ -857,10 +850,7 @@ WARN_FORMAT = "$file:$line: $text"
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
||||
# messages should be written. If left blank the output is written to standard
|
||||
# error (stderr). In case the file specified cannot be opened for writing the
|
||||
# warning and error messages are written to standard error. When as file - is
|
||||
# specified the warning and error messages are written to standard output
|
||||
# (stdout).
|
||||
# error (stderr).
|
||||
|
||||
WARN_LOGFILE =
|
||||
|
||||
@@ -904,10 +894,10 @@ INPUT_ENCODING = UTF-8
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
|
||||
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
|
||||
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
|
||||
# *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS =
|
||||
|
||||
@@ -949,7 +939,7 @@ EXCLUDE_PATTERNS = .svn \
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# ANamespace::AClass, ANamespace::*Test
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
@@ -1234,7 +1224,7 @@ HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
# this color. Hue is specified as an angle on a color-wheel, see
|
||||
# this color. Hue is specified as an angle on a colorwheel, see
|
||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||
# purple, and 360 is red again.
|
||||
@@ -1244,7 +1234,7 @@ HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||
# in the HTML output. For a value of 0 the output will use gray-scales only. A
|
||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
||||
# value of 255 will produce the most vivid colors.
|
||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@@ -1326,13 +1316,6 @@ GENERATE_DOCSET = NO
|
||||
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
|
||||
# This tag determines the URL of the docset feed. A documentation feed provides
|
||||
# an umbrella under which multiple documentation sets from a single provider
|
||||
# (such as a company or product suite) can be grouped.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_FEEDURL =
|
||||
|
||||
# This tag specifies a string that should uniquely identify the documentation
|
||||
# set bundle. This should be a reverse domain-name style string, e.g.
|
||||
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
||||
@@ -1358,12 +1341,8 @@ DOCSET_PUBLISHER_NAME = Publisher
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# on Windows. In the beginning of 2021 Microsoft took the original page, with
|
||||
# a.o. the download links, offline the HTML help workshop was already many years
|
||||
# in maintenance mode). You can download the HTML help workshop from the web
|
||||
# archives at Installation executable (see:
|
||||
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
|
||||
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
|
||||
# (see:
|
||||
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
@@ -1522,28 +1501,16 @@ DISABLE_INDEX = NO
|
||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||
# (i.e. any modern browser). Windows users are probably better off using the
|
||||
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
||||
# further fine tune the look of the index (see "Fine-tuning the output"). As an
|
||||
# example, the default style sheet generated by doxygen has an example that
|
||||
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
|
||||
# Since the tree basically has the same information as the tab index, you could
|
||||
# consider setting DISABLE_INDEX to YES when enabling this option.
|
||||
# further fine-tune the look of the index. As an example, the default style
|
||||
# sheet generated by doxygen has an example that shows how to put an image at
|
||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
||||
# the same information as the tab index, you could consider setting
|
||||
# DISABLE_INDEX to YES when enabling this option.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
|
||||
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
|
||||
# area (value NO) or if it should extend to the full height of the window (value
|
||||
# YES). Setting this to YES gives a layout similar to
|
||||
# https://docs.readthedocs.io with more room for contents, but less room for the
|
||||
# project logo, title, and description. If either GENERATE_TREEVIEW or
|
||||
# DISABLE_INDEX is set to NO, this option has no effect.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
FULL_SIDEBAR = NO
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
#
|
||||
@@ -1568,13 +1535,6 @@ TREEVIEW_WIDTH = 246
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
|
||||
# addresses.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
OBFUSCATE_EMAILS = YES
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
@@ -1623,29 +1583,11 @@ FORMULA_MACROFILE =
|
||||
|
||||
USE_MATHJAX = NO
|
||||
|
||||
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
|
||||
# Note that the different versions of MathJax have different requirements with
|
||||
# regards to the different settings, so it is possible that also other MathJax
|
||||
# settings have to be changed when switching between the different MathJax
|
||||
# versions.
|
||||
# Possible values are: MathJax_2 and MathJax_3.
|
||||
# The default value is: MathJax_2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_VERSION = MathJax_2
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. For more details about the output format see MathJax
|
||||
# version 2 (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/latest/web/components/output.html).
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
|
||||
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
|
||||
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
|
||||
# is the name for Mathjax version 3, for MathJax version 2 this will be
|
||||
# translated into HTML-CSS) and SVG.
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@@ -1658,21 +1600,15 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment. The default value is:
|
||||
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
|
||||
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
# for MathJax version 2 (see
|
||||
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
|
||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
# For example for MathJax version 3 (see
|
||||
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
|
||||
# MATHJAX_EXTENSIONS = ams
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_EXTENSIONS =
|
||||
@@ -1852,31 +1788,29 @@ PAPER_TYPE = a4
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
|
||||
# the generated LaTeX document. The header should contain everything until the
|
||||
# first chapter. If it is left blank doxygen will generate a standard header. It
|
||||
# is highly recommended to start with a default header using
|
||||
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
|
||||
# and then modify the file new_header.tex. See also section "Doxygen usage" for
|
||||
# information on how to generate the default header that doxygen normally uses.
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
||||
# generated LaTeX document. The header should contain everything until the first
|
||||
# chapter. If it is left blank doxygen will generate a standard header. See
|
||||
# section "Doxygen usage" for information on how to let doxygen write the
|
||||
# default header to a separate file.
|
||||
#
|
||||
# Note: Only use a user-defined header if you know what you are doing!
|
||||
# Note: The header is subject to change so you typically have to regenerate the
|
||||
# default header when upgrading to a newer version of doxygen. The following
|
||||
# commands have a special meaning inside the header (and footer): For a
|
||||
# description of the possible markers and block names see the documentation.
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
||||
# string, for the replacement values of the other commands the user is referred
|
||||
# to HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_HEADER =
|
||||
|
||||
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
|
||||
# the generated LaTeX document. The footer should contain everything after the
|
||||
# last chapter. If it is left blank doxygen will generate a standard footer. See
|
||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||
# generated LaTeX document. The footer should contain everything after the last
|
||||
# chapter. If it is left blank doxygen will generate a standard footer. See
|
||||
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||
# special commands can be used inside the footer. See also section "Doxygen
|
||||
# usage" for information on how to generate the default footer that doxygen
|
||||
# normally uses. Note: Only use a user-defined footer if you know what you are
|
||||
# doing!
|
||||
# special commands can be used inside the footer.
|
||||
#
|
||||
# Note: Only use a user-defined footer if you know what you are doing!
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_FOOTER =
|
||||
@@ -1921,7 +1855,8 @@ USE_PDFLATEX = NO
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||
# if errors occur, instead of asking the user for help.
|
||||
# if errors occur, instead of asking the user for help. This option is also used
|
||||
# when generating formulas in HTML.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@@ -1934,6 +1869,16 @@ LATEX_BATCHMODE = NO
|
||||
|
||||
LATEX_HIDE_INDICES = NO
|
||||
|
||||
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
|
||||
# code with syntax highlighting in the LaTeX output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_SOURCE_CODE = NO
|
||||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. See
|
||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
@@ -2014,6 +1959,16 @@ RTF_STYLESHEET_FILE =
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
||||
# with syntax highlighting in the RTF output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_SOURCE_CODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2110,6 +2065,15 @@ GENERATE_DOCBOOK = NO
|
||||
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
|
||||
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
||||
# program listings (including syntax highlighting and cross-referencing
|
||||
# information) to the DOCBOOK output. Note that enabling this will significantly
|
||||
# increase the size of the DOCBOOK output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2290,6 +2254,15 @@ EXTERNAL_PAGES = YES
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
||||
# disabled, but it is recommended to install and use dot, since it yields more
|
||||
# powerful graphs.
|
||||
# The default value is: YES.
|
||||
|
||||
CLASS_DIAGRAMS = NO
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
@@ -2346,16 +2319,13 @@ DOT_FONTSIZE = 10
|
||||
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
|
||||
# graph for each documented class showing the direct and indirect inheritance
|
||||
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
|
||||
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
|
||||
# to TEXT the direct and indirect inheritance relations will be shown as texts /
|
||||
# links.
|
||||
# Possible values are: NO, YES, TEXT and GRAPH.
|
||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
||||
# each documented class showing the direct and indirect inheritance relations.
|
||||
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
CLASS_GRAPH = TEXT
|
||||
CLASS_GRAPH = YES
|
||||
|
||||
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
|
||||
# graph for each documented class showing the direct and indirect implementation
|
||||
@@ -2482,13 +2452,6 @@ GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
|
||||
# of child directories generated in directory dependency graphs by dot.
|
||||
# Minimum value: 1, maximum value: 25, default value: 1.
|
||||
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
|
||||
|
||||
DIR_GRAPH_MAX_DEPTH = 1
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot. For an explanation of the image formats see the section
|
||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||
@@ -2542,10 +2505,10 @@ MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
|
||||
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||
# path where java can find the plantuml.jar file or to the filename of jar file
|
||||
# to be used. If left blank, it is assumed PlantUML is not used or called during
|
||||
# a preprocessing step. Doxygen will generate a warning when it encounters a
|
||||
# \startuml command in this case and will not generate output for the diagram.
|
||||
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
||||
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
||||
# generate a warning when it encounters a \startuml command in this case and
|
||||
# will not generate output for the diagram.
|
||||
|
||||
PLANTUML_JAR_PATH =
|
||||
|
||||
@@ -2607,8 +2570,6 @@ DOT_MULTI_TARGETS = YES
|
||||
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||
# graphs.
|
||||
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
|
||||
# graphical representation for inheritance and collaboration diagrams is used.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
@@ -2617,8 +2578,8 @@ GENERATE_LEGEND = YES
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||
# files that are used to generate the various graphs.
|
||||
#
|
||||
# Note: This setting is not only used for dot files but also for msc temporary
|
||||
# files.
|
||||
# Note: This setting is not only used for dot files but also for msc and
|
||||
# plantuml temporary files.
|
||||
# The default value is: YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
@@ -1,502 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
@@ -5,6 +5,5 @@ BSD-2-Clause BSD-2-Clause-license.txt https://spdx.org/licenses/BS
|
||||
BSD-3-Clause BSD-3-Clause-license.txt https://spdx.org/licenses/BSD-3-Clause.html
|
||||
GPL-2.0-or-later GPL-license.txt https://spdx.org/licenses/GPL-2.0-or-later.html
|
||||
GPL-3.0-or-later GPL3-license.txt https://spdx.org/licenses/GPL-3.0-or-later.html
|
||||
LGPL-2.1-or-later LGPL2.1-license.txt https://spdx.org/licenses/LGPL-2.1-or-later.html
|
||||
MIT MIT-license.txt https://spdx.org/licenses/MIT.html
|
||||
Zlib Zlib-license.txt https://spdx.org/licenses/Zlib.html
|
||||
|
@@ -16,6 +16,7 @@ and <output-filename> is where to write the generated man page.
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from typing import (
|
||||
|
@@ -41,7 +41,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
|
||||
else:
|
||||
layout.label(text="", translate=False, icon_value=icon)
|
||||
# 'GRID' layout type should be as compact as possible (typically a single icon!).
|
||||
elif self.layout_type == 'GRID':
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
|
@@ -73,7 +73,7 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
|
||||
layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
|
||||
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
|
||||
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
if flt_flag & self.VGROUP_EMPTY:
|
||||
layout.enabled = False
|
||||
|
@@ -63,7 +63,6 @@ import os
|
||||
import sys
|
||||
import inspect
|
||||
import shutil
|
||||
import time
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
@@ -400,7 +399,6 @@ MODULE_GROUPING = {
|
||||
|
||||
# converting bytes to strings, due to T30154
|
||||
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
|
||||
BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
|
||||
|
||||
# '2.83.0 Beta' or '2.83.0' or '2.83.1'
|
||||
BLENDER_VERSION_STRING = bpy.app.version_string
|
||||
@@ -409,13 +407,9 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 Git hash
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % (BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
|
||||
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
|
||||
else:
|
||||
# Fallback: Should not be used
|
||||
BLENDER_VERSION_HASH = "Hash Unknown"
|
||||
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
|
||||
BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
|
||||
|
||||
# '2_83'
|
||||
BLENDER_VERSION_PATH = "%d_%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
@@ -1758,12 +1752,11 @@ except ModuleNotFoundError:
|
||||
fw("html_split_index = True\n")
|
||||
fw("html_static_path = ['static']\n")
|
||||
fw("templates_path = ['templates']\n")
|
||||
fw("html_context = {'commit': '%s - %s'}\n" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE))
|
||||
fw("html_context = {'commit': '%s'}\n" % BLENDER_VERSION_HASH)
|
||||
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
|
||||
fw("html_favicon = 'static/favicon.ico'\n")
|
||||
fw("html_logo = 'static/blender_logo.svg'\n")
|
||||
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
|
||||
fw("html_last_updated_fmt = None\n\n")
|
||||
fw("html_last_updated_fmt = '%m/%d/%Y'\n\n")
|
||||
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
||||
fw(" html_css_files = ['css/version_switch.css']\n")
|
||||
fw(" html_js_files = ['js/version_switch.js']\n")
|
||||
|
@@ -1,6 +1,5 @@
|
||||
/* Override RTD theme */
|
||||
.rst-versions {
|
||||
display: none;
|
||||
border-top: 0px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
27
extern/fmtlib/LICENSE.rst
vendored
27
extern/fmtlib/LICENSE.rst
vendored
@@ -1,27 +0,0 @@
|
||||
Copyright (c) 2012 - present, Victor Zverovich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
--- Optional exception to the license ---
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into a machine-executable object form of such
|
||||
source code, you may redistribute such embedded portions in such object form
|
||||
without including the above copyright and permission notices.
|
8
extern/fmtlib/README.blender
vendored
8
extern/fmtlib/README.blender
vendored
@@ -1,8 +0,0 @@
|
||||
Project: {fmt}
|
||||
URL: https://github.com/fmtlib/fmt
|
||||
License: MIT
|
||||
Upstream version: 8.1.1 (b6f4cea)
|
||||
Local modifications:
|
||||
|
||||
- Took only files needed for Blender: LICENSE, README and include/fmt
|
||||
folder's core.h, format-inl.h, format.h
|
528
extern/fmtlib/README.rst
vendored
528
extern/fmtlib/README.rst
vendored
@@ -1,528 +0,0 @@
|
||||
{fmt}
|
||||
=====
|
||||
|
||||
.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg
|
||||
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux
|
||||
|
||||
.. image:: https://github.com/fmtlib/fmt/workflows/macos/badge.svg
|
||||
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos
|
||||
|
||||
.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg
|
||||
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true
|
||||
:target: https://ci.appveyor.com/project/vitaut/fmt
|
||||
|
||||
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
|
||||
:alt: fmt is continuously fuzzed at oss-fuzz
|
||||
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
|
||||
colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
|
||||
Summary&q=proj%3Dfmt&can=1
|
||||
|
||||
.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
|
||||
:alt: Ask questions at StackOverflow with the tag fmt
|
||||
:target: https://stackoverflow.com/questions/tagged/fmt
|
||||
|
||||
**{fmt}** is an open-source formatting library providing a fast and safe
|
||||
alternative to C stdio and C++ iostreams.
|
||||
|
||||
If you like this project, please consider donating to the BYSOL
|
||||
Foundation that helps victims of political repressions in Belarus:
|
||||
https://bysol.org/en/bs/general/.
|
||||
|
||||
`Documentation <https://fmt.dev>`__
|
||||
|
||||
Q&A: ask questions on `StackOverflow with the tag fmt
|
||||
<https://stackoverflow.com/questions/tagged/fmt>`_.
|
||||
|
||||
Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
|
||||
for localization
|
||||
* Implementation of `C++20 std::format
|
||||
<https://en.cppreference.com/w/cpp/utility/format>`__
|
||||
* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
|
||||
`format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
|
||||
* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
|
||||
round-trip guarantees
|
||||
* Safe `printf implementation
|
||||
<https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
|
||||
extension for positional arguments
|
||||
* Extensibility: `support for user-defined types
|
||||
<https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
|
||||
* High performance: faster than common standard library implementations of
|
||||
``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
|
||||
and `Converting a hundred million integers to strings per second
|
||||
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
|
||||
* Small code size both in terms of source code with the minimum configuration
|
||||
consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
|
||||
and compiled code; see `Compile time and code bloat`_
|
||||
* Reliability: the library has an extensive set of `tests
|
||||
<https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
|
||||
<https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
|
||||
Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_
|
||||
* Safety: the library is fully type safe, errors in format strings can be
|
||||
reported at compile time, automatic memory management prevents buffer overflow
|
||||
errors
|
||||
* Ease of use: small self-contained code base, no external dependencies,
|
||||
permissive MIT `license
|
||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
|
||||
* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
|
||||
consistent output across platforms and support for older compilers
|
||||
* Clean warning-free codebase even on high warning levels such as
|
||||
``-Wall -Wextra -pedantic``
|
||||
* Locale-independence by default
|
||||
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
|
||||
|
||||
See the `documentation <https://fmt.dev>`_ for more details.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("Hello, world!\n");
|
||||
}
|
||||
|
||||
**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = fmt::format("The answer is {}.", 42);
|
||||
// s == "The answer is 42."
|
||||
|
||||
**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
|
||||
// s == "I'd rather be happy than right."
|
||||
|
||||
**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
int main() {
|
||||
using namespace std::literals::chrono_literals;
|
||||
fmt::print("Default format: {} {}\n", 42s, 100ms);
|
||||
fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
|
||||
}
|
||||
|
||||
Output::
|
||||
|
||||
Default format: 42s 100ms
|
||||
strftime-like format: 03:15:30
|
||||
|
||||
**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <vector>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
int main() {
|
||||
std::vector<int> v = {1, 2, 3};
|
||||
fmt::print("{}\n", v);
|
||||
}
|
||||
|
||||
Output::
|
||||
|
||||
[1, 2, 3]
|
||||
|
||||
**Check a format string at compile time**
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = fmt::format("{:d}", "I am not a number");
|
||||
|
||||
This gives a compile-time error in C++20 because ``d`` is an invalid format
|
||||
specifier for a string.
|
||||
|
||||
**Write a file from a single thread**
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/os.h>
|
||||
|
||||
int main() {
|
||||
auto out = fmt::output_file("guide.txt");
|
||||
out.print("Don't {}", "Panic");
|
||||
}
|
||||
|
||||
This can be `5 to 9 times faster than fprintf
|
||||
<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
|
||||
|
||||
**Print with colors and text styles**
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/color.h>
|
||||
|
||||
int main() {
|
||||
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
|
||||
"Hello, {}!\n", "world");
|
||||
fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
|
||||
fmt::emphasis::underline, "Hello, {}!\n", "мир");
|
||||
fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
|
||||
"Hello, {}!\n", "世界");
|
||||
}
|
||||
|
||||
Output on a modern terminal:
|
||||
|
||||
.. image:: https://user-images.githubusercontent.com/
|
||||
576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
|
||||
|
||||
Benchmarks
|
||||
----------
|
||||
|
||||
Speed tests
|
||||
~~~~~~~~~~~
|
||||
|
||||
================= ============= ===========
|
||||
Library Method Run Time, s
|
||||
================= ============= ===========
|
||||
libc printf 1.04
|
||||
libc++ std::ostream 3.05
|
||||
{fmt} 6.1.1 fmt::print 0.75
|
||||
Boost Format 1.67 boost::format 7.24
|
||||
Folly Format folly::format 2.23
|
||||
================= ============= ===========
|
||||
|
||||
{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
|
||||
|
||||
The above results were generated by building ``tinyformat_test.cpp`` on macOS
|
||||
10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
|
||||
best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
|
||||
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
|
||||
further details refer to the `source
|
||||
<https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc>`_.
|
||||
|
||||
{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
|
||||
floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
|
||||
and faster than `double-conversion <https://github.com/google/double-conversion>`_ and
|
||||
`ryu <https://github.com/ulfjack/ryu>`_:
|
||||
|
||||
.. image:: https://user-images.githubusercontent.com/576385/
|
||||
95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png
|
||||
:target: https://fmt.dev/unknown_mac64_clang12.0.html
|
||||
|
||||
Compile time and code bloat
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The script `bloat-test.py
|
||||
<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
|
||||
from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
|
||||
tests compile time and code bloat for nontrivial projects.
|
||||
It generates 100 translation units and uses ``printf()`` or its alternative
|
||||
five times in each to simulate a medium sized project. The resulting
|
||||
executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
|
||||
macOS Sierra, best of three) is shown in the following tables.
|
||||
|
||||
**Optimized build (-O3)**
|
||||
|
||||
============= =============== ==================== ==================
|
||||
Method Compile Time, s Executable size, KiB Stripped size, KiB
|
||||
============= =============== ==================== ==================
|
||||
printf 2.6 29 26
|
||||
printf+string 16.4 29 26
|
||||
iostreams 31.1 59 55
|
||||
{fmt} 19.0 37 34
|
||||
Boost Format 91.9 226 203
|
||||
Folly Format 115.7 101 88
|
||||
============= =============== ==================== ==================
|
||||
|
||||
As you can see, {fmt} has 60% less overhead in terms of resulting binary code
|
||||
size compared to iostreams and comes pretty close to ``printf``. Boost Format
|
||||
and Folly Format have the largest overheads.
|
||||
|
||||
``printf+string`` is the same as ``printf`` but with extra ``<string>``
|
||||
include to measure the overhead of the latter.
|
||||
|
||||
**Non-optimized build**
|
||||
|
||||
============= =============== ==================== ==================
|
||||
Method Compile Time, s Executable size, KiB Stripped size, KiB
|
||||
============= =============== ==================== ==================
|
||||
printf 2.2 33 30
|
||||
printf+string 16.0 33 30
|
||||
iostreams 28.3 56 52
|
||||
{fmt} 18.2 59 50
|
||||
Boost Format 54.1 365 303
|
||||
Folly Format 79.9 445 430
|
||||
============= =============== ==================== ==================
|
||||
|
||||
``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
|
||||
compare formatting function overhead only. Boost Format is a
|
||||
header-only library so it doesn't provide any linkage options.
|
||||
|
||||
Running the tests
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please refer to `Building the library`__ for the instructions on how to build
|
||||
the library and run the unit tests.
|
||||
|
||||
__ https://fmt.dev/latest/usage.html#building-the-library
|
||||
|
||||
Benchmarks reside in a separate repository,
|
||||
`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
|
||||
so to run the benchmarks you first need to clone this repository and
|
||||
generate Makefiles with CMake::
|
||||
|
||||
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git
|
||||
$ cd format-benchmark
|
||||
$ cmake .
|
||||
|
||||
Then you can run the speed test::
|
||||
|
||||
$ make speed-test
|
||||
|
||||
or the bloat test::
|
||||
|
||||
$ make bloat-test
|
||||
|
||||
Migrating code
|
||||
--------------
|
||||
|
||||
`clang-tidy-fmt <https://github.com/mikecrowe/clang-tidy-fmt>`_ provides clang
|
||||
tidy checks for converting occurrences of ``printf`` and ``fprintf`` to
|
||||
``fmt::print``.
|
||||
|
||||
Projects using this library
|
||||
---------------------------
|
||||
|
||||
* `0 A.D. <https://play0ad.com/>`_: a free, open-source, cross-platform
|
||||
real-time strategy game
|
||||
|
||||
* `2GIS <https://2gis.ru/>`_: free business listings with a city map
|
||||
|
||||
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
||||
an open-source library for mathematical programming
|
||||
|
||||
* `Aseprite <https://github.com/aseprite/aseprite>`_:
|
||||
animated sprite editor & pixel art tool
|
||||
|
||||
* `AvioBook <https://www.aviobook.aero/en>`_: a comprehensive aircraft
|
||||
operations suite
|
||||
|
||||
* `Blizzard Battle.net <https://battle.net/>`_: an online gaming platform
|
||||
|
||||
* `Celestia <https://celestia.space/>`_: real-time 3D visualization of space
|
||||
|
||||
* `Ceph <https://ceph.com/>`_: a scalable distributed storage system
|
||||
|
||||
* `ccache <https://ccache.dev/>`_: a compiler cache
|
||||
|
||||
* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database
|
||||
management system
|
||||
|
||||
* `CUAUV <https://cuauv.org/>`_: Cornell University's autonomous underwater
|
||||
vehicle
|
||||
|
||||
* `Drake <https://drake.mit.edu/>`_: a planning, control, and analysis toolbox
|
||||
for nonlinear dynamical systems (MIT)
|
||||
|
||||
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
|
||||
(Lyft)
|
||||
|
||||
* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
|
||||
|
||||
* `fmtlog <https://github.com/MengRao/fmtlog>`_: a performant fmtlib-style
|
||||
logging library with latency in nanoseconds
|
||||
|
||||
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
|
||||
|
||||
* `Grand Mountain Adventure
|
||||
<https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_:
|
||||
A beautiful open-world ski & snowboarding game
|
||||
|
||||
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||
Player vs Player Gaming Network with tweaks
|
||||
|
||||
* `KBEngine <https://github.com/kbengine/kbengine>`_: an open-source MMOG server
|
||||
engine
|
||||
|
||||
* `Keypirinha <https://keypirinha.com/>`_: a semantic launcher for Windows
|
||||
|
||||
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): home theater software
|
||||
|
||||
* `Knuth <https://kth.cash/>`_: high-performance Bitcoin full-node
|
||||
|
||||
* `Microsoft Verona <https://github.com/microsoft/verona>`_:
|
||||
research programming language for concurrent ownership
|
||||
|
||||
* `MongoDB <https://mongodb.com/>`_: distributed document database
|
||||
|
||||
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: a small tool to
|
||||
generate randomized datasets
|
||||
|
||||
* `OpenSpace <https://openspaceproject.com/>`_: an open-source
|
||||
astrovisualization framework
|
||||
|
||||
* `PenUltima Online (POL) <https://www.polserver.com/>`_:
|
||||
an MMO server, compatible with most Ultima Online clients
|
||||
|
||||
* `PyTorch <https://github.com/pytorch/pytorch>`_: an open-source machine
|
||||
learning library
|
||||
|
||||
* `quasardb <https://www.quasardb.net/>`_: a distributed, high-performance,
|
||||
associative database
|
||||
|
||||
* `Quill <https://github.com/odygrd/quill>`_: asynchronous low-latency logging library
|
||||
|
||||
* `QKW <https://github.com/ravijanjam/qkw>`_: generalizing aliasing to simplify
|
||||
navigation, and executing complex multi-line terminal command sequences
|
||||
|
||||
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: a Redis cluster
|
||||
proxy
|
||||
|
||||
* `redpanda <https://vectorized.io/redpanda>`_: a 10x faster Kafka® replacement
|
||||
for mission critical systems written in C++
|
||||
|
||||
* `rpclib <http://rpclib.net/>`_: a modern C++ msgpack-RPC server and client
|
||||
library
|
||||
|
||||
* `Salesforce Analytics Cloud
|
||||
<https://www.salesforce.com/analytics-cloud/overview/>`_:
|
||||
business intelligence software
|
||||
|
||||
* `Scylla <https://www.scylladb.com/>`_: a Cassandra-compatible NoSQL data store
|
||||
that can handle 1 million transactions per second on a single server
|
||||
|
||||
* `Seastar <http://www.seastar-project.org/>`_: an advanced, open-source C++
|
||||
framework for high-performance server applications on modern hardware
|
||||
|
||||
* `spdlog <https://github.com/gabime/spdlog>`_: super fast C++ logging library
|
||||
|
||||
* `Stellar <https://www.stellar.org/>`_: financial platform
|
||||
|
||||
* `Touch Surgery <https://www.touchsurgery.com/>`_: surgery simulator
|
||||
|
||||
* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: open-source
|
||||
MMORPG framework
|
||||
|
||||
* `Windows Terminal <https://github.com/microsoft/terminal>`_: the new Windows
|
||||
terminal
|
||||
|
||||
`More... <https://github.com/search?q=fmtlib&type=Code>`_
|
||||
|
||||
If you are aware of other projects using this library, please let me know
|
||||
by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
|
||||
`issue <https://github.com/fmtlib/fmt/issues>`_.
|
||||
|
||||
Motivation
|
||||
----------
|
||||
|
||||
So why yet another formatting library?
|
||||
|
||||
There are plenty of methods for doing this task, from standard ones like
|
||||
the printf family of function and iostreams to Boost Format and FastFormat
|
||||
libraries. The reason for creating a new library is that every existing
|
||||
solution that I found either had serious issues or didn't provide
|
||||
all the features I needed.
|
||||
|
||||
printf
|
||||
~~~~~~
|
||||
|
||||
The good thing about ``printf`` is that it is pretty fast and readily available
|
||||
being a part of the C standard library. The main drawback is that it
|
||||
doesn't support user-defined types. ``printf`` also has safety issues although
|
||||
they are somewhat mitigated with `__attribute__ ((format (printf, ...))
|
||||
<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
|
||||
There is a POSIX extension that adds positional arguments required for
|
||||
`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
|
||||
to ``printf`` but it is not a part of C99 and may not be available on some
|
||||
platforms.
|
||||
|
||||
iostreams
|
||||
~~~~~~~~~
|
||||
|
||||
The main issue with iostreams is best illustrated with an example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
|
||||
|
||||
which is a lot of typing compared to printf:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
printf("%.2f\n", 1.23456);
|
||||
|
||||
Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams
|
||||
don't support positional arguments by design.
|
||||
|
||||
The good part is that iostreams support user-defined types and are safe although
|
||||
error handling is awkward.
|
||||
|
||||
Boost Format
|
||||
~~~~~~~~~~~~
|
||||
|
||||
This is a very powerful library which supports both ``printf``-like format
|
||||
strings and positional arguments. Its main drawback is performance. According to
|
||||
various benchmarks, it is much slower than other methods considered here. Boost
|
||||
Format also has excessive build times and severe code bloat issues (see
|
||||
`Benchmarks`_).
|
||||
|
||||
FastFormat
|
||||
~~~~~~~~~~
|
||||
|
||||
This is an interesting library which is fast, safe and has positional arguments.
|
||||
However, it has significant limitations, citing its author:
|
||||
|
||||
Three features that have no hope of being accommodated within the
|
||||
current design are:
|
||||
|
||||
* Leading zeros (or any other non-space padding)
|
||||
* Octal/hexadecimal encoding
|
||||
* Runtime width/alignment specification
|
||||
|
||||
It is also quite big and has a heavy dependency, STLSoft, which might be too
|
||||
restrictive for using it in some projects.
|
||||
|
||||
Boost Spirit.Karma
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is not really a formatting library but I decided to include it here for
|
||||
completeness. As iostreams, it suffers from the problem of mixing verbatim text
|
||||
with arguments. The library is pretty fast, but slower on integer formatting
|
||||
than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
|
||||
see `Converting a hundred million integers to strings per second
|
||||
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
{fmt} is distributed under the MIT `license
|
||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
|
||||
|
||||
Documentation License
|
||||
---------------------
|
||||
|
||||
The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
|
||||
section in the documentation is based on the one from Python `string module
|
||||
documentation <https://docs.python.org/3/library/string.html#module-string>`_.
|
||||
For this reason the documentation is distributed under the Python Software
|
||||
Foundation license available in `doc/python-license.txt
|
||||
<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
|
||||
It only applies if you distribute the documentation of {fmt}.
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
|
||||
The {fmt} library is maintained by Victor Zverovich (`vitaut
|
||||
<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
|
||||
<https://github.com/foonathan>`_) with contributions from many other people.
|
||||
See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
|
||||
`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
|
||||
Let us know if your contribution is not listed or mentioned incorrectly and
|
||||
we'll make it right.
|
3236
extern/fmtlib/include/fmt/core.h
vendored
3236
extern/fmtlib/include/fmt/core.h
vendored
File diff suppressed because it is too large
Load Diff
2643
extern/fmtlib/include/fmt/format-inl.h
vendored
2643
extern/fmtlib/include/fmt/format-inl.h
vendored
File diff suppressed because it is too large
Load Diff
3104
extern/fmtlib/include/fmt/format.h
vendored
3104
extern/fmtlib/include/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -423,7 +423,6 @@ TEST(atomic, atomic_fetch_and_and_uint32)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 32 bit signed int atomics
|
||||
* \{ */
|
||||
|
||||
@@ -560,7 +559,6 @@ TEST(atomic, atomic_fetch_and_and_int32)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 16 bit signed int atomics
|
||||
* \{ */
|
||||
|
||||
@@ -594,9 +592,6 @@ TEST(atomic, atomic_fetch_and_and_int16)
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 8 bit unsigned int atomics
|
||||
* \{ */
|
||||
|
||||
@@ -643,7 +638,6 @@ TEST(atomic, atomic_fetch_and_and_int8)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name char aliases
|
||||
* \{ */
|
||||
|
||||
@@ -667,7 +661,6 @@ TEST(atomic, atomic_fetch_and_and_char)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name size_t aliases
|
||||
* \{ */
|
||||
|
||||
@@ -779,7 +772,6 @@ TEST(atomic, atomic_fetch_and_update_max_z)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name unsigned int aliases
|
||||
* \{ */
|
||||
|
||||
@@ -875,7 +867,6 @@ TEST(atomic, atomic_cas_u)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name pointer aliases
|
||||
* \{ */
|
||||
|
||||
@@ -894,7 +885,6 @@ TEST(atomic, atomic_cas_ptr)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name floating point atomics
|
||||
* \{ */
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# Standalone or with Blender
|
||||
if(NOT WITH_BLENDER)
|
||||
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
|
||||
set(CYCLES_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
|
||||
else()
|
||||
set(WITH_CYCLES_BLENDER ON)
|
||||
@@ -215,15 +215,6 @@ add_definitions(
|
||||
-DCCL_NAMESPACE_END=}
|
||||
)
|
||||
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${BOOST_INCLUDE_DIR}
|
||||
${OPENIMAGEIO_INCLUDE_DIRS}
|
||||
${OPENEXR_INCLUDE_DIRS}
|
||||
${PUGIXML_INCLUDE_DIR}
|
||||
${TBB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(WITH_CYCLES_DEBUG)
|
||||
add_definitions(-DWITH_CYCLES_DEBUG)
|
||||
endif()
|
||||
@@ -264,6 +255,7 @@ endif()
|
||||
|
||||
if(WITH_CYCLES_EMBREE)
|
||||
add_definitions(-DWITH_EMBREE)
|
||||
add_definitions(-DEMBREE_STATIC_LIB)
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${EMBREE_INCLUDE_DIRS}
|
||||
@@ -288,6 +280,7 @@ endif()
|
||||
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
add_definitions(-DWITH_OPENIMAGEDENOISE)
|
||||
add_definitions(-DOIDN_STATIC_LIB)
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${OPENIMAGEDENOISE_INCLUDE_DIRS}
|
||||
@@ -315,6 +308,17 @@ if(NOT OPENIMAGEIO_PUGIXML_FOUND)
|
||||
add_definitions(-DWITH_SYSTEM_PUGIXML)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${BOOST_INCLUDE_DIR}
|
||||
${OPENIMAGEIO_INCLUDE_DIRS}
|
||||
${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
|
||||
${OPENEXR_INCLUDE_DIR}
|
||||
${OPENEXR_INCLUDE_DIRS}
|
||||
${PUGIXML_INCLUDE_DIR}
|
||||
${TBB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
include_directories(../third_party/atomic)
|
||||
else()
|
||||
@@ -331,14 +335,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
unset(_has_no_error_unused_macros)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD))
|
||||
message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE")
|
||||
set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF)
|
||||
endif()
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE))
|
||||
set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
|
||||
if(MSVC)
|
||||
set(MAX_MSVC 1800)
|
||||
@@ -399,10 +395,6 @@ if(WITH_GTESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
add_subdirectory(hydra)
|
||||
endif()
|
||||
|
||||
if(NOT WITH_BLENDER)
|
||||
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
|
||||
delayed_do_install(${CMAKE_BINARY_DIR}/bin)
|
||||
endif()
|
||||
|
@@ -11,7 +11,7 @@ set(INC
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(LIB
|
||||
set(LIBRARIES
|
||||
cycles_device
|
||||
cycles_kernel
|
||||
cycles_scene
|
||||
@@ -22,34 +22,22 @@ set(LIB
|
||||
cycles_util
|
||||
)
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
list(APPEND INC_SYS
|
||||
${ALEMBIC_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND LIB
|
||||
${ALEMBIC_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB cycles_kernel_osl)
|
||||
list(APPEND LIBRARIES cycles_kernel_osl)
|
||||
endif()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
list(APPEND LIB extern_sky)
|
||||
list(APPEND LIBRARIES extern_sky)
|
||||
else()
|
||||
list(APPEND LIB bf_intern_sky)
|
||||
list(APPEND LIBRARIES bf_intern_sky)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
list(APPEND INC_SYS ${GLEW_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS})
|
||||
list(APPEND LIB ${CYCLES_GL_LIBRARIES} ${CYCLES_GLEW_LIBRARIES} ${SDL2_LIBRARIES})
|
||||
list(APPEND LIBRARIES ${CYCLES_GL_LIBRARIES} ${SDL2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
cycles_external_libraries_append(LIB)
|
||||
|
||||
# Common configuration.
|
||||
|
||||
include_directories(${INC})
|
||||
@@ -80,7 +68,8 @@ if(WITH_CYCLES_STANDALONE)
|
||||
add_executable(cycles ${SRC} ${INC} ${INC_SYS})
|
||||
unset(SRC)
|
||||
|
||||
target_link_libraries(cycles PRIVATE ${LIB})
|
||||
target_link_libraries(cycles ${LIBRARIES})
|
||||
cycles_target_link_libraries(cycles)
|
||||
|
||||
if(APPLE)
|
||||
if(WITH_OPENCOLORIO)
|
||||
@@ -123,12 +112,9 @@ if(WITH_CYCLES_CUBIN_COMPILER)
|
||||
set(INC
|
||||
../../../extern/cuew/include
|
||||
)
|
||||
set(LIB
|
||||
)
|
||||
cycles_external_libraries_append(LIB)
|
||||
add_executable(cycles_cubin_cc ${SRC})
|
||||
include_directories(${INC})
|
||||
target_link_libraries(cycles_cubin_cc PRIVATE ${LIB})
|
||||
cycles_target_link_libraries(cycles_cubin_cc)
|
||||
unset(SRC)
|
||||
unset(INC)
|
||||
endif()
|
||||
|
@@ -121,9 +121,9 @@ static void session_init()
|
||||
options.session->set_display_driver(make_unique<OpenGLDisplayDriver>(
|
||||
window_opengl_context_enable, window_opengl_context_disable));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (!options.output_filepath.empty()) {
|
||||
if (!options.output_filepath.empty()) {
|
||||
options.session->set_output_driver(make_unique<OIIOOutputDriver>(
|
||||
options.output_filepath, options.output_pass, session_print));
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "graph/node_xml.h"
|
||||
|
||||
#include "scene/alembic.h"
|
||||
#include "scene/background.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/film.h"
|
||||
@@ -193,31 +192,6 @@ static void xml_read_camera(XMLReadState &state, xml_node node)
|
||||
cam->update(state.scene);
|
||||
}
|
||||
|
||||
/* Alembic */
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
static void xml_read_alembic(XMLReadState &state, xml_node graph_node)
|
||||
{
|
||||
AlembicProcedural *proc = state.scene->create_node<AlembicProcedural>();
|
||||
xml_read_node(state, proc, graph_node);
|
||||
|
||||
for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
|
||||
if (string_iequals(node.name(), "object")) {
|
||||
string path;
|
||||
if (xml_read_string(&path, node, "path")) {
|
||||
ustring object_path(path, 0);
|
||||
AlembicObject *object = static_cast<AlembicObject *>(
|
||||
proc->get_or_create_object(object_path));
|
||||
|
||||
array<Node *> used_shaders = object->get_used_shaders();
|
||||
used_shaders.push_back_slow(state.shader);
|
||||
object->set_used_shaders(used_shaders);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shader */
|
||||
|
||||
static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node graph_node)
|
||||
@@ -673,11 +647,6 @@ static void xml_read_scene(XMLReadState &state, xml_node scene_node)
|
||||
if (xml_read_string(&src, node, "src"))
|
||||
xml_read_include(state, src);
|
||||
}
|
||||
#ifdef WITH_ALEMBIC
|
||||
else if (string_iequals(node.name(), "alembic")) {
|
||||
xml_read_alembic(state, node);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
fprintf(stderr, "Unknown node \"%s\".\n", node.name());
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ bool OpenGLDisplayDriver::update_begin(const Params ¶ms, int texture_width,
|
||||
|
||||
/* 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
|
||||
* 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
|
||||
|
@@ -83,17 +83,6 @@ class CyclesRender(bpy.types.RenderEngine):
|
||||
# viewport render
|
||||
def view_update(self, context, depsgraph):
|
||||
if not self.session:
|
||||
# When starting a new render session in viewport (by switching
|
||||
# viewport to Rendered shading) unpause the render. The way to think
|
||||
# of it is: artist requests render, so we start to render.
|
||||
# Do it for both original and evaluated scene so that Cycles
|
||||
# immediately reacts to un-paused render.
|
||||
cscene = context.scene.cycles
|
||||
cscene_eval = depsgraph.scene_eval.cycles
|
||||
if cscene.preview_pause or cscene_eval.preview_pause:
|
||||
cscene.preview_pause = False
|
||||
cscene_eval.preview_pause = False
|
||||
|
||||
engine.create(self, context.blend_data,
|
||||
context.region, context.space_data, context.region_data)
|
||||
|
||||
|
@@ -226,11 +226,7 @@ def list_render_passes(scene, srl):
|
||||
if aov.type == 'VALUE':
|
||||
yield (aov.name, "X", 'VALUE')
|
||||
else:
|
||||
yield (aov.name, "RGBA", 'COLOR')
|
||||
|
||||
# Light groups.
|
||||
for lightgroup in srl.lightgroups:
|
||||
yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
|
||||
yield (aov.name, "RGB", 'COLOR')
|
||||
|
||||
|
||||
def register_passes(engine, scene, view_layer):
|
||||
|
@@ -65,8 +65,8 @@ enum_panorama_types = (
|
||||
)
|
||||
|
||||
enum_curve_shape = (
|
||||
('RIBBONS', "Rounded Ribbons", "Render curves as flat ribbons with rounded normals, for fast rendering"),
|
||||
('THICK', "3D Curves", "Render curves as circular 3D geometry, for accurate results when viewing closely"),
|
||||
('RIBBONS', "Rounded Ribbons", "Render hair as flat ribbon with rounded normals, for fast rendering"),
|
||||
('THICK', "3D Curves", "Render hair as 3D curve, for accurate results when viewing hair close up"),
|
||||
)
|
||||
|
||||
enum_use_layer_samples = (
|
||||
@@ -216,6 +216,7 @@ enum_direct_light_sampling_type = (
|
||||
)
|
||||
|
||||
def update_render_passes(self, context):
|
||||
scene = context.scene
|
||||
view_layer = context.view_layer
|
||||
view_layer.update_render_passes()
|
||||
|
||||
@@ -348,8 +349,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
scrambling_distance: FloatProperty(
|
||||
name="Scrambling Distance",
|
||||
default=1.0,
|
||||
min=0.0, soft_max=1.0,
|
||||
description="Reduce randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts if set too low",
|
||||
min=0.0, max=1.0,
|
||||
description="Reduce randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts if set too low. Only works when not using adaptive sampling",
|
||||
)
|
||||
preview_scrambling_distance: BoolProperty(
|
||||
name="Scrambling Distance viewport",
|
||||
@@ -360,7 +361,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
auto_scrambling_distance: BoolProperty(
|
||||
name="Automatic Scrambling Distance",
|
||||
default=False,
|
||||
description="Automatically reduce the randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts",
|
||||
description="Automatically reduce the randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts. Only works when not using adaptive sampling",
|
||||
)
|
||||
|
||||
use_layer_samples: EnumProperty(
|
||||
@@ -428,14 +429,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
min_light_bounces: IntProperty(
|
||||
name="Min Light Bounces",
|
||||
description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
|
||||
"but can also be less efficient for more complex geometry like curves and volumes",
|
||||
"but can also be less efficient for more complex geometry like hair and volumes",
|
||||
min=0, max=1024,
|
||||
default=0,
|
||||
)
|
||||
min_transparent_bounces: IntProperty(
|
||||
name="Min Transparent Bounces",
|
||||
description="Minimum number of transparent bounces. Setting this higher reduces noise in the first bounces, "
|
||||
"but can also be less efficient for more complex geometry like curves and volumes",
|
||||
"but can also be less efficient for more complex geometry like hair and volumes",
|
||||
min=0, max=1024,
|
||||
default=0,
|
||||
)
|
||||
@@ -649,8 +650,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
default=False,
|
||||
)
|
||||
debug_use_hair_bvh: BoolProperty(
|
||||
name="Use Curves BVH",
|
||||
description="Use special type BVH optimized for curves (uses more ram but renders faster)",
|
||||
name="Use Hair BVH",
|
||||
description="Use special type BVH optimized for hair (uses more ram but renders faster)",
|
||||
default=True,
|
||||
)
|
||||
debug_use_compact_bvh: BoolProperty(
|
||||
@@ -1012,12 +1013,6 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
|
||||
"note that this will make the light invisible",
|
||||
default=False,
|
||||
)
|
||||
is_caustics_light: BoolProperty(
|
||||
name="Shadow Caustics",
|
||||
description="Generate approximate caustics in shadows of refractive surfaces. "
|
||||
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
|
||||
default=False,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
@@ -1034,12 +1029,6 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
|
||||
|
||||
class CyclesWorldSettings(bpy.types.PropertyGroup):
|
||||
|
||||
is_caustics_light: BoolProperty(
|
||||
name="Shadow Caustics",
|
||||
description="Generate approximate caustics in shadows of refractive surfaces. "
|
||||
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
|
||||
default=False,
|
||||
)
|
||||
sampling_method: EnumProperty(
|
||||
name="Sampling Method",
|
||||
description="How to sample the background light",
|
||||
@@ -1238,21 +1227,6 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
|
||||
subtype='DISTANCE',
|
||||
)
|
||||
|
||||
is_caustics_caster: BoolProperty(
|
||||
name="Cast Shadow Caustics",
|
||||
description="With refractive materials, generate approximate caustics in shadows of this object. "
|
||||
"Up to 10 bounces inside this object are taken into account. Lights, caster and receiver objects "
|
||||
"must have shadow caustics options set to enable this",
|
||||
default=False,
|
||||
)
|
||||
|
||||
is_caustics_receiver: BoolProperty(
|
||||
name="Receive Shadow Caustics",
|
||||
description="Receive approximate caustics from refractive materials in shadows on this object. "
|
||||
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
|
||||
default=False,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
bpy.types.Object.cycles = PointerProperty(
|
||||
@@ -1270,7 +1244,7 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
|
||||
|
||||
shape: EnumProperty(
|
||||
name="Shape",
|
||||
description="Form of curves",
|
||||
description="Form of hair",
|
||||
items=enum_curve_shape,
|
||||
default='RIBBONS',
|
||||
)
|
||||
@@ -1284,8 +1258,8 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
bpy.types.Scene.cycles_curves = PointerProperty(
|
||||
name="Cycles Curves Rendering Settings",
|
||||
description="Cycles curves rendering settings",
|
||||
name="Cycles Hair Rendering Settings",
|
||||
description="Cycles hair rendering settings",
|
||||
type=cls,
|
||||
)
|
||||
|
||||
@@ -1379,7 +1353,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
items=CyclesPreferences.get_device_types,
|
||||
)
|
||||
|
||||
devices: CollectionProperty(type=CyclesDeviceSettings)
|
||||
devices: bpy.props.CollectionProperty(type=CyclesDeviceSettings)
|
||||
|
||||
peer_memory: BoolProperty(
|
||||
name="Distribute memory across devices",
|
||||
@@ -1540,12 +1514,9 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
row.prop(self, "peer_memory")
|
||||
|
||||
if compute_device_type == 'METAL':
|
||||
import platform
|
||||
# MetalRT only works on Apple Silicon at present, pending argument encoding fixes on AMD
|
||||
if platform.machine() == 'arm64':
|
||||
row = layout.row()
|
||||
row.use_property_split = True
|
||||
row.prop(self, "use_metalrt")
|
||||
row = layout.row()
|
||||
row.use_property_split = True
|
||||
row.prop(self, "use_metalrt")
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
|
@@ -11,8 +11,7 @@ from bl_ui.utils import PresetPanel
|
||||
from bpy.types import Panel
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
|
||||
from bl_ui.properties_render import draw_curves_settings
|
||||
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel
|
||||
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel
|
||||
|
||||
class CyclesPresetPanel(PresetPanel, Panel):
|
||||
COMPAT_ENGINES = {'CYCLES'}
|
||||
@@ -289,8 +288,11 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
|
||||
layout.separator()
|
||||
|
||||
heading = layout.column(align=True, heading="Scrambling Distance")
|
||||
heading.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
|
||||
heading.prop(cscene, "auto_scrambling_distance", text="Automatic")
|
||||
heading.prop(cscene, "preview_scrambling_distance", text="Viewport")
|
||||
sub = heading.row()
|
||||
sub.active = not cscene.use_preview_adaptive_sampling
|
||||
sub.prop(cscene, "preview_scrambling_distance", text="Viewport")
|
||||
heading.prop(cscene, "scrambling_distance", text="Multiplier")
|
||||
|
||||
layout.separator()
|
||||
@@ -336,8 +338,8 @@ class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
|
||||
col.prop(cscene, "dicing_camera")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_curves(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Curves"
|
||||
class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Hair"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
@@ -353,13 +355,6 @@ class CYCLES_RENDER_PT_curves(CyclesButtonsPanel, Panel):
|
||||
if ccscene.shape == 'RIBBONS':
|
||||
col.prop(ccscene, "subdivisions", text="Curve Subdivisions")
|
||||
|
||||
class CYCLES_RENDER_PT_curves_viewport_display(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Viewport Display"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_curves"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
draw_curves_settings(self, context)
|
||||
|
||||
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Volumes"
|
||||
@@ -757,7 +752,7 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
|
||||
col = layout.column(heading="Include")
|
||||
col.prop(view_layer, "use_sky", text="Environment")
|
||||
col.prop(view_layer, "use_solid", text="Surfaces")
|
||||
col.prop(view_layer, "use_strand", text="Curves")
|
||||
col.prop(view_layer, "use_strand", text="Hair")
|
||||
col.prop(view_layer, "use_volumes", text="Volumes")
|
||||
|
||||
col = layout.column(heading="Use")
|
||||
@@ -883,12 +878,6 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel):
|
||||
bl_parent_id = "CYCLES_RENDER_PT_passes"
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_passes_lightgroups(CyclesButtonsPanel, ViewLayerLightgroupsPanel):
|
||||
bl_label = "Light Groups"
|
||||
bl_context = "view_layer"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_passes"
|
||||
|
||||
|
||||
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Post Processing"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -1034,7 +1023,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
if CyclesButtonsPanel.poll(context) and ob:
|
||||
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'CURVES', 'POINTCLOUD'}:
|
||||
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'HAIR', 'POINTCLOUD'}:
|
||||
return True
|
||||
if ob.instance_type == 'COLLECTION' and ob.instance_collection:
|
||||
return True
|
||||
@@ -1073,7 +1062,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
|
||||
|
||||
def has_geometry_visibility(ob):
|
||||
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT', 'VOLUME', 'POINTCLOUD', 'CURVES'}) or
|
||||
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT', 'VOLUME', 'POINTCLOUD', 'HAIR'}) or
|
||||
(ob.instance_type == 'COLLECTION' and ob.instance_collection))
|
||||
|
||||
|
||||
@@ -1099,10 +1088,6 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel):
|
||||
bl_parent_id = "CYCLES_OBJECT_PT_shading"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object.type != 'LIGHT'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
@@ -1120,10 +1105,6 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
|
||||
bl_parent_id = "CYCLES_OBJECT_PT_shading"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object.type != 'LIGHT'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
@@ -1139,52 +1120,6 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
|
||||
col.prop(cob, "ao_distance")
|
||||
|
||||
|
||||
class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Caustics"
|
||||
bl_parent_id = "CYCLES_OBJECT_PT_shading"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
col = layout.column()
|
||||
|
||||
ob = context.object
|
||||
cob = ob.cycles
|
||||
col.prop(cob, "is_caustics_caster")
|
||||
col.prop(cob, "is_caustics_receiver")
|
||||
|
||||
|
||||
class CYCLES_OBJECT_PT_lightgroup(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Light Group"
|
||||
bl_parent_id = "CYCLES_OBJECT_PT_shading"
|
||||
bl_context = "object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ob = context.object
|
||||
|
||||
view_layer = context.view_layer
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.use_property_decorate = False
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.prop_search(ob, "lightgroup", view_layer, "lightgroups", text="Light Group", results_are_suggestions=True)
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.active = bool(ob.lightgroup) and not any(lg.name == ob.lightgroup for lg in view_layer.lightgroups)
|
||||
sub.operator("scene.view_layer_add_lightgroup", icon='ADD', text="").name = ob.lightgroup
|
||||
|
||||
|
||||
class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Visibility"
|
||||
bl_context = "object"
|
||||
@@ -1360,8 +1295,6 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
|
||||
sub.active = not (light.type == 'AREA' and clamp.is_portal)
|
||||
sub.prop(clamp, "cast_shadow")
|
||||
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
|
||||
if not use_metal(context):
|
||||
sub.prop(clamp, "is_caustics_light", text="Shadow Caustics")
|
||||
|
||||
if light.type == 'AREA':
|
||||
col.prop(clamp, "is_portal", text="Portal")
|
||||
@@ -1437,21 +1370,10 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
|
||||
world = context.world
|
||||
view_layer = context.view_layer
|
||||
|
||||
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
|
||||
layout.prop(world, "color")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.use_property_decorate = False
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group", results_are_suggestions=True)
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.active = bool(world.lightgroup) and not any(lg.name == world.lightgroup for lg in view_layer.lightgroups)
|
||||
sub.operator("scene.view_layer_add_lightgroup", icon='ADD', text="").name = world.lightgroup
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Volume"
|
||||
@@ -1569,8 +1491,6 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
|
||||
subsub.active = cworld.sampling_method == 'MANUAL'
|
||||
subsub.prop(cworld, "sample_map_resolution")
|
||||
sub.prop(cworld, "max_bounces")
|
||||
sub.prop(cworld, "is_caustics_light", text="Shadow Caustics")
|
||||
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
|
||||
@@ -1916,20 +1836,13 @@ class CYCLES_RENDER_PT_bake_output_margin(CyclesButtonsPanel, Panel):
|
||||
cbk = scene.render.bake
|
||||
rd = scene.render
|
||||
|
||||
if (cscene.bake_type == 'NORMAL' and cbk.normal_space == 'TANGENT') or cscene.bake_type == 'UV':
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
else:
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin_type", text="Type")
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
else:
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin_type", text="Type")
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
else:
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin_type", text="Type")
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin_type", text="Type")
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
|
||||
|
||||
|
||||
@@ -2239,8 +2152,7 @@ classes = (
|
||||
CYCLES_RENDER_PT_light_paths_fast_gi,
|
||||
CYCLES_RENDER_PT_volumes,
|
||||
CYCLES_RENDER_PT_subdivision,
|
||||
CYCLES_RENDER_PT_curves,
|
||||
CYCLES_RENDER_PT_curves_viewport_display,
|
||||
CYCLES_RENDER_PT_hair,
|
||||
CYCLES_RENDER_PT_simplify,
|
||||
CYCLES_RENDER_PT_simplify_viewport,
|
||||
CYCLES_RENDER_PT_simplify_render,
|
||||
@@ -2265,7 +2177,6 @@ classes = (
|
||||
CYCLES_RENDER_PT_passes_light,
|
||||
CYCLES_RENDER_PT_passes_crypto,
|
||||
CYCLES_RENDER_PT_passes_aov,
|
||||
CYCLES_RENDER_PT_passes_lightgroups,
|
||||
CYCLES_RENDER_PT_filter,
|
||||
CYCLES_RENDER_PT_override,
|
||||
CYCLES_PT_post_processing,
|
||||
@@ -2276,8 +2187,6 @@ classes = (
|
||||
CYCLES_OBJECT_PT_shading,
|
||||
CYCLES_OBJECT_PT_shading_shadow_terminator,
|
||||
CYCLES_OBJECT_PT_shading_gi_approximation,
|
||||
CYCLES_OBJECT_PT_shading_caustics,
|
||||
CYCLES_OBJECT_PT_lightgroup,
|
||||
CYCLES_OBJECT_PT_visibility,
|
||||
CYCLES_OBJECT_PT_visibility_ray_visibility,
|
||||
CYCLES_OBJECT_PT_visibility_culling,
|
||||
|
@@ -5,6 +5,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
import math
|
||||
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
|
@@ -114,9 +114,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
light->set_cast_shadow(get_boolean(clight, "cast_shadow"));
|
||||
light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
|
||||
|
||||
/* caustics light */
|
||||
light->set_use_caustics(get_boolean(clight, "is_caustics_light"));
|
||||
|
||||
light->set_max_bounces(get_int(clight, "max_bounces"));
|
||||
|
||||
if (b_ob_info.real_object != b_ob_info.iter_object) {
|
||||
@@ -143,9 +140,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
|
||||
light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
|
||||
|
||||
/* lightgroup */
|
||||
light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup()));
|
||||
|
||||
/* tag */
|
||||
light->tag_update(scene);
|
||||
}
|
||||
@@ -182,9 +176,6 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
|
||||
/* force enable light again when world is resynced */
|
||||
light->set_is_enabled(true);
|
||||
|
||||
/* caustic light */
|
||||
light->set_use_caustics(get_boolean(cworld, "is_caustics_light"));
|
||||
|
||||
light->tag_update(scene);
|
||||
light_map.set_recalc(b_world);
|
||||
}
|
||||
|
@@ -66,8 +66,9 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
|
||||
}
|
||||
|
||||
/* Other object types that are not meshes but evaluate to meshes are presented to render engines
|
||||
* as separate instance objects. Metaballs have not been affected by that change yet. */
|
||||
if (type == BL::Object::type_META) {
|
||||
* as separate instance objects. Metaballs and surface objects have not been affected by that
|
||||
* change yet. */
|
||||
if (type == BL::Object::type_SURFACE || type == BL::Object::type_META) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -297,12 +298,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
}
|
||||
object->set_ao_distance(ao_distance);
|
||||
|
||||
bool is_caustics_caster = get_boolean(cobject, "is_caustics_caster");
|
||||
object->set_is_caustics_caster(is_caustics_caster);
|
||||
|
||||
bool is_caustics_receiver = get_boolean(cobject, "is_caustics_receiver");
|
||||
object->set_is_caustics_receiver(is_caustics_receiver);
|
||||
|
||||
/* sync the asset name for Cryptomatte */
|
||||
BL::Object parent = b_ob.parent();
|
||||
ustring parent_name;
|
||||
@@ -324,9 +319,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
(object->get_geometry() && object->get_geometry()->is_modified())) {
|
||||
object->name = b_ob.name().c_str();
|
||||
object->set_pass_id(b_ob.pass_index());
|
||||
const BL::Array<float, 4> object_color = b_ob.color();
|
||||
object->set_color(get_float3(object_color));
|
||||
object->set_alpha(object_color[3]);
|
||||
object->set_color(get_float3(b_ob.color()));
|
||||
object->set_tfm(tfm);
|
||||
|
||||
/* dupli texture coordinates and random_id */
|
||||
@@ -342,9 +335,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
|
||||
}
|
||||
|
||||
/* lightgroup */
|
||||
object->set_lightgroup(ustring(b_ob.lightgroup()));
|
||||
|
||||
object->tag_update(scene);
|
||||
}
|
||||
|
||||
@@ -430,7 +420,7 @@ static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
|
||||
return value;
|
||||
}
|
||||
|
||||
return zero_float4();
|
||||
return make_float4(0.0f);
|
||||
}
|
||||
|
||||
bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
|
||||
@@ -629,8 +619,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
|
||||
bool has_subdivision_modifier = false;
|
||||
BL::MeshSequenceCacheModifier b_mesh_cache(PointerRNA_NULL);
|
||||
|
||||
/* Experimental as Blender does not have good support for procedurals at the moment. */
|
||||
if (experimental) {
|
||||
/* Experimental as Blender does not have good support for procedurals at the moment, also
|
||||
* only available in preview renders since currently do not have a good cache policy, the
|
||||
* data being loaded at once for all the frames. */
|
||||
if (experimental && b_v3d) {
|
||||
b_mesh_cache = object_mesh_cache_find(b_ob, &has_subdivision_modifier);
|
||||
use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural();
|
||||
}
|
||||
|
@@ -271,7 +271,6 @@ static ShaderNode *add_node(Scene *scene,
|
||||
curves->set_min_x(min_x);
|
||||
curves->set_max_x(max_x);
|
||||
curves->set_curves(curve_mapping_curves);
|
||||
curves->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
|
||||
node = curves;
|
||||
}
|
||||
if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
|
||||
@@ -285,7 +284,6 @@ static ShaderNode *add_node(Scene *scene,
|
||||
curves->set_min_x(min_x);
|
||||
curves->set_max_x(max_x);
|
||||
curves->set_curves(curve_mapping_curves);
|
||||
curves->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
|
||||
node = curves;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeFloatCurve)) {
|
||||
@@ -299,7 +297,6 @@ static ShaderNode *add_node(Scene *scene,
|
||||
curve->set_min_x(min_x);
|
||||
curve->set_max_x(max_x);
|
||||
curve->set_curve(curve_mapping_curve);
|
||||
curve->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
|
||||
node = curve;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
|
||||
@@ -1532,8 +1529,6 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
background->set_use_shader(view_layer.use_background_shader ||
|
||||
viewport_parameters.use_custom_shader());
|
||||
|
||||
background->set_lightgroup(ustring(b_world ? b_world.lightgroup() : ""));
|
||||
|
||||
background->tag_update(scene);
|
||||
}
|
||||
|
||||
@@ -1579,13 +1574,18 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all)
|
||||
void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
|
||||
{
|
||||
/* for auto refresh images */
|
||||
ImageManager *image_manager = scene->image_manager;
|
||||
const int frame = b_scene.frame_current();
|
||||
const bool auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
||||
|
||||
shader_map.pre_sync();
|
||||
|
||||
sync_world(b_depsgraph, b_v3d, update_all);
|
||||
sync_lights(b_depsgraph, update_all);
|
||||
sync_materials(b_depsgraph, update_all);
|
||||
sync_world(b_depsgraph, b_v3d, auto_refresh_update);
|
||||
sync_lights(b_depsgraph, auto_refresh_update);
|
||||
sync_materials(b_depsgraph, auto_refresh_update);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -246,12 +246,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
int height,
|
||||
void **python_thread_state)
|
||||
{
|
||||
/* For auto refresh images. */
|
||||
ImageManager *image_manager = scene->image_manager;
|
||||
const int frame = b_scene.frame_current();
|
||||
const bool auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
||||
|
||||
if (!has_updates_ && !auto_refresh_update) {
|
||||
if (!has_updates_) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -266,7 +261,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
sync_view_layer(b_view_layer);
|
||||
sync_integrator(b_view_layer, background);
|
||||
sync_film(b_view_layer, b_v3d);
|
||||
sync_shaders(b_depsgraph, b_v3d, auto_refresh_update);
|
||||
sync_shaders(b_depsgraph, b_v3d);
|
||||
sync_images();
|
||||
|
||||
geometry_synced.clear(); /* use for objects and motion sync */
|
||||
@@ -346,48 +341,31 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
|
||||
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
|
||||
integrator->set_sampling_pattern(sampling_pattern);
|
||||
|
||||
int samples = 1;
|
||||
bool use_adaptive_sampling = false;
|
||||
if (preview) {
|
||||
samples = get_int(cscene, "preview_samples");
|
||||
use_adaptive_sampling = RNA_boolean_get(&cscene, "use_preview_adaptive_sampling");
|
||||
integrator->set_use_adaptive_sampling(use_adaptive_sampling);
|
||||
integrator->set_adaptive_threshold(get_float(cscene, "preview_adaptive_threshold"));
|
||||
integrator->set_adaptive_min_samples(get_int(cscene, "preview_adaptive_min_samples"));
|
||||
}
|
||||
else {
|
||||
samples = get_int(cscene, "samples");
|
||||
use_adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
|
||||
integrator->set_use_adaptive_sampling(use_adaptive_sampling);
|
||||
integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
|
||||
integrator->set_adaptive_min_samples(get_int(cscene, "adaptive_min_samples"));
|
||||
}
|
||||
|
||||
int samples = get_int(cscene, "samples");
|
||||
float scrambling_distance = get_float(cscene, "scrambling_distance");
|
||||
bool auto_scrambling_distance = get_boolean(cscene, "auto_scrambling_distance");
|
||||
if (auto_scrambling_distance) {
|
||||
if (samples == 0) {
|
||||
/* If samples is 0, then viewport rendering is set to render infinitely. In that case we
|
||||
* override the samples value with 4096 so the Automatic Scrambling Distance algorithm
|
||||
* picks a Scrambling Distance value with a good balance of performance and correlation
|
||||
* artifacts when rendering to high sample counts. */
|
||||
samples = 4096;
|
||||
}
|
||||
|
||||
if (use_adaptive_sampling) {
|
||||
/* If Adaptive Sampling is enabled, use "min_samples" in the Automatic Scrambling Distance
|
||||
* algorithm to avoid artifacts common with Adaptive Sampling + Scrambling Distance. */
|
||||
const AdaptiveSampling adaptive_sampling = integrator->get_adaptive_sampling();
|
||||
samples = min(samples, adaptive_sampling.min_samples);
|
||||
}
|
||||
scrambling_distance *= 4.0f / sqrtf(samples);
|
||||
}
|
||||
|
||||
/* Only use scrambling distance in the viewport if user wants to. */
|
||||
/* only use scrambling distance in the viewport if user wants to and disable with AS */
|
||||
bool preview_scrambling_distance = get_boolean(cscene, "preview_scrambling_distance");
|
||||
if (preview && !preview_scrambling_distance) {
|
||||
if ((preview && !preview_scrambling_distance) || use_adaptive_sampling)
|
||||
scrambling_distance = 1.0f;
|
||||
}
|
||||
|
||||
if (scrambling_distance != 1.0f) {
|
||||
VLOG(3) << "Using scrambling distance: " << scrambling_distance;
|
||||
@@ -745,20 +723,6 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
|
||||
}
|
||||
}
|
||||
|
||||
/* Light Group passes. */
|
||||
BL::ViewLayer::lightgroups_iterator b_lightgroup_iter;
|
||||
for (b_view_layer.lightgroups.begin(b_lightgroup_iter);
|
||||
b_lightgroup_iter != b_view_layer.lightgroups.end();
|
||||
++b_lightgroup_iter) {
|
||||
BL::Lightgroup b_lightgroup(*b_lightgroup_iter);
|
||||
|
||||
string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
|
||||
|
||||
b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
|
||||
Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
|
||||
pass->set_lightgroup(ustring(b_lightgroup.name()));
|
||||
}
|
||||
|
||||
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
|
||||
}
|
||||
|
||||
|
@@ -114,7 +114,7 @@ class BlenderSync {
|
||||
/* Shader */
|
||||
array<Node *> find_used_shaders(BL::Object &b_ob);
|
||||
void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
|
||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
|
||||
|
||||
/* Object */
|
||||
|
@@ -203,7 +203,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange &job,
|
||||
bestSAH = min(sah, bestSAH);
|
||||
}
|
||||
|
||||
int4 mask = float3_to_float4(cent_bounds_.size()) <= zero_float4();
|
||||
int4 mask = float3_to_float4(cent_bounds_.size()) <= make_float4(0.0f);
|
||||
bestSAH = insert<3>(select(mask, make_float4(FLT_MAX), bestSAH), FLT_MAX);
|
||||
|
||||
/* find best dimension */
|
||||
|
@@ -19,11 +19,7 @@ endmacro()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(APPLE)
|
||||
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")
|
||||
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/darwin")
|
||||
else()
|
||||
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/darwin_arm64")
|
||||
endif()
|
||||
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/darwin")
|
||||
elseif(WIN32)
|
||||
if(CMAKE_CL_64)
|
||||
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/win64_vc15")
|
||||
@@ -52,24 +48,18 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED _cycles_lib_dir)
|
||||
message(STATUS "Using precompiled libraries at ${_cycles_lib_dir}")
|
||||
endif()
|
||||
|
||||
# Avoid namespace pollustion.
|
||||
unset(LIBDIR_NATIVE_ABI)
|
||||
unset(LIBDIR_CENTOS7_ABI)
|
||||
endif()
|
||||
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
_set_default(ALEMBIC_ROOT_DIR "${_cycles_lib_dir}/alembic")
|
||||
_set_default(BOOST_ROOT "${_cycles_lib_dir}/boost")
|
||||
_set_default(BLOSC_ROOT_DIR "${_cycles_lib_dir}/blosc")
|
||||
_set_default(EMBREE_ROOT_DIR "${_cycles_lib_dir}/embree")
|
||||
_set_default(GLEW_ROOT_DIR "${_cycles_lib_dir}/glew")
|
||||
_set_default(JPEG_ROOT "${_cycles_lib_dir}/jpeg")
|
||||
_set_default(LLVM_ROOT_DIR "${_cycles_lib_dir}/llvm")
|
||||
_set_default(CLANG_ROOT_DIR "${_cycles_lib_dir}/llvm")
|
||||
_set_default(OPENCOLORIO_ROOT_DIR "${_cycles_lib_dir}/opencolorio")
|
||||
_set_default(OPENEXR_ROOT_DIR "${_cycles_lib_dir}/openexr")
|
||||
_set_default(OPENIMAGEDENOISE_ROOT_DIR "${_cycles_lib_dir}/openimagedenoise")
|
||||
@@ -79,7 +69,6 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
_set_default(OPENVDB_ROOT_DIR "${_cycles_lib_dir}/openvdb")
|
||||
_set_default(OSL_ROOT_DIR "${_cycles_lib_dir}/osl")
|
||||
_set_default(PNG_ROOT "${_cycles_lib_dir}/png")
|
||||
_set_default(PUGIXML_ROOT_DIR "${_cycles_lib_dir}/pugixml")
|
||||
_set_default(TBB_ROOT_DIR "${_cycles_lib_dir}/tbb")
|
||||
_set_default(TIFF_ROOT "${_cycles_lib_dir}/tiff")
|
||||
_set_default(ZLIB_ROOT "${_cycles_lib_dir}/zlib")
|
||||
@@ -91,23 +80,6 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# USD
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
set(WITH_USD ON)
|
||||
endif()
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
find_package(pxr CONFIG REQUIRED PATHS ${PXR_ROOT} ${USD_ROOT} NO_DEFAULT_PATH)
|
||||
if(pxr_FOUND)
|
||||
set(PXR_LIBRARY_DIR ${PXR_CMAKE_DIR}/lib)
|
||||
set(USD_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
|
||||
else()
|
||||
set(WITH_USD OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# Zlib
|
||||
###########################################################################
|
||||
@@ -120,7 +92,7 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
set(ZLIB_LIBRARY ${_cycles_lib_dir}/zlib/lib/libz_st.lib)
|
||||
set(ZLIB_DIR ${_cycles_lib_dir}/zlib)
|
||||
set(ZLIB_FOUND ON)
|
||||
elseif(NOT APPLE)
|
||||
else()
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
@@ -154,45 +126,32 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
-DOIIO_STATIC_DEFINE
|
||||
)
|
||||
|
||||
set(OPENIMAGEIO_INCLUDE_DIR ${OPENIMAGEIO_ROOT_DIR}/include)
|
||||
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR} ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO)
|
||||
# Special exceptions for libraries which needs explicit debug version
|
||||
set(OPENIMAGEIO_LIBRARIES
|
||||
set(OPENIMAGEIO_LIBRARY
|
||||
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO.lib
|
||||
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util.lib
|
||||
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_d.lib
|
||||
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util_d.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
set(PUGIXML_INCLUDE_DIR ${PUGIXML_ROOT_DIR}/include)
|
||||
set(PUGIXML_LIBRARIES
|
||||
optimized ${PUGIXML_ROOT_DIR}/lib/pugixml.lib
|
||||
debug ${PUGIXML_ROOT_DIR}/lib/pugixml_d.lib
|
||||
)
|
||||
find_package(OpenImageIO REQUIRED)
|
||||
if(OPENIMAGEIO_PUGIXML_FOUND)
|
||||
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
|
||||
set(PUGIXML_LIBRARIES "")
|
||||
else()
|
||||
find_package(OpenImageIO REQUIRED)
|
||||
if(OPENIMAGEIO_PUGIXML_FOUND)
|
||||
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO")
|
||||
set(PUGIXML_LIBRARIES "")
|
||||
else()
|
||||
find_package(PugiXML REQUIRED)
|
||||
endif()
|
||||
find_package(PugiXML REQUIRED)
|
||||
endif()
|
||||
|
||||
# Dependencies
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENJPEG_INCLUDE_DIR ${OPENJPEG}/include/openjpeg-2.3)
|
||||
set(OPENJPEG_LIBRARIES ${_cycles_lib_dir}/openjpeg/lib/openjp2${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
find_package(OpenJPEG REQUIRED)
|
||||
set(OPENJPEG_LIBRARY ${_cycles_lib_dir}/openjpeg/lib/openjp2${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(OpenJPEG REQUIRED)
|
||||
find_package(TIFF REQUIRED)
|
||||
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
set(PNG_NAMES png16 libpng16 png libpng)
|
||||
endif()
|
||||
find_package(PNG REQUIRED)
|
||||
endif()
|
||||
|
||||
@@ -202,71 +161,76 @@ endif()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENEXR_INCLUDE_DIR ${OPENEXR_ROOT_DIR}/include)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_ROOT_DIR}/include/OpenEXR)
|
||||
set(OPENEXR_LIBRARIES
|
||||
set(OPENEXR_IEX_LIBRARY
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Iex_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Half_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmImf_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Imath_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmThread_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Iex_s_d.lib
|
||||
)
|
||||
set(OPENEXR_HALF_LIBRARY
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Half_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Half_s_d.lib
|
||||
)
|
||||
set(OPENEXR_ILMIMF_LIBRARY
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmImf_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/IlmImf_s_d.lib
|
||||
)
|
||||
set(OPENEXR_IMATH_LIBRARY
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Imath_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Imath_s_d.lib
|
||||
)
|
||||
set(OPENEXR_ILMTHREAD_LIBRARY
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmThread_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/IlmThread_s_d.lib
|
||||
)
|
||||
else()
|
||||
find_package(OpenEXR REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(OpenEXR REQUIRED)
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenShadingLanguage & LLVM
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OSL)
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
set(LLVM_STATIC ON)
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
set(LLVM_STATIC ON)
|
||||
endif()
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
# TODO(sergey): On Windows llvm-config doesn't give proper results for the
|
||||
# library names, use hardcoded libraries for now.
|
||||
file(GLOB _llvm_libs_release ${LLVM_ROOT_DIR}/lib/*.lib)
|
||||
file(GLOB _llvm_libs_debug ${LLVM_ROOT_DIR}/debug/lib/*.lib)
|
||||
set(_llvm_libs)
|
||||
foreach(_llvm_lib_path ${_llvm_libs_release})
|
||||
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
|
||||
list(APPEND _llvm_libs optimized ${_llvm_lib_name})
|
||||
endforeach()
|
||||
foreach(_llvm_lib_path ${_llvm_libs_debug})
|
||||
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
|
||||
list(APPEND _llvm_libs debug ${_llvm_lib_name})
|
||||
endforeach()
|
||||
set(LLVM_LIBRARY ${_llvm_libs})
|
||||
unset(_llvm_lib_name)
|
||||
unset(_llvm_lib_path)
|
||||
unset(_llvm_libs)
|
||||
unset(_llvm_libs_debug)
|
||||
unset(_llvm_libs_release)
|
||||
|
||||
set(OSL_INCLUDE_DIR ${OSL_ROOT_DIR}/include)
|
||||
set(OSL_LIBRARIES
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslcomp.lib
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslexec.lib
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslquery.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslcomp_d.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslexec_d.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslquery_d.lib
|
||||
${PUGIXML_LIBRARIES}
|
||||
)
|
||||
|
||||
find_program(OSL_COMPILER NAMES oslc PATHS ${OSL_ROOT_DIR}/bin)
|
||||
else()
|
||||
find_package(OSL REQUIRED)
|
||||
find_package(LLVM REQUIRED)
|
||||
find_package(Clang REQUIRED)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
# TODO(sergey): On Windows llvm-config doesn't give proper results for the
|
||||
# library names, use hardcoded libraries for now.
|
||||
file(GLOB _llvm_libs_release ${LLVM_ROOT_DIR}/lib/*.lib)
|
||||
file(GLOB _llvm_libs_debug ${LLVM_ROOT_DIR}/debug/lib/*.lib)
|
||||
set(_llvm_libs)
|
||||
foreach(_llvm_lib_path ${_llvm_libs_release})
|
||||
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
|
||||
list(APPEND _llvm_libs optimized ${_llvm_lib_name})
|
||||
endforeach()
|
||||
foreach(_llvm_lib_path ${_llvm_libs_debug})
|
||||
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
|
||||
list(APPEND _llvm_libs debug ${_llvm_lib_name})
|
||||
endforeach()
|
||||
set(LLVM_LIBRARY ${_llvm_libs})
|
||||
unset(_llvm_lib_name)
|
||||
unset(_llvm_lib_path)
|
||||
unset(_llvm_libs)
|
||||
unset(_llvm_libs_debug)
|
||||
unset(_llvm_libs_release)
|
||||
|
||||
set(OSL_LIBRARIES
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslcomp.lib
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslexec.lib
|
||||
optimized ${OSL_ROOT_DIR}/lib/oslquery.lib
|
||||
optimized ${OSL_ROOT_DIR}/lib/pugixml.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslcomp_d.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslexec_d.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/oslquery_d.lib
|
||||
debug ${OSL_ROOT_DIR}/lib/pugixml_d.lib
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -274,23 +238,22 @@ endif()
|
||||
# OpenColorIO
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENCOLORIO)
|
||||
set(WITH_OPENCOLORIO ON)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO_ROOT_DIR}/include)
|
||||
set(OPENCOLORIO_LIBRARIES
|
||||
optimized ${OPENCOLORIO_ROOT_DIR}/lib/OpenColorIO.lib
|
||||
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp.lib
|
||||
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libexpatMD.lib
|
||||
optimized ${OPENCOLORIO_ROOT_DIR}/lib/pystring.lib
|
||||
debug ${OPENCOLORIO_ROOT_DIR}/lib/OpencolorIO_d.lib
|
||||
debug ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp_d.lib
|
||||
debug ${OPENCOLORIO_ROOT_DIR}/lib/libexpatdMD.lib
|
||||
debug ${OPENCOLORIO_ROOT_DIR}/lib/pystring_d.lib
|
||||
)
|
||||
else()
|
||||
if(WITH_CYCLES_OPENCOLORIO)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
find_package(OpenColorIO REQUIRED)
|
||||
set(WITH_OPENCOLORIO ON)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENCOLORIO_LIBPATH ${_cycles_lib_dir}/opencolorio/lib)
|
||||
set(OPENCOLORIO_LIBRARIES
|
||||
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/tinyxml.lib
|
||||
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/tinyxml_d.lib
|
||||
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -311,61 +274,22 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(BOOST_INCLUDE_DIR ${BOOST_ROOT}/include)
|
||||
set(BOOST_VERSION_HEADER ${BOOST_INCLUDE_DIR}/boost/version.hpp)
|
||||
if(EXISTS ${BOOST_VERSION_HEADER})
|
||||
file(STRINGS "${BOOST_VERSION_HEADER}" BOOST_LIB_VERSION REGEX "#define BOOST_LIB_VERSION ")
|
||||
if(BOOST_LIB_VERSION MATCHES "#define BOOST_LIB_VERSION \"([0-9_]+)\"")
|
||||
set(BOOST_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT BOOST_VERSION)
|
||||
message(FATAL_ERROR "Unable to determine Boost version")
|
||||
endif()
|
||||
set(BOOST_POSTFIX "vc141-mt-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_DEBUG_POSTFIX "vc141-mt-gd-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_LIBRARIES
|
||||
optimized ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_iostreams-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_regex-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_system-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_thread-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_iostreams-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_regex-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_system-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_thread-${BOOST_DEBUG_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_DEBUG_POSTFIX}
|
||||
)
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_wave-${BOOST_POSTFIX}
|
||||
debug ${BOOST_ROOT}/lib/libboost_wave-${BOOST_DEBUG_POSTFIX})
|
||||
endif()
|
||||
else()
|
||||
set(__boost_packages iostreams filesystem regex system thread date_time)
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND __boost_packages wave)
|
||||
endif()
|
||||
find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
|
||||
if(NOT Boost_FOUND)
|
||||
# Try to find non-multithreaded if -mt not found, this flag
|
||||
# doesn't matter for us, it has nothing to do with thread
|
||||
# safety, but keep it to not disturb build setups.
|
||||
set(Boost_USE_MULTITHREADED OFF)
|
||||
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
|
||||
endif()
|
||||
unset(__boost_packages)
|
||||
|
||||
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
|
||||
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
|
||||
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
|
||||
set(__boost_packages filesystem regex system thread date_time)
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND __boost_packages wave)
|
||||
endif()
|
||||
|
||||
find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
|
||||
if(NOT Boost_FOUND)
|
||||
# Try to find non-multithreaded if -mt not found, this flag
|
||||
# doesn't matter for us, it has nothing to do with thread
|
||||
# safety, but keep it to not disturb build setups.
|
||||
set(Boost_USE_MULTITHREADED OFF)
|
||||
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
|
||||
endif()
|
||||
unset(__boost_packages)
|
||||
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
|
||||
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
|
||||
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
|
||||
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
|
||||
endif()
|
||||
|
||||
@@ -373,30 +297,47 @@ endif()
|
||||
# Embree
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_EMBREE)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/include)
|
||||
set(EMBREE_LIBRARIES
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree3.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx2.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_sse42.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/lexers.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/math.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/simd.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/tasking.lib
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/sys.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree3_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_avx2_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_avx_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_sse42_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/lexers_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/math_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/simd_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/sys_d.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/tasking_d.lib
|
||||
)
|
||||
else()
|
||||
if(WITH_CYCLES_EMBREE)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(EMBREE_TASKING_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/tasking.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/tasking_d.lib
|
||||
)
|
||||
set(EMBREE_EMBREE3_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree3.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree3_d.lib
|
||||
)
|
||||
set(EMBREE_EMBREE_AVX_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_avx_d.lib
|
||||
)
|
||||
set(EMBREE_EMBREE_AVX2_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx2.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_avx2_d.lib
|
||||
)
|
||||
set(EMBREE_EMBREE_SSE42_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/embree_sse42.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/embree_sse42_d.lib
|
||||
)
|
||||
set(EMBREE_LEXERS_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/lexers.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/lexers_d.lib
|
||||
)
|
||||
set(EMBREE_MATH_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/math.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/math_d.lib
|
||||
)
|
||||
set(EMBREE_SIMD_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/simd.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/simd_d.lib
|
||||
)
|
||||
set(EMBREE_SYS_LIBRARY
|
||||
optimized ${EMBREE_ROOT_DIR}/lib/sys.lib
|
||||
debug ${EMBREE_ROOT_DIR}/lib/sys_d.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(Embree 3.8.0 REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
@@ -405,45 +346,29 @@ endif()
|
||||
# Logging
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_LOGGING)
|
||||
find_package(Glog REQUIRED)
|
||||
find_package(Gflags REQUIRED)
|
||||
if(WITH_CYCLES_LOGGING)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
find_package(Glog REQUIRED)
|
||||
find_package(Gflags REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenSubdiv
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR AND (WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV))
|
||||
find_library(OPENSUBDIV_LIBRARY_CPU_DEBUG_PXR NAMES osdCPU_d osdCPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
find_library(OPENSUBDIV_LIBRARY_GPU_DEBUG_PXR NAMES osdGPU_d osdGPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
find_library(OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR NAMES osdCPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
find_library(OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR NAMES osdGPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
if(OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR AND OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR)
|
||||
set(OPENSUBDIV_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR}
|
||||
optimized ${OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR}
|
||||
debug ${OPENSUBDIV_LIBRARY_CPU_DEBUG_PXR}
|
||||
debug ${OPENSUBDIV_LIBRARY_GPU_DEBUG_PXR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(WITH_CYCLES_OPENSUBDIV)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
find_package(OpenSubdiv REQUIRED)
|
||||
set(WITH_OPENSUBDIV ON)
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENSUBDIV)
|
||||
set(WITH_OPENSUBDIV ON)
|
||||
|
||||
if(NOT OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR OR NOT OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_ROOT_DIR}/include)
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU.lib
|
||||
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU_d.lib
|
||||
)
|
||||
else()
|
||||
find_package(OpenSubdiv REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -452,29 +377,18 @@ endif()
|
||||
# OpenVDB
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR AND (WITH_OPENVDB OR WITH_CYCLES_OPENVDB))
|
||||
find_library(OPENVDB_LIBRARY_PXR NAMES openvdb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
if(OPENVDB_LIBRARY_PXR)
|
||||
set(OPENVDB_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
|
||||
set(OPENVDB_LIBRARIES ${OPENVDB_LIBRARY_PXR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENVDB)
|
||||
set(WITH_OPENVDB ON)
|
||||
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
|
||||
|
||||
if(NOT OPENVDB_LIBRARY_PXR)
|
||||
find_package(OpenVDB REQUIRED)
|
||||
|
||||
if(WITH_CYCLES_OPENVDB)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(BLOSC_LIBRARY
|
||||
optimized ${BLOSC_ROOT_DIR}/lib/libblosc.lib
|
||||
debug ${BLOSC_ROOT_DIR}/lib/libblosc_d.lib
|
||||
)
|
||||
else()
|
||||
find_package(Blosc REQUIRED)
|
||||
optimized ${BLOSC_ROOT_DIR}/lib/libblosc.lib
|
||||
debug ${BLOSC_ROOT_DIR}/lib/libblosc_d.lib)
|
||||
endif()
|
||||
|
||||
find_package(OpenVDB REQUIRED)
|
||||
find_package(Blosc REQUIRED)
|
||||
set(WITH_OPENVDB ON)
|
||||
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -482,21 +396,21 @@ endif()
|
||||
# OpenImageDenoise
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENIMAGEDENOISE)
|
||||
set(WITH_OPENIMAGEDENOISE ON)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE_ROOT_DIR}/include)
|
||||
set(OPENIMAGEDENOISE_LIBRARIES
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise.lib
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common.lib
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise_d.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common_d.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl_d.lib
|
||||
)
|
||||
else()
|
||||
if(WITH_CYCLES_OPENIMAGEDENOISE)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
find_package(OpenImageDenoise REQUIRED)
|
||||
set(WITH_OPENIMAGEDENOISE ON)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENIMAGEDENOISE_LIBRARIES
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise.lib
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common.lib
|
||||
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise_d.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common_d.lib
|
||||
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl_d.lib)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -504,30 +418,15 @@ endif()
|
||||
# TBB
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR)
|
||||
find_library(TBB_LIBRARY_DEBUG_PXR NAMES tbb_debug tbb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
find_library(TBB_LIBRARY_RELEASE_PXR NAMES tbb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
|
||||
if(TBB_LIBRARY_RELEASE_PXR)
|
||||
set(TBB_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
|
||||
set(TBB_LIBRARIES
|
||||
optimized ${TBB_LIBRARY_RELEASE_PXR}
|
||||
debug ${TBB_LIBRARY_DEBUG_PXR}
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(TBB_LIBRARY
|
||||
optimized ${TBB_ROOT_DIR}/lib/tbb.lib
|
||||
debug ${TBB_ROOT_DIR}/lib/debug/tbb_debug.lib
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(NOT TBB_LIBRARY_RELEASE_PXR)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(TBB_INCLUDE_DIRS ${TBB_ROOT_DIR}/include)
|
||||
set(TBB_LIBRARIES
|
||||
optimized ${TBB_ROOT_DIR}/lib/tbb.lib
|
||||
debug ${TBB_ROOT_DIR}/lib/tbb_debug.lib
|
||||
)
|
||||
else()
|
||||
find_package(TBB REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
find_package(TBB REQUIRED)
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
@@ -535,41 +434,16 @@ endif()
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if((WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) OR
|
||||
WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(GLEW_LIBRARY "${_cycles_lib_dir}/opengl/lib/glew.lib")
|
||||
set(GLEW_INCLUDE_DIR "${_cycles_lib_dir}/opengl/include")
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
else()
|
||||
find_package(GLEW REQUIRED)
|
||||
endif()
|
||||
|
||||
set(CYCLES_GLEW_LIBRARIES ${GLEW_LIBRARY})
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(GLEW_LIBRARY "${_cycles_lib_dir}/opengl/lib/glew.lib")
|
||||
set(GLEW_INCLUDE_DIR "${_cycles_lib_dir}/opengl/include")
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
endif()
|
||||
|
||||
find_package(GLEW REQUIRED)
|
||||
else()
|
||||
# Workaround for unconventional variable name use in Blender.
|
||||
set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
|
||||
set(CYCLES_GLEW_LIBRARIES bf_intern_glew_mx ${BLENDER_GLEW_LIBRARIES})
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# Alembic
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_ALEMBIC)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(ALEMBIC_INCLUDE_DIRS ${_cycles_lib_dir}/alembic/include)
|
||||
set(ALEMBIC_LIBRARIES
|
||||
optimized ${_cycles_lib_dir}/alembic/lib/Alembic.lib
|
||||
debug ${_cycles_lib_dir}/alembic/lib/Alembic_d.lib)
|
||||
else()
|
||||
find_package(Alembic REQUIRED)
|
||||
endif()
|
||||
|
||||
set(WITH_ALEMBIC ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
@@ -579,25 +453,29 @@ endif()
|
||||
# Detect system libraries again
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
unset(CMAKE_IGNORE_PATH)
|
||||
unset(_cycles_lib_dir)
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenGL
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(NOT DEFINED OpenGL_GL_PREFERENCE)
|
||||
set(OpenGL_GL_PREFERENCE "LEGACY")
|
||||
endif()
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
set(CYCLES_GL_LIBRARIES ${OPENGL_gl_LIBRARY})
|
||||
else()
|
||||
set(CYCLES_GL_LIBRARIES ${BLENDER_GL_LIBRARIES})
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(NOT DEFINED OpenGL_GL_PREFERENCE)
|
||||
set(OpenGL_GL_PREFERENCE "LEGACY")
|
||||
endif()
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
set(CYCLES_GL_LIBRARIES
|
||||
${OPENGL_gl_LIBRARY}
|
||||
${OPENGL_glu_LIBRARY}
|
||||
${GLEW_LIBRARY}
|
||||
)
|
||||
else()
|
||||
set(CYCLES_GL_LIBRARIES
|
||||
bf_intern_glew_mx
|
||||
${BLENDER_GL_LIBRARIES}
|
||||
${BLENDER_GLEW_LIBRARIES})
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
@@ -607,7 +485,7 @@ endif()
|
||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||
# We can't use the version from the Blender precompiled libraries because
|
||||
# it does not include the video subsystem.
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(SDL2)
|
||||
|
||||
if(NOT SDL2_FOUND)
|
||||
set(WITH_CYCLES_STANDALONE_GUI OFF)
|
||||
@@ -638,6 +516,7 @@ if(WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# HIP
|
||||
###########################################################################
|
||||
@@ -675,15 +554,4 @@ if(WITH_CYCLES_DEVICE_METAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# macOS
|
||||
###########################################################################
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
# On macOS, always use zlib from system.
|
||||
if(APPLE)
|
||||
set(ZLIB_ROOT /usr)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
unset(_cycles_lib_dir)
|
||||
|
@@ -73,44 +73,34 @@ macro(cycles_add_library target library_deps)
|
||||
cycles_set_solution_folder(${target})
|
||||
endmacro()
|
||||
|
||||
macro(cycles_external_libraries_append libraries)
|
||||
macro(cycles_target_link_libraries target)
|
||||
if(WITH_CYCLES_LOGGING)
|
||||
list(APPEND ${libraries} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
|
||||
target_link_libraries(${target} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND ${libraries} ${OSL_LIBRARIES} ${CLANG_LIBRARIES} ${LLVM_LIBRARY})
|
||||
target_link_libraries(${target} ${OSL_LIBRARIES} ${LLVM_LIBRARY})
|
||||
endif()
|
||||
if(WITH_CYCLES_EMBREE)
|
||||
list(APPEND ${libraries} ${EMBREE_LIBRARIES})
|
||||
target_link_libraries(${target} ${EMBREE_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENSUBDIV)
|
||||
list(APPEND ${libraries} ${OPENSUBDIV_LIBRARIES})
|
||||
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENCOLORIO)
|
||||
list(APPEND ${libraries} ${OPENCOLORIO_LIBRARIES})
|
||||
if(APPLE)
|
||||
list(APPEND ${libraries} "-framework IOKit")
|
||||
endif()
|
||||
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENVDB)
|
||||
list(APPEND ${libraries} ${OPENVDB_LIBRARIES} ${BLOSC_LIBRARIES})
|
||||
target_link_libraries(${target} ${OPENVDB_LIBRARIES} ${BLOSC_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
list(APPEND ${libraries} ${OPENIMAGEDENOISE_LIBRARIES})
|
||||
if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
|
||||
list(APPEND ${libraries} "-framework Accelerate")
|
||||
endif()
|
||||
target_link_libraries(${target} ${OPENIMAGEDENOISE_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_ALEMBIC)
|
||||
list(APPEND ${libraries} ${ALEMBIC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
list(APPEND ${libraries}
|
||||
target_link_libraries(
|
||||
${target}
|
||||
${OPENIMAGEIO_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
${TIFF_LIBRARY}
|
||||
${WEBP_LIBRARIES}
|
||||
${OPENJPEG_LIBRARIES}
|
||||
${OPENEXR_LIBRARIES}
|
||||
${OPENEXR_LIBRARIES} # For circular dependencies between libs.
|
||||
@@ -124,26 +114,26 @@ macro(cycles_external_libraries_append libraries)
|
||||
|
||||
if(WITH_CYCLES_DEVICE_CUDA OR WITH_CYCLES_DEVICE_OPTIX)
|
||||
if(WITH_CUDA_DYNLOAD)
|
||||
list(APPEND ${libraries} extern_cuew)
|
||||
target_link_libraries(${target} extern_cuew)
|
||||
else()
|
||||
list(APPEND ${libraries} ${CUDA_CUDA_LIBRARY})
|
||||
target_link_libraries(${target} ${CUDA_CUDA_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEVICE_HIP AND WITH_HIP_DYNLOAD)
|
||||
list(APPEND ${libraries} extern_hipew)
|
||||
target_link_libraries(${target} extern_hipew)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
list(APPEND ${libraries} extern_libc_compat)
|
||||
target_link_libraries(${target} extern_libc_compat)
|
||||
else()
|
||||
list(APPEND ${libraries} bf_intern_libc_compat)
|
||||
target_link_libraries(${target} bf_intern_libc_compat)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CYCLES_STANDALONE_REPOSITORY)
|
||||
list(APPEND ${libraries} bf_intern_guardedalloc)
|
||||
target_link_libraries(${target} bf_intern_guardedalloc)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -153,13 +143,13 @@ macro(cycles_install_libraries target)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install(
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${TBB_ROOT_DIR}/lib/debug/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb_d${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION $<TARGET_FILE_DIR:${target}>)
|
||||
else()
|
||||
install(
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${TBB_ROOT_DIR}/lib/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION $<TARGET_FILE_DIR:${target}>)
|
||||
endif()
|
||||
|
@@ -8,6 +8,7 @@ set(INC
|
||||
|
||||
set(INC_SYS
|
||||
${GLEW_INCLUDE_DIR}
|
||||
../../../extern/clew/include
|
||||
)
|
||||
|
||||
if(WITH_CYCLES_DEVICE_OPTIX OR WITH_CYCLES_DEVICE_CUDA)
|
||||
@@ -196,8 +197,7 @@ cycles_add_library(cycles_device "${LIB}" ${SRC})
|
||||
source_group("cpu" FILES ${SRC_CPU})
|
||||
source_group("cuda" FILES ${SRC_CUDA})
|
||||
source_group("dummy" FILES ${SRC_DUMMY})
|
||||
source_group("hip" FILES ${SRC_HIP})
|
||||
source_group("multi" FILES ${SRC_MULTI})
|
||||
source_group("metal" FILES ${SRC_METAL})
|
||||
source_group("optix" FILES ${SRC_OPTIX})
|
||||
source_group("common" FILES ${SRC_BASE} ${SRC_HEADERS})
|
||||
source_group("common" FILES ${SRC} ${SRC_HEADERS})
|
||||
|
@@ -191,7 +191,7 @@ device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_
|
||||
|
||||
void CPUDevice::const_copy_to(const char *name, void *host, size_t size)
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
#if WITH_EMBREE
|
||||
if (strcmp(name, "__data") == 0) {
|
||||
assert(size <= sizeof(KernelData));
|
||||
|
||||
|
@@ -77,11 +77,11 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
||||
}
|
||||
case METAL_GPU_APPLE: {
|
||||
max_threads_per_threadgroup = 512;
|
||||
use_metalrt = info.use_metalrt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
use_metalrt = info.use_metalrt;
|
||||
if (auto metalrt = getenv("CYCLES_METALRT")) {
|
||||
use_metalrt = (atoi(metalrt) != 0);
|
||||
}
|
||||
|
@@ -33,191 +33,6 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
// A minimal copy of functionality `optix_denoiser_tiling.h` which allows to fix integer overflow
|
||||
// issues without bumping SDK or driver requirement.
|
||||
//
|
||||
// The original code is Copyright NVIDIA Corporation, BSD-3-Clause.
|
||||
namespace {
|
||||
|
||||
static OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input,
|
||||
const OptixImage2D &output,
|
||||
unsigned int overlapWindowSizeInPixels,
|
||||
unsigned int tileWidth,
|
||||
unsigned int tileHeight,
|
||||
std::vector<OptixUtilDenoiserImageTile> &tiles)
|
||||
{
|
||||
if (tileWidth == 0 || tileHeight == 0)
|
||||
return OPTIX_ERROR_INVALID_VALUE;
|
||||
|
||||
unsigned int inPixelStride = optixUtilGetPixelStride(input);
|
||||
unsigned int outPixelStride = optixUtilGetPixelStride(output);
|
||||
|
||||
int inp_w = std::min(tileWidth + 2 * overlapWindowSizeInPixels, input.width);
|
||||
int inp_h = std::min(tileHeight + 2 * overlapWindowSizeInPixels, input.height);
|
||||
int inp_y = 0, copied_y = 0;
|
||||
|
||||
do {
|
||||
int inputOffsetY = inp_y == 0 ? 0 :
|
||||
std::max((int)overlapWindowSizeInPixels,
|
||||
inp_h - ((int)input.height - inp_y));
|
||||
int copy_y = inp_y == 0 ? std::min(input.height, tileHeight + overlapWindowSizeInPixels) :
|
||||
std::min(tileHeight, input.height - copied_y);
|
||||
|
||||
int inp_x = 0, copied_x = 0;
|
||||
do {
|
||||
int inputOffsetX = inp_x == 0 ? 0 :
|
||||
std::max((int)overlapWindowSizeInPixels,
|
||||
inp_w - ((int)input.width - inp_x));
|
||||
int copy_x = inp_x == 0 ? std::min(input.width, tileWidth + overlapWindowSizeInPixels) :
|
||||
std::min(tileWidth, input.width - copied_x);
|
||||
|
||||
OptixUtilDenoiserImageTile tile;
|
||||
tile.input.data = input.data + (size_t)(inp_y - inputOffsetY) * input.rowStrideInBytes +
|
||||
+(size_t)(inp_x - inputOffsetX) * inPixelStride;
|
||||
tile.input.width = inp_w;
|
||||
tile.input.height = inp_h;
|
||||
tile.input.rowStrideInBytes = input.rowStrideInBytes;
|
||||
tile.input.pixelStrideInBytes = input.pixelStrideInBytes;
|
||||
tile.input.format = input.format;
|
||||
|
||||
tile.output.data = output.data + (size_t)inp_y * output.rowStrideInBytes +
|
||||
(size_t)inp_x * outPixelStride;
|
||||
tile.output.width = copy_x;
|
||||
tile.output.height = copy_y;
|
||||
tile.output.rowStrideInBytes = output.rowStrideInBytes;
|
||||
tile.output.pixelStrideInBytes = output.pixelStrideInBytes;
|
||||
tile.output.format = output.format;
|
||||
|
||||
tile.inputOffsetX = inputOffsetX;
|
||||
tile.inputOffsetY = inputOffsetY;
|
||||
tiles.push_back(tile);
|
||||
|
||||
inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
|
||||
copied_x += copy_x;
|
||||
} while (inp_x < static_cast<int>(input.width));
|
||||
|
||||
inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
|
||||
copied_y += copy_y;
|
||||
} while (inp_y < static_cast<int>(input.height));
|
||||
|
||||
return OPTIX_SUCCESS;
|
||||
}
|
||||
|
||||
static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser,
|
||||
CUstream stream,
|
||||
const OptixDenoiserParams *params,
|
||||
CUdeviceptr denoiserState,
|
||||
size_t denoiserStateSizeInBytes,
|
||||
const OptixDenoiserGuideLayer *guideLayer,
|
||||
const OptixDenoiserLayer *layers,
|
||||
unsigned int numLayers,
|
||||
CUdeviceptr scratch,
|
||||
size_t scratchSizeInBytes,
|
||||
unsigned int overlapWindowSizeInPixels,
|
||||
unsigned int tileWidth,
|
||||
unsigned int tileHeight)
|
||||
{
|
||||
if (!guideLayer || !layers)
|
||||
return OPTIX_ERROR_INVALID_VALUE;
|
||||
|
||||
std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles(numLayers);
|
||||
std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers);
|
||||
for (unsigned int l = 0; l < numLayers; l++) {
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].input,
|
||||
layers[l].output,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
tiles[l]))
|
||||
return res;
|
||||
|
||||
if (layers[l].previousOutput.data) {
|
||||
OptixImage2D dummyOutput = layers[l].previousOutput;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].previousOutput,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
prevTiles[l]))
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<OptixUtilDenoiserImageTile> albedoTiles;
|
||||
if (guideLayer->albedo.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->albedo;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
albedoTiles))
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<OptixUtilDenoiserImageTile> normalTiles;
|
||||
if (guideLayer->normal.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->normal;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
normalTiles))
|
||||
return res;
|
||||
}
|
||||
std::vector<OptixUtilDenoiserImageTile> flowTiles;
|
||||
if (guideLayer->flow.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->flow;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
flowTiles))
|
||||
return res;
|
||||
}
|
||||
|
||||
for (size_t t = 0; t < tiles[0].size(); t++) {
|
||||
std::vector<OptixDenoiserLayer> tlayers;
|
||||
for (unsigned int l = 0; l < numLayers; l++) {
|
||||
OptixDenoiserLayer layer = {};
|
||||
layer.input = (tiles[l])[t].input;
|
||||
layer.output = (tiles[l])[t].output;
|
||||
if (layers[l].previousOutput.data)
|
||||
layer.previousOutput = (prevTiles[l])[t].input;
|
||||
tlayers.push_back(layer);
|
||||
}
|
||||
|
||||
OptixDenoiserGuideLayer gl = {};
|
||||
if (guideLayer->albedo.data)
|
||||
gl.albedo = albedoTiles[t].input;
|
||||
|
||||
if (guideLayer->normal.data)
|
||||
gl.normal = normalTiles[t].input;
|
||||
|
||||
if (guideLayer->flow.data)
|
||||
gl.flow = flowTiles[t].input;
|
||||
|
||||
if (const OptixResult res = optixDenoiserInvoke(denoiser,
|
||||
stream,
|
||||
params,
|
||||
denoiserState,
|
||||
denoiserStateSizeInBytes,
|
||||
&gl,
|
||||
&tlayers[0],
|
||||
numLayers,
|
||||
(tiles[0])[t].inputOffsetX,
|
||||
(tiles[0])[t].inputOffsetY,
|
||||
scratch,
|
||||
scratchSizeInBytes))
|
||||
return res;
|
||||
}
|
||||
return OPTIX_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OptiXDevice::Denoiser::Denoiser(OptiXDevice *device)
|
||||
: device(device), queue(device), state(device, "__denoiser_state", true)
|
||||
{
|
||||
@@ -1260,20 +1075,20 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
|
||||
/* Finally run denoising. */
|
||||
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
|
||||
|
||||
optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
|
||||
denoiser_.queue.stream(),
|
||||
¶ms,
|
||||
denoiser_.state.device_pointer,
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
&guide_layers,
|
||||
&image_layers,
|
||||
1,
|
||||
denoiser_.state.device_pointer +
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
denoiser_.sizes.withOverlapScratchSizeInBytes,
|
||||
denoiser_.sizes.overlapWindowSizeInPixels,
|
||||
denoiser_.configured_size.x,
|
||||
denoiser_.configured_size.y));
|
||||
optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
|
||||
denoiser_.queue.stream(),
|
||||
¶ms,
|
||||
denoiser_.state.device_pointer,
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
&guide_layers,
|
||||
&image_layers,
|
||||
1,
|
||||
denoiser_.state.device_pointer +
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
denoiser_.sizes.withOverlapScratchSizeInBytes,
|
||||
denoiser_.sizes.overlapWindowSizeInPixels,
|
||||
denoiser_.configured_size.x,
|
||||
denoiser_.configured_size.y));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -100,7 +100,7 @@ class DeviceQueue {
|
||||
* based on number of cores and/or available memory. */
|
||||
virtual int num_concurrent_states(const size_t state_size) const = 0;
|
||||
|
||||
/* Number of states which keeps the device occupied with work without losing performance.
|
||||
/* Number of states which keeps the device occupied with work without loosing performance.
|
||||
* The renderer will add more work (when available) when number of active paths falls below this
|
||||
* value. */
|
||||
virtual int num_concurrent_busy_states() const = 0;
|
||||
|
@@ -1,151 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2022 Blender Foundation
|
||||
|
||||
#####################################################################
|
||||
# Cycles Hydra render delegate
|
||||
#####################################################################
|
||||
|
||||
set(INC
|
||||
..
|
||||
)
|
||||
set(INC_SYS
|
||||
${USD_INCLUDE_DIRS}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(LIB
|
||||
cycles_scene
|
||||
cycles_session
|
||||
cycles_graph
|
||||
${CYCLES_GLEW_LIBRARIES}
|
||||
)
|
||||
cycles_external_libraries_append(LIB)
|
||||
|
||||
set(INC_HD_CYCLES
|
||||
attribute.h
|
||||
camera.h
|
||||
config.h
|
||||
curves.h
|
||||
display_driver.h
|
||||
field.h
|
||||
geometry.h
|
||||
geometry.inl
|
||||
instancer.h
|
||||
light.h
|
||||
material.h
|
||||
mesh.h
|
||||
node_util.h
|
||||
output_driver.h
|
||||
pointcloud.h
|
||||
render_buffer.h
|
||||
render_delegate.h
|
||||
render_pass.h
|
||||
session.h
|
||||
volume.h
|
||||
)
|
||||
|
||||
set(SRC_HD_CYCLES
|
||||
attribute.cpp
|
||||
curves.cpp
|
||||
camera.cpp
|
||||
display_driver.cpp
|
||||
field.cpp
|
||||
instancer.cpp
|
||||
light.cpp
|
||||
material.cpp
|
||||
mesh.cpp
|
||||
node_util.cpp
|
||||
output_driver.cpp
|
||||
pointcloud.cpp
|
||||
render_buffer.cpp
|
||||
render_delegate.cpp
|
||||
render_pass.cpp
|
||||
session.cpp
|
||||
volume.cpp
|
||||
)
|
||||
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
|
||||
if(WITH_OPENVDB)
|
||||
add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
|
||||
list(APPEND INC_SYS
|
||||
${OPENVDB_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
add_library(hdCyclesStatic STATIC
|
||||
${SRC_HD_CYCLES}
|
||||
${INC_HD_CYCLES}
|
||||
)
|
||||
|
||||
target_compile_options(hdCyclesStatic
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/wd4003 /wd4244 /wd4506>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-float-conversion -Wno-double-promotion -Wno-deprecated>
|
||||
)
|
||||
|
||||
target_compile_definitions(hdCyclesStatic
|
||||
PRIVATE
|
||||
GLOG_NO_ABBREVIATED_SEVERITIES=1
|
||||
OSL_DEBUG=$<CONFIG:DEBUG>
|
||||
TBB_USE_DEBUG=$<CONFIG:DEBUG>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:NOMINMAX=1>
|
||||
)
|
||||
|
||||
target_link_libraries(hdCyclesStatic
|
||||
PUBLIC
|
||||
hd
|
||||
hgi
|
||||
hgiGL
|
||||
PRIVATE
|
||||
${LIB}
|
||||
)
|
||||
|
||||
set(HdCyclesPluginName hdCycles)
|
||||
add_library(${HdCyclesPluginName} SHARED
|
||||
plugin.h
|
||||
plugin.cpp
|
||||
)
|
||||
|
||||
set_target_properties(${HdCyclesPluginName}
|
||||
PROPERTIES PREFIX ""
|
||||
)
|
||||
|
||||
target_compile_definitions(${HdCyclesPluginName}
|
||||
PRIVATE
|
||||
MFB_PACKAGE_NAME=${HdCyclesPluginName}
|
||||
MFB_ALT_PACKAGE_NAME=${HdCyclesPluginName}
|
||||
GLOG_NO_ABBREVIATED_SEVERITIES=1
|
||||
OSL_DEBUG=$<CONFIG:DEBUG>
|
||||
TBB_USE_DEBUG=$<CONFIG:DEBUG>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:NOMINMAX=1>
|
||||
)
|
||||
|
||||
target_link_libraries(${HdCyclesPluginName}
|
||||
hdCyclesStatic
|
||||
)
|
||||
|
||||
if(WITH_CYCLES_BLENDER)
|
||||
set(CYCLES_HYDRA_INSTALL_PATH "../")
|
||||
else()
|
||||
set(CYCLES_HYDRA_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
|
||||
# Put the root plugInfo.json one level up
|
||||
delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "plugInfo.json" ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
|
||||
delayed_install("" $<TARGET_FILE:${HdCyclesPluginName}> ${CYCLES_HYDRA_INSTALL_PATH})
|
||||
|
||||
set(PLUG_INFO_ROOT "..")
|
||||
|
||||
file(RELATIVE_PATH PLUG_INFO_LIBRARY_PATH "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}" "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
file(RELATIVE_PATH PLUG_INFO_RESOURCE_PATH "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}" "${CYCLES_INSTALL_PATH}")
|
||||
|
||||
configure_file(resources/plugInfo.json
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resources/plugInfo.json
|
||||
@ONLY
|
||||
)
|
||||
|
||||
delayed_install("${CMAKE_CURRENT_BINARY_DIR}/resources" "plugInfo.json" "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}/resources")
|
@@ -1,71 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/attribute.h"
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/scene.h"
|
||||
|
||||
#include <pxr/base/gf/vec2f.h>
|
||||
#include <pxr/base/gf/vec3f.h>
|
||||
#include <pxr/base/gf/vec4f.h>
|
||||
#include <pxr/base/vt/array.h>
|
||||
#include <pxr/imaging/hd/tokens.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
void ApplyPrimvars(AttributeSet &attributes,
|
||||
const ustring &name,
|
||||
VtValue value,
|
||||
AttributeElement elem,
|
||||
AttributeStandard std)
|
||||
{
|
||||
const void *data = HdGetValueData(value);
|
||||
size_t size = value.GetArraySize();
|
||||
|
||||
const HdType valueType = HdGetValueTupleType(value).type;
|
||||
|
||||
TypeDesc attrType = CCL_NS::TypeUnknown;
|
||||
switch (valueType) {
|
||||
case HdTypeFloat:
|
||||
attrType = CCL_NS::TypeFloat;
|
||||
size *= sizeof(float);
|
||||
break;
|
||||
case HdTypeFloatVec2:
|
||||
attrType = CCL_NS::TypeFloat2;
|
||||
size *= sizeof(float2);
|
||||
static_assert(sizeof(GfVec2f) == sizeof(float2));
|
||||
break;
|
||||
case HdTypeFloatVec3: {
|
||||
attrType = CCL_NS::TypeVector;
|
||||
size *= sizeof(float3);
|
||||
// The Cycles "float3" data type is padded to "float4", so need to convert the array
|
||||
const auto &valueData = value.Get<VtVec3fArray>();
|
||||
VtArray<float3> valueConverted;
|
||||
valueConverted.reserve(valueData.size());
|
||||
for (const GfVec3f &vec : valueData) {
|
||||
valueConverted.push_back(make_float3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
data = valueConverted.data();
|
||||
value = std::move(valueConverted);
|
||||
break;
|
||||
}
|
||||
case HdTypeFloatVec4:
|
||||
attrType = CCL_NS::TypeFloat4;
|
||||
size *= sizeof(float4);
|
||||
static_assert(sizeof(GfVec4f) == sizeof(float4));
|
||||
break;
|
||||
default:
|
||||
TF_WARN("Unsupported attribute type %d", static_cast<int>(valueType));
|
||||
return;
|
||||
}
|
||||
|
||||
Attribute *const attr = attributes.add(name, attrType, elem);
|
||||
attr->std = std;
|
||||
|
||||
assert(size == attr->buffer.size());
|
||||
std::memcpy(attr->data(), data, size);
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,21 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "scene/attribute.h"
|
||||
|
||||
#include <pxr/base/vt/value.h>
|
||||
#include <pxr/imaging/hd/types.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
void ApplyPrimvars(CCL_NS::AttributeSet &attributes,
|
||||
const CCL_NS::ustring &name,
|
||||
PXR_NS::VtValue value,
|
||||
CCL_NS::AttributeElement elem,
|
||||
CCL_NS::AttributeStandard std);
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,334 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/camera.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/camera.h"
|
||||
|
||||
#include <pxr/base/gf/frustum.h>
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
#include <pxr/usd/usdGeom/tokens.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
extern Transform convert_transform(const GfMatrix4d &matrix);
|
||||
Transform convert_camera_transform(const GfMatrix4d &matrix, float metersPerUnit)
|
||||
{
|
||||
Transform t = convert_transform(matrix);
|
||||
// Flip Z axis
|
||||
t.x.z *= -1.0f;
|
||||
t.y.z *= -1.0f;
|
||||
t.z.z *= -1.0f;
|
||||
// Scale translation
|
||||
t.x.w *= metersPerUnit;
|
||||
t.y.w *= metersPerUnit;
|
||||
t.z.w *= metersPerUnit;
|
||||
return t;
|
||||
}
|
||||
|
||||
#if PXR_VERSION < 2102
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
(projection)
|
||||
(orthographic)
|
||||
);
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
HdCyclesCamera::HdCyclesCamera(const SdfPath &sprimId) : HdCamera(sprimId)
|
||||
{
|
||||
#if PXR_VERSION >= 2102
|
||||
// Synchronize default values
|
||||
_horizontalAperture = _data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT;
|
||||
_verticalAperture = _data.GetVerticalAperture() * GfCamera::APERTURE_UNIT;
|
||||
_horizontalApertureOffset = _data.GetHorizontalApertureOffset() * GfCamera::APERTURE_UNIT;
|
||||
_verticalApertureOffset = _data.GetVerticalApertureOffset() * GfCamera::APERTURE_UNIT;
|
||||
_focalLength = _data.GetFocalLength() * GfCamera::FOCAL_LENGTH_UNIT;
|
||||
_clippingRange = _data.GetClippingRange();
|
||||
_fStop = _data.GetFStop();
|
||||
_focusDistance = _data.GetFocusDistance();
|
||||
#endif
|
||||
}
|
||||
|
||||
HdCyclesCamera::~HdCyclesCamera()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesCamera::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
return DirtyBits::AllDirty;
|
||||
}
|
||||
|
||||
void HdCyclesCamera::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
if (*dirtyBits == DirtyBits::Clean) {
|
||||
return;
|
||||
}
|
||||
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
|
||||
#if PXR_VERSION >= 2102
|
||||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
sceneDelegate->SampleTransform(id, &_transformSamples);
|
||||
|
||||
bool transform_found = false;
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
if (_transformSamples.times[i] == 0.0f) {
|
||||
_transform = _transformSamples.values[i];
|
||||
_data.SetTransform(_transform);
|
||||
transform_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!transform_found && _transformSamples.count) {
|
||||
_transform = _transformSamples.values[0];
|
||||
_data.SetTransform(_transform);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (*dirtyBits & DirtyBits::DirtyViewMatrix) {
|
||||
sceneDelegate->SampleTransform(id, &_transformSamples);
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->worldToViewMatrix);
|
||||
if (!value.IsEmpty()) {
|
||||
_worldToViewMatrix = value.Get<GfMatrix4d>();
|
||||
_worldToViewInverseMatrix = _worldToViewMatrix.GetInverse();
|
||||
_data.SetTransform(_worldToViewInverseMatrix);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PXR_VERSION < 2111
|
||||
if (*dirtyBits & DirtyBits::DirtyProjMatrix) {
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->projectionMatrix);
|
||||
if (!value.IsEmpty()) {
|
||||
_projectionMatrix = value.Get<GfMatrix4d>();
|
||||
const float focalLength = _data.GetFocalLength(); // Get default focal length
|
||||
# if PXR_VERSION >= 2102
|
||||
_data.SetFromViewAndProjectionMatrix(GetViewMatrix(), _projectionMatrix, focalLength);
|
||||
# else
|
||||
if (_projectionMatrix[2][3] < -0.5) {
|
||||
_data.SetProjection(GfCamera::Perspective);
|
||||
|
||||
const float horizontalAperture = (2.0 * focalLength) / _projectionMatrix[0][0];
|
||||
_data.SetHorizontalAperture(horizontalAperture);
|
||||
_data.SetHorizontalApertureOffset(0.5 * horizontalAperture * _projectionMatrix[2][0]);
|
||||
const float verticalAperture = (2.0 * focalLength) / _projectionMatrix[1][1];
|
||||
_data.SetVerticalAperture(verticalAperture);
|
||||
_data.SetVerticalApertureOffset(0.5 * verticalAperture * _projectionMatrix[2][1]);
|
||||
|
||||
_data.SetClippingRange(
|
||||
GfRange1f(_projectionMatrix[3][2] / (_projectionMatrix[2][2] - 1.0),
|
||||
_projectionMatrix[3][2] / (_projectionMatrix[2][2] + 1.0)));
|
||||
}
|
||||
else {
|
||||
_data.SetProjection(GfCamera::Orthographic);
|
||||
|
||||
const float horizontalAperture = (2.0 / GfCamera::APERTURE_UNIT) / _projectionMatrix[0][0];
|
||||
_data.SetHorizontalAperture(horizontalAperture);
|
||||
_data.SetHorizontalApertureOffset(-0.5 * horizontalAperture * _projectionMatrix[3][0]);
|
||||
const float verticalAperture = (2.0 / GfCamera::APERTURE_UNIT) / _projectionMatrix[1][1];
|
||||
_data.SetVerticalAperture(verticalAperture);
|
||||
_data.SetVerticalApertureOffset(-0.5 * verticalAperture * _projectionMatrix[3][1]);
|
||||
|
||||
const double nearMinusFarHalf = 1.0 / _projectionMatrix[2][2];
|
||||
const double nearPlusFarHalf = nearMinusFarHalf * _projectionMatrix[3][2];
|
||||
_data.SetClippingRange(
|
||||
GfRange1f(nearPlusFarHalf + nearMinusFarHalf, nearPlusFarHalf - nearMinusFarHalf));
|
||||
}
|
||||
# endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyWindowPolicy) {
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->windowPolicy);
|
||||
if (!value.IsEmpty()) {
|
||||
_windowPolicy = value.Get<CameraUtilConformWindowPolicy>();
|
||||
}
|
||||
}
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyClipPlanes) {
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->clipPlanes);
|
||||
if (!value.IsEmpty()) {
|
||||
_clipPlanes = value.Get<std::vector<GfVec4d>>();
|
||||
}
|
||||
}
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyParams) {
|
||||
#if PXR_VERSION >= 2102
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->projection);
|
||||
if (!value.IsEmpty()) {
|
||||
_projection = value.Get<Projection>();
|
||||
_data.SetProjection(_projection != Orthographic ? GfCamera::Perspective :
|
||||
GfCamera::Orthographic);
|
||||
}
|
||||
#else
|
||||
value = sceneDelegate->GetCameraParamValue(id, _tokens->projection);
|
||||
if (!value.IsEmpty()) {
|
||||
_data.SetProjection(value.Get<TfToken>() != _tokens->orthographic ? GfCamera::Perspective :
|
||||
GfCamera::Orthographic);
|
||||
}
|
||||
#endif
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->horizontalAperture);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto horizontalAperture = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_horizontalAperture = horizontalAperture;
|
||||
#endif
|
||||
_data.SetHorizontalAperture(horizontalAperture / GfCamera::APERTURE_UNIT);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->verticalAperture);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto verticalAperture = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_verticalAperture = verticalAperture;
|
||||
#endif
|
||||
_data.SetVerticalAperture(verticalAperture / GfCamera::APERTURE_UNIT);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->horizontalApertureOffset);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto horizontalApertureOffset = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_horizontalApertureOffset = horizontalApertureOffset;
|
||||
#endif
|
||||
_data.SetHorizontalApertureOffset(horizontalApertureOffset / GfCamera::APERTURE_UNIT);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->verticalApertureOffset);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto verticalApertureOffset = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_verticalApertureOffset = verticalApertureOffset;
|
||||
#endif
|
||||
_data.SetVerticalApertureOffset(verticalApertureOffset / GfCamera::APERTURE_UNIT);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->focalLength);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto focalLength = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_focalLength = focalLength;
|
||||
#endif
|
||||
_data.SetFocalLength(focalLength / GfCamera::FOCAL_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->clippingRange);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto clippingRange = value.Get<GfRange1f>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_clippingRange = clippingRange;
|
||||
#endif
|
||||
_data.SetClippingRange(clippingRange);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->fStop);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto fStop = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_fStop = fStop;
|
||||
#endif
|
||||
_data.SetFStop(fStop);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->focusDistance);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto focusDistance = value.Get<float>();
|
||||
#if PXR_VERSION >= 2102
|
||||
_focusDistance = focusDistance;
|
||||
#endif
|
||||
_data.SetFocusDistance(focusDistance);
|
||||
}
|
||||
}
|
||||
|
||||
*dirtyBits = DirtyBits::Clean;
|
||||
}
|
||||
|
||||
void HdCyclesCamera::Finalize(HdRenderParam *renderParam)
|
||||
{
|
||||
HdCamera::Finalize(renderParam);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam, Camera *cam) const
|
||||
{
|
||||
ApplyCameraSettings(renderParam, _data, _windowPolicy, cam);
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
array<Transform> motion(_transformSamples.count);
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
motion[i] = convert_camera_transform(_transformSamples.values[i], metersPerUnit);
|
||||
}
|
||||
cam->set_motion(motion);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfCamera &dataUnconformedWindow,
|
||||
CameraUtilConformWindowPolicy windowPolicy,
|
||||
Camera *cam)
|
||||
{
|
||||
const float width = cam->get_full_width();
|
||||
const float height = cam->get_full_height();
|
||||
|
||||
auto data = dataUnconformedWindow;
|
||||
CameraUtilConformWindow(&data, windowPolicy, width / height);
|
||||
|
||||
static_assert(GfCamera::Perspective == CAMERA_PERSPECTIVE &&
|
||||
GfCamera::Orthographic == CAMERA_ORTHOGRAPHIC);
|
||||
cam->set_camera_type(static_cast<CameraType>(data.GetProjection()));
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
auto viewplane = data.GetFrustum().GetWindow();
|
||||
auto focalLength = 1.0f;
|
||||
if (data.GetProjection() == GfCamera::Perspective) {
|
||||
viewplane *= 2.0 / viewplane.GetSize()[1]; // Normalize viewplane
|
||||
focalLength = data.GetFocalLength() * GfCamera::FOCAL_LENGTH_UNIT * metersPerUnit;
|
||||
|
||||
cam->set_fov(GfDegreesToRadians(data.GetFieldOfView(GfCamera::FOVVertical)));
|
||||
}
|
||||
|
||||
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
|
||||
cam->set_nearclip(data.GetClippingRange().GetMin() * metersPerUnit);
|
||||
cam->set_farclip(data.GetClippingRange().GetMax() * metersPerUnit);
|
||||
|
||||
cam->set_viewplane_left(viewplane.GetMin()[0]);
|
||||
cam->set_viewplane_right(viewplane.GetMax()[0]);
|
||||
cam->set_viewplane_bottom(viewplane.GetMin()[1]);
|
||||
cam->set_viewplane_top(viewplane.GetMax()[1]);
|
||||
|
||||
if (data.GetFStop() != 0.0f) {
|
||||
cam->set_focaldistance(data.GetFocusDistance() * metersPerUnit);
|
||||
cam->set_aperturesize(focalLength / (2.0f * data.GetFStop()));
|
||||
}
|
||||
|
||||
cam->set_matrix(convert_camera_transform(data.GetTransform(), metersPerUnit));
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfMatrix4d &worldToViewMatrix,
|
||||
const GfMatrix4d &projectionMatrix,
|
||||
const std::vector<GfVec4d> &clipPlanes,
|
||||
Camera *cam)
|
||||
{
|
||||
#if PXR_VERSION >= 2102
|
||||
GfCamera data;
|
||||
data.SetFromViewAndProjectionMatrix(worldToViewMatrix, projectionMatrix);
|
||||
|
||||
ApplyCameraSettings(renderParam, data, CameraUtilFit, cam);
|
||||
#else
|
||||
TF_CODING_ERROR("Not implemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,45 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/base/gf/camera.h>
|
||||
#include <pxr/imaging/hd/camera.h>
|
||||
#include <pxr/imaging/hd/timeSampleArray.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesCamera final : public PXR_NS::HdCamera {
|
||||
public:
|
||||
HdCyclesCamera(const PXR_NS::SdfPath &sprimId);
|
||||
~HdCyclesCamera() override;
|
||||
|
||||
void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam, CCL_NS::Camera *targetCamera) const;
|
||||
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfCamera &cameraData,
|
||||
PXR_NS::CameraUtilConformWindowPolicy windowPolicy,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfMatrix4d &worldToViewMatrix,
|
||||
const PXR_NS::GfMatrix4d &projectionMatrix,
|
||||
const std::vector<PXR_NS::GfVec4d> &clipPlanes,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
|
||||
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
private:
|
||||
PXR_NS::GfCamera _data;
|
||||
PXR_NS::HdTimeSampleArray<PXR_NS::GfMatrix4d, 2> _transformSamples;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,45 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pxr/pxr.h>
|
||||
|
||||
#define CCL_NS ccl
|
||||
#define CCL_NAMESPACE_USING_DIRECTIVE using namespace CCL_NS;
|
||||
|
||||
#define HD_CYCLES_NS HdCycles
|
||||
#define HDCYCLES_NAMESPACE_OPEN_SCOPE \
|
||||
namespace HD_CYCLES_NS { \
|
||||
CCL_NAMESPACE_USING_DIRECTIVE; \
|
||||
PXR_NAMESPACE_USING_DIRECTIVE;
|
||||
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE }
|
||||
|
||||
namespace HD_CYCLES_NS {
|
||||
class HdCyclesCamera;
|
||||
class HdCyclesDelegate;
|
||||
class HdCyclesSession;
|
||||
class HdCyclesRenderBuffer;
|
||||
} // namespace HD_CYCLES_NS
|
||||
|
||||
namespace CCL_NS {
|
||||
class AttributeSet;
|
||||
class BufferParams;
|
||||
class Camera;
|
||||
class Geometry;
|
||||
class Hair;
|
||||
class Light;
|
||||
class Mesh;
|
||||
class Object;
|
||||
class ParticleSystem;
|
||||
class Pass;
|
||||
class PointCloud;
|
||||
class Scene;
|
||||
class Session;
|
||||
class SessionParams;
|
||||
class Shader;
|
||||
class ShaderGraph;
|
||||
class ShaderNode;
|
||||
class Volume;
|
||||
} // namespace CCL_NS
|
@@ -1,210 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/curves.h"
|
||||
#include "hydra/geometry.inl"
|
||||
#include "scene/hair.h"
|
||||
|
||||
#include <pxr/imaging/hd/extComputationUtils.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesCurves::HdCyclesCurves(const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
: HdCyclesGeometry(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesCurves::~HdCyclesCurves()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesCurves::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
|
||||
HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology;
|
||||
return bits;
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesCurves::_PropagateDirtyBits(HdDirtyBits bits) const
|
||||
{
|
||||
if (bits & (HdChangeTracker::DirtyTopology)) {
|
||||
// Changing topology clears the geometry, so need to populate everything again
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
|
||||
HdChangeTracker::DirtyPrimvar;
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
void HdCyclesCurves::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
|
||||
{
|
||||
if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
|
||||
PopulateTopology(sceneDelegate);
|
||||
}
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyPoints) {
|
||||
PopulatePoints(sceneDelegate);
|
||||
}
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyWidths) {
|
||||
PopulateWidths(sceneDelegate);
|
||||
}
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
|
||||
PopulatePrimvars(sceneDelegate);
|
||||
}
|
||||
|
||||
rebuild = (_geom->curve_keys_is_modified()) || (_geom->curve_radius_is_modified());
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulatePoints(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
VtValue value;
|
||||
|
||||
for (const HdExtComputationPrimvarDescriptor &desc :
|
||||
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
|
||||
if (desc.name == HdTokens->points) {
|
||||
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
|
||||
const auto valueStoreIt = valueStore.find(desc.name);
|
||||
if (valueStoreIt != valueStore.end()) {
|
||||
value = std::move(valueStoreIt->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
value = GetPrimvar(sceneDelegate, HdTokens->points);
|
||||
}
|
||||
|
||||
if (!value.IsHolding<VtVec3fArray>()) {
|
||||
TF_WARN("Invalid points data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &points = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
array<float3> pointsDataCycles;
|
||||
pointsDataCycles.reserve(points.size());
|
||||
|
||||
for (const GfVec3f &point : points) {
|
||||
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
|
||||
}
|
||||
|
||||
_geom->set_curve_keys(pointsDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
|
||||
const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
|
||||
|
||||
if (!value.IsHolding<VtFloatArray>()) {
|
||||
TF_WARN("Invalid widths data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &widths = value.UncheckedGet<VtFloatArray>();
|
||||
|
||||
array<float> radiusDataCycles;
|
||||
radiusDataCycles.reserve(widths.size());
|
||||
|
||||
if (interpolation == HdInterpolationConstant) {
|
||||
TF_VERIFY(widths.size() == 1);
|
||||
|
||||
const float constantRadius = widths[0] * 0.5f;
|
||||
|
||||
for (size_t i = 0; i < _geom->num_keys(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(constantRadius);
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationVertex) {
|
||||
TF_VERIFY(widths.size() == _geom->num_keys());
|
||||
|
||||
for (size_t i = 0; i < _geom->num_keys(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
_geom->set_curve_radius(radiusDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
Scene *const scene = (Scene *)_geom->get_owner();
|
||||
|
||||
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
|
||||
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_CURVE_KEY),
|
||||
std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_CURVE_KEY),
|
||||
std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_CURVE),
|
||||
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
|
||||
};
|
||||
|
||||
for (const auto &interpolation : interpolations) {
|
||||
for (const HdPrimvarDescriptor &desc :
|
||||
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
|
||||
// Skip special primvars that are handled separately
|
||||
if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VtValue value = GetPrimvar(sceneDelegate, desc.name);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ustring name(desc.name.GetString());
|
||||
|
||||
AttributeStandard std = ATTR_STD_NONE;
|
||||
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
|
||||
std = ATTR_STD_UV;
|
||||
}
|
||||
else if (desc.name == HdTokens->displayColor &&
|
||||
interpolation.first == HdInterpolationConstant) {
|
||||
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
|
||||
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
|
||||
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
|
||||
}
|
||||
}
|
||||
|
||||
// Skip attributes that are not needed
|
||||
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
|
||||
_geom->need_attribute(scene, name)) {
|
||||
ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulateTopology(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
// Clear geometry before populating it again with updated topology
|
||||
_geom->clear(true);
|
||||
|
||||
HdBasisCurvesTopology topology = GetBasisCurvesTopology(sceneDelegate);
|
||||
|
||||
_geom->reserve_curves(topology.GetNumCurves(), topology.CalculateNeededNumberOfControlPoints());
|
||||
|
||||
const VtIntArray vertCounts = topology.GetCurveVertexCounts();
|
||||
|
||||
for (int curve = 0, key = 0; curve < topology.GetNumCurves(); ++curve) {
|
||||
// Always reference shader at index zero, which is the primitive material
|
||||
_geom->add_curve(key, 0);
|
||||
|
||||
key += vertCounts[curve];
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,42 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "hydra/geometry.h"
|
||||
|
||||
#include <pxr/imaging/hd/basisCurves.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesCurves final : public HdCyclesGeometry<PXR_NS::HdBasisCurves, CCL_NS::Hair> {
|
||||
public:
|
||||
HdCyclesCurves(
|
||||
const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId = {}
|
||||
#endif
|
||||
);
|
||||
~HdCyclesCurves() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
private:
|
||||
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
|
||||
|
||||
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdDirtyBits dirtyBits,
|
||||
bool &rebuild) override;
|
||||
|
||||
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
void PopulateWidths(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
void PopulateTopology(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,240 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#ifdef _WIN32
|
||||
// Include first to avoid "NOGDI" definition set in Cycles headers
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "hydra/display_driver.h"
|
||||
#include "hydra/render_buffer.h"
|
||||
#include "hydra/session.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <pxr/imaging/hgiGL/texture.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi)
|
||||
: _renderParam(renderParam), _hgi(hgi)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hdc_ = GetDC(CreateWindowA("STATIC",
|
||||
"HdCycles",
|
||||
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
64,
|
||||
NULL,
|
||||
NULL,
|
||||
GetModuleHandle(NULL),
|
||||
NULL));
|
||||
|
||||
int pixelFormat = GetPixelFormat(wglGetCurrentDC());
|
||||
PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)};
|
||||
DescribePixelFormat((HDC)hdc_, pixelFormat, sizeof(pfd), &pfd);
|
||||
SetPixelFormat((HDC)hdc_, pixelFormat, &pfd);
|
||||
|
||||
TF_VERIFY(gl_context_ = wglCreateContext((HDC)hdc_));
|
||||
TF_VERIFY(wglShareLists(wglGetCurrentContext(), (HGLRC)gl_context_));
|
||||
#endif
|
||||
|
||||
glewInit();
|
||||
|
||||
glGenBuffers(1, &gl_pbo_id_);
|
||||
}
|
||||
|
||||
HdCyclesDisplayDriver::~HdCyclesDisplayDriver()
|
||||
{
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &gl_pbo_id_);
|
||||
|
||||
#ifdef _WIN32
|
||||
TF_VERIFY(wglDeleteContext((HGLRC)gl_context_));
|
||||
DestroyWindow(WindowFromDC((HDC)hdc_));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::next_tile_begin()
|
||||
{
|
||||
}
|
||||
|
||||
bool HdCyclesDisplayDriver::update_begin(const Params ¶ms,
|
||||
int texture_width,
|
||||
int texture_height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!hdc_ || !gl_context_) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
graphics_interop_activate();
|
||||
|
||||
if (gl_render_sync_) {
|
||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
if (pbo_size_.x != params.full_size.x || pbo_size_.y != params.full_size.y) {
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER,
|
||||
sizeof(half4) * params.full_size.x * params.full_size.y,
|
||||
0,
|
||||
GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
pbo_size_ = params.full_size;
|
||||
}
|
||||
|
||||
need_update_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::update_end()
|
||||
{
|
||||
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
graphics_interop_deactivate();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::flush()
|
||||
{
|
||||
graphics_interop_activate();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
graphics_interop_deactivate();
|
||||
}
|
||||
|
||||
half4 *HdCyclesDisplayDriver::map_texture_buffer()
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
|
||||
|
||||
const auto mapped_rgba_pixels = static_cast<half4 *>(
|
||||
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
||||
|
||||
if (need_clear_ && mapped_rgba_pixels) {
|
||||
memset(mapped_rgba_pixels, 0, sizeof(half4) * pbo_size_.x * pbo_size_.y);
|
||||
need_clear_ = false;
|
||||
}
|
||||
|
||||
return mapped_rgba_pixels;
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::unmap_texture_buffer()
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
DisplayDriver::GraphicsInterop HdCyclesDisplayDriver::graphics_interop_get()
|
||||
{
|
||||
GraphicsInterop interop_dst;
|
||||
interop_dst.buffer_width = pbo_size_.x;
|
||||
interop_dst.buffer_height = pbo_size_.y;
|
||||
interop_dst.opengl_pbo_id = gl_pbo_id_;
|
||||
|
||||
interop_dst.need_clear = need_clear_;
|
||||
need_clear_ = false;
|
||||
|
||||
return interop_dst;
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::graphics_interop_activate()
|
||||
{
|
||||
mutex_.lock();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Do not change context if this is called in the main thread
|
||||
if (wglGetCurrentContext() == nullptr) {
|
||||
TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::graphics_interop_deactivate()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wglGetCurrentContext() == gl_context_) {
|
||||
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::clear()
|
||||
{
|
||||
need_clear_ = true;
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::draw(const Params ¶ms)
|
||||
{
|
||||
const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(
|
||||
_renderParam->GetDisplayAovBinding().renderBuffer);
|
||||
if (!renderBuffer || // Ensure this render buffer matches the texture dimensions
|
||||
(renderBuffer->GetWidth() != params.size.x || renderBuffer->GetHeight() != params.size.y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cycles 'DisplayDriver' only supports 'half4' format
|
||||
TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4);
|
||||
|
||||
const thread_scoped_lock lock(mutex_);
|
||||
|
||||
const GfVec3i dimensions(params.size.x, params.size.y, 1);
|
||||
if (!texture_ || texture_->GetDescriptor().dimensions != dimensions) {
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
}
|
||||
|
||||
HgiTextureDesc texDesc;
|
||||
texDesc.usage = 0;
|
||||
texDesc.format = HgiFormatFloat16Vec4;
|
||||
texDesc.type = HgiTextureType2D;
|
||||
texDesc.dimensions = dimensions;
|
||||
texDesc.sampleCount = HgiSampleCount1;
|
||||
|
||||
texture_ = _hgi->CreateTexture(texDesc);
|
||||
|
||||
renderBuffer->SetResource(VtValue(texture_));
|
||||
}
|
||||
|
||||
HgiGLTexture *const texture = dynamic_cast<HgiGLTexture *>(texture_.Get());
|
||||
if (!texture || !need_update_ || pbo_size_.x != params.size.x || pbo_size_.y != params.size.y) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gl_upload_sync_) {
|
||||
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->GetTextureId());
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pbo_size_.x, pbo_size_.y, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
need_update_ = false;
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,61 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "session/display_driver.h"
|
||||
#include "util/thread.h"
|
||||
|
||||
#include <pxr/imaging/hgi/hgi.h>
|
||||
#include <pxr/imaging/hgi/texture.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
||||
public:
|
||||
HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi);
|
||||
~HdCyclesDisplayDriver();
|
||||
|
||||
private:
|
||||
void next_tile_begin() override;
|
||||
|
||||
bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||
void update_end() override;
|
||||
|
||||
void flush() override;
|
||||
|
||||
CCL_NS::half4 *map_texture_buffer() override;
|
||||
void unmap_texture_buffer() override;
|
||||
|
||||
GraphicsInterop graphics_interop_get() override;
|
||||
|
||||
void graphics_interop_activate() override;
|
||||
void graphics_interop_deactivate() override;
|
||||
|
||||
void clear() override;
|
||||
|
||||
void draw(const Params ¶ms) override;
|
||||
|
||||
HdCyclesSession *const _renderParam;
|
||||
Hgi *const _hgi;
|
||||
|
||||
#ifdef _WIN32
|
||||
void *hdc_ = nullptr;
|
||||
void *gl_context_ = nullptr;
|
||||
#endif
|
||||
|
||||
CCL_NS::thread_mutex mutex_;
|
||||
|
||||
PXR_NS::HgiTextureHandle texture_;
|
||||
unsigned int gl_pbo_id_ = 0;
|
||||
CCL_NS::int2 pbo_size_ = CCL_NS::make_int2(0, 0);
|
||||
bool need_update_ = false;
|
||||
std::atomic_bool need_clear_ = false;
|
||||
|
||||
void *gl_render_sync_ = nullptr;
|
||||
void *gl_upload_sync_ = nullptr;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,90 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/field.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/image_vdb.h"
|
||||
#include "scene/scene.h"
|
||||
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
#include <pxr/usd/sdf/assetPath.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
#if PXR_VERSION < 2108
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
(fieldName)
|
||||
);
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
class HdCyclesVolumeLoader : public VDBImageLoader {
|
||||
public:
|
||||
HdCyclesVolumeLoader(const std::string &filePath, const std::string &gridName)
|
||||
: VDBImageLoader(gridName)
|
||||
{
|
||||
openvdb::io::File file(filePath);
|
||||
file.setCopyMaxBytes(0);
|
||||
if (file.open()) {
|
||||
grid = file.readGrid(gridName);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
HdCyclesField::HdCyclesField(const SdfPath &bprimId, const TfToken &typeId) : HdField(bprimId)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesField::~HdCyclesField()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesField::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
return DirtyBits::DirtyParams;
|
||||
}
|
||||
|
||||
void HdCyclesField::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
#ifdef WITH_OPENVDB
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyParams) {
|
||||
value = sceneDelegate->Get(id, HdFieldTokens->filePath);
|
||||
if (value.IsHolding<SdfAssetPath>()) {
|
||||
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
|
||||
if (filename.empty()) {
|
||||
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
|
||||
}
|
||||
|
||||
# if PXR_VERSION >= 2108
|
||||
value = sceneDelegate->Get(id, HdFieldTokens->fieldName);
|
||||
# else
|
||||
value = sceneDelegate->Get(id, _tokens->fieldName);
|
||||
# endif
|
||||
if (value.IsHolding<TfToken>()) {
|
||||
ImageLoader *const loader = new HdCyclesVolumeLoader(
|
||||
filename, value.UncheckedGet<TfToken>().GetString());
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
ImageParams params;
|
||||
params.frame = 0.0f;
|
||||
|
||||
_handle = lock.scene->image_manager->add_image(loader, params, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*dirtyBits = DirtyBits::Clean;
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,34 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "scene/image.h"
|
||||
|
||||
#include <pxr/imaging/hd/field.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesField final : public PXR_NS::HdField {
|
||||
public:
|
||||
HdCyclesField(const PXR_NS::SdfPath &bprimId, const PXR_NS::TfToken &typeId);
|
||||
~HdCyclesField() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
|
||||
CCL_NS::ImageHandle GetImageHandle() const
|
||||
{
|
||||
return _handle;
|
||||
}
|
||||
|
||||
private:
|
||||
CCL_NS::ImageHandle _handle;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,54 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/rprim.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
template<typename Base, typename CyclesBase> class HdCyclesGeometry : public Base {
|
||||
public:
|
||||
HdCyclesGeometry(const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId
|
||||
#endif
|
||||
);
|
||||
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits,
|
||||
const PXR_NS::TfToken &reprToken) override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
virtual void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
protected:
|
||||
void _InitRepr(const PXR_NS::TfToken &reprToken, PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
|
||||
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
|
||||
|
||||
virtual void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdDirtyBits dirtyBits,
|
||||
bool &rebuild) = 0;
|
||||
|
||||
PXR_NS::HdInterpolation GetPrimvarInterpolation(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
const PXR_NS::TfToken &name) const;
|
||||
|
||||
CyclesBase *_geom = nullptr;
|
||||
std::vector<CCL_NS::Object *> _instances;
|
||||
|
||||
private:
|
||||
void Initialize(PXR_NS::HdRenderParam *renderParam);
|
||||
|
||||
void InitializeInstance(int index);
|
||||
|
||||
PXR_NS::GfMatrix4d _geomTransform;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,251 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/attribute.h"
|
||||
#include "hydra/geometry.h"
|
||||
#include "hydra/instancer.h"
|
||||
#include "hydra/material.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/scene.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
extern Transform convert_transform(const GfMatrix4d &matrix);
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
HdCyclesGeometry<Base, CyclesBase>::HdCyclesGeometry(const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
: Base(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
),
|
||||
_geomTransform(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
void HdCyclesGeometry<Base, CyclesBase>::_InitRepr(const TfToken &reprToken,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
TF_UNUSED(reprToken);
|
||||
TF_UNUSED(dirtyBits);
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
HdDirtyBits HdCyclesGeometry<Base, CyclesBase>::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
return HdChangeTracker::DirtyPrimID | HdChangeTracker::DirtyTransform |
|
||||
HdChangeTracker::DirtyMaterialId | HdChangeTracker::DirtyVisibility |
|
||||
HdChangeTracker::DirtyInstancer;
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
HdDirtyBits HdCyclesGeometry<Base, CyclesBase>::_PropagateDirtyBits(HdDirtyBits bits) const
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
void HdCyclesGeometry<Base, CyclesBase>::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits,
|
||||
const TfToken &reprToken)
|
||||
{
|
||||
TF_UNUSED(reprToken);
|
||||
|
||||
if (*dirtyBits == HdChangeTracker::Clean) {
|
||||
return;
|
||||
}
|
||||
|
||||
Initialize(renderParam);
|
||||
|
||||
#if PXR_VERSION >= 2102
|
||||
Base::_UpdateInstancer(sceneDelegate, dirtyBits);
|
||||
HdInstancer::_SyncInstancerAndParents(sceneDelegate->GetRenderIndex(), Base::GetInstancerId());
|
||||
#endif
|
||||
Base::_UpdateVisibility(sceneDelegate, dirtyBits);
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
|
||||
#if HD_API_VERSION >= 37 && PXR_VERSION >= 2105
|
||||
Base::SetMaterialId(sceneDelegate->GetMaterialId(Base::GetId()));
|
||||
#else
|
||||
Base::_SetMaterialId(sceneDelegate->GetRenderIndex().GetChangeTracker(),
|
||||
sceneDelegate->GetMaterialId(Base::GetId()));
|
||||
#endif
|
||||
|
||||
const auto material = static_cast<const HdCyclesMaterial *>(
|
||||
sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material,
|
||||
Base::GetMaterialId()));
|
||||
|
||||
array<Node *> usedShaders(1);
|
||||
if (material && material->GetCyclesShader()) {
|
||||
usedShaders[0] = material->GetCyclesShader();
|
||||
}
|
||||
else {
|
||||
usedShaders[0] = lock.scene->default_surface;
|
||||
}
|
||||
|
||||
for (Node *shader : usedShaders) {
|
||||
static_cast<Shader *>(shader)->tag_used(lock.scene);
|
||||
}
|
||||
|
||||
_geom->set_used_shaders(usedShaders);
|
||||
}
|
||||
|
||||
const SdfPath &id = Base::GetId();
|
||||
|
||||
if (HdChangeTracker::IsPrimIdDirty(*dirtyBits, id)) {
|
||||
// This needs to be corrected in the AOV
|
||||
_instances[0]->set_pass_id(Base::GetPrimId() + 1);
|
||||
}
|
||||
|
||||
if (HdChangeTracker::IsTransformDirty(*dirtyBits, id)) {
|
||||
_geomTransform = sceneDelegate->GetTransform(id);
|
||||
}
|
||||
|
||||
if (HdChangeTracker::IsTransformDirty(*dirtyBits, id) ||
|
||||
HdChangeTracker::IsInstancerDirty(*dirtyBits, id)) {
|
||||
const auto instancer = static_cast<HdCyclesInstancer *>(
|
||||
sceneDelegate->GetRenderIndex().GetInstancer(Base::GetInstancerId()));
|
||||
|
||||
// Make sure the first object attribute is the instanceId
|
||||
assert(_instances[0]->attributes.size() >= 1 &&
|
||||
_instances[0]->attributes.front().name() == HdAovTokens->instanceId.GetString());
|
||||
|
||||
VtMatrix4dArray transforms;
|
||||
if (instancer) {
|
||||
transforms = instancer->ComputeInstanceTransforms(id);
|
||||
_instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), +0.0f);
|
||||
}
|
||||
else {
|
||||
// Default to a single instance with an identity transform
|
||||
transforms.push_back(GfMatrix4d(1.0));
|
||||
_instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), -1.0f);
|
||||
}
|
||||
|
||||
const size_t oldSize = _instances.size();
|
||||
const size_t newSize = transforms.size();
|
||||
|
||||
// Resize instance list
|
||||
for (size_t i = newSize; i < oldSize; ++i) {
|
||||
lock.scene->delete_node(_instances[i]);
|
||||
}
|
||||
_instances.resize(newSize);
|
||||
for (size_t i = oldSize; i < newSize; ++i) {
|
||||
_instances[i] = lock.scene->create_node<Object>();
|
||||
InitializeInstance(static_cast<int>(i));
|
||||
}
|
||||
|
||||
// Update transforms of all instances
|
||||
for (size_t i = 0; i < transforms.size(); ++i) {
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
convert_transform(_geomTransform * transforms[i]);
|
||||
_instances[i]->set_tfm(tfm);
|
||||
}
|
||||
}
|
||||
|
||||
if (HdChangeTracker::IsVisibilityDirty(*dirtyBits, id)) {
|
||||
for (Object *instance : _instances) {
|
||||
instance->set_visibility(Base::IsVisible() ? ~0 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Must happen after material ID update, so that attribute decisions can be made
|
||||
// based on it (e.g. check whether an attribute is actually needed)
|
||||
bool rebuild = false;
|
||||
Populate(sceneDelegate, *dirtyBits, rebuild);
|
||||
|
||||
if (_geom->is_modified() || rebuild) {
|
||||
_geom->tag_update(lock.scene, rebuild);
|
||||
}
|
||||
|
||||
for (Object *instance : _instances) {
|
||||
instance->tag_update(lock.scene);
|
||||
}
|
||||
|
||||
*dirtyBits = HdChangeTracker::Clean;
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
void HdCyclesGeometry<Base, CyclesBase>::Finalize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (!_geom && _instances.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
lock.scene->delete_node(_geom);
|
||||
_geom = nullptr;
|
||||
|
||||
lock.scene->delete_nodes(set<Object *>(_instances.begin(), _instances.end()));
|
||||
_instances.clear();
|
||||
_instances.shrink_to_fit();
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
void HdCyclesGeometry<Base, CyclesBase>::Initialize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (_geom) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
// Create geometry
|
||||
_geom = lock.scene->create_node<CyclesBase>();
|
||||
_geom->name = Base::GetId().GetString();
|
||||
|
||||
// Create default instance
|
||||
_instances.push_back(lock.scene->create_node<Object>());
|
||||
InitializeInstance(0);
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
void HdCyclesGeometry<Base, CyclesBase>::InitializeInstance(int index)
|
||||
{
|
||||
Object *instance = _instances[index];
|
||||
instance->set_geometry(_geom);
|
||||
|
||||
instance->attributes.emplace_back(HdAovTokens->instanceId.GetString(),
|
||||
_instances.size() == 1 ? -1.0f : static_cast<float>(index));
|
||||
|
||||
instance->set_color(make_float3(0.8f, 0.8f, 0.8f));
|
||||
instance->set_random_id(hash_uint2(hash_string(_geom->name.c_str()), index));
|
||||
}
|
||||
|
||||
template<typename Base, typename CyclesBase>
|
||||
HdInterpolation HdCyclesGeometry<Base, CyclesBase>::GetPrimvarInterpolation(
|
||||
HdSceneDelegate *sceneDelegate, const TfToken &name) const
|
||||
{
|
||||
for (int i = 0; i < HdInterpolationCount; ++i) {
|
||||
for (const HdPrimvarDescriptor &desc :
|
||||
Base::GetPrimvarDescriptors(sceneDelegate, static_cast<HdInterpolation>(i))) {
|
||||
if (desc.name == name) {
|
||||
return static_cast<HdInterpolation>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HdInterpolationCount;
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,138 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/instancer.h"
|
||||
|
||||
#include <pxr/base/gf/quatd.h>
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesInstancer::HdCyclesInstancer(HdSceneDelegate *delegate,
|
||||
const SdfPath &instancerId
|
||||
#if PXR_VERSION <= 2011
|
||||
,
|
||||
const SdfPath &parentId
|
||||
#endif
|
||||
)
|
||||
: HdInstancer(delegate,
|
||||
instancerId
|
||||
#if PXR_VERSION <= 2011
|
||||
,
|
||||
parentId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesInstancer::~HdCyclesInstancer()
|
||||
{
|
||||
}
|
||||
|
||||
#if PXR_VERSION > 2011
|
||||
void HdCyclesInstancer::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
_UpdateInstancer(sceneDelegate, dirtyBits);
|
||||
|
||||
if (HdChangeTracker::IsAnyPrimvarDirty(*dirtyBits, GetId())) {
|
||||
SyncPrimvars();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void HdCyclesInstancer::SyncPrimvars()
|
||||
{
|
||||
HdSceneDelegate *const sceneDelegate = GetDelegate();
|
||||
const HdDirtyBits dirtyBits =
|
||||
sceneDelegate->GetRenderIndex().GetChangeTracker().GetInstancerDirtyBits(GetId());
|
||||
|
||||
for (const HdPrimvarDescriptor &desc :
|
||||
sceneDelegate->GetPrimvarDescriptors(GetId(), HdInterpolationInstance)) {
|
||||
if (!HdChangeTracker::IsPrimvarDirty(dirtyBits, GetId(), desc.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const VtValue value = sceneDelegate->Get(GetId(), desc.name);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desc.name == HdInstancerTokens->translate) {
|
||||
_translate = value.Get<VtVec3fArray>();
|
||||
}
|
||||
else if (desc.name == HdInstancerTokens->rotate) {
|
||||
_rotate = value.Get<VtVec4fArray>();
|
||||
}
|
||||
else if (desc.name == HdInstancerTokens->scale) {
|
||||
_scale = value.Get<VtVec3fArray>();
|
||||
}
|
||||
else if (desc.name == HdInstancerTokens->instanceTransform) {
|
||||
_instanceTransform = value.Get<VtMatrix4dArray>();
|
||||
}
|
||||
}
|
||||
|
||||
sceneDelegate->GetRenderIndex().GetChangeTracker().MarkInstancerClean(GetId());
|
||||
}
|
||||
|
||||
VtMatrix4dArray HdCyclesInstancer::ComputeInstanceTransforms(const SdfPath &prototypeId)
|
||||
{
|
||||
#if PXR_VERSION <= 2011
|
||||
SyncPrimvars();
|
||||
#endif
|
||||
|
||||
const VtIntArray instanceIndices = GetDelegate()->GetInstanceIndices(GetId(), prototypeId);
|
||||
const GfMatrix4d instanceTransform = GetDelegate()->GetInstancerTransform(GetId());
|
||||
|
||||
VtMatrix4dArray transforms;
|
||||
transforms.reserve(instanceIndices.size());
|
||||
|
||||
for (int index : instanceIndices) {
|
||||
GfMatrix4d transform = instanceTransform;
|
||||
|
||||
if (index < _translate.size()) {
|
||||
GfMatrix4d translateMat(1);
|
||||
translateMat.SetTranslate(_translate[index]);
|
||||
transform *= translateMat;
|
||||
}
|
||||
|
||||
if (index < _rotate.size()) {
|
||||
GfMatrix4d rotateMat(1);
|
||||
const GfVec4f &quat = _rotate[index];
|
||||
rotateMat.SetRotate(GfQuatd(quat[0], quat[1], quat[2], quat[3]));
|
||||
transform *= rotateMat;
|
||||
}
|
||||
|
||||
if (index < _scale.size()) {
|
||||
GfMatrix4d scaleMat(1);
|
||||
scaleMat.SetScale(_scale[index]);
|
||||
transform *= scaleMat;
|
||||
}
|
||||
|
||||
if (index < _instanceTransform.size()) {
|
||||
transform *= _instanceTransform[index];
|
||||
}
|
||||
|
||||
transforms.push_back(transform);
|
||||
}
|
||||
|
||||
VtMatrix4dArray resultTransforms;
|
||||
|
||||
if (const auto instancer = static_cast<HdCyclesInstancer *>(
|
||||
GetDelegate()->GetRenderIndex().GetInstancer(GetParentId()))) {
|
||||
for (const GfMatrix4d &parentTransform : instancer->ComputeInstanceTransforms(GetId())) {
|
||||
for (const GfMatrix4d &localTransform : transforms) {
|
||||
resultTransforms.push_back(parentTransform * localTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultTransforms = std::move(transforms);
|
||||
}
|
||||
|
||||
return resultTransforms;
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,45 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/base/gf/matrix4d.h>
|
||||
#include <pxr/base/gf/vec3f.h>
|
||||
#include <pxr/base/gf/vec4f.h>
|
||||
#include <pxr/base/vt/array.h>
|
||||
#include <pxr/imaging/hd/instancer.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesInstancer final : public PXR_NS::HdInstancer {
|
||||
public:
|
||||
HdCyclesInstancer(PXR_NS::HdSceneDelegate *delegate,
|
||||
const PXR_NS::SdfPath &instancerId
|
||||
#if PXR_VERSION <= 2011
|
||||
,
|
||||
const PXR_NS::SdfPath &parentId
|
||||
#endif
|
||||
);
|
||||
~HdCyclesInstancer() override;
|
||||
|
||||
#if PXR_VERSION > 2011
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
#endif
|
||||
|
||||
PXR_NS::VtMatrix4dArray ComputeInstanceTransforms(const PXR_NS::SdfPath &prototypeId);
|
||||
|
||||
private:
|
||||
void SyncPrimvars();
|
||||
|
||||
PXR_NS::VtVec3fArray _translate;
|
||||
PXR_NS::VtVec4fArray _rotate;
|
||||
PXR_NS::VtVec3fArray _scale;
|
||||
PXR_NS::VtMatrix4dArray _instanceTransform;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,404 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/light.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_graph.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
#include <pxr/usd/sdf/assetPath.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
extern Transform convert_transform(const GfMatrix4d &matrix);
|
||||
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
(visibleInPrimaryRay)
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
HdCyclesLight::HdCyclesLight(const SdfPath &sprimId, const TfToken &lightType)
|
||||
: HdLight(sprimId), _lightType(lightType)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesLight::~HdCyclesLight()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesLight::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
return DirtyBits::DirtyTransform | DirtyBits::DirtyParams;
|
||||
}
|
||||
|
||||
void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
if (*dirtyBits == DirtyBits::Clean) {
|
||||
return;
|
||||
}
|
||||
|
||||
Initialize(renderParam);
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
#if PXR_VERSION >= 2011
|
||||
convert_transform(sceneDelegate->GetTransform(id));
|
||||
#else
|
||||
convert_transform(
|
||||
sceneDelegate->GetLightParamValue(id, HdTokens->transform)
|
||||
.Get<GfMatrix4d>());
|
||||
#endif
|
||||
_light->set_tfm(tfm);
|
||||
|
||||
_light->set_co(transform_get_column(&tfm, 3));
|
||||
_light->set_dir(-transform_get_column(&tfm, 2));
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->diskLight || _lightType == HdPrimTypeTokens->rectLight) {
|
||||
_light->set_axisu(transform_get_column(&tfm, 0));
|
||||
_light->set_axisv(transform_get_column(&tfm, 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyParams) {
|
||||
float3 strength = make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->color);
|
||||
if (!value.IsEmpty()) {
|
||||
const auto color = value.Get<GfVec3f>();
|
||||
strength = make_float3(color[0], color[1], color[2]);
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->exposure);
|
||||
if (!value.IsEmpty()) {
|
||||
strength *= exp2(value.Get<float>());
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->intensity);
|
||||
if (!value.IsEmpty()) {
|
||||
strength *= value.Get<float>();
|
||||
}
|
||||
|
||||
// Cycles lights are normalized by default, so need to scale intensity if Hydra light is not
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->normalize);
|
||||
const bool normalize = value.IsHolding<bool>() && value.UncheckedGet<bool>();
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, _tokens->visibleInPrimaryRay);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_use_camera(value.Get<bool>());
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shadowEnable);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_cast_shadow(value.Get<bool>());
|
||||
}
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->distantLight) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->angle);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_angle(GfDegreesToRadians(value.Get<float>()));
|
||||
}
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->diskLight) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
|
||||
if (!value.IsEmpty()) {
|
||||
const float size = value.Get<float>() * 2.0f;
|
||||
_light->set_sizeu(size);
|
||||
_light->set_sizev(size);
|
||||
}
|
||||
|
||||
if (!normalize) {
|
||||
const float radius = _light->get_sizeu() * 0.5f;
|
||||
strength *= M_PI * radius * radius;
|
||||
}
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->rectLight) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->width);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_sizeu(value.Get<float>());
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->height);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_sizev(value.Get<float>());
|
||||
}
|
||||
|
||||
if (!normalize) {
|
||||
strength *= _light->get_sizeu() * _light->get_sizeu();
|
||||
}
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->sphereLight) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_size(value.Get<float>());
|
||||
}
|
||||
|
||||
bool shaping = false;
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingConeAngle);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_spot_angle(GfDegreesToRadians(value.Get<float>()) * 2.0f);
|
||||
shaping = true;
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingConeSoftness);
|
||||
if (!value.IsEmpty()) {
|
||||
_light->set_spot_smooth(value.Get<float>());
|
||||
shaping = true;
|
||||
}
|
||||
|
||||
_light->set_light_type(shaping ? LIGHT_SPOT : LIGHT_POINT);
|
||||
|
||||
if (!normalize) {
|
||||
const float radius = _light->get_size();
|
||||
strength *= M_PI * radius * radius * 4.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const bool visible = sceneDelegate->GetVisible(id);
|
||||
// Disable invisible lights by zeroing the strength
|
||||
// So 'LightManager::test_enabled_lights' updates the enabled flag correctly
|
||||
if (!visible) {
|
||||
strength = zero_float3();
|
||||
}
|
||||
|
||||
_light->set_strength(strength);
|
||||
_light->set_is_enabled(visible);
|
||||
|
||||
PopulateShaderGraph(sceneDelegate);
|
||||
}
|
||||
// Need to update shader graph when transform changes in case transform was baked into it
|
||||
else if (_light->tfm_is_modified() && (_lightType == HdPrimTypeTokens->domeLight ||
|
||||
_light->get_shader()->has_surface_spatial_varying)) {
|
||||
PopulateShaderGraph(sceneDelegate);
|
||||
}
|
||||
|
||||
if (_light->is_modified()) {
|
||||
_light->tag_update(lock.scene);
|
||||
}
|
||||
|
||||
*dirtyBits = DirtyBits::Clean;
|
||||
}
|
||||
|
||||
void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
auto graph = new ShaderGraph();
|
||||
ShaderNode *outputNode = nullptr;
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
|
||||
// Bake strength into shader graph, since only the shader is used for background lights
|
||||
bgNode->set_color(_light->get_strength());
|
||||
graph->add(bgNode);
|
||||
|
||||
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
|
||||
|
||||
outputNode = bgNode;
|
||||
}
|
||||
else {
|
||||
EmissionNode *emissionNode = graph->create_node<EmissionNode>();
|
||||
emissionNode->set_color(one_float3());
|
||||
emissionNode->set_strength(1.0f);
|
||||
graph->add(emissionNode);
|
||||
|
||||
graph->connect(emissionNode->output("Emission"), graph->output()->input("Surface"));
|
||||
|
||||
outputNode = emissionNode;
|
||||
}
|
||||
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
bool hasSpatialVarying = false;
|
||||
bool hasColorTemperature = false;
|
||||
|
||||
if (sceneDelegate != nullptr) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->enableColorTemperature);
|
||||
const bool enableColorTemperature = value.IsHolding<bool>() && value.UncheckedGet<bool>();
|
||||
|
||||
if (enableColorTemperature) {
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->colorTemperature);
|
||||
if (value.IsHolding<float>()) {
|
||||
BlackbodyNode *blackbodyNode = graph->create_node<BlackbodyNode>();
|
||||
blackbodyNode->set_temperature(value.UncheckedGet<float>());
|
||||
graph->add(blackbodyNode);
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
mathNode->set_vector2(_light->get_strength());
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(blackbodyNode->output("Color"), mathNode->input("Vector1"));
|
||||
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
|
||||
}
|
||||
else {
|
||||
graph->connect(blackbodyNode->output("Color"), outputNode->input("Color"));
|
||||
}
|
||||
|
||||
hasColorTemperature = true;
|
||||
}
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingIesFile);
|
||||
if (value.IsHolding<SdfAssetPath>()) {
|
||||
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
|
||||
if (filename.empty()) {
|
||||
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
|
||||
}
|
||||
|
||||
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
|
||||
coordNode->set_ob_tfm(_light->get_tfm());
|
||||
coordNode->set_use_transform(true);
|
||||
graph->add(coordNode);
|
||||
|
||||
IESLightNode *iesNode = graph->create_node<IESLightNode>();
|
||||
iesNode->set_filename(ustring(filename));
|
||||
|
||||
graph->connect(coordNode->output("Normal"), iesNode->input("Vector"));
|
||||
graph->connect(iesNode->output("Fac"), outputNode->input("Strength"));
|
||||
|
||||
hasSpatialVarying = true;
|
||||
}
|
||||
|
||||
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->textureFile);
|
||||
if (value.IsHolding<SdfAssetPath>()) {
|
||||
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
|
||||
if (filename.empty()) {
|
||||
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
|
||||
}
|
||||
|
||||
ImageSlotTextureNode *textureNode = nullptr;
|
||||
if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
Transform tfm = _light->get_tfm();
|
||||
transform_set_column(&tfm, 3, zero_float3()); // Remove translation
|
||||
|
||||
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
|
||||
coordNode->set_ob_tfm(tfm);
|
||||
coordNode->set_use_transform(true);
|
||||
graph->add(coordNode);
|
||||
|
||||
textureNode = graph->create_node<EnvironmentTextureNode>();
|
||||
static_cast<EnvironmentTextureNode *>(textureNode)->set_filename(ustring(filename));
|
||||
graph->add(textureNode);
|
||||
|
||||
graph->connect(coordNode->output("Object"), textureNode->input("Vector"));
|
||||
|
||||
hasSpatialVarying = true;
|
||||
}
|
||||
else {
|
||||
GeometryNode *coordNode = graph->create_node<GeometryNode>();
|
||||
graph->add(coordNode);
|
||||
|
||||
textureNode = graph->create_node<ImageTextureNode>();
|
||||
static_cast<ImageTextureNode *>(textureNode)->set_filename(ustring(filename));
|
||||
graph->add(textureNode);
|
||||
|
||||
graph->connect(coordNode->output("Parametric"), textureNode->input("Vector"));
|
||||
}
|
||||
|
||||
if (hasColorTemperature) {
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
|
||||
ShaderInput *const outputNodeInput = outputNode->input("Color");
|
||||
graph->connect(outputNodeInput->link, mathNode->input("Vector2"));
|
||||
graph->disconnect(outputNodeInput);
|
||||
graph->connect(mathNode->output("Vector"), outputNodeInput);
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
mathNode->set_vector2(_light->get_strength());
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
|
||||
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
|
||||
}
|
||||
else {
|
||||
graph->connect(textureNode->output("Color"), outputNode->input("Color"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader *const shader = _light->get_shader();
|
||||
shader->set_graph(graph);
|
||||
shader->tag_update((Scene *)_light->get_owner());
|
||||
|
||||
shader->has_surface_spatial_varying = hasSpatialVarying;
|
||||
}
|
||||
|
||||
void HdCyclesLight::Finalize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (!_light) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
lock.scene->delete_node(_light);
|
||||
_light = nullptr;
|
||||
}
|
||||
|
||||
void HdCyclesLight::Initialize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (_light) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
_light = lock.scene->create_node<Light>();
|
||||
_light->name = GetId().GetString();
|
||||
|
||||
_light->set_random_id(hash_uint2(hash_string(_light->name.c_str()), 0));
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
_light->set_light_type(LIGHT_BACKGROUND);
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->distantLight) {
|
||||
_light->set_light_type(LIGHT_DISTANT);
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->diskLight) {
|
||||
_light->set_light_type(LIGHT_AREA);
|
||||
_light->set_round(true);
|
||||
_light->set_size(1.0f);
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->rectLight) {
|
||||
_light->set_light_type(LIGHT_AREA);
|
||||
_light->set_round(false);
|
||||
_light->set_size(1.0f);
|
||||
}
|
||||
else if (_lightType == HdPrimTypeTokens->sphereLight) {
|
||||
_light->set_light_type(LIGHT_POINT);
|
||||
_light->set_size(1.0f);
|
||||
}
|
||||
|
||||
_light->set_use_mis(true);
|
||||
_light->set_use_camera(false);
|
||||
|
||||
Shader *const shader = lock.scene->create_node<Shader>();
|
||||
_light->set_shader(shader);
|
||||
|
||||
// Create default shader graph
|
||||
PopulateShaderGraph(nullptr);
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,35 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/light.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesLight final : public PXR_NS::HdLight {
|
||||
public:
|
||||
HdCyclesLight(const PXR_NS::SdfPath &sprimId, const PXR_NS::TfToken &lightType);
|
||||
~HdCyclesLight() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
|
||||
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
private:
|
||||
void Initialize(PXR_NS::HdRenderParam *renderParam);
|
||||
|
||||
void PopulateShaderGraph(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
CCL_NS::Light *_light = nullptr;
|
||||
PXR_NS::TfToken _lightType;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,584 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/material.h"
|
||||
#include "hydra/node_util.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_graph.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
|
||||
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(CyclesMaterialTokens,
|
||||
((cyclesSurface, "cycles:surface"))
|
||||
((cyclesDisplacement, "cycles:displacement"))
|
||||
((cyclesVolume, "cycles:volume"))
|
||||
(UsdPreviewSurface)
|
||||
(UsdUVTexture)
|
||||
(UsdPrimvarReader_float)
|
||||
(UsdPrimvarReader_float2)
|
||||
(UsdPrimvarReader_float3)
|
||||
(UsdPrimvarReader_float4)
|
||||
(UsdPrimvarReader_int)
|
||||
(UsdTransform2d)
|
||||
(a)
|
||||
(rgb)
|
||||
(r)
|
||||
(g)
|
||||
(b)
|
||||
(result)
|
||||
(st)
|
||||
(wrapS)
|
||||
(wrapT)
|
||||
(periodic)
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
// Simple class to handle remapping of USDPreviewSurface nodes and parameters to Cycles equivalents
|
||||
class UsdToCyclesMapping {
|
||||
using ParamMap = std::unordered_map<TfToken, ustring, TfToken::HashFunctor>;
|
||||
|
||||
public:
|
||||
UsdToCyclesMapping(const char *nodeType, ParamMap paramMap)
|
||||
: _nodeType(nodeType), _paramMap(std::move(paramMap))
|
||||
{
|
||||
}
|
||||
|
||||
ustring nodeType() const
|
||||
{
|
||||
return _nodeType;
|
||||
}
|
||||
|
||||
virtual std::string parameterName(const TfToken &name,
|
||||
const ShaderInput *inputConnection,
|
||||
VtValue *value = nullptr) const
|
||||
{
|
||||
// UsdNode.name -> Node.input
|
||||
// These all follow a simple pattern that we can just remap
|
||||
// based on the name or 'Node.input' type
|
||||
if (inputConnection) {
|
||||
if (name == CyclesMaterialTokens->a) {
|
||||
return "alpha";
|
||||
}
|
||||
if (name == CyclesMaterialTokens->rgb) {
|
||||
return "color";
|
||||
}
|
||||
// TODO: Is there a better mapping than 'color'?
|
||||
if (name == CyclesMaterialTokens->r || name == CyclesMaterialTokens->g ||
|
||||
name == CyclesMaterialTokens->b) {
|
||||
return "color";
|
||||
}
|
||||
|
||||
if (name == CyclesMaterialTokens->result) {
|
||||
switch (inputConnection->socket_type.type) {
|
||||
case SocketType::BOOLEAN:
|
||||
case SocketType::FLOAT:
|
||||
case SocketType::INT:
|
||||
case SocketType::UINT:
|
||||
return "alpha";
|
||||
case SocketType::COLOR:
|
||||
case SocketType::VECTOR:
|
||||
case SocketType::POINT:
|
||||
case SocketType::NORMAL:
|
||||
default:
|
||||
return "color";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simple mapping case
|
||||
const auto it = _paramMap.find(name);
|
||||
return it != _paramMap.end() ? it->second.string() : name.GetString();
|
||||
}
|
||||
|
||||
private:
|
||||
const ustring _nodeType;
|
||||
ParamMap _paramMap;
|
||||
};
|
||||
|
||||
class UsdToCyclesTexture : public UsdToCyclesMapping {
|
||||
public:
|
||||
using UsdToCyclesMapping::UsdToCyclesMapping;
|
||||
|
||||
std::string parameterName(const TfToken &name,
|
||||
const ShaderInput *inputConnection,
|
||||
VtValue *value) const override
|
||||
{
|
||||
if (value) {
|
||||
// Remap UsdUVTexture.wrapS and UsdUVTexture.wrapT to cycles_image_texture.extension
|
||||
if (name == CyclesMaterialTokens->wrapS || name == CyclesMaterialTokens->wrapT) {
|
||||
std::string valueString = VtValue::Cast<std::string>(*value).Get<std::string>();
|
||||
|
||||
// A value of 'repeat' in USD is equivalent to 'periodic' in Cycles
|
||||
if (valueString == "repeat") {
|
||||
*value = VtValue(CyclesMaterialTokens->periodic);
|
||||
}
|
||||
|
||||
return "extension";
|
||||
}
|
||||
}
|
||||
|
||||
return UsdToCyclesMapping::parameterName(name, inputConnection, value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
class UsdToCycles {
|
||||
const UsdToCyclesMapping UsdPreviewSurface = {
|
||||
"principled_bsdf",
|
||||
{
|
||||
{TfToken("diffuseColor"), ustring("base_color")},
|
||||
{TfToken("emissiveColor"), ustring("emission")},
|
||||
{TfToken("specularColor"), ustring("specular")},
|
||||
{TfToken("clearcoatRoughness"), ustring("clearcoat_roughness")},
|
||||
{TfToken("opacity"), ustring("alpha")},
|
||||
// opacityThreshold
|
||||
// occlusion
|
||||
// displacement
|
||||
}};
|
||||
const UsdToCyclesTexture UsdUVTexture = {
|
||||
"image_texture",
|
||||
{
|
||||
{CyclesMaterialTokens->st, ustring("vector")},
|
||||
{CyclesMaterialTokens->wrapS, ustring("extension")},
|
||||
{CyclesMaterialTokens->wrapT, ustring("extension")},
|
||||
{TfToken("file"), ustring("filename")},
|
||||
{TfToken("sourceColorSpace"), ustring("colorspace")},
|
||||
}};
|
||||
const UsdToCyclesMapping UsdPrimvarReader = {"attribute",
|
||||
{{TfToken("varname"), ustring("attribute")}}};
|
||||
|
||||
public:
|
||||
const UsdToCyclesMapping *findUsd(const TfToken &usdNodeType)
|
||||
{
|
||||
if (usdNodeType == CyclesMaterialTokens->UsdPreviewSurface) {
|
||||
return &UsdPreviewSurface;
|
||||
}
|
||||
if (usdNodeType == CyclesMaterialTokens->UsdUVTexture) {
|
||||
return &UsdUVTexture;
|
||||
}
|
||||
if (usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float ||
|
||||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float2 ||
|
||||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float3 ||
|
||||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float4 ||
|
||||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_int) {
|
||||
return &UsdPrimvarReader;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
const UsdToCyclesMapping *findCycles(const ustring &cyclesNodeType)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
TfStaticData<UsdToCycles> sUsdToCyles;
|
||||
|
||||
} // namespace
|
||||
|
||||
HdCyclesMaterial::HdCyclesMaterial(const SdfPath &sprimId) : HdMaterial(sprimId)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesMaterial::~HdCyclesMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesMaterial::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
return DirtyBits::DirtyResource | DirtyBits::DirtyParams;
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::Sync(HdSceneDelegate *sceneDelegate,
|
||||
HdRenderParam *renderParam,
|
||||
HdDirtyBits *dirtyBits)
|
||||
{
|
||||
if (*dirtyBits == DirtyBits::Clean) {
|
||||
return;
|
||||
}
|
||||
|
||||
Initialize(renderParam);
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
const bool dirtyParams = (*dirtyBits & DirtyBits::DirtyParams);
|
||||
const bool dirtyResource = (*dirtyBits & DirtyBits::DirtyResource);
|
||||
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
|
||||
if (dirtyResource || dirtyParams) {
|
||||
value = sceneDelegate->GetMaterialResource(id);
|
||||
|
||||
#if 1
|
||||
const HdMaterialNetwork2 *network = nullptr;
|
||||
std::unique_ptr<HdMaterialNetwork2> networkConverted;
|
||||
if (value.IsHolding<HdMaterialNetwork2>()) {
|
||||
network = &value.UncheckedGet<HdMaterialNetwork2>();
|
||||
}
|
||||
else if (value.IsHolding<HdMaterialNetworkMap>()) {
|
||||
const auto &networkOld = value.UncheckedGet<HdMaterialNetworkMap>();
|
||||
// In the case of only parameter updates, there is no need to waste time converting to a
|
||||
// HdMaterialNetwork2, as supporting HdMaterialNetworkMap for parameters only is trivial.
|
||||
if (!_nodes.empty() && !dirtyResource) {
|
||||
for (const auto &networkEntry : networkOld.map) {
|
||||
UpdateParameters(networkEntry.second);
|
||||
}
|
||||
_shader->tag_modified();
|
||||
}
|
||||
else {
|
||||
networkConverted = std::make_unique<HdMaterialNetwork2>();
|
||||
HdMaterialNetwork2ConvertFromHdMaterialNetworkMap(networkOld, networkConverted.get());
|
||||
network = networkConverted.get();
|
||||
}
|
||||
}
|
||||
else {
|
||||
TF_RUNTIME_ERROR("Could not get a HdMaterialNetwork2.");
|
||||
}
|
||||
|
||||
if (network) {
|
||||
if (!_nodes.empty() && !dirtyResource) {
|
||||
UpdateParameters(*network);
|
||||
_shader->tag_modified();
|
||||
}
|
||||
else {
|
||||
PopulateShaderGraph(*network);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_shader->is_modified()) {
|
||||
_shader->tag_update(lock.scene);
|
||||
}
|
||||
|
||||
*dirtyBits = DirtyBits::Clean;
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::UpdateParameters(NodeDesc &nodeDesc,
|
||||
const std::map<TfToken, VtValue> ¶meters,
|
||||
const SdfPath &nodePath)
|
||||
{
|
||||
for (const std::pair<TfToken, VtValue> ¶m : parameters) {
|
||||
VtValue value = param.second;
|
||||
|
||||
// See if the parameter name is in USDPreviewSurface terms, and needs to be converted
|
||||
const UsdToCyclesMapping *inputMapping = nodeDesc.mapping;
|
||||
const std::string inputName = inputMapping ?
|
||||
inputMapping->parameterName(param.first, nullptr, &value) :
|
||||
param.first.GetString();
|
||||
|
||||
// Find the input to write the parameter value to
|
||||
const SocketType *input = nullptr;
|
||||
for (const SocketType &socket : nodeDesc.node->type->inputs) {
|
||||
if (string_iequals(socket.name.string(), inputName) || socket.ui_name == inputName) {
|
||||
input = &socket;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
TF_WARN("Could not find parameter '%s' on node '%s' ('%s')",
|
||||
param.first.GetText(),
|
||||
nodePath.GetText(),
|
||||
nodeDesc.node->name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
SetNodeValue(nodeDesc.node, *input, value);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::UpdateParameters(const HdMaterialNetwork &network)
|
||||
{
|
||||
for (const HdMaterialNode &nodeEntry : network.nodes) {
|
||||
const SdfPath &nodePath = nodeEntry.path;
|
||||
|
||||
const auto nodeIt = _nodes.find(nodePath);
|
||||
if (nodeIt == _nodes.end()) {
|
||||
TF_RUNTIME_ERROR("Could not update parameters on missing node '%s'", nodePath.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateParameters(nodeIt->second, nodeEntry.parameters, nodePath);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::UpdateParameters(const HdMaterialNetwork2 &network)
|
||||
{
|
||||
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : network.nodes) {
|
||||
const SdfPath &nodePath = nodeEntry.first;
|
||||
|
||||
const auto nodeIt = _nodes.find(nodePath);
|
||||
if (nodeIt == _nodes.end()) {
|
||||
TF_RUNTIME_ERROR("Could not update parameters on missing node '%s'", nodePath.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateParameters(nodeIt->second, nodeEntry.second.parameters, nodePath);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::UpdateConnections(NodeDesc &nodeDesc,
|
||||
const HdMaterialNode2 &matNode,
|
||||
const SdfPath &nodePath,
|
||||
ShaderGraph *shaderGraph)
|
||||
{
|
||||
for (const std::pair<TfToken, std::vector<HdMaterialConnection2>> &connection :
|
||||
matNode.inputConnections) {
|
||||
const TfToken &dstSocketName = connection.first;
|
||||
|
||||
const UsdToCyclesMapping *inputMapping = nodeDesc.mapping;
|
||||
const std::string inputName = inputMapping ?
|
||||
inputMapping->parameterName(dstSocketName, nullptr) :
|
||||
dstSocketName.GetString();
|
||||
|
||||
// Find the input to connect to on the passed in node
|
||||
ShaderInput *input = nullptr;
|
||||
for (ShaderInput *in : nodeDesc.node->inputs) {
|
||||
if (string_iequals(in->socket_type.name.string(), inputName)) {
|
||||
input = in;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
TF_WARN("Ignoring connection on '%s.%s', input '%s' was not found",
|
||||
nodePath.GetText(),
|
||||
dstSocketName.GetText(),
|
||||
dstSocketName.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now find the output to connect from
|
||||
const auto &connectedNodes = connection.second;
|
||||
if (connectedNodes.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Hydra allows multiple connections of the same input
|
||||
// Unsure how to handle this in Cycles, so just use the first
|
||||
if (connectedNodes.size() > 1) {
|
||||
TF_WARN(
|
||||
"Ignoring multiple connections to '%s.%s'", nodePath.GetText(), dstSocketName.GetText());
|
||||
}
|
||||
|
||||
const SdfPath &upstreamNodePath = connectedNodes.front().upstreamNode;
|
||||
const TfToken &upstreamOutputName = connectedNodes.front().upstreamOutputName;
|
||||
|
||||
const auto srcNodeIt = _nodes.find(upstreamNodePath);
|
||||
if (srcNodeIt == _nodes.end()) {
|
||||
TF_WARN("Ignoring connection from '%s.%s' to '%s.%s', node '%s' was not found",
|
||||
upstreamNodePath.GetText(),
|
||||
upstreamOutputName.GetText(),
|
||||
nodePath.GetText(),
|
||||
dstSocketName.GetText(),
|
||||
upstreamNodePath.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
const UsdToCyclesMapping *outputMapping = srcNodeIt->second.mapping;
|
||||
const std::string outputName = outputMapping ?
|
||||
outputMapping->parameterName(upstreamOutputName, input) :
|
||||
upstreamOutputName.GetString();
|
||||
|
||||
ShaderOutput *output = nullptr;
|
||||
for (ShaderOutput *out : srcNodeIt->second.node->outputs) {
|
||||
if (string_iequals(out->socket_type.name.string(), outputName)) {
|
||||
output = out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!output) {
|
||||
TF_WARN("Ignoring connection from '%s.%s' to '%s.%s', output '%s' was not found",
|
||||
upstreamNodePath.GetText(),
|
||||
upstreamOutputName.GetText(),
|
||||
nodePath.GetText(),
|
||||
dstSocketName.GetText(),
|
||||
upstreamOutputName.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
shaderGraph->connect(output, input);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::PopulateShaderGraph(const HdMaterialNetwork2 &networkMap)
|
||||
{
|
||||
_nodes.clear();
|
||||
|
||||
auto graph = new ShaderGraph();
|
||||
|
||||
// Iterate all the nodes first and build a complete but unconnected graph with parameters set
|
||||
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : networkMap.nodes) {
|
||||
NodeDesc nodeDesc = {};
|
||||
const SdfPath &nodePath = nodeEntry.first;
|
||||
|
||||
const auto nodeIt = _nodes.find(nodePath);
|
||||
// Create new node only if it does not exist yet
|
||||
if (nodeIt != _nodes.end()) {
|
||||
nodeDesc = nodeIt->second;
|
||||
}
|
||||
else {
|
||||
// E.g. cycles_principled_bsdf or UsdPreviewSurface
|
||||
const std::string &nodeTypeId = nodeEntry.second.nodeTypeId.GetString();
|
||||
|
||||
ustring cyclesType(nodeTypeId);
|
||||
// Interpret a node type ID prefixed with cycles_<type> or cycles:<type> as a node of <type>
|
||||
if (nodeTypeId.rfind("cycles", 0) == 0) {
|
||||
cyclesType = nodeTypeId.substr(7);
|
||||
nodeDesc.mapping = sUsdToCyles->findCycles(cyclesType);
|
||||
}
|
||||
else {
|
||||
// Check if any remapping is needed (e.g. for USDPreviewSurface to Cycles nodes)
|
||||
nodeDesc.mapping = sUsdToCyles->findUsd(nodeEntry.second.nodeTypeId);
|
||||
if (nodeDesc.mapping) {
|
||||
cyclesType = nodeDesc.mapping->nodeType();
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a native Cycles' node-type, just do the lookup now.
|
||||
if (const NodeType *nodeType = NodeType::find(cyclesType)) {
|
||||
nodeDesc.node = static_cast<ShaderNode *>(nodeType->create(nodeType));
|
||||
nodeDesc.node->set_owner(graph);
|
||||
|
||||
graph->add(nodeDesc.node);
|
||||
|
||||
_nodes.emplace(nodePath, nodeDesc);
|
||||
}
|
||||
else {
|
||||
TF_RUNTIME_ERROR("Could not create node '%s'", nodePath.GetText());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateParameters(nodeDesc, nodeEntry.second.parameters, nodePath);
|
||||
}
|
||||
|
||||
// Now that all nodes have been constructed, iterate the network again and build up any
|
||||
// connections between nodes
|
||||
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : networkMap.nodes) {
|
||||
const SdfPath &nodePath = nodeEntry.first;
|
||||
|
||||
const auto nodeIt = _nodes.find(nodePath);
|
||||
if (nodeIt == _nodes.end()) {
|
||||
TF_RUNTIME_ERROR("Could not find node '%s' to connect", nodePath.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateConnections(nodeIt->second, nodeEntry.second, nodePath, graph);
|
||||
}
|
||||
|
||||
// Finally connect the terminals to the graph output (Surface, Volume, Displacement)
|
||||
for (const std::pair<TfToken, HdMaterialConnection2> &terminalEntry : networkMap.terminals) {
|
||||
const TfToken &terminalName = terminalEntry.first;
|
||||
const HdMaterialConnection2 &connection = terminalEntry.second;
|
||||
|
||||
const auto nodeIt = _nodes.find(connection.upstreamNode);
|
||||
if (nodeIt == _nodes.end()) {
|
||||
TF_RUNTIME_ERROR("Could not find terminal node '%s'", connection.upstreamNode.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderNode *const node = nodeIt->second.node;
|
||||
|
||||
const char *inputName = nullptr;
|
||||
const char *outputName = nullptr;
|
||||
if (terminalName == HdMaterialTerminalTokens->surface ||
|
||||
terminalName == CyclesMaterialTokens->cyclesSurface) {
|
||||
inputName = "Surface";
|
||||
// Find default output name based on the node if none is provided
|
||||
if (node->type->name == "add_closure" || node->type->name == "mix_closure") {
|
||||
outputName = "Closure";
|
||||
}
|
||||
else if (node->type->name == "emission") {
|
||||
outputName = "Emission";
|
||||
}
|
||||
else {
|
||||
outputName = "BSDF";
|
||||
}
|
||||
}
|
||||
else if (terminalName == HdMaterialTerminalTokens->displacement ||
|
||||
terminalName == CyclesMaterialTokens->cyclesDisplacement) {
|
||||
inputName = outputName = "Displacement";
|
||||
}
|
||||
else if (terminalName == HdMaterialTerminalTokens->volume ||
|
||||
terminalName == CyclesMaterialTokens->cyclesVolume) {
|
||||
inputName = outputName = "Volume";
|
||||
}
|
||||
|
||||
if (!connection.upstreamOutputName.IsEmpty()) {
|
||||
outputName = connection.upstreamOutputName.GetText();
|
||||
}
|
||||
|
||||
ShaderInput *const input = inputName ? graph->output()->input(inputName) : nullptr;
|
||||
if (!input) {
|
||||
TF_RUNTIME_ERROR("Could not find terminal input '%s.%s'",
|
||||
connection.upstreamNode.GetText(),
|
||||
inputName ? inputName : "<null>");
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderOutput *const output = outputName ? node->output(outputName) : nullptr;
|
||||
if (!output) {
|
||||
TF_RUNTIME_ERROR("Could not find terminal output '%s.%s'",
|
||||
connection.upstreamNode.GetText(),
|
||||
outputName ? outputName : "<null>");
|
||||
continue;
|
||||
}
|
||||
|
||||
graph->connect(output, input);
|
||||
}
|
||||
|
||||
// Create the instanceId AOV output
|
||||
{
|
||||
const ustring instanceId(HdAovTokens->instanceId.GetString());
|
||||
|
||||
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
|
||||
aovNode->set_name(instanceId);
|
||||
graph->add(aovNode);
|
||||
|
||||
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
|
||||
instanceIdNode->set_attribute(instanceId);
|
||||
graph->add(instanceIdNode);
|
||||
|
||||
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
|
||||
}
|
||||
|
||||
_shader->set_graph(graph);
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::Finalize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (!_shader) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
_nodes.clear();
|
||||
|
||||
lock.scene->delete_node(_shader);
|
||||
_shader = nullptr;
|
||||
}
|
||||
|
||||
void HdCyclesMaterial::Initialize(HdRenderParam *renderParam)
|
||||
{
|
||||
if (_shader) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneLock lock(renderParam);
|
||||
|
||||
_shader = lock.scene->create_node<Shader>();
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,63 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/material.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesMaterial final : public PXR_NS::HdMaterial {
|
||||
public:
|
||||
HdCyclesMaterial(const PXR_NS::SdfPath &sprimId);
|
||||
~HdCyclesMaterial() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdRenderParam *renderParam,
|
||||
PXR_NS::HdDirtyBits *dirtyBits) override;
|
||||
|
||||
#if PXR_VERSION < 2011
|
||||
void Reload() override
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
CCL_NS::Shader *GetCyclesShader() const
|
||||
{
|
||||
return _shader;
|
||||
}
|
||||
|
||||
private:
|
||||
struct NodeDesc {
|
||||
CCL_NS::ShaderNode *node;
|
||||
const class UsdToCyclesMapping *mapping;
|
||||
};
|
||||
|
||||
void Initialize(PXR_NS::HdRenderParam *renderParam);
|
||||
|
||||
void UpdateParameters(NodeDesc &nodeDesc,
|
||||
const std::map<PXR_NS::TfToken, PXR_NS::VtValue> ¶meters,
|
||||
const PXR_NS::SdfPath &nodePath);
|
||||
|
||||
void UpdateParameters(const PXR_NS::HdMaterialNetwork &network);
|
||||
void UpdateParameters(const PXR_NS::HdMaterialNetwork2 &network);
|
||||
|
||||
void UpdateConnections(NodeDesc &nodeDesc,
|
||||
const PXR_NS::HdMaterialNode2 &matNode,
|
||||
const PXR_NS::SdfPath &nodePath,
|
||||
CCL_NS::ShaderGraph *shaderGraph);
|
||||
|
||||
void PopulateShaderGraph(const PXR_NS::HdMaterialNetwork2 &network);
|
||||
|
||||
CCL_NS::Shader *_shader = nullptr;
|
||||
std::unordered_map<PXR_NS::SdfPath, NodeDesc, PXR_NS::SdfPath::Hash> _nodes;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,524 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/mesh.h"
|
||||
#include "hydra/geometry.inl"
|
||||
#include "scene/mesh.h"
|
||||
|
||||
#include <pxr/base/gf/vec2f.h>
|
||||
#include <pxr/imaging/hd/extComputationUtils.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
VtValue ComputeTriangulatedUniformPrimvar(VtValue value, const VtIntArray &primitiveParams)
|
||||
{
|
||||
T output;
|
||||
output.reserve(primitiveParams.size());
|
||||
const T &input = value.Get<T>();
|
||||
|
||||
for (size_t i = 0; i < primitiveParams.size(); ++i) {
|
||||
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(primitiveParams[i]);
|
||||
|
||||
output.push_back(input[faceIndex]);
|
||||
}
|
||||
|
||||
return VtValue(output);
|
||||
}
|
||||
|
||||
VtValue ComputeTriangulatedUniformPrimvar(VtValue value,
|
||||
const HdType valueType,
|
||||
const VtIntArray &primitiveParams)
|
||||
{
|
||||
switch (valueType) {
|
||||
case HdTypeFloat:
|
||||
return ComputeTriangulatedUniformPrimvar<VtFloatArray>(value, primitiveParams);
|
||||
case HdTypeFloatVec2:
|
||||
return ComputeTriangulatedUniformPrimvar<VtVec2fArray>(value, primitiveParams);
|
||||
case HdTypeFloatVec3:
|
||||
return ComputeTriangulatedUniformPrimvar<VtVec3fArray>(value, primitiveParams);
|
||||
case HdTypeFloatVec4:
|
||||
return ComputeTriangulatedUniformPrimvar<VtVec4fArray>(value, primitiveParams);
|
||||
default:
|
||||
TF_RUNTIME_ERROR("Unsupported attribute type %d", static_cast<int>(valueType));
|
||||
return VtValue();
|
||||
}
|
||||
}
|
||||
|
||||
VtValue ComputeTriangulatedFaceVaryingPrimvar(VtValue value,
|
||||
const HdType valueType,
|
||||
HdMeshUtil &meshUtil)
|
||||
{
|
||||
if (meshUtil.ComputeTriangulatedFaceVaryingPrimvar(
|
||||
HdGetValueData(value), value.GetArraySize(), valueType, &value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return VtValue();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Transform convert_transform(const GfMatrix4d &matrix)
|
||||
{
|
||||
return make_transform(matrix[0][0],
|
||||
matrix[1][0],
|
||||
matrix[2][0],
|
||||
matrix[3][0],
|
||||
matrix[0][1],
|
||||
matrix[1][1],
|
||||
matrix[2][1],
|
||||
matrix[3][1],
|
||||
matrix[0][2],
|
||||
matrix[1][2],
|
||||
matrix[2][2],
|
||||
matrix[3][2]);
|
||||
}
|
||||
|
||||
HdCyclesMesh::HdCyclesMesh(const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
: HdCyclesGeometry(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
),
|
||||
_util(&_topology, rprimId)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesMesh::~HdCyclesMesh()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesMesh::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals |
|
||||
HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology |
|
||||
HdChangeTracker::DirtyDisplayStyle | HdChangeTracker::DirtySubdivTags;
|
||||
return bits;
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesMesh::_PropagateDirtyBits(HdDirtyBits bits) const
|
||||
{
|
||||
if (bits & (HdChangeTracker::DirtyMaterialId)) {
|
||||
// Update used shaders from geometry subsets if any exist in the topology
|
||||
bits |= HdChangeTracker::DirtyTopology;
|
||||
}
|
||||
|
||||
if (bits & (HdChangeTracker::DirtyTopology | HdChangeTracker::DirtyDisplayStyle |
|
||||
HdChangeTracker::DirtySubdivTags)) {
|
||||
// Do full topology update when display style or subdivision changes
|
||||
bits |= HdChangeTracker::DirtyTopology | HdChangeTracker::DirtyDisplayStyle |
|
||||
HdChangeTracker::DirtySubdivTags;
|
||||
}
|
||||
|
||||
if (bits & (HdChangeTracker::DirtyTopology)) {
|
||||
// Changing topology clears the geometry, so need to populate everything again
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals |
|
||||
HdChangeTracker::DirtyPrimvar;
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
void HdCyclesMesh::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
|
||||
{
|
||||
if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
|
||||
PopulateTopology(sceneDelegate);
|
||||
}
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyPoints) {
|
||||
PopulatePoints(sceneDelegate);
|
||||
}
|
||||
|
||||
// Must happen after topology update, so that normals attribute size can be calculated
|
||||
if (dirtyBits & HdChangeTracker::DirtyNormals) {
|
||||
PopulateNormals(sceneDelegate);
|
||||
}
|
||||
|
||||
// Must happen after topology update, so that appropriate attribute set can be selected
|
||||
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
|
||||
PopulatePrimvars(sceneDelegate);
|
||||
}
|
||||
|
||||
rebuild = (_geom->triangles_is_modified()) || (_geom->subd_start_corner_is_modified()) ||
|
||||
(_geom->subd_num_corners_is_modified()) || (_geom->subd_shader_is_modified()) ||
|
||||
(_geom->subd_smooth_is_modified()) || (_geom->subd_ptex_offset_is_modified()) ||
|
||||
(_geom->subd_face_corners_is_modified());
|
||||
}
|
||||
|
||||
void HdCyclesMesh::PopulatePoints(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
VtValue value;
|
||||
|
||||
for (const HdExtComputationPrimvarDescriptor &desc :
|
||||
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
|
||||
if (desc.name == HdTokens->points) {
|
||||
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
|
||||
const auto valueStoreIt = valueStore.find(desc.name);
|
||||
if (valueStoreIt != valueStore.end()) {
|
||||
value = std::move(valueStoreIt->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
value = GetPoints(sceneDelegate);
|
||||
}
|
||||
|
||||
if (!value.IsHolding<VtVec3fArray>()) {
|
||||
TF_WARN("Invalid points data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &points = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
TF_VERIFY(points.size() >= static_cast<size_t>(_topology.GetNumPoints()));
|
||||
|
||||
array<float3> pointsDataCycles;
|
||||
pointsDataCycles.reserve(points.size());
|
||||
for (const GfVec3f &point : points) {
|
||||
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
|
||||
}
|
||||
|
||||
_geom->set_verts(pointsDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesMesh::PopulateNormals(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
_geom->attributes.remove(ATTR_STD_FACE_NORMAL);
|
||||
_geom->attributes.remove(ATTR_STD_VERTEX_NORMAL);
|
||||
|
||||
// Authored normals should only exist on triangle meshes
|
||||
if (_geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
VtValue value;
|
||||
HdInterpolation interpolation = HdInterpolationCount;
|
||||
|
||||
for (int i = 0; i < HdInterpolationCount && interpolation == HdInterpolationCount; ++i) {
|
||||
for (const HdExtComputationPrimvarDescriptor &desc :
|
||||
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(),
|
||||
static_cast<HdInterpolation>(i))) {
|
||||
if (desc.name == HdTokens->normals) {
|
||||
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
|
||||
const auto valueStoreIt = valueStore.find(desc.name);
|
||||
if (valueStoreIt != valueStore.end()) {
|
||||
value = std::move(valueStoreIt->second);
|
||||
interpolation = static_cast<HdInterpolation>(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->normals);
|
||||
if (interpolation == HdInterpolationCount) {
|
||||
return; // Ignore missing normals
|
||||
}
|
||||
|
||||
value = GetNormals(sceneDelegate);
|
||||
}
|
||||
|
||||
if (!value.IsHolding<VtVec3fArray>()) {
|
||||
TF_WARN("Invalid normals data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &normals = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
if (interpolation == HdInterpolationConstant) {
|
||||
TF_VERIFY(normals.size() == 1);
|
||||
|
||||
const GfVec3f constantNormal = normals[0];
|
||||
|
||||
float3 *const N = _geom->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
|
||||
for (size_t i = 0; i < _geom->get_verts().size(); ++i) {
|
||||
N[i] = make_float3(constantNormal[0], constantNormal[1], constantNormal[2]);
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationUniform) {
|
||||
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumFaces()));
|
||||
|
||||
float3 *const N = _geom->attributes.add(ATTR_STD_FACE_NORMAL)->data_float3();
|
||||
for (size_t i = 0; i < _geom->num_triangles(); ++i) {
|
||||
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(_primitiveParams[i]);
|
||||
|
||||
N[i] = make_float3(normals[faceIndex][0], normals[faceIndex][1], normals[faceIndex][2]);
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationVertex || interpolation == HdInterpolationVarying) {
|
||||
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumPoints()) &&
|
||||
static_cast<size_t>(_topology.GetNumPoints()) == _geom->get_verts().size());
|
||||
|
||||
float3 *const N = _geom->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
|
||||
for (size_t i = 0; i < _geom->get_verts().size(); ++i) {
|
||||
N[i] = make_float3(normals[i][0], normals[i][1], normals[i][2]);
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationFaceVarying) {
|
||||
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumFaceVaryings()));
|
||||
|
||||
if (!_util.ComputeTriangulatedFaceVaryingPrimvar(
|
||||
normals.data(), normals.size(), HdTypeFloatVec3, &value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &normalsTriangulated = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
// Cycles has no standard attribute for face-varying normals, so this is a lossy transformation
|
||||
float3 *const N = _geom->attributes.add(ATTR_STD_FACE_NORMAL)->data_float3();
|
||||
for (size_t i = 0; i < _geom->num_triangles(); ++i) {
|
||||
GfVec3f averageNormal = normalsTriangulated[i * 3] + normalsTriangulated[i * 3 + 1] +
|
||||
normalsTriangulated[i * 3 + 2];
|
||||
GfNormalize(&averageNormal);
|
||||
|
||||
N[i] = make_float3(averageNormal[0], averageNormal[1], averageNormal[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMesh::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
Scene *const scene = (Scene *)_geom->get_owner();
|
||||
|
||||
const bool subdivision = _geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE;
|
||||
AttributeSet &attributes = subdivision ? _geom->subd_attributes : _geom->attributes;
|
||||
|
||||
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
|
||||
std::make_pair(HdInterpolationFaceVarying, ATTR_ELEMENT_CORNER),
|
||||
std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_FACE),
|
||||
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_VERTEX),
|
||||
std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_VERTEX),
|
||||
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
|
||||
};
|
||||
|
||||
for (const auto &interpolation : interpolations) {
|
||||
for (const HdPrimvarDescriptor &desc :
|
||||
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
|
||||
// Skip special primvars that are handled separately
|
||||
if (desc.name == HdTokens->points || desc.name == HdTokens->normals) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VtValue value = GetPrimvar(sceneDelegate, desc.name);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ustring name(desc.name.GetString());
|
||||
|
||||
AttributeStandard std = ATTR_STD_NONE;
|
||||
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
|
||||
std = ATTR_STD_UV;
|
||||
}
|
||||
else if (interpolation.first == HdInterpolationVertex) {
|
||||
if (desc.name == HdTokens->displayColor || desc.role == HdPrimvarRoleTokens->color) {
|
||||
std = ATTR_STD_VERTEX_COLOR;
|
||||
}
|
||||
else if (desc.name == HdTokens->normals) {
|
||||
std = ATTR_STD_VERTEX_NORMAL;
|
||||
}
|
||||
}
|
||||
else if (desc.name == HdTokens->displayColor &&
|
||||
interpolation.first == HdInterpolationConstant) {
|
||||
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
|
||||
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
|
||||
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
|
||||
}
|
||||
}
|
||||
|
||||
// Skip attributes that are not needed
|
||||
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
|
||||
_geom->need_attribute(scene, name)) {
|
||||
const HdType valueType = HdGetValueTupleType(value).type;
|
||||
|
||||
if (!subdivision) {
|
||||
// Adjust attributes for polygons that were triangulated
|
||||
if (interpolation.first == HdInterpolationUniform) {
|
||||
value = ComputeTriangulatedUniformPrimvar(value, valueType, _primitiveParams);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (interpolation.first == HdInterpolationFaceVarying) {
|
||||
value = ComputeTriangulatedFaceVaryingPrimvar(value, valueType, _util);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApplyPrimvars(attributes, name, value, interpolation.second, std);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMesh::PopulateTopology(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
// Clear geometry before populating it again with updated topology
|
||||
_geom->clear(true);
|
||||
|
||||
const HdDisplayStyle displayStyle = GetDisplayStyle(sceneDelegate);
|
||||
_topology = HdMeshTopology(GetMeshTopology(sceneDelegate), displayStyle.refineLevel);
|
||||
|
||||
const TfToken subdivScheme = _topology.GetScheme();
|
||||
if (subdivScheme == PxOsdOpenSubdivTokens->bilinear && _topology.GetRefineLevel() > 0) {
|
||||
_geom->set_subdivision_type(Mesh::SUBDIVISION_LINEAR);
|
||||
}
|
||||
else if (subdivScheme == PxOsdOpenSubdivTokens->catmullClark && _topology.GetRefineLevel() > 0) {
|
||||
_geom->set_subdivision_type(Mesh::SUBDIVISION_CATMULL_CLARK);
|
||||
}
|
||||
else {
|
||||
_geom->set_subdivision_type(Mesh::SUBDIVISION_NONE);
|
||||
}
|
||||
|
||||
const bool smooth = !displayStyle.flatShadingEnabled;
|
||||
const bool subdivision = _geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE;
|
||||
|
||||
// Initialize lookup table from polygon face to material shader index
|
||||
VtIntArray faceShaders(_topology.GetNumFaces(), 0);
|
||||
|
||||
HdGeomSubsets const &geomSubsets = _topology.GetGeomSubsets();
|
||||
if (!geomSubsets.empty()) {
|
||||
array<Node *> usedShaders = std::move(_geom->get_used_shaders());
|
||||
// Remove any previous materials except for the material assigned to the prim
|
||||
usedShaders.resize(1);
|
||||
|
||||
std::unordered_map<SdfPath, int, SdfPath::Hash> materials;
|
||||
|
||||
for (const HdGeomSubset &geomSubset : geomSubsets) {
|
||||
TF_VERIFY(geomSubset.type == HdGeomSubset::TypeFaceSet);
|
||||
|
||||
int shader = 0;
|
||||
const auto it = materials.find(geomSubset.materialId);
|
||||
if (it != materials.end()) {
|
||||
shader = it->second;
|
||||
}
|
||||
else {
|
||||
const auto material = static_cast<const HdCyclesMaterial *>(
|
||||
sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material,
|
||||
geomSubset.materialId));
|
||||
|
||||
if (material && material->GetCyclesShader()) {
|
||||
shader = static_cast<int>(usedShaders.size());
|
||||
usedShaders.push_back_slow(material->GetCyclesShader());
|
||||
|
||||
materials.emplace(geomSubset.materialId, shader);
|
||||
}
|
||||
}
|
||||
|
||||
for (int face : geomSubset.indices) {
|
||||
faceShaders[face] = shader;
|
||||
}
|
||||
}
|
||||
|
||||
_geom->set_used_shaders(usedShaders);
|
||||
}
|
||||
|
||||
const VtIntArray vertIndx = _topology.GetFaceVertexIndices();
|
||||
const VtIntArray vertCounts = _topology.GetFaceVertexCounts();
|
||||
|
||||
if (!subdivision) {
|
||||
VtVec3iArray triangles;
|
||||
_util.ComputeTriangleIndices(&triangles, &_primitiveParams);
|
||||
|
||||
_geom->reserve_mesh(_topology.GetNumPoints(), triangles.size());
|
||||
|
||||
for (size_t i = 0; i < _primitiveParams.size(); ++i) {
|
||||
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(_primitiveParams[i]);
|
||||
|
||||
const GfVec3i triangle = triangles[i];
|
||||
_geom->add_triangle(triangle[0], triangle[1], triangle[2], faceShaders[faceIndex], smooth);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PxOsdSubdivTags subdivTags = GetSubdivTags(sceneDelegate);
|
||||
_topology.SetSubdivTags(subdivTags);
|
||||
|
||||
size_t numNgons = 0;
|
||||
size_t numCorners = 0;
|
||||
for (int vertCount : vertCounts) {
|
||||
numNgons += (vertCount == 4) ? 0 : 1;
|
||||
numCorners += vertCount;
|
||||
}
|
||||
|
||||
_geom->reserve_subd_faces(_topology.GetNumFaces(), numNgons, numCorners);
|
||||
|
||||
// TODO: Handle hole indices
|
||||
size_t faceIndex = 0;
|
||||
size_t indexOffset = 0;
|
||||
for (int vertCount : vertCounts) {
|
||||
_geom->add_subd_face(&vertIndx[indexOffset], vertCount, faceShaders[faceIndex], smooth);
|
||||
|
||||
faceIndex++;
|
||||
indexOffset += vertCount;
|
||||
}
|
||||
|
||||
const VtIntArray creaseLengths = subdivTags.GetCreaseLengths();
|
||||
if (!creaseLengths.empty()) {
|
||||
size_t numCreases = 0;
|
||||
for (int creaseLength : creaseLengths) {
|
||||
numCreases += creaseLength - 1;
|
||||
}
|
||||
|
||||
_geom->reserve_subd_creases(numCreases);
|
||||
|
||||
const VtIntArray creaseIndices = subdivTags.GetCreaseIndices();
|
||||
const VtFloatArray creaseWeights = subdivTags.GetCreaseWeights();
|
||||
|
||||
indexOffset = 0;
|
||||
size_t creaseLengthOffset = 0;
|
||||
size_t createWeightOffset = 0;
|
||||
for (int creaseLength : creaseLengths) {
|
||||
for (int j = 0; j < creaseLength - 1; ++j, ++createWeightOffset) {
|
||||
const int v0 = creaseIndices[indexOffset + j];
|
||||
const int v1 = creaseIndices[indexOffset + j + 1];
|
||||
|
||||
float weight = creaseWeights.size() == creaseLengths.size() ?
|
||||
creaseWeights[creaseLengthOffset] :
|
||||
creaseWeights[createWeightOffset];
|
||||
|
||||
_geom->add_edge_crease(v0, v1, weight);
|
||||
}
|
||||
|
||||
indexOffset += creaseLength;
|
||||
creaseLengthOffset++;
|
||||
}
|
||||
|
||||
const VtIntArray cornerIndices = subdivTags.GetCornerIndices();
|
||||
const VtFloatArray cornerWeights = subdivTags.GetCornerWeights();
|
||||
|
||||
for (size_t i = 0; i < cornerIndices.size(); ++i) {
|
||||
_geom->add_vertex_crease(cornerIndices[i], cornerWeights[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_geom->set_subd_dicing_rate(1.0f);
|
||||
_geom->set_subd_max_level(_topology.GetRefineLevel());
|
||||
_geom->set_subd_objecttoworld(_instances[0]->get_tfm());
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesMesh::Finalize(PXR_NS::HdRenderParam *renderParam)
|
||||
{
|
||||
_topology = HdMeshTopology();
|
||||
_primitiveParams.clear();
|
||||
|
||||
HdCyclesGeometry<PXR_NS::HdMesh, Mesh>::Finalize(renderParam);
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,49 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "hydra/geometry.h"
|
||||
|
||||
#include <pxr/imaging/hd/mesh.h>
|
||||
#include <pxr/imaging/hd/meshUtil.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesMesh final : public HdCyclesGeometry<PXR_NS::HdMesh, CCL_NS::Mesh> {
|
||||
public:
|
||||
HdCyclesMesh(
|
||||
const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId = {}
|
||||
#endif
|
||||
);
|
||||
~HdCyclesMesh() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
private:
|
||||
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
|
||||
|
||||
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdDirtyBits dirtyBits,
|
||||
bool &rebuild) override;
|
||||
|
||||
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
void PopulateNormals(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
void PopulateTopology(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
PXR_NS::HdMeshUtil _util;
|
||||
PXR_NS::HdMeshTopology _topology;
|
||||
PXR_NS::VtIntArray _primitiveParams;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,562 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/node_util.h"
|
||||
#include "util/transform.h"
|
||||
|
||||
#include <pxr/base/gf/matrix3d.h>
|
||||
#include <pxr/base/gf/matrix3f.h>
|
||||
#include <pxr/base/gf/matrix4d.h>
|
||||
#include <pxr/base/gf/matrix4f.h>
|
||||
#include <pxr/base/gf/vec2f.h>
|
||||
#include <pxr/base/gf/vec3f.h>
|
||||
#include <pxr/base/vt/array.h>
|
||||
#include <pxr/usd/sdf/assetPath.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename DstType> DstType convertToCycles(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<DstType>()) {
|
||||
return value.UncheckedGet<DstType>();
|
||||
}
|
||||
|
||||
VtValue castedValue = VtValue::Cast<DstType>(value);
|
||||
if (castedValue.IsHolding<DstType>()) {
|
||||
return castedValue.UncheckedGet<DstType>();
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to Cycles type");
|
||||
return DstType(0);
|
||||
}
|
||||
|
||||
template<> float2 convertToCycles<float2>(const VtValue &value)
|
||||
{
|
||||
const GfVec2f convertedValue = convertToCycles<GfVec2f>(value);
|
||||
return make_float2(convertedValue[0], convertedValue[1]);
|
||||
}
|
||||
|
||||
template<> float3 convertToCycles<float3>(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<GfVec3f>()) {
|
||||
const GfVec3f convertedValue = value.UncheckedGet<GfVec3f>();
|
||||
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
||||
}
|
||||
if (value.IsHolding<GfVec4f>()) {
|
||||
const GfVec4f convertedValue = value.UncheckedGet<GfVec4f>();
|
||||
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
||||
}
|
||||
|
||||
if (value.CanCast<GfVec3f>()) {
|
||||
const GfVec3f convertedValue = VtValue::Cast<GfVec3f>(value).UncheckedGet<GfVec3f>();
|
||||
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
||||
}
|
||||
if (value.CanCast<GfVec4f>()) {
|
||||
const GfVec4f convertedValue = VtValue::Cast<GfVec4f>(value).UncheckedGet<GfVec4f>();
|
||||
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to float3");
|
||||
return zero_float3();
|
||||
}
|
||||
|
||||
template<> ustring convertToCycles<ustring>(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<TfToken>()) {
|
||||
return ustring(value.UncheckedGet<TfToken>().GetString());
|
||||
}
|
||||
if (value.IsHolding<std::string>()) {
|
||||
return ustring(value.UncheckedGet<std::string>());
|
||||
}
|
||||
if (value.IsHolding<SdfAssetPath>()) {
|
||||
const SdfAssetPath &path = value.UncheckedGet<SdfAssetPath>();
|
||||
return ustring(path.GetResolvedPath());
|
||||
}
|
||||
|
||||
if (value.CanCast<TfToken>()) {
|
||||
return convertToCycles<ustring>(VtValue::Cast<TfToken>(value));
|
||||
}
|
||||
if (value.CanCast<std::string>()) {
|
||||
return convertToCycles<ustring>(VtValue::Cast<std::string>(value));
|
||||
}
|
||||
if (value.CanCast<SdfAssetPath>()) {
|
||||
return convertToCycles<ustring>(VtValue::Cast<SdfAssetPath>(value));
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to ustring");
|
||||
return ustring();
|
||||
}
|
||||
|
||||
template<typename Matrix>
|
||||
Transform convertMatrixToCycles(
|
||||
const typename std::enable_if<Matrix::numRows == 3 && Matrix::numColumns == 3, Matrix>::type
|
||||
&matrix)
|
||||
{
|
||||
return make_transform(matrix[0][0],
|
||||
matrix[1][0],
|
||||
matrix[2][0],
|
||||
0,
|
||||
matrix[0][1],
|
||||
matrix[1][1],
|
||||
matrix[2][1],
|
||||
0,
|
||||
matrix[0][2],
|
||||
matrix[1][2],
|
||||
matrix[2][2],
|
||||
0);
|
||||
}
|
||||
|
||||
template<typename Matrix>
|
||||
Transform convertMatrixToCycles(
|
||||
const typename std::enable_if<Matrix::numRows == 4 && Matrix::numColumns == 4, Matrix>::type
|
||||
&matrix)
|
||||
{
|
||||
return make_transform(matrix[0][0],
|
||||
matrix[1][0],
|
||||
matrix[2][0],
|
||||
matrix[3][0],
|
||||
matrix[0][1],
|
||||
matrix[1][1],
|
||||
matrix[2][1],
|
||||
matrix[3][1],
|
||||
matrix[0][2],
|
||||
matrix[1][2],
|
||||
matrix[2][2],
|
||||
matrix[3][2]);
|
||||
}
|
||||
|
||||
template<> Transform convertToCycles<Transform>(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<GfMatrix4f>()) {
|
||||
return convertMatrixToCycles<GfMatrix4f>(value.UncheckedGet<GfMatrix4f>());
|
||||
}
|
||||
if (value.IsHolding<GfMatrix3f>()) {
|
||||
return convertMatrixToCycles<GfMatrix3f>(value.UncheckedGet<GfMatrix3f>());
|
||||
}
|
||||
if (value.IsHolding<GfMatrix4d>()) {
|
||||
return convertMatrixToCycles<GfMatrix4d>(value.UncheckedGet<GfMatrix4d>());
|
||||
}
|
||||
if (value.IsHolding<GfMatrix3d>()) {
|
||||
return convertMatrixToCycles<GfMatrix3d>(value.UncheckedGet<GfMatrix3d>());
|
||||
}
|
||||
|
||||
if (value.CanCast<GfMatrix4f>()) {
|
||||
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4f>(value));
|
||||
}
|
||||
if (value.CanCast<GfMatrix3f>()) {
|
||||
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3f>(value));
|
||||
}
|
||||
if (value.CanCast<GfMatrix4d>()) {
|
||||
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4d>(value));
|
||||
}
|
||||
if (value.CanCast<GfMatrix3d>()) {
|
||||
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3d>(value));
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to Transform");
|
||||
return transform_identity();
|
||||
}
|
||||
|
||||
template<typename DstType, typename SrcType = DstType>
|
||||
array<DstType> convertToCyclesArray(const VtValue &value)
|
||||
{
|
||||
static_assert(sizeof(DstType) == sizeof(SrcType),
|
||||
"Size mismatch between VtArray and array base type");
|
||||
|
||||
using SrcArray = VtArray<SrcType>;
|
||||
|
||||
if (value.IsHolding<SrcArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<SrcArray>();
|
||||
array<DstType> cyclesArray;
|
||||
cyclesArray.resize(valueData.size());
|
||||
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
|
||||
return cyclesArray;
|
||||
}
|
||||
|
||||
if (value.CanCast<SrcArray>()) {
|
||||
VtValue castedValue = VtValue::Cast<SrcArray>(value);
|
||||
const auto &valueData = castedValue.UncheckedGet<SrcArray>();
|
||||
array<DstType> cyclesArray;
|
||||
cyclesArray.resize(valueData.size());
|
||||
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
|
||||
return cyclesArray;
|
||||
}
|
||||
|
||||
return array<DstType>();
|
||||
}
|
||||
|
||||
template<> array<float3> convertToCyclesArray<float3, GfVec3f>(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<VtVec3fArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<VtVec3fArray>();
|
||||
array<float3> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const GfVec3f &vec : valueData) {
|
||||
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
if (value.IsHolding<VtVec4fArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<VtVec4fArray>();
|
||||
array<float3> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const GfVec4f &vec : valueData) {
|
||||
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
|
||||
if (value.CanCast<VtVec3fArray>()) {
|
||||
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec3fArray>(value));
|
||||
}
|
||||
if (value.CanCast<VtVec4fArray>()) {
|
||||
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec4fArray>(value));
|
||||
}
|
||||
|
||||
return array<float3>();
|
||||
}
|
||||
|
||||
template<> array<ustring> convertToCyclesArray<ustring, void>(const VtValue &value)
|
||||
{
|
||||
using SdfPathArray = VtArray<SdfAssetPath>;
|
||||
|
||||
if (value.IsHolding<VtStringArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<VtStringArray>();
|
||||
array<ustring> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const auto &element : valueData) {
|
||||
cyclesArray.push_back_reserved(ustring(element));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
if (value.IsHolding<VtTokenArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<VtTokenArray>();
|
||||
array<ustring> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const auto &element : valueData) {
|
||||
cyclesArray.push_back_reserved(ustring(element.GetString()));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
if (value.IsHolding<SdfPathArray>()) {
|
||||
const auto &valueData = value.UncheckedGet<SdfPathArray>();
|
||||
array<ustring> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const auto &element : valueData) {
|
||||
cyclesArray.push_back_reserved(ustring(element.GetResolvedPath()));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
|
||||
if (value.CanCast<VtStringArray>()) {
|
||||
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtStringArray>(value));
|
||||
}
|
||||
if (value.CanCast<VtTokenArray>()) {
|
||||
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtTokenArray>(value));
|
||||
}
|
||||
if (value.CanCast<SdfPathArray>()) {
|
||||
return convertToCyclesArray<ustring, void>(VtValue::Cast<SdfPathArray>(value));
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to array<ustring>");
|
||||
return array<ustring>();
|
||||
}
|
||||
|
||||
template<typename MatrixArray> array<Transform> convertToCyclesTransformArray(const VtValue &value)
|
||||
{
|
||||
assert(value.IsHolding<MatrixArray>());
|
||||
|
||||
const auto &valueData = value.UncheckedGet<MatrixArray>();
|
||||
array<Transform> cyclesArray;
|
||||
cyclesArray.reserve(valueData.size());
|
||||
for (const auto &element : valueData) {
|
||||
cyclesArray.push_back_reserved(
|
||||
convertMatrixToCycles<typename MatrixArray::value_type>(element));
|
||||
}
|
||||
return cyclesArray;
|
||||
}
|
||||
|
||||
template<> array<Transform> convertToCyclesArray<Transform, void>(const VtValue &value)
|
||||
{
|
||||
if (value.IsHolding<VtMatrix4fArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix4fArray>(value);
|
||||
}
|
||||
if (value.IsHolding<VtMatrix3fArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix3fArray>(value);
|
||||
}
|
||||
if (value.IsHolding<VtMatrix4dArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix4dArray>(value);
|
||||
}
|
||||
if (value.IsHolding<VtMatrix3dArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix3dArray>(value);
|
||||
}
|
||||
|
||||
if (value.CanCast<VtMatrix4fArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix4fArray>(VtValue::Cast<VtMatrix4fArray>(value));
|
||||
}
|
||||
if (value.CanCast<VtMatrix3fArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix3fArray>(VtValue::Cast<VtMatrix3fArray>(value));
|
||||
}
|
||||
if (value.CanCast<VtMatrix4dArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix4dArray>(VtValue::Cast<VtMatrix4dArray>(value));
|
||||
}
|
||||
if (value.CanCast<VtMatrix3dArray>()) {
|
||||
return convertToCyclesTransformArray<VtMatrix3dArray>(VtValue::Cast<VtMatrix3dArray>(value));
|
||||
}
|
||||
|
||||
TF_WARN("Could not convert VtValue to array<Transform>");
|
||||
return array<Transform>();
|
||||
}
|
||||
|
||||
template<typename SrcType> VtValue convertFromCycles(const SrcType &value)
|
||||
{
|
||||
return VtValue(value);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCycles<float2>(const float2 &value)
|
||||
{
|
||||
const GfVec2f convertedValue(value.x, value.y);
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCycles<float3>(const float3 &value)
|
||||
{
|
||||
const GfVec3f convertedValue(value.x, value.y, value.z);
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCycles<ustring>(const ustring &value)
|
||||
{
|
||||
return VtValue(value.string());
|
||||
}
|
||||
|
||||
GfMatrix4f convertMatrixFromCycles(const Transform &matrix)
|
||||
{
|
||||
return GfMatrix4f(matrix[0][0],
|
||||
matrix[1][0],
|
||||
matrix[2][0],
|
||||
0.0f,
|
||||
matrix[0][1],
|
||||
matrix[1][1],
|
||||
matrix[2][1],
|
||||
0.0f,
|
||||
matrix[0][2],
|
||||
matrix[1][2],
|
||||
matrix[2][2],
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCycles<Transform>(const Transform &value)
|
||||
{
|
||||
return VtValue(convertMatrixFromCycles(value));
|
||||
}
|
||||
|
||||
template<typename SrcType, typename DstType = SrcType>
|
||||
VtValue convertFromCyclesArray(const array<SrcType> &value)
|
||||
{
|
||||
static_assert(sizeof(DstType) == sizeof(SrcType),
|
||||
"Size mismatch between VtArray and array base type");
|
||||
|
||||
VtArray<DstType> convertedValue;
|
||||
convertedValue.resize(value.size());
|
||||
std::memcpy(convertedValue.data(), value.data(), value.size() * sizeof(SrcType));
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
|
||||
{
|
||||
VtVec3fArray convertedValue;
|
||||
convertedValue.reserve(value.size());
|
||||
for (const auto &element : value) {
|
||||
convertedValue.push_back(GfVec3f(element.x, element.y, element.z));
|
||||
}
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCyclesArray<ustring, void>(const array<ustring> &value)
|
||||
{
|
||||
VtStringArray convertedValue;
|
||||
convertedValue.reserve(value.size());
|
||||
for (const auto &element : value) {
|
||||
convertedValue.push_back(element.string());
|
||||
}
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCyclesArray<Transform, void>(const array<Transform> &value)
|
||||
{
|
||||
VtMatrix4fArray convertedValue;
|
||||
convertedValue.reserve(value.size());
|
||||
for (const auto &element : value) {
|
||||
convertedValue.push_back(convertMatrixFromCycles(element));
|
||||
}
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
|
||||
{
|
||||
switch (socket.type) {
|
||||
default:
|
||||
case SocketType::UNDEFINED:
|
||||
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
|
||||
break;
|
||||
|
||||
case SocketType::BOOLEAN:
|
||||
node->set(socket, convertToCycles<bool>(value));
|
||||
break;
|
||||
case SocketType::FLOAT:
|
||||
node->set(socket, convertToCycles<float>(value));
|
||||
break;
|
||||
case SocketType::INT:
|
||||
node->set(socket, convertToCycles<int>(value));
|
||||
break;
|
||||
case SocketType::UINT:
|
||||
node->set(socket, convertToCycles<unsigned int>(value));
|
||||
break;
|
||||
case SocketType::COLOR:
|
||||
case SocketType::VECTOR:
|
||||
case SocketType::POINT:
|
||||
case SocketType::NORMAL:
|
||||
node->set(socket, convertToCycles<float3>(value));
|
||||
break;
|
||||
case SocketType::POINT2:
|
||||
node->set(socket, convertToCycles<float2>(value));
|
||||
break;
|
||||
case SocketType::CLOSURE:
|
||||
// Handled by node connections
|
||||
break;
|
||||
case SocketType::STRING:
|
||||
node->set(socket, convertToCycles<ustring>(value));
|
||||
break;
|
||||
case SocketType::ENUM:
|
||||
// Enum's can accept a string or an int
|
||||
if (value.IsHolding<TfToken>() || value.IsHolding<std::string>()) {
|
||||
node->set(socket, convertToCycles<ustring>(value));
|
||||
}
|
||||
else {
|
||||
node->set(socket, convertToCycles<int>(value));
|
||||
}
|
||||
break;
|
||||
case SocketType::TRANSFORM:
|
||||
node->set(socket, convertToCycles<Transform>(value));
|
||||
break;
|
||||
case SocketType::NODE:
|
||||
// TODO: renderIndex->GetRprim()->cycles_node ?
|
||||
TF_WARN("Unimplemented conversion: SocketType::NODE");
|
||||
break;
|
||||
|
||||
case SocketType::BOOLEAN_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<bool>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::FLOAT_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<float>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::INT_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<int>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::COLOR_ARRAY:
|
||||
case SocketType::VECTOR_ARRAY:
|
||||
case SocketType::POINT_ARRAY:
|
||||
case SocketType::NORMAL_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<float3, GfVec3f>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::POINT2_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<float2, GfVec2f>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::STRING_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<ustring, void>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::TRANSFORM_ARRAY: {
|
||||
auto cyclesArray = convertToCyclesArray<Transform, void>(value);
|
||||
node->set(socket, cyclesArray);
|
||||
break;
|
||||
}
|
||||
case SocketType::NODE_ARRAY: {
|
||||
// TODO: renderIndex->GetRprim()->cycles_node ?
|
||||
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VtValue GetNodeValue(const Node *node, const SocketType &socket)
|
||||
{
|
||||
switch (socket.type) {
|
||||
default:
|
||||
case SocketType::UNDEFINED:
|
||||
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
|
||||
return VtValue();
|
||||
|
||||
case SocketType::BOOLEAN:
|
||||
return convertFromCycles(node->get_bool(socket));
|
||||
case SocketType::FLOAT:
|
||||
return convertFromCycles(node->get_float(socket));
|
||||
case SocketType::INT:
|
||||
return convertFromCycles(node->get_int(socket));
|
||||
case SocketType::UINT:
|
||||
return convertFromCycles(node->get_uint(socket));
|
||||
case SocketType::COLOR:
|
||||
case SocketType::VECTOR:
|
||||
case SocketType::POINT:
|
||||
case SocketType::NORMAL:
|
||||
return convertFromCycles(node->get_float3(socket));
|
||||
case SocketType::POINT2:
|
||||
return convertFromCycles(node->get_float2(socket));
|
||||
case SocketType::CLOSURE:
|
||||
return VtValue();
|
||||
case SocketType::STRING:
|
||||
return convertFromCycles(node->get_string(socket));
|
||||
case SocketType::ENUM:
|
||||
return convertFromCycles(node->get_int(socket));
|
||||
case SocketType::TRANSFORM:
|
||||
return convertFromCycles(node->get_transform(socket));
|
||||
case SocketType::NODE:
|
||||
TF_WARN("Unimplemented conversion: SocketType::NODE");
|
||||
return VtValue();
|
||||
|
||||
case SocketType::BOOLEAN_ARRAY:
|
||||
return convertFromCyclesArray(node->get_bool_array(socket));
|
||||
case SocketType::FLOAT_ARRAY:
|
||||
return convertFromCyclesArray(node->get_float_array(socket));
|
||||
case SocketType::INT_ARRAY:
|
||||
return convertFromCyclesArray(node->get_int_array(socket));
|
||||
case SocketType::COLOR_ARRAY:
|
||||
case SocketType::VECTOR_ARRAY:
|
||||
case SocketType::POINT_ARRAY:
|
||||
case SocketType::NORMAL_ARRAY:
|
||||
return convertFromCyclesArray<float3, GfVec3f>(node->get_float3_array(socket));
|
||||
case SocketType::POINT2_ARRAY:
|
||||
return convertFromCyclesArray<float2, GfVec2f>(node->get_float2_array(socket));
|
||||
case SocketType::STRING_ARRAY:
|
||||
return convertFromCyclesArray<ustring, void>(node->get_string_array(socket));
|
||||
case SocketType::TRANSFORM_ARRAY:
|
||||
return convertFromCyclesArray<Transform, void>(node->get_transform_array(socket));
|
||||
case SocketType::NODE_ARRAY: {
|
||||
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
|
||||
return VtValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,18 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graph/node.h"
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/base/vt/value.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
void SetNodeValue(CCL_NS::Node *node, const CCL_NS::SocketType &socket, const VtValue &value);
|
||||
|
||||
VtValue GetNodeValue(const CCL_NS::Node *node, const CCL_NS::SocketType &socket);
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,78 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/output_driver.h"
|
||||
#include "hydra/render_buffer.h"
|
||||
#include "hydra/session.h"
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesOutputDriver::HdCyclesOutputDriver(HdCyclesSession *renderParam)
|
||||
: _renderParam(renderParam)
|
||||
{
|
||||
}
|
||||
|
||||
void HdCyclesOutputDriver::write_render_tile(const Tile &tile)
|
||||
{
|
||||
update_render_tile(tile);
|
||||
|
||||
// Update convergence state of all render buffers
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
|
||||
renderBuffer->SetConverged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HdCyclesOutputDriver::update_render_tile(const Tile &tile)
|
||||
{
|
||||
std::vector<float> pixels;
|
||||
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (aovBinding == _renderParam->GetDisplayAovBinding()) {
|
||||
continue; // Display AOV binding is already updated by Cycles display driver
|
||||
}
|
||||
|
||||
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
|
||||
const HdFormat format = renderBuffer->GetFormat();
|
||||
if (format == HdFormatInvalid) {
|
||||
continue; // Skip invalid AOV bindings
|
||||
}
|
||||
|
||||
const size_t channels = HdGetComponentCount(format);
|
||||
// Avoid extra copy by mapping render buffer directly when dimensions/format match the tile
|
||||
if (tile.offset.x == 0 && tile.offset.y == 0 && tile.size.x == renderBuffer->GetWidth() &&
|
||||
tile.size.y == renderBuffer->GetHeight() &&
|
||||
(format >= HdFormatFloat32 && format <= HdFormatFloat32Vec4)) {
|
||||
float *const data = static_cast<float *>(renderBuffer->Map());
|
||||
TF_VERIFY(tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, data));
|
||||
renderBuffer->Unmap();
|
||||
}
|
||||
else {
|
||||
pixels.resize(channels * tile.size.x * tile.size.y);
|
||||
if (tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, pixels.data())) {
|
||||
const bool isId = aovBinding.aovName == HdAovTokens->primId ||
|
||||
aovBinding.aovName == HdAovTokens->elementId ||
|
||||
aovBinding.aovName == HdAovTokens->instanceId;
|
||||
|
||||
renderBuffer->WritePixels(pixels.data(),
|
||||
GfVec2i(tile.offset.x, tile.offset.y),
|
||||
GfVec2i(tile.size.x, tile.size.y),
|
||||
channels,
|
||||
isId);
|
||||
}
|
||||
else {
|
||||
// Do not warn on missing elementId, which is a standard AOV but is not implememted
|
||||
if (aovBinding.aovName != HdAovTokens->elementId) {
|
||||
TF_RUNTIME_ERROR("Could not find pass for AOV '%s'", aovBinding.aovName.GetText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,23 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "session/output_driver.h"
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesOutputDriver final : public CCL_NS::OutputDriver {
|
||||
public:
|
||||
HdCyclesOutputDriver(HdCyclesSession *renderParam);
|
||||
|
||||
private:
|
||||
void write_render_tile(const Tile &tile) override;
|
||||
bool update_render_tile(const Tile &tile) override;
|
||||
|
||||
HdCyclesSession *const _renderParam;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"Includes": [ "*/resources/" ]
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/plugin.h"
|
||||
#include "hydra/render_delegate.h"
|
||||
#include "util/log.h"
|
||||
#include "util/path.h"
|
||||
|
||||
#include <pxr/base/arch/fileSystem.h>
|
||||
#include <pxr/base/plug/plugin.h>
|
||||
#include <pxr/base/plug/thisPlugin.h>
|
||||
#include <pxr/base/tf/envSetting.h>
|
||||
#include <pxr/imaging/hd/rendererPluginRegistry.h>
|
||||
|
||||
PXR_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
#ifdef WITH_CYCLES_LOGGING
|
||||
TF_DEFINE_ENV_SETTING(CYCLES_LOGGING, false, "Enable Cycles logging")
|
||||
TF_DEFINE_ENV_SETTING(CYCLES_LOGGING_SEVERITY, 1, "Cycles logging verbosity")
|
||||
#endif
|
||||
|
||||
HdCyclesPlugin::HdCyclesPlugin()
|
||||
{
|
||||
const PlugPluginPtr plugin = PLUG_THIS_PLUGIN;
|
||||
// Initialize Cycles paths relative to the plugin resource path
|
||||
std::string rootPath = PXR_NS::ArchAbsPath(plugin->GetResourcePath());
|
||||
CCL_NS::path_init(std::move(rootPath));
|
||||
|
||||
#ifdef WITH_CYCLES_LOGGING
|
||||
if (TfGetEnvSetting(CYCLES_LOGGING)) {
|
||||
CCL_NS::util_logging_start();
|
||||
CCL_NS::util_logging_verbosity_set(TfGetEnvSetting(CYCLES_LOGGING_SEVERITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HdCyclesPlugin::~HdCyclesPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
bool HdCyclesPlugin::IsSupported() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HdRenderDelegate *HdCyclesPlugin::CreateRenderDelegate()
|
||||
{
|
||||
return CreateRenderDelegate({});
|
||||
}
|
||||
|
||||
HdRenderDelegate *HdCyclesPlugin::CreateRenderDelegate(const HdRenderSettingsMap &settingsMap)
|
||||
{
|
||||
return new HD_CYCLES_NS::HdCyclesDelegate(settingsMap);
|
||||
}
|
||||
|
||||
void HdCyclesPlugin::DeleteRenderDelegate(HdRenderDelegate *renderDelegate)
|
||||
{
|
||||
delete renderDelegate;
|
||||
}
|
||||
|
||||
// USD's type system accounts for namespace, so we'd have to register our name as
|
||||
// HdCycles::HdCyclesPlugin in plugInfo.json, which isn't all that bad for JSON,
|
||||
// but those colons may cause issues for any USD specific tooling. So just put our
|
||||
// plugin class in the pxr namespace (which USD's type system will elide).
|
||||
TF_REGISTRY_FUNCTION(TfType)
|
||||
{
|
||||
HdRendererPluginRegistry::Define<PXR_NS::HdCyclesPlugin>();
|
||||
}
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
@@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include <pxr/imaging/hd/rendererPlugin.h>
|
||||
|
||||
PXR_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesPlugin final : public PXR_NS::HdRendererPlugin {
|
||||
public:
|
||||
HdCyclesPlugin();
|
||||
~HdCyclesPlugin() override;
|
||||
|
||||
bool IsSupported() const override;
|
||||
|
||||
PXR_NS::HdRenderDelegate *CreateRenderDelegate() override;
|
||||
PXR_NS::HdRenderDelegate *CreateRenderDelegate(const PXR_NS::HdRenderSettingsMap &) override;
|
||||
|
||||
void DeleteRenderDelegate(PXR_NS::HdRenderDelegate *) override;
|
||||
};
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
@@ -1,199 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/pointcloud.h"
|
||||
#include "hydra/geometry.inl"
|
||||
#include "scene/pointcloud.h"
|
||||
|
||||
#include <pxr/imaging/hd/extComputationUtils.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesPoints::HdCyclesPoints(const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
: HdCyclesGeometry(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesPoints::~HdCyclesPoints()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesPoints::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
|
||||
HdChangeTracker::DirtyPrimvar;
|
||||
return bits;
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesPoints::_PropagateDirtyBits(HdDirtyBits bits) const
|
||||
{
|
||||
// Points and widths always have to be updated together
|
||||
if (bits & (HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths)) {
|
||||
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths;
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
void HdCyclesPoints::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
|
||||
{
|
||||
if (dirtyBits & (HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths)) {
|
||||
const size_t numPoints = _geom->num_points();
|
||||
|
||||
PopulatePoints(sceneDelegate);
|
||||
PopulateWidths(sceneDelegate);
|
||||
|
||||
rebuild = _geom->num_points() != numPoints;
|
||||
|
||||
array<int> shaders;
|
||||
shaders.reserve(_geom->num_points());
|
||||
for (size_t i = 0; i < _geom->num_points(); ++i) {
|
||||
shaders.push_back_reserved(0);
|
||||
}
|
||||
|
||||
_geom->set_shader(shaders);
|
||||
}
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
|
||||
PopulatePrimvars(sceneDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesPoints::PopulatePoints(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
VtValue value;
|
||||
|
||||
for (const HdExtComputationPrimvarDescriptor &desc :
|
||||
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
|
||||
if (desc.name == HdTokens->points) {
|
||||
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
|
||||
const auto valueStoreIt = valueStore.find(desc.name);
|
||||
if (valueStoreIt != valueStore.end()) {
|
||||
value = std::move(valueStoreIt->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
value = GetPrimvar(sceneDelegate, HdTokens->points);
|
||||
}
|
||||
|
||||
if (!value.IsHolding<VtVec3fArray>()) {
|
||||
TF_WARN("Invalid points data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &points = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
array<float3> pointsDataCycles;
|
||||
pointsDataCycles.reserve(points.size());
|
||||
|
||||
for (const GfVec3f &point : points) {
|
||||
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
|
||||
}
|
||||
|
||||
_geom->set_points(pointsDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesPoints::PopulateWidths(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
|
||||
const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
|
||||
|
||||
if (!value.IsHolding<VtFloatArray>()) {
|
||||
TF_WARN("Invalid widths data for %s", GetId().GetText());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &widths = value.UncheckedGet<VtFloatArray>();
|
||||
|
||||
array<float> radiusDataCycles;
|
||||
radiusDataCycles.reserve(_geom->num_points());
|
||||
|
||||
if (interpolation == HdInterpolationConstant) {
|
||||
TF_VERIFY(widths.size() == 1);
|
||||
|
||||
const float constantRadius = widths[0] * 0.5f;
|
||||
|
||||
for (size_t i = 0; i < _geom->num_points(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(constantRadius);
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationVertex) {
|
||||
TF_VERIFY(widths.size() == _geom->num_points());
|
||||
|
||||
for (size_t i = 0; i < _geom->num_points(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
_geom->set_radius(radiusDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesPoints::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
|
||||
{
|
||||
Scene *const scene = (Scene *)_geom->get_owner();
|
||||
|
||||
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
|
||||
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_VERTEX),
|
||||
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
|
||||
};
|
||||
|
||||
for (const auto &interpolation : interpolations) {
|
||||
for (const HdPrimvarDescriptor &desc :
|
||||
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
|
||||
// Skip special primvars that are handled separately
|
||||
if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VtValue value = GetPrimvar(sceneDelegate, desc.name);
|
||||
if (value.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ustring name(desc.name.GetString());
|
||||
|
||||
AttributeStandard std = ATTR_STD_NONE;
|
||||
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
|
||||
std = ATTR_STD_UV;
|
||||
}
|
||||
else if (interpolation.first == HdInterpolationVertex) {
|
||||
if (desc.name == HdTokens->displayColor || desc.role == HdPrimvarRoleTokens->color) {
|
||||
std = ATTR_STD_VERTEX_COLOR;
|
||||
}
|
||||
else if (desc.name == HdTokens->normals) {
|
||||
std = ATTR_STD_VERTEX_NORMAL;
|
||||
}
|
||||
}
|
||||
else if (desc.name == HdTokens->displayColor &&
|
||||
interpolation.first == HdInterpolationConstant) {
|
||||
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
|
||||
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
|
||||
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
|
||||
}
|
||||
}
|
||||
|
||||
// Skip attributes that are not needed
|
||||
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
|
||||
_geom->need_attribute(scene, name)) {
|
||||
ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,40 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "hydra/geometry.h"
|
||||
|
||||
#include <pxr/imaging/hd/points.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesPoints final : public HdCyclesGeometry<PXR_NS::HdPoints, CCL_NS::PointCloud> {
|
||||
public:
|
||||
HdCyclesPoints(
|
||||
const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId = {}
|
||||
#endif
|
||||
);
|
||||
~HdCyclesPoints() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
private:
|
||||
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
|
||||
|
||||
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdDirtyBits dirtyBits,
|
||||
bool &rebuild) override;
|
||||
|
||||
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
void PopulateWidths(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
|
||||
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,276 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/render_buffer.h"
|
||||
#include "hydra/session.h"
|
||||
#include "util/half.h"
|
||||
|
||||
#include <pxr/base/gf/vec3i.h>
|
||||
#include <pxr/base/gf/vec4f.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesRenderBuffer::HdCyclesRenderBuffer(const SdfPath &bprimId) : HdRenderBuffer(bprimId)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesRenderBuffer::~HdCyclesRenderBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::Finalize(HdRenderParam *renderParam)
|
||||
{
|
||||
// Remove this render buffer from AOV bindings
|
||||
// This ensures that 'OutputDriver' does not attempt to write to it anymore
|
||||
static_cast<HdCyclesSession *>(renderParam)->RemoveAovBinding(this);
|
||||
|
||||
HdRenderBuffer::Finalize(renderParam);
|
||||
}
|
||||
|
||||
bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format, bool multiSampled)
|
||||
{
|
||||
if (dimensions[2] != 1) {
|
||||
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::Allocate called with dimensions that are not 2D.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t oldSize = _data.size();
|
||||
const size_t newSize = dimensions[0] * dimensions[1] * HdDataSizeOfFormat(format);
|
||||
if (oldSize == newSize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsMapped()) {
|
||||
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::Allocate called while buffer is mapped.");
|
||||
return false;
|
||||
}
|
||||
|
||||
_width = dimensions[0];
|
||||
_height = dimensions[1];
|
||||
_format = format;
|
||||
|
||||
_data.resize(newSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::_Deallocate()
|
||||
{
|
||||
_width = 0u;
|
||||
_height = 0u;
|
||||
_format = HdFormatInvalid;
|
||||
|
||||
_data.clear();
|
||||
_data.shrink_to_fit();
|
||||
|
||||
_resource = VtValue();
|
||||
}
|
||||
|
||||
void *HdCyclesRenderBuffer::Map()
|
||||
{
|
||||
// Mapping is not implemented when a resource is set
|
||||
if (!_resource.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
++_mapped;
|
||||
|
||||
return _data.data();
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::Unmap()
|
||||
{
|
||||
--_mapped;
|
||||
}
|
||||
|
||||
bool HdCyclesRenderBuffer::IsMapped() const
|
||||
{
|
||||
return _mapped != 0;
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::Resolve()
|
||||
{
|
||||
}
|
||||
|
||||
bool HdCyclesRenderBuffer::IsConverged() const
|
||||
{
|
||||
return _converged;
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::SetConverged(bool converged)
|
||||
{
|
||||
_converged = converged;
|
||||
}
|
||||
|
||||
VtValue HdCyclesRenderBuffer::GetResource(bool multiSampled) const
|
||||
{
|
||||
TF_UNUSED(multiSampled);
|
||||
|
||||
return _resource;
|
||||
}
|
||||
|
||||
void HdCyclesRenderBuffer::SetResource(const VtValue &resource)
|
||||
{
|
||||
_resource = resource;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SimpleConversion {
|
||||
static float convert(float value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
struct IdConversion {
|
||||
static int32_t convert(float value)
|
||||
{
|
||||
return static_cast<int32_t>(value) - 1;
|
||||
}
|
||||
};
|
||||
struct UInt8Conversion {
|
||||
static uint8_t convert(float value)
|
||||
{
|
||||
return static_cast<uint8_t>(value * 255.f);
|
||||
}
|
||||
};
|
||||
struct SInt8Conversion {
|
||||
static int8_t convert(float value)
|
||||
{
|
||||
return static_cast<int8_t>(value * 127.f);
|
||||
}
|
||||
};
|
||||
struct HalfConversion {
|
||||
static half convert(float value)
|
||||
{
|
||||
return float_to_half_image(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename SrcT, typename DstT, typename Convertor = SimpleConversion>
|
||||
void writePixels(const SrcT *srcPtr,
|
||||
const GfVec2i &srcSize,
|
||||
int srcChannelCount,
|
||||
DstT *dstPtr,
|
||||
const GfVec2i &dstSize,
|
||||
int dstChannelCount,
|
||||
const Convertor &convertor = {})
|
||||
{
|
||||
const auto writeSize = GfVec2i(GfMin(srcSize[0], dstSize[0]), GfMin(srcSize[1], dstSize[1]));
|
||||
const auto writeChannelCount = GfMin(srcChannelCount, dstChannelCount);
|
||||
|
||||
for (int y = 0; y < writeSize[1]; ++y) {
|
||||
for (int x = 0; x < writeSize[0]; ++x) {
|
||||
for (int c = 0; c < writeChannelCount; ++c) {
|
||||
dstPtr[x * dstChannelCount + c] = convertor.convert(srcPtr[x * srcChannelCount + c]);
|
||||
}
|
||||
}
|
||||
srcPtr += srcSize[0] * srcChannelCount;
|
||||
dstPtr += dstSize[0] * dstChannelCount;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void HdCyclesRenderBuffer::WritePixels(const float *srcPixels,
|
||||
const PXR_NS::GfVec2i &srcOffset,
|
||||
const GfVec2i &srcDims,
|
||||
int srcChannels,
|
||||
bool isId)
|
||||
{
|
||||
uint8_t *dstPixels = _data.data();
|
||||
|
||||
const size_t formatSize = HdDataSizeOfFormat(_format);
|
||||
dstPixels += srcOffset[1] * (formatSize * _width) + srcOffset[0] * formatSize;
|
||||
|
||||
switch (_format) {
|
||||
case HdFormatUNorm8:
|
||||
case HdFormatUNorm8Vec2:
|
||||
case HdFormatUNorm8Vec3:
|
||||
case HdFormatUNorm8Vec4:
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
dstPixels,
|
||||
GfVec2i(_width, _height),
|
||||
1 + (_format - HdFormatUNorm8),
|
||||
UInt8Conversion());
|
||||
break;
|
||||
|
||||
case HdFormatSNorm8:
|
||||
case HdFormatSNorm8Vec2:
|
||||
case HdFormatSNorm8Vec3:
|
||||
case HdFormatSNorm8Vec4:
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
dstPixels,
|
||||
GfVec2i(_width, _height),
|
||||
1 + (_format - HdFormatSNorm8),
|
||||
SInt8Conversion());
|
||||
break;
|
||||
|
||||
case HdFormatFloat16:
|
||||
case HdFormatFloat16Vec2:
|
||||
case HdFormatFloat16Vec3:
|
||||
case HdFormatFloat16Vec4:
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
reinterpret_cast<half *>(dstPixels),
|
||||
GfVec2i(_width, _height),
|
||||
1 + (_format - HdFormatFloat16),
|
||||
HalfConversion());
|
||||
break;
|
||||
|
||||
case HdFormatFloat32:
|
||||
case HdFormatFloat32Vec2:
|
||||
case HdFormatFloat32Vec3:
|
||||
case HdFormatFloat32Vec4:
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
reinterpret_cast<float *>(dstPixels),
|
||||
GfVec2i(_width, _height),
|
||||
1 + (_format - HdFormatFloat32));
|
||||
break;
|
||||
|
||||
case HdFormatInt32:
|
||||
// Special case for ID AOVs (see 'HdCyclesMesh::Sync')
|
||||
if (isId) {
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
reinterpret_cast<int *>(dstPixels),
|
||||
GfVec2i(_width, _height),
|
||||
1,
|
||||
IdConversion());
|
||||
}
|
||||
else {
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
reinterpret_cast<int *>(dstPixels),
|
||||
GfVec2i(_width, _height),
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case HdFormatInt32Vec2:
|
||||
case HdFormatInt32Vec3:
|
||||
case HdFormatInt32Vec4:
|
||||
writePixels(srcPixels,
|
||||
srcDims,
|
||||
srcChannels,
|
||||
reinterpret_cast<int *>(dstPixels),
|
||||
GfVec2i(_width, _height),
|
||||
1 + (_format - HdFormatInt32));
|
||||
break;
|
||||
|
||||
default:
|
||||
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::WritePixels called with unsupported format.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,85 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/renderBuffer.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
|
||||
public:
|
||||
HdCyclesRenderBuffer(const PXR_NS::SdfPath &bprimId);
|
||||
~HdCyclesRenderBuffer() override;
|
||||
|
||||
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
|
||||
|
||||
bool Allocate(const PXR_NS::GfVec3i &dimensions,
|
||||
PXR_NS::HdFormat format,
|
||||
bool multiSampled) override;
|
||||
|
||||
unsigned int GetWidth() const override
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
unsigned int GetHeight() const override
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
unsigned int GetDepth() const override
|
||||
{
|
||||
return 1u;
|
||||
}
|
||||
|
||||
PXR_NS::HdFormat GetFormat() const override
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
bool IsMultiSampled() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void *Map() override;
|
||||
|
||||
void Unmap() override;
|
||||
|
||||
bool IsMapped() const override;
|
||||
|
||||
void Resolve() override;
|
||||
|
||||
bool IsConverged() const override;
|
||||
|
||||
void SetConverged(bool converged);
|
||||
|
||||
PXR_NS::VtValue GetResource(bool multiSampled = false) const override;
|
||||
|
||||
void SetResource(const PXR_NS::VtValue &resource);
|
||||
|
||||
void WritePixels(const float *pixels,
|
||||
const PXR_NS::GfVec2i &offset,
|
||||
const PXR_NS::GfVec2i &dims,
|
||||
int channels,
|
||||
bool isId = false);
|
||||
|
||||
private:
|
||||
void _Deallocate() override;
|
||||
|
||||
unsigned int _width = 0u;
|
||||
unsigned int _height = 0u;
|
||||
PXR_NS::HdFormat _format = PXR_NS::HdFormatInvalid;
|
||||
|
||||
std::vector<uint8_t> _data;
|
||||
PXR_NS::VtValue _resource;
|
||||
|
||||
std::atomic_int _mapped = 0;
|
||||
std::atomic_bool _converged = false;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,523 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/render_delegate.h"
|
||||
#include "hydra/camera.h"
|
||||
#include "hydra/curves.h"
|
||||
#include "hydra/field.h"
|
||||
#include "hydra/instancer.h"
|
||||
#include "hydra/light.h"
|
||||
#include "hydra/material.h"
|
||||
#include "hydra/mesh.h"
|
||||
#include "hydra/node_util.h"
|
||||
#include "hydra/pointcloud.h"
|
||||
#include "hydra/render_buffer.h"
|
||||
#include "hydra/render_pass.h"
|
||||
#include "hydra/session.h"
|
||||
#include "hydra/volume.h"
|
||||
#include "scene/integrator.h"
|
||||
#include "scene/scene.h"
|
||||
#include "session/session.h"
|
||||
|
||||
#include <pxr/base/tf/getenv.h>
|
||||
#include <pxr/imaging/hd/extComputation.h>
|
||||
#include <pxr/imaging/hgi/tokens.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
(cycles)
|
||||
(openvdbAsset)
|
||||
);
|
||||
|
||||
TF_DEFINE_PRIVATE_TOKENS(HdCyclesRenderSettingsTokens,
|
||||
(stageMetersPerUnit)
|
||||
((device, "cycles:device"))
|
||||
((threads, "cycles:threads"))
|
||||
((timeLimit, "cycles:time_limit"))
|
||||
((samples, "cycles:samples"))
|
||||
((sampleOffset, "cycles:sample_offset"))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
namespace {
|
||||
|
||||
const TfTokenVector kSupportedRPrimTypes = {
|
||||
HdPrimTypeTokens->basisCurves,
|
||||
HdPrimTypeTokens->mesh,
|
||||
HdPrimTypeTokens->points,
|
||||
#ifdef WITH_OPENVDB
|
||||
HdPrimTypeTokens->volume,
|
||||
#endif
|
||||
};
|
||||
|
||||
const TfTokenVector kSupportedSPrimTypes = {
|
||||
HdPrimTypeTokens->camera,
|
||||
HdPrimTypeTokens->material,
|
||||
HdPrimTypeTokens->diskLight,
|
||||
HdPrimTypeTokens->distantLight,
|
||||
HdPrimTypeTokens->domeLight,
|
||||
HdPrimTypeTokens->rectLight,
|
||||
HdPrimTypeTokens->sphereLight,
|
||||
HdPrimTypeTokens->extComputation,
|
||||
};
|
||||
|
||||
const TfTokenVector kSupportedBPrimTypes = {
|
||||
HdPrimTypeTokens->renderBuffer,
|
||||
#ifdef WITH_OPENVDB
|
||||
_tokens->openvdbAsset,
|
||||
#endif
|
||||
};
|
||||
|
||||
SessionParams GetSessionParams(const HdRenderSettingsMap &settings)
|
||||
{
|
||||
SessionParams params;
|
||||
params.threads = 0;
|
||||
params.background = false;
|
||||
params.use_resolution_divider = false;
|
||||
|
||||
HdRenderSettingsMap::const_iterator it;
|
||||
|
||||
// Pull all setting that contribute to device creation first
|
||||
it = settings.find(HdCyclesRenderSettingsTokens->threads);
|
||||
if (it != settings.end()) {
|
||||
params.threads = VtValue::Cast<int>(it->second).GetWithDefault(params.threads);
|
||||
}
|
||||
|
||||
// Get the Cycles device from settings or environment, falling back to CPU
|
||||
std::string deviceType = Device::string_from_type(DEVICE_CPU);
|
||||
it = settings.find(HdCyclesRenderSettingsTokens->device);
|
||||
if (it != settings.end()) {
|
||||
deviceType = VtValue::Cast<std::string>(it->second).GetWithDefault(deviceType);
|
||||
}
|
||||
else {
|
||||
const std::string deviceTypeEnv = TfGetenv("CYCLES_DEVICE");
|
||||
if (!deviceTypeEnv.empty()) {
|
||||
deviceType = deviceTypeEnv;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to all uppercase for Device::type_from_string
|
||||
std::transform(deviceType.begin(), deviceType.end(), deviceType.begin(), ::toupper);
|
||||
|
||||
vector<DeviceInfo> devices = Device::available_devices(
|
||||
DEVICE_MASK(Device::type_from_string(deviceType.c_str())));
|
||||
if (devices.empty()) {
|
||||
devices = Device::available_devices(DEVICE_MASK_CPU);
|
||||
if (!devices.empty()) {
|
||||
params.device = devices.front();
|
||||
}
|
||||
}
|
||||
else {
|
||||
params.device = Device::get_multi_device(devices, params.threads, params.background);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
HdCyclesDelegate::HdCyclesDelegate(const HdRenderSettingsMap &settingsMap, Session *session_)
|
||||
: HdRenderDelegate()
|
||||
{
|
||||
_renderParam = session_ ? std::make_unique<HdCyclesSession>(session_) :
|
||||
std::make_unique<HdCyclesSession>(GetSessionParams(settingsMap));
|
||||
|
||||
// If the delegate owns the session, pull any remaining settings
|
||||
if (!session_) {
|
||||
for (const auto &setting : settingsMap) {
|
||||
// Skip over the settings known to be used for initialization only
|
||||
if (setting.first == HdCyclesRenderSettingsTokens->device ||
|
||||
setting.first == HdCyclesRenderSettingsTokens->threads) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SetRenderSetting(setting.first, setting.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HdCyclesDelegate::~HdCyclesDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::SetDrivers(const HdDriverVector &drivers)
|
||||
{
|
||||
for (HdDriver *hdDriver : drivers) {
|
||||
if (hdDriver->name == HgiTokens->renderDriver && hdDriver->driver.IsHolding<Hgi *>()) {
|
||||
_hgi = hdDriver->driver.UncheckedGet<Hgi *>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HdCyclesDelegate::IsDisplaySupported() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _hgi && _hgi->GetAPIName() == HgiTokens->OpenGL;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const TfTokenVector &HdCyclesDelegate::GetSupportedRprimTypes() const
|
||||
{
|
||||
return kSupportedRPrimTypes;
|
||||
}
|
||||
|
||||
const TfTokenVector &HdCyclesDelegate::GetSupportedSprimTypes() const
|
||||
{
|
||||
return kSupportedSPrimTypes;
|
||||
}
|
||||
|
||||
const TfTokenVector &HdCyclesDelegate::GetSupportedBprimTypes() const
|
||||
{
|
||||
return kSupportedBPrimTypes;
|
||||
}
|
||||
|
||||
HdRenderParam *HdCyclesDelegate::GetRenderParam() const
|
||||
{
|
||||
return _renderParam.get();
|
||||
}
|
||||
|
||||
HdResourceRegistrySharedPtr HdCyclesDelegate::GetResourceRegistry() const
|
||||
{
|
||||
return HdResourceRegistrySharedPtr();
|
||||
}
|
||||
|
||||
bool HdCyclesDelegate::IsPauseSupported() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HdCyclesDelegate::Pause()
|
||||
{
|
||||
_renderParam->session->set_pause(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HdCyclesDelegate::Resume()
|
||||
{
|
||||
_renderParam->session->set_pause(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
HdRenderPassSharedPtr HdCyclesDelegate::CreateRenderPass(HdRenderIndex *index,
|
||||
const HdRprimCollection &collection)
|
||||
{
|
||||
return HdRenderPassSharedPtr(new HdCyclesRenderPass(index, collection, _renderParam.get()));
|
||||
}
|
||||
|
||||
HdInstancer *HdCyclesDelegate::CreateInstancer(HdSceneDelegate *delegate,
|
||||
const SdfPath &instancerId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &parentId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return new HdCyclesInstancer(delegate,
|
||||
instancerId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
parentId
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::DestroyInstancer(HdInstancer *instancer)
|
||||
{
|
||||
delete instancer;
|
||||
}
|
||||
|
||||
HdRprim *HdCyclesDelegate::CreateRprim(const TfToken &typeId,
|
||||
const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (typeId == HdPrimTypeTokens->mesh) {
|
||||
return new HdCyclesMesh(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
);
|
||||
}
|
||||
if (typeId == HdPrimTypeTokens->basisCurves) {
|
||||
return new HdCyclesCurves(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
);
|
||||
}
|
||||
if (typeId == HdPrimTypeTokens->points) {
|
||||
return new HdCyclesPoints(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#ifdef WITH_OPENVDB
|
||||
if (typeId == HdPrimTypeTokens->volume) {
|
||||
return new HdCyclesVolume(rprimId
|
||||
# if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
# endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
TF_CODING_ERROR("Unknown Rprim type %s", typeId.GetText());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::DestroyRprim(HdRprim *rPrim)
|
||||
{
|
||||
delete rPrim;
|
||||
}
|
||||
|
||||
HdSprim *HdCyclesDelegate::CreateSprim(const TfToken &typeId, const SdfPath &sprimId)
|
||||
{
|
||||
if (typeId == HdPrimTypeTokens->camera) {
|
||||
return new HdCyclesCamera(sprimId);
|
||||
}
|
||||
if (typeId == HdPrimTypeTokens->material) {
|
||||
return new HdCyclesMaterial(sprimId);
|
||||
}
|
||||
if (typeId == HdPrimTypeTokens->diskLight || typeId == HdPrimTypeTokens->distantLight ||
|
||||
typeId == HdPrimTypeTokens->domeLight || typeId == HdPrimTypeTokens->rectLight ||
|
||||
typeId == HdPrimTypeTokens->sphereLight) {
|
||||
return new HdCyclesLight(sprimId, typeId);
|
||||
}
|
||||
if (typeId == HdPrimTypeTokens->extComputation) {
|
||||
return new HdExtComputation(sprimId);
|
||||
}
|
||||
|
||||
TF_CODING_ERROR("Unknown Sprim type %s", typeId.GetText());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HdSprim *HdCyclesDelegate::CreateFallbackSprim(const TfToken &typeId)
|
||||
{
|
||||
return CreateSprim(typeId, SdfPath::EmptyPath());
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::DestroySprim(HdSprim *sPrim)
|
||||
{
|
||||
delete sPrim;
|
||||
}
|
||||
|
||||
HdBprim *HdCyclesDelegate::CreateBprim(const TfToken &typeId, const SdfPath &bprimId)
|
||||
{
|
||||
if (typeId == HdPrimTypeTokens->renderBuffer) {
|
||||
return new HdCyclesRenderBuffer(bprimId);
|
||||
}
|
||||
#ifdef WITH_OPENVDB
|
||||
if (typeId == _tokens->openvdbAsset) {
|
||||
return new HdCyclesField(bprimId, typeId);
|
||||
}
|
||||
#endif
|
||||
|
||||
TF_RUNTIME_ERROR("Unknown Bprim type %s", typeId.GetText());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HdBprim *HdCyclesDelegate::CreateFallbackBprim(const TfToken &typeId)
|
||||
{
|
||||
return CreateBprim(typeId, SdfPath::EmptyPath());
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::DestroyBprim(HdBprim *bPrim)
|
||||
{
|
||||
delete bPrim;
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::CommitResources(HdChangeTracker *tracker)
|
||||
{
|
||||
TF_UNUSED(tracker);
|
||||
|
||||
const SceneLock lock(_renderParam.get());
|
||||
|
||||
_renderParam->UpdateScene();
|
||||
}
|
||||
|
||||
TfToken HdCyclesDelegate::GetMaterialBindingPurpose() const
|
||||
{
|
||||
return HdTokens->full;
|
||||
}
|
||||
|
||||
#if HD_API_VERSION < 41
|
||||
TfToken HdCyclesDelegate::GetMaterialNetworkSelector() const
|
||||
{
|
||||
return _tokens->cycles;
|
||||
}
|
||||
#else
|
||||
TfTokenVector HdCyclesDelegate::GetMaterialRenderContexts() const
|
||||
{
|
||||
return {_tokens->cycles};
|
||||
}
|
||||
#endif
|
||||
|
||||
VtDictionary HdCyclesDelegate::GetRenderStats() const
|
||||
{
|
||||
const Stats &stats = _renderParam->session->stats;
|
||||
const Progress &progress = _renderParam->session->progress;
|
||||
|
||||
double totalTime, renderTime;
|
||||
progress.get_time(totalTime, renderTime);
|
||||
double fractionDone = progress.get_progress();
|
||||
|
||||
std::string status, substatus;
|
||||
progress.get_status(status, substatus);
|
||||
if (!substatus.empty()) {
|
||||
status += " | " + substatus;
|
||||
}
|
||||
|
||||
return {{"rendererName", VtValue("Cycles")},
|
||||
{"rendererVersion", VtValue(GfVec3i(0, 0, 0))},
|
||||
{"percentDone", VtValue(floor_to_int(fractionDone * 100))},
|
||||
{"fractionDone", VtValue(fractionDone)},
|
||||
{"loadClockTime", VtValue(totalTime - renderTime)},
|
||||
{"peakMemory", VtValue(stats.mem_peak)},
|
||||
{"totalClockTime", VtValue(totalTime)},
|
||||
{"totalMemory", VtValue(stats.mem_used)},
|
||||
{"renderProgressAnnotation", VtValue(status)}};
|
||||
}
|
||||
|
||||
HdAovDescriptor HdCyclesDelegate::GetDefaultAovDescriptor(const TfToken &name) const
|
||||
{
|
||||
if (name == HdAovTokens->color) {
|
||||
HdFormat colorFormat = HdFormatFloat32Vec4;
|
||||
if (IsDisplaySupported()) {
|
||||
// Can use Cycles 'DisplayDriver' in OpenGL, but it only supports 'half4' format
|
||||
colorFormat = HdFormatFloat16Vec4;
|
||||
}
|
||||
|
||||
return HdAovDescriptor(colorFormat, false, VtValue(GfVec4f(0.0f)));
|
||||
}
|
||||
if (name == HdAovTokens->depth) {
|
||||
return HdAovDescriptor(HdFormatFloat32, false, VtValue(1.0f));
|
||||
}
|
||||
if (name == HdAovTokens->normal) {
|
||||
return HdAovDescriptor(HdFormatFloat32Vec3, false, VtValue(GfVec3f(0.0f)));
|
||||
}
|
||||
if (name == HdAovTokens->primId || name == HdAovTokens->instanceId ||
|
||||
name == HdAovTokens->elementId) {
|
||||
return HdAovDescriptor(HdFormatInt32, false, VtValue(-1));
|
||||
}
|
||||
|
||||
return HdAovDescriptor();
|
||||
}
|
||||
|
||||
HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() const
|
||||
{
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
|
||||
HdRenderSettingDescriptorList descriptors;
|
||||
|
||||
descriptors.push_back({
|
||||
"Time Limit",
|
||||
HdCyclesRenderSettingsTokens->timeLimit,
|
||||
VtValue(0.0),
|
||||
});
|
||||
descriptors.push_back({
|
||||
"Sample Count",
|
||||
HdCyclesRenderSettingsTokens->samples,
|
||||
VtValue(1024),
|
||||
});
|
||||
descriptors.push_back({
|
||||
"Sample Offset",
|
||||
HdCyclesRenderSettingsTokens->sampleOffset,
|
||||
VtValue(0),
|
||||
});
|
||||
|
||||
for (const SocketType &socket : scene->integrator->type->inputs) {
|
||||
descriptors.push_back({socket.ui_name.string(),
|
||||
TfToken("cycles:integrator:" + socket.name.string()),
|
||||
GetNodeValue(scene->integrator, socket)});
|
||||
}
|
||||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS::VtValue &value)
|
||||
{
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
_renderParam->SetStageMetersPerUnit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(_renderParam->GetStageMetersPerUnit()));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
session->set_time_limit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(session->params.time_limit));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->samples) {
|
||||
static const int max_samples = Integrator::MAX_SAMPLES;
|
||||
int samples = VtValue::Cast<int>(value).GetWithDefault(session->params.samples);
|
||||
samples = std::min(std::max(1, samples), max_samples);
|
||||
session->set_samples(samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
session->params.sample_offset = VtValue::Cast<int>(value).GetWithDefault(
|
||||
session->params.sample_offset);
|
||||
++_settingsVersion;
|
||||
}
|
||||
else {
|
||||
const std::string &keyString = key.GetString();
|
||||
if (keyString.rfind("cycles:integrator:", 0) == 0) {
|
||||
ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
|
||||
if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
|
||||
SetNodeValue(scene->integrator, *socket, value);
|
||||
++_settingsVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VtValue HdCyclesDelegate::GetRenderSetting(const TfToken &key) const
|
||||
{
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
return VtValue(_renderParam->GetStageMetersPerUnit());
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->device) {
|
||||
return VtValue(TfToken(Device::string_from_type(session->params.device.type)));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->threads) {
|
||||
return VtValue(session->params.threads);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
return VtValue(session->params.time_limit);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->samples) {
|
||||
return VtValue(session->params.samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
return VtValue(session->params.sample_offset);
|
||||
}
|
||||
else {
|
||||
const std::string &keyString = key.GetString();
|
||||
if (keyString.rfind("cycles:integrator:", 0) == 0) {
|
||||
ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
|
||||
if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
|
||||
return GetNodeValue(scene->integrator, *socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return VtValue();
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,98 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/renderDelegate.h>
|
||||
#include <pxr/imaging/hgi/hgi.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesDelegate final : public PXR_NS::HdRenderDelegate {
|
||||
public:
|
||||
HdCyclesDelegate(const PXR_NS::HdRenderSettingsMap &settingsMap,
|
||||
CCL_NS::Session *session_ = nullptr);
|
||||
~HdCyclesDelegate() override;
|
||||
|
||||
void SetDrivers(const PXR_NS::HdDriverVector &drivers) override;
|
||||
|
||||
bool IsDisplaySupported() const;
|
||||
|
||||
PXR_NS::Hgi *GetHgi() const
|
||||
{
|
||||
return _hgi;
|
||||
}
|
||||
|
||||
const PXR_NS::TfTokenVector &GetSupportedRprimTypes() const override;
|
||||
const PXR_NS::TfTokenVector &GetSupportedSprimTypes() const override;
|
||||
const PXR_NS::TfTokenVector &GetSupportedBprimTypes() const override;
|
||||
|
||||
PXR_NS::HdRenderParam *GetRenderParam() const override;
|
||||
|
||||
PXR_NS::HdResourceRegistrySharedPtr GetResourceRegistry() const override;
|
||||
|
||||
PXR_NS::HdRenderSettingDescriptorList GetRenderSettingDescriptors() const override;
|
||||
|
||||
bool IsPauseSupported() const override;
|
||||
|
||||
bool Pause() override;
|
||||
bool Resume() override;
|
||||
|
||||
PXR_NS::HdRenderPassSharedPtr CreateRenderPass(
|
||||
PXR_NS::HdRenderIndex *index, const PXR_NS::HdRprimCollection &collection) override;
|
||||
|
||||
PXR_NS::HdInstancer *CreateInstancer(PXR_NS::HdSceneDelegate *delegate,
|
||||
const PXR_NS::SdfPath &id
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId
|
||||
#endif
|
||||
) override;
|
||||
void DestroyInstancer(PXR_NS::HdInstancer *instancer) override;
|
||||
|
||||
PXR_NS::HdRprim *CreateRprim(const PXR_NS::TfToken &typeId,
|
||||
const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId
|
||||
#endif
|
||||
) override;
|
||||
void DestroyRprim(PXR_NS::HdRprim *rPrim) override;
|
||||
|
||||
PXR_NS::HdSprim *CreateSprim(const PXR_NS::TfToken &typeId,
|
||||
const PXR_NS::SdfPath &sprimId) override;
|
||||
PXR_NS::HdSprim *CreateFallbackSprim(const PXR_NS::TfToken &typeId) override;
|
||||
void DestroySprim(PXR_NS::HdSprim *sPrim) override;
|
||||
|
||||
PXR_NS::HdBprim *CreateBprim(const PXR_NS::TfToken &typeId,
|
||||
const PXR_NS::SdfPath &bprimId) override;
|
||||
PXR_NS::HdBprim *CreateFallbackBprim(const PXR_NS::TfToken &typeId) override;
|
||||
void DestroyBprim(PXR_NS::HdBprim *bPrim) override;
|
||||
|
||||
void CommitResources(PXR_NS::HdChangeTracker *tracker) override;
|
||||
|
||||
PXR_NS::TfToken GetMaterialBindingPurpose() const override;
|
||||
|
||||
#if HD_API_VERSION < 41
|
||||
PXR_NS::TfToken GetMaterialNetworkSelector() const override;
|
||||
#else
|
||||
PXR_NS::TfTokenVector GetMaterialRenderContexts() const override;
|
||||
#endif
|
||||
|
||||
PXR_NS::VtDictionary GetRenderStats() const override;
|
||||
|
||||
PXR_NS::HdAovDescriptor GetDefaultAovDescriptor(const PXR_NS::TfToken &name) const override;
|
||||
|
||||
void SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS::VtValue &value) override;
|
||||
|
||||
PXR_NS::VtValue GetRenderSetting(const PXR_NS::TfToken &key) const override;
|
||||
|
||||
private:
|
||||
PXR_NS::Hgi *_hgi = nullptr;
|
||||
std::unique_ptr<HdCyclesSession> _renderParam;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,176 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/render_pass.h"
|
||||
#include "hydra/camera.h"
|
||||
#include "hydra/display_driver.h"
|
||||
#include "hydra/output_driver.h"
|
||||
#include "hydra/render_buffer.h"
|
||||
#include "hydra/render_delegate.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/integrator.h"
|
||||
#include "scene/scene.h"
|
||||
#include "session/session.h"
|
||||
|
||||
#include <pxr/imaging/hd/renderPassState.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
HdCyclesRenderPass::HdCyclesRenderPass(HdRenderIndex *index,
|
||||
HdRprimCollection const &collection,
|
||||
HdCyclesSession *renderParam)
|
||||
: HdRenderPass(index, collection), _renderParam(renderParam)
|
||||
{
|
||||
Session *const session = _renderParam->session;
|
||||
// Reset cancel state so session thread can continue rendering
|
||||
session->progress.reset();
|
||||
|
||||
session->set_output_driver(make_unique<HdCyclesOutputDriver>(renderParam));
|
||||
|
||||
const auto renderDelegate = static_cast<const HdCyclesDelegate *>(
|
||||
GetRenderIndex()->GetRenderDelegate());
|
||||
if (renderDelegate->IsDisplaySupported()) {
|
||||
session->set_display_driver(
|
||||
make_unique<HdCyclesDisplayDriver>(renderParam, renderDelegate->GetHgi()));
|
||||
}
|
||||
}
|
||||
|
||||
HdCyclesRenderPass::~HdCyclesRenderPass()
|
||||
{
|
||||
Session *const session = _renderParam->session;
|
||||
session->cancel(true);
|
||||
}
|
||||
|
||||
bool HdCyclesRenderPass::IsConverged() const
|
||||
{
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (aovBinding.renderBuffer && !aovBinding.renderBuffer->IsConverged()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HdCyclesRenderPass::ResetConverged()
|
||||
{
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
|
||||
renderBuffer->SetConverged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesRenderPass::_Execute(const HdRenderPassStateSharedPtr &renderPassState,
|
||||
const TfTokenVector &renderTags)
|
||||
{
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (session->progress.get_cancel()) {
|
||||
return; // Something went wrong and cannot continue without recreating the session
|
||||
}
|
||||
|
||||
if (scene->mutex.try_lock()) {
|
||||
const auto renderDelegate = static_cast<HdCyclesDelegate *>(
|
||||
GetRenderIndex()->GetRenderDelegate());
|
||||
|
||||
const unsigned int settingsVersion = renderDelegate->GetRenderSettingsVersion();
|
||||
|
||||
// Update requested AOV bindings
|
||||
const HdRenderPassAovBindingVector &aovBindings = renderPassState->GetAovBindings();
|
||||
if (_renderParam->GetAovBindings() != aovBindings ||
|
||||
// Need to resync passes when denoising is enabled or disabled to update the pass mode
|
||||
(settingsVersion != _lastSettingsVersion &&
|
||||
scene->integrator->use_denoise_is_modified())) {
|
||||
_renderParam->SyncAovBindings(aovBindings);
|
||||
|
||||
if (renderDelegate->IsDisplaySupported()) {
|
||||
// Update display pass to the first requested color AOV
|
||||
HdRenderPassAovBinding displayAovBinding = !aovBindings.empty() ? aovBindings.front() :
|
||||
HdRenderPassAovBinding();
|
||||
if (displayAovBinding.aovName == HdAovTokens->color && displayAovBinding.renderBuffer) {
|
||||
_renderParam->SetDisplayAovBinding(displayAovBinding);
|
||||
}
|
||||
else {
|
||||
_renderParam->SetDisplayAovBinding(HdRenderPassAovBinding());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera dimensions to the viewport size
|
||||
#if PXR_VERSION >= 2102
|
||||
CameraUtilFraming framing = renderPassState->GetFraming();
|
||||
if (!framing.IsValid()) {
|
||||
const GfVec4f vp = renderPassState->GetViewport();
|
||||
framing = CameraUtilFraming(GfRect2i(GfVec2i(0), int(vp[2]), int(vp[3])));
|
||||
}
|
||||
|
||||
scene->camera->set_full_width(framing.dataWindow.GetWidth());
|
||||
scene->camera->set_full_height(framing.dataWindow.GetHeight());
|
||||
#else
|
||||
const GfVec4f vp = renderPassState->GetViewport();
|
||||
scene->camera->set_full_width(int(vp[2]));
|
||||
scene->camera->set_full_height(int(vp[3]));
|
||||
#endif
|
||||
|
||||
if (const auto camera = static_cast<const HdCyclesCamera *>(renderPassState->GetCamera())) {
|
||||
camera->ApplyCameraSettings(_renderParam, scene->camera);
|
||||
}
|
||||
else {
|
||||
HdCyclesCamera::ApplyCameraSettings(_renderParam,
|
||||
renderPassState->GetWorldToViewMatrix(),
|
||||
renderPassState->GetProjectionMatrix(),
|
||||
renderPassState->GetClipPlanes(),
|
||||
scene->camera);
|
||||
}
|
||||
|
||||
// Reset session if the session, scene, camera or AOV bindings changed
|
||||
if (scene->need_reset() || settingsVersion != _lastSettingsVersion) {
|
||||
_lastSettingsVersion = settingsVersion;
|
||||
|
||||
// Reset convergence state of all render buffers
|
||||
ResetConverged();
|
||||
|
||||
BufferParams buffer_params;
|
||||
#if PXR_VERSION >= 2102
|
||||
buffer_params.full_x = static_cast<int>(framing.displayWindow.GetMin()[0]);
|
||||
buffer_params.full_y = static_cast<int>(framing.displayWindow.GetMin()[1]);
|
||||
buffer_params.full_width = static_cast<int>(framing.displayWindow.GetSize()[0]);
|
||||
buffer_params.full_height = static_cast<int>(framing.displayWindow.GetSize()[1]);
|
||||
|
||||
buffer_params.window_x = framing.dataWindow.GetMinX() - buffer_params.full_x;
|
||||
buffer_params.window_y = framing.dataWindow.GetMinY() - buffer_params.full_y;
|
||||
buffer_params.window_width = framing.dataWindow.GetWidth();
|
||||
buffer_params.window_height = framing.dataWindow.GetHeight();
|
||||
|
||||
buffer_params.width = buffer_params.window_width;
|
||||
buffer_params.height = buffer_params.window_height;
|
||||
#else
|
||||
buffer_params.width = static_cast<int>(vp[2]);
|
||||
buffer_params.height = static_cast<int>(vp[3]);
|
||||
buffer_params.full_width = buffer_params.width;
|
||||
buffer_params.full_height = buffer_params.height;
|
||||
buffer_params.window_width = buffer_params.width;
|
||||
buffer_params.window_height = buffer_params.height;
|
||||
#endif
|
||||
|
||||
session->reset(session->params, buffer_params);
|
||||
}
|
||||
|
||||
scene->mutex.unlock();
|
||||
|
||||
// Start Cycles render thread if not already running
|
||||
session->start();
|
||||
}
|
||||
|
||||
session->draw();
|
||||
}
|
||||
|
||||
void HdCyclesRenderPass::_MarkCollectionDirty()
|
||||
{
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,34 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
|
||||
#include <pxr/imaging/hd/renderPass.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesRenderPass final : public PXR_NS::HdRenderPass {
|
||||
public:
|
||||
HdCyclesRenderPass(PXR_NS::HdRenderIndex *index,
|
||||
const PXR_NS::HdRprimCollection &collection,
|
||||
HdCyclesSession *renderParam);
|
||||
~HdCyclesRenderPass() override;
|
||||
|
||||
bool IsConverged() const override;
|
||||
|
||||
private:
|
||||
void ResetConverged();
|
||||
|
||||
void _Execute(const PXR_NS::HdRenderPassStateSharedPtr &renderPassState,
|
||||
const PXR_NS::TfTokenVector &renderTags) override;
|
||||
|
||||
void _MarkCollectionDirty() override;
|
||||
|
||||
HdCyclesSession *_renderParam;
|
||||
unsigned int _lastSettingsVersion = 0;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"Plugins": [
|
||||
{
|
||||
"Info": {
|
||||
"Types": {
|
||||
"HdCyclesPlugin": {
|
||||
"bases": [
|
||||
"HdRendererPlugin"
|
||||
],
|
||||
"displayName": "Cycles",
|
||||
"priority": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"LibraryPath": "@PLUG_INFO_LIBRARY_PATH@",
|
||||
"Name": "hdCycles",
|
||||
"ResourcePath": "@PLUG_INFO_RESOURCE_PATH@",
|
||||
"Root": "@PLUG_INFO_ROOT@",
|
||||
"Type": "library"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,170 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/session.h"
|
||||
#include "scene/shader.h"
|
||||
// Have to include shader.h before background.h so that 'set_shader' uses the correct 'set'
|
||||
// overload taking a 'Node *', rather than the one taking a 'bool'
|
||||
#include "scene/background.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/shader_graph.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "session/session.h"
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
namespace {
|
||||
|
||||
const std::unordered_map<TfToken, PassType, TfToken::HashFunctor> kAovToPass = {
|
||||
{HdAovTokens->color, PASS_COMBINED},
|
||||
{HdAovTokens->depth, PASS_DEPTH},
|
||||
{HdAovTokens->normal, PASS_NORMAL},
|
||||
{HdAovTokens->primId, PASS_OBJECT_ID},
|
||||
{HdAovTokens->instanceId, PASS_AOV_VALUE},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
SceneLock::SceneLock(const HdRenderParam *renderParam)
|
||||
: scene(static_cast<const HdCyclesSession *>(renderParam)->session->scene),
|
||||
sceneLock(scene->mutex)
|
||||
{
|
||||
}
|
||||
|
||||
SceneLock::~SceneLock()
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesSession::HdCyclesSession(Session *session_) : session(session_), _ownCyclesSession(false)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesSession::HdCyclesSession(const SessionParams ¶ms)
|
||||
: session(new Session(params, SceneParams())), _ownCyclesSession(true)
|
||||
{
|
||||
Scene *const scene = session->scene;
|
||||
|
||||
// Create background with ambient light
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
|
||||
bgNode->set_color(one_float3());
|
||||
graph->add(bgNode);
|
||||
|
||||
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
|
||||
|
||||
scene->default_background->set_graph(graph);
|
||||
scene->default_background->tag_update(scene);
|
||||
}
|
||||
|
||||
// Wire up object color in default surface material
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
ObjectInfoNode *objectNode = graph->create_node<ObjectInfoNode>();
|
||||
graph->add(objectNode);
|
||||
|
||||
DiffuseBsdfNode *diffuseNode = graph->create_node<DiffuseBsdfNode>();
|
||||
graph->add(diffuseNode);
|
||||
|
||||
graph->connect(objectNode->output("Color"), diffuseNode->input("Color"));
|
||||
graph->connect(diffuseNode->output("BSDF"), graph->output()->input("Surface"));
|
||||
|
||||
#if 1
|
||||
// Create the instanceId AOV output
|
||||
const ustring instanceId(HdAovTokens->instanceId.GetString());
|
||||
|
||||
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
|
||||
aovNode->set_name(instanceId);
|
||||
graph->add(aovNode);
|
||||
|
||||
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
|
||||
instanceIdNode->set_attribute(instanceId);
|
||||
graph->add(instanceIdNode);
|
||||
|
||||
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
|
||||
#endif
|
||||
|
||||
scene->default_surface->set_graph(graph);
|
||||
scene->default_surface->tag_update(scene);
|
||||
}
|
||||
}
|
||||
|
||||
HdCyclesSession::~HdCyclesSession()
|
||||
{
|
||||
if (_ownCyclesSession) {
|
||||
delete session;
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesSession::UpdateScene()
|
||||
{
|
||||
Scene *const scene = session->scene;
|
||||
|
||||
// Update background depending on presence of a background light
|
||||
if (scene->light_manager->need_update()) {
|
||||
Light *background_light = nullptr;
|
||||
for (Light *light : scene->lights) {
|
||||
if (light->get_light_type() == LIGHT_BACKGROUND) {
|
||||
background_light = light;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!background_light) {
|
||||
scene->background->set_shader(scene->default_background);
|
||||
scene->background->set_transparent(true);
|
||||
}
|
||||
else {
|
||||
scene->background->set_shader(background_light->get_shader());
|
||||
scene->background->set_transparent(false);
|
||||
}
|
||||
|
||||
scene->background->tag_update(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesSession::SyncAovBindings(const HdRenderPassAovBindingVector &aovBindings)
|
||||
{
|
||||
Scene *const scene = session->scene;
|
||||
|
||||
// Delete all existing passes
|
||||
scene->delete_nodes(set<Pass *>(scene->passes.begin(), scene->passes.end()));
|
||||
|
||||
// Update passes with requested AOV bindings
|
||||
_aovBindings = aovBindings;
|
||||
for (const HdRenderPassAovBinding &aovBinding : aovBindings) {
|
||||
const auto cyclesAov = kAovToPass.find(aovBinding.aovName);
|
||||
if (cyclesAov == kAovToPass.end()) {
|
||||
// TODO: Use PASS_AOV_COLOR and PASS_AOV_VALUE for these?
|
||||
TF_WARN("Unknown pass %s", aovBinding.aovName.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
const PassType type = cyclesAov->second;
|
||||
const PassMode mode = PassMode::DENOISED;
|
||||
|
||||
Pass *pass = scene->create_node<Pass>();
|
||||
pass->set_type(type);
|
||||
pass->set_mode(mode);
|
||||
pass->set_name(ustring(aovBinding.aovName.GetString()));
|
||||
}
|
||||
}
|
||||
|
||||
void HdCyclesSession::RemoveAovBinding(HdRenderBuffer *renderBuffer)
|
||||
{
|
||||
for (HdRenderPassAovBinding &aovBinding : _aovBindings) {
|
||||
if (renderBuffer == aovBinding.renderBuffer) {
|
||||
aovBinding.renderBuffer = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (renderBuffer == _displayAovBinding.renderBuffer) {
|
||||
_displayAovBinding.renderBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,70 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "util/thread.h"
|
||||
|
||||
#include <pxr/imaging/hd/renderDelegate.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
struct SceneLock {
|
||||
SceneLock(const PXR_NS::HdRenderParam *renderParam);
|
||||
~SceneLock();
|
||||
|
||||
CCL_NS::Scene *scene;
|
||||
|
||||
private:
|
||||
CCL_NS::thread_scoped_lock sceneLock;
|
||||
};
|
||||
|
||||
class HdCyclesSession final : public PXR_NS::HdRenderParam {
|
||||
public:
|
||||
HdCyclesSession(CCL_NS::Session *session_);
|
||||
HdCyclesSession(const CCL_NS::SessionParams ¶ms);
|
||||
~HdCyclesSession() override;
|
||||
|
||||
void UpdateScene();
|
||||
|
||||
double GetStageMetersPerUnit() const
|
||||
{
|
||||
return _stageMetersPerUnit;
|
||||
}
|
||||
|
||||
void SetStageMetersPerUnit(double stageMetersPerUnit)
|
||||
{
|
||||
_stageMetersPerUnit = stageMetersPerUnit;
|
||||
}
|
||||
|
||||
PXR_NS::HdRenderPassAovBinding GetDisplayAovBinding() const
|
||||
{
|
||||
return _displayAovBinding;
|
||||
}
|
||||
|
||||
void SetDisplayAovBinding(const PXR_NS::HdRenderPassAovBinding &aovBinding)
|
||||
{
|
||||
_displayAovBinding = aovBinding;
|
||||
}
|
||||
|
||||
const PXR_NS::HdRenderPassAovBindingVector &GetAovBindings() const
|
||||
{
|
||||
return _aovBindings;
|
||||
}
|
||||
|
||||
void SyncAovBindings(const PXR_NS::HdRenderPassAovBindingVector &aovBindings);
|
||||
|
||||
void RemoveAovBinding(PXR_NS::HdRenderBuffer *renderBuffer);
|
||||
|
||||
CCL_NS::Session *session;
|
||||
|
||||
private:
|
||||
const bool _ownCyclesSession;
|
||||
double _stageMetersPerUnit = 0.01;
|
||||
PXR_NS::HdRenderPassAovBindingVector _aovBindings;
|
||||
PXR_NS::HdRenderPassAovBinding _displayAovBinding;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,91 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/volume.h"
|
||||
#include "hydra/field.h"
|
||||
#include "hydra/geometry.inl"
|
||||
#include "scene/volume.h"
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
(openvdbAsset)
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
HdCyclesVolume::HdCyclesVolume(const SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const SdfPath &instancerId
|
||||
#endif
|
||||
)
|
||||
: HdCyclesGeometry(rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
instancerId
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
HdCyclesVolume::~HdCyclesVolume()
|
||||
{
|
||||
}
|
||||
|
||||
HdDirtyBits HdCyclesVolume::GetInitialDirtyBitsMask() const
|
||||
{
|
||||
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
|
||||
bits |= HdChangeTracker::DirtyVolumeField;
|
||||
return bits;
|
||||
}
|
||||
|
||||
void HdCyclesVolume::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
|
||||
{
|
||||
Scene *const scene = (Scene *)_geom->get_owner();
|
||||
|
||||
if (dirtyBits & HdChangeTracker::DirtyVolumeField) {
|
||||
for (const HdVolumeFieldDescriptor &field :
|
||||
sceneDelegate->GetVolumeFieldDescriptors(GetId())) {
|
||||
if (const auto openvdbAsset = static_cast<HdCyclesField *>(
|
||||
sceneDelegate->GetRenderIndex().GetBprim(_tokens->openvdbAsset, field.fieldId))) {
|
||||
const ustring name(field.fieldName.GetString());
|
||||
|
||||
AttributeStandard std = ATTR_STD_NONE;
|
||||
if (name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
|
||||
std = ATTR_STD_VOLUME_DENSITY;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
|
||||
std = ATTR_STD_VOLUME_COLOR;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
|
||||
std = ATTR_STD_VOLUME_FLAME;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
|
||||
std = ATTR_STD_VOLUME_HEAT;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
|
||||
std = ATTR_STD_VOLUME_TEMPERATURE;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
|
||||
std = ATTR_STD_VOLUME_VELOCITY;
|
||||
}
|
||||
|
||||
// Skip attributes that are not needed
|
||||
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
|
||||
_geom->need_attribute(scene, name)) {
|
||||
Attribute *const attr = (std != ATTR_STD_NONE) ?
|
||||
_geom->attributes.add(std) :
|
||||
_geom->attributes.add(
|
||||
name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
|
||||
attr->data_voxel() = openvdbAsset->GetImageHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rebuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -1,33 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 NVIDIA Corporation
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hydra/config.h"
|
||||
#include "hydra/geometry.h"
|
||||
|
||||
#include <pxr/imaging/hd/volume.h>
|
||||
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
class HdCyclesVolume final : public HdCyclesGeometry<PXR_NS::HdVolume, CCL_NS::Volume> {
|
||||
public:
|
||||
HdCyclesVolume(
|
||||
const PXR_NS::SdfPath &rprimId
|
||||
#if PXR_VERSION < 2102
|
||||
,
|
||||
const PXR_NS::SdfPath &instancerId = {}
|
||||
#endif
|
||||
);
|
||||
~HdCyclesVolume() override;
|
||||
|
||||
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
|
||||
|
||||
private:
|
||||
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
|
||||
PXR_NS::HdDirtyBits dirtyBits,
|
||||
bool &rebuild) override;
|
||||
};
|
||||
|
||||
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|
@@ -80,8 +80,7 @@ static bool is_single_supported_device(Device *device, DenoiserType type)
|
||||
|
||||
if (!device->info.multi_devices.empty()) {
|
||||
/* Some configurations will use multi_devices, but keep the type of an individual device.
|
||||
* This does simplify checks for homogeneous setups, but here we really need a single device.
|
||||
*/
|
||||
* This does simplify checks for homogenous setups, but here we really need a single device. */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -18,11 +18,7 @@ CCL_NAMESPACE_BEGIN
|
||||
*/
|
||||
|
||||
PassAccessor::PassAccessInfo::PassAccessInfo(const BufferPass &pass)
|
||||
: type(pass.type),
|
||||
mode(pass.mode),
|
||||
include_albedo(pass.include_albedo),
|
||||
is_lightgroup(!pass.lightgroup.empty()),
|
||||
offset(pass.offset)
|
||||
: type(pass.type), mode(pass.mode), include_albedo(pass.include_albedo), offset(pass.offset)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -131,8 +127,7 @@ bool PassAccessor::get_render_tile_pixels(const RenderBuffers *render_buffers,
|
||||
|
||||
const PassType type = pass_access_info_.type;
|
||||
const PassMode mode = pass_access_info_.mode;
|
||||
const PassInfo pass_info = Pass::get_info(
|
||||
type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
|
||||
const PassInfo pass_info = Pass::get_info(type, pass_access_info_.include_albedo);
|
||||
int num_written_components = pass_info.num_components;
|
||||
|
||||
if (pass_info.num_components == 1) {
|
||||
@@ -220,8 +215,8 @@ void PassAccessor::init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
|
||||
const Destination &destination) const
|
||||
{
|
||||
const PassMode mode = pass_access_info_.mode;
|
||||
const PassInfo &pass_info = Pass::get_info(
|
||||
pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
|
||||
const PassInfo &pass_info = Pass::get_info(pass_access_info_.type,
|
||||
pass_access_info_.include_albedo);
|
||||
|
||||
kfilm_convert->pass_offset = pass_access_info_.offset;
|
||||
kfilm_convert->pass_stride = buffer_params.pass_stride;
|
||||
@@ -284,8 +279,8 @@ bool PassAccessor::set_render_tile_pixels(RenderBuffers *render_buffers, const S
|
||||
return false;
|
||||
}
|
||||
|
||||
const PassInfo pass_info = Pass::get_info(
|
||||
pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
|
||||
const PassInfo pass_info = Pass::get_info(pass_access_info_.type,
|
||||
pass_access_info_.include_albedo);
|
||||
|
||||
const BufferParams &buffer_params = render_buffers->params;
|
||||
|
||||
|
@@ -28,7 +28,6 @@ class PassAccessor {
|
||||
PassType type = PASS_NONE;
|
||||
PassMode mode = PassMode::NOISY;
|
||||
bool include_albedo = false;
|
||||
bool is_lightgroup = false;
|
||||
int offset = -1;
|
||||
|
||||
/* For the shadow catcher matte pass: whether to approximate shadow catcher pass into its
|
||||
|
@@ -355,9 +355,6 @@ void PathTrace::path_trace(RenderWork &render_work)
|
||||
|
||||
const int num_works = path_trace_works_.size();
|
||||
|
||||
tbb::task_group_context *tbb_ctx = tbb::task::self().group();
|
||||
tbb_ctx->capture_fp_settings();
|
||||
|
||||
tbb::parallel_for(0, num_works, [&](int i) {
|
||||
const double work_start_time = time_dt();
|
||||
const int num_samples = render_work.path_trace.num_samples;
|
||||
@@ -469,7 +466,7 @@ void PathTrace::set_denoiser_params(const DenoiseParams ¶ms)
|
||||
denoiser_ = Denoiser::create(device_, params);
|
||||
|
||||
/* Only take into account the "immediate" cancel to have interactive rendering responding to
|
||||
* navigation as quickly as possible, but allow to run denoiser after user hit Escape key while
|
||||
* navigation as quickly as possible, but allow to run denoiser after user hit Esc button while
|
||||
* doing offline rendering. */
|
||||
denoiser_->is_cancelled_cb = [this]() { return render_cancel_.is_requested; };
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user