Mesh: Replace auto smooth with node group #108014

Merged
Hans Goudey merged 149 commits from HooglyBoogly/blender:refactor-mesh-corner-normals-lazy into main 2023-10-20 16:54:20 +02:00
371 changed files with 5016 additions and 2972 deletions
Showing only changes of commit d902497e04 - Show all commits

View File

@ -6,15 +6,24 @@
set(EMBREE_EXTRA_ARGS set(EMBREE_EXTRA_ARGS
-DEMBREE_ISPC_SUPPORT=OFF -DEMBREE_ISPC_SUPPORT=OFF
-DEMBREE_TUTORIALS=OFF -DEMBREE_TUTORIALS=OFF
-DEMBREE_STATIC_LIB=ON -DEMBREE_STATIC_LIB=OFF
-DEMBREE_RAY_MASK=ON -DEMBREE_RAY_MASK=ON
-DEMBREE_FILTER_FUNCTION=ON -DEMBREE_FILTER_FUNCTION=ON
-DEMBREE_BACKFACE_CULLING=OFF -DEMBREE_BACKFACE_CULLING=OFF
-DEMBREE_BACKFACE_CULLING_CURVES=ON
-DEMBREE_BACKFACE_CULLING_SPHERES=ON
-DEMBREE_TASKING_SYSTEM=TBB -DEMBREE_TASKING_SYSTEM=TBB
-DEMBREE_TBB_ROOT=${LIBDIR}/tbb -DEMBREE_TBB_ROOT=${LIBDIR}/tbb
-DTBB_ROOT=${LIBDIR}/tbb -DTBB_ROOT=${LIBDIR}/tbb
) )
if(WIN32)
set(EMBREE_EXTRA_ARGS
${EMBREE_EXTRA_ARGS}
-DCMAKE_DEBUG_POSTFIX=_d
)
endif()
if(NOT BLENDER_PLATFORM_ARM) if(NOT BLENDER_PLATFORM_ARM)
set(EMBREE_EXTRA_ARGS set(EMBREE_EXTRA_ARGS
${EMBREE_EXTRA_ARGS} ${EMBREE_EXTRA_ARGS}
@ -45,25 +54,19 @@ add_dependencies(
) )
if(WIN32) if(WIN32)
if(BUILD_MODE STREQUAL Release) if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_embree after_install ExternalProject_Add_Step(external_embree after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree ${HARVEST_TARGET}/embree COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/include ${HARVEST_TARGET}/embree/include
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/lib ${HARVEST_TARGET}/embree/lib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/share ${HARVEST_TARGET}/embree/share
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/bin/embree4.dll ${HARVEST_TARGET}/embree/bin/embree4.dll
DEPENDEES install DEPENDEES install
) )
else() else()
ExternalProject_Add_Step(external_embree after_install ExternalProject_Add_Step(external_embree after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree3.lib ${HARVEST_TARGET}/embree/lib/embree3_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/bin/embree4_d.dll ${HARVEST_TARGET}/embree/bin/embree4_d.dll
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_avx.lib ${HARVEST_TARGET}/embree/lib/embree_avx_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree4_d.lib ${HARVEST_TARGET}/embree/lib/embree4_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_avx2.lib ${HARVEST_TARGET}/embree/lib/embree_avx2_d.lib DEPENDEES install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_sse42.lib ${HARVEST_TARGET}/embree/lib/embree_sse42_d.lib )
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/lexers.lib ${HARVEST_TARGET}/embree/lib/lexers_d.lib endif()
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/math.lib ${HARVEST_TARGET}/embree/lib/math_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/simd.lib ${HARVEST_TARGET}/embree/lib/simd_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/sys.lib ${HARVEST_TARGET}/embree/lib/sys_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/tasking.lib ${HARVEST_TARGET}/embree/lib/tasking_d.lib
DEPENDEES install
)
endif()
endif() endif()

View File

@ -218,6 +218,7 @@ else()
harvest(openimagedenoise/lib openimagedenoise/lib "*.a") harvest(openimagedenoise/lib openimagedenoise/lib "*.a")
harvest(embree/include embree/include "*.h") harvest(embree/include embree/include "*.h")
harvest(embree/lib embree/lib "*.a") harvest(embree/lib embree/lib "*.a")
harvest(embree/lib embree/lib "*${SHAREDLIBEXT}*")
harvest(openpgl/include openpgl/include "*.h") harvest(openpgl/include openpgl/include "*.h")
harvest(openpgl/lib openpgl/lib "*.a") harvest(openpgl/lib openpgl/lib "*.a")
harvest(openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION} openpgl/lib/cmake/openpgl "*.cmake") harvest(openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION} openpgl/lib/cmake/openpgl "*.cmake")

View File

@ -478,9 +478,9 @@ set(SQLITE_HASH_TYPE SHA1)
set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz) set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*") set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
set(EMBREE_VERSION 3.13.4) set(EMBREE_VERSION 4.0.1)
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip) set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
set(EMBREE_HASH 52d0be294d6c88ba7a6c9e046796e7be) set(EMBREE_HASH dd26617719a587e126b341d1b32f7fd0)
set(EMBREE_HASH_TYPE MD5) set(EMBREE_HASH_TYPE MD5)
set(EMBREE_FILE embree-v${EMBREE_VERSION}.zip) set(EMBREE_FILE embree-v${EMBREE_VERSION}.zip)
@ -534,10 +534,10 @@ set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/
set(WL_PROTOCOLS_HASH a28ff59a56e2ebb746048b6ef8d931d6) set(WL_PROTOCOLS_HASH a28ff59a56e2ebb746048b6ef8d931d6)
set(WL_PROTOCOLS_HASH_TYPE MD5) set(WL_PROTOCOLS_HASH_TYPE MD5)
set(WAYLAND_VERSION 1.21.0) set(WAYLAND_VERSION 1.22.0)
set(WAYLAND_FILE wayland-${WAYLAND_VERSION}.tar.xz) set(WAYLAND_FILE wayland-${WAYLAND_VERSION}.tar.xz)
set(WAYLAND_URI https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.21.0/downloads/wayland-${WAYLAND_VERSION}.tar.xz) set(WAYLAND_URI https://gitlab.freedesktop.org/wayland/wayland/-/releases/${WAYLAND_VERSION}/downloads/wayland-${WAYLAND_VERSION}.tar.xz)
set(WAYLAND_HASH f2653a2293bcd882d756c6a83d278903) set(WAYLAND_HASH 7410ab549e3928fce9381455b17b0803)
set(WAYLAND_HASH_TYPE MD5) set(WAYLAND_HASH_TYPE MD5)
set(WAYLAND_LIBDECOR_VERSION 0.1.0) set(WAYLAND_LIBDECOR_VERSION 0.1.0)

View File

@ -1,19 +1,8 @@
diff -Naur org/kernels/rtcore_config.h.in embree-3.13.4/kernels/rtcore_config.h.in
--- org/kernels/rtcore_config.h.in 2022-06-14 22:13:52 -0600
+++ embree-3.13.4/kernels/rtcore_config.h.in 2022-06-24 15:20:12 -0600
@@ -14,6 +14,7 @@
#cmakedefine01 EMBREE_MIN_WIDTH
#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
+#cmakedefine EMBREE_STATIC_LIB
#cmakedefine EMBREE_API_NAMESPACE
#if defined(EMBREE_API_NAMESPACE)
diff --git a/kernels/CMakeLists.txt b/kernels/CMakeLists.txt diff --git a/kernels/CMakeLists.txt b/kernels/CMakeLists.txt
index 7c2f43d..106b1d5 100644 index 7c2f43d..106b1d5 100644
--- a/kernels/CMakeLists.txt --- a/kernels/CMakeLists.txt
+++ b/kernels/CMakeLists.txt +++ b/kernels/CMakeLists.txt
@@ -201,6 +201,12 @@ embree_files(EMBREE_LIBRARY_FILES_AVX512 ${AVX512}) @@ -208,6 +208,12 @@ embree_files(EMBREE_LIBRARY_FILES_AVX512 ${AVX512})
#message("AVX2: ${EMBREE_LIBRARY_FILES_AVX2}") #message("AVX2: ${EMBREE_LIBRARY_FILES_AVX2}")
#message("AVX512: ${EMBREE_LIBRARY_FILES_AVX512}") #message("AVX512: ${EMBREE_LIBRARY_FILES_AVX512}")
@ -26,7 +15,7 @@ index 7c2f43d..106b1d5 100644
# replaces all .cpp files with a dummy file that includes that .cpp file # replaces all .cpp files with a dummy file that includes that .cpp file
# this is to work around an ICC name mangling issue related to lambda functions under windows # this is to work around an ICC name mangling issue related to lambda functions under windows
MACRO (CreateISADummyFiles list isa) MACRO (CreateISADummyFiles list isa)
@@ -277,7 +283,7 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) @@ -311,7 +317,7 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX)
ENDIF() ENDIF()
ENDIF() ENDIF()
@ -35,3 +24,128 @@ index 7c2f43d..106b1d5 100644
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2}) DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2})
ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2})
TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking) TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking)
diff --git a/include/embree4/rtcore_device.h b/include/embree4/rtcore_device.h
index 45bf95583..62ee7787d 100644
--- a/include/embree4/rtcore_device.h
+++ b/include/embree4/rtcore_device.h
@@ -55,6 +55,7 @@ enum RTCDeviceProperty
RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66,
RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED = 67,
RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED = 68,
+ RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED = 69,
RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED = 96,
RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED = 97,
diff --git a/kernels/common/device.cpp b/kernels/common/device.cpp
index 3ffac7e37..215ccc961 100644
--- a/kernels/common/device.cpp
+++ b/kernels/common/device.cpp
@@ -170,6 +170,9 @@ namespace embree
#if defined (EMBREE_BACKFACE_CULLING_CURVES)
v += "backfacecullingcurves ";
#endif
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
+ v += "backfacecullingspheres ";
+#endif
#if defined(EMBREE_FILTER_FUNCTION)
v += "intersection_filter ";
#endif
@@ -477,6 +480,12 @@ namespace embree
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
#endif
+#if defined(EMBREE_BACKFACE_CULLING_SPHERES)
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 1;
+#else
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 0;
+#endif
+
#if defined(EMBREE_COMPACT_POLYS)
case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
#else
diff --git a/kernels/config.h.in b/kernels/config.h.in
index f02c90360..ba9acde56 100644
--- a/kernels/config.h.in
+++ b/kernels/config.h.in
@@ -5,6 +5,7 @@
#cmakedefine EMBREE_STAT_COUNTERS
#cmakedefine EMBREE_BACKFACE_CULLING
#cmakedefine EMBREE_BACKFACE_CULLING_CURVES
+#cmakedefine EMBREE_BACKFACE_CULLING_SPHERES
#cmakedefine EMBREE_FILTER_FUNCTION
#cmakedefine EMBREE_IGNORE_INVALID_RAYS
#cmakedefine EMBREE_GEOMETRY_TRIANGLE
diff --git a/kernels/geometry/sphere_intersector.h b/kernels/geometry/sphere_intersector.h
index 074f910a2..30f490818 100644
--- a/kernels/geometry/sphere_intersector.h
+++ b/kernels/geometry/sphere_intersector.h
@@ -106,8 +106,13 @@ namespace embree
const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
+ /* check if there is a first hit */
+ const vbool<M> valid_first = valid_front;
+#else
/* check if there is a first hit */
const vbool<M> valid_first = valid_front | valid_back;
+#endif
if (unlikely(none(valid_first)))
return false;
@@ -120,7 +125,8 @@ namespace embree
/* invoke intersection filter for first hit */
const bool is_hit_first = epilog(valid_first, hit);
-
+
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
/* check for possible second hits before potentially accepted hit */
const vfloat<M> t_second = t_back;
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
@@ -131,7 +137,9 @@ namespace embree
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
const bool is_hit_second = epilog(valid_second, hit);
-
+#else
+ constexpr bool is_hit_second = false;
+#endif
return is_hit_first | is_hit_second;
}
@@ -186,8 +194,13 @@ namespace embree
const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
+ /* check if there is a first hit */
+ const vbool<M> valid_first = valid_front;
+#else
/* check if there is a first hit */
const vbool<M> valid_first = valid_front | valid_back;
+#endif
if (unlikely(none(valid_first)))
return false;
@@ -200,7 +213,8 @@ namespace embree
/* invoke intersection filter for first hit */
const bool is_hit_first = epilog(valid_first, hit);
-
+
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
/* check for possible second hits before potentially accepted hit */
const vfloat<M> t_second = t_back;
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
@@ -211,7 +225,9 @@ namespace embree
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
const bool is_hit_second = epilog(valid_second, hit);
-
+#else
+ constexpr bool is_hit_second = false;
+#endif
return is_hit_first | is_hit_second;
}
};

View File

@ -23,6 +23,7 @@ SET(_embree_SEARCH_DIRS
FIND_PATH(EMBREE_INCLUDE_DIR FIND_PATH(EMBREE_INCLUDE_DIR
NAMES NAMES
embree4/rtcore.h
embree3/rtcore.h embree3/rtcore.h
HINTS HINTS
${_embree_SEARCH_DIRS} ${_embree_SEARCH_DIRS}
@ -30,28 +31,67 @@ FIND_PATH(EMBREE_INCLUDE_DIR
include include
) )
IF(NOT (("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") OR (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")))) IF(EXISTS ${EMBREE_INCLUDE_DIR}/embree4/rtcore_config.h)
SET(_embree_SIMD_COMPONENTS SET(EMBREE_MAJOR_VERSION 4)
embree_sse42 ELSE()
embree_avx SET(EMBREE_MAJOR_VERSION 3)
embree_avx2
)
ENDIF() ENDIF()
SET(_embree_FIND_COMPONENTS IF(EMBREE_INCLUDE_DIR)
embree3 FILE(READ ${EMBREE_INCLUDE_DIR}/embree${EMBREE_MAJOR_VERSION}/rtcore_config.h _embree_config_header)
${_embree_SIMD_COMPONENTS} IF(_embree_config_header MATCHES "#define EMBREE_STATIC_LIB")
lexers SET(EMBREE_STATIC_LIB TRUE)
math ELSE()
simd SET(EMBREE_STATIC_LIB FALSE)
sys ENDIF()
tasking IF(_embree_config_header MATCHES "#define EMBREE_SYCL_SUPPORT")
) SET(EMBREE_SYCL_SUPPORT TRUE)
ELSE()
SET(EMBREE_SYCL_SUPPORT FALSE)
ENDIF()
UNSET(_embree_config_header)
ENDIF()
IF(EMBREE_STATIC_LIB)
IF(NOT (("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") OR (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))))
SET(_embree_SIMD_COMPONENTS
embree_sse42
embree_avx
embree_avx2
)
ENDIF()
IF(EMBREE_SYCL_SUPPORT)
SET(_embree_GPU_COMPONENTS
embree4_sycl
embree_rthwif
)
ENDIF()
SET(_embree_FIND_COMPONENTS
embree${EMBREE_MAJOR_VERSION}
${_embree_SIMD_COMPONENTS}
${_embree_GPU_COMPONENTS}
lexers
math
simd
sys
tasking
)
ELSE()
SET(_embree_FIND_COMPONENTS
embree${EMBREE_MAJOR_VERSION}
)
IF(EMBREE_SYCL_SUPPORT)
LIST(APPEND _embree_FIND_COMPONENTS
embree4_sycl
)
ENDIF()
ENDIF()
SET(_embree_LIBRARIES) SET(_embree_LIBRARIES)
FOREACH(COMPONENT ${_embree_FIND_COMPONENTS}) FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
FIND_LIBRARY(EMBREE_${UPPERCOMPONENT}_LIBRARY FIND_LIBRARY(EMBREE_${UPPERCOMPONENT}_LIBRARY
NAMES NAMES
${COMPONENT} ${COMPONENT}
@ -60,18 +100,9 @@ FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})
PATH_SUFFIXES PATH_SUFFIXES
lib64 lib lib64 lib
) )
IF(NOT EMBREE_${UPPERCOMPONENT}_LIBRARY)
IF(EMBREE_EMBREE3_LIBRARY)
# If we can't find all the static libraries, try to fall back to the shared library if found.
# This allows building with a shared embree library
SET(_embree_LIBRARIES ${EMBREE_EMBREE3_LIBRARY})
BREAK()
ENDIF()
ENDIF()
LIST(APPEND _embree_LIBRARIES "${EMBREE_${UPPERCOMPONENT}_LIBRARY}") LIST(APPEND _embree_LIBRARIES "${EMBREE_${UPPERCOMPONENT}_LIBRARY}")
ENDFOREACH() ENDFOREACH()
# handle the QUIETLY and REQUIRED arguments and set EMBREE_FOUND to TRUE if # handle the QUIETLY and REQUIRED arguments and set EMBREE_FOUND to TRUE if
# all listed variables are TRUE # all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
@ -85,6 +116,9 @@ ENDIF()
MARK_AS_ADVANCED( MARK_AS_ADVANCED(
EMBREE_INCLUDE_DIR EMBREE_INCLUDE_DIR
EMBREE_MAJOR_VERSION
EMBREE_SYCL_SUPPORT
EMBREE_STATIC_LIB
) )
FOREACH(COMPONENT ${_embree_FIND_COMPONENTS}) FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})

View File

@ -108,6 +108,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL
IF(SYCL_FOUND) IF(SYCL_FOUND)
SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl) SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl)
SET(SYCL_LIBRARIES ${SYCL_LIBRARY})
ELSE() ELSE()
SET(SYCL_SYCL_FOUND FALSE) SET(SYCL_SYCL_FOUND FALSE)
ENDIF() ENDIF()

View File

@ -330,6 +330,7 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
endforeach() endforeach()
set(EMBREE_LIBRARIES ${_embree_libraries_force_load}) set(EMBREE_LIBRARIES ${_embree_libraries_force_load})
endif() endif()
add_bundled_libraries(embree/lib)
if(WITH_OPENIMAGEDENOISE) if(WITH_OPENIMAGEDENOISE)
find_package(OpenImageDenoise REQUIRED) find_package(OpenImageDenoise REQUIRED)

View File

@ -317,7 +317,7 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
endif() endif()
endif() endif()
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)))
set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation") set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation")
if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR) if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR)
set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO}) set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO})
@ -453,6 +453,7 @@ add_bundled_libraries(opencolorio/lib)
if(WITH_CYCLES AND WITH_CYCLES_EMBREE) if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
find_package(Embree 3.8.0 REQUIRED) find_package(Embree 3.8.0 REQUIRED)
endif() endif()
add_bundled_libraries(embree/lib)
if(WITH_OPENIMAGEDENOISE) if(WITH_OPENIMAGEDENOISE)
find_package_wrapper(OpenImageDenoise) find_package_wrapper(OpenImageDenoise)

View File

@ -850,27 +850,75 @@ endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE) if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
windows_find_package(Embree) windows_find_package(Embree)
if(NOT Embree_FOUND) if(NOT Embree_FOUND)
set(EMBREE_ROOT_DIR ${LIBDIR}/embree)
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include) set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
set(EMBREE_LIBRARIES
optimized ${LIBDIR}/embree/lib/embree3.lib
optimized ${LIBDIR}/embree/lib/embree_avx2.lib
optimized ${LIBDIR}/embree/lib/embree_avx.lib
optimized ${LIBDIR}/embree/lib/embree_sse42.lib
optimized ${LIBDIR}/embree/lib/lexers.lib
optimized ${LIBDIR}/embree/lib/math.lib
optimized ${LIBDIR}/embree/lib/simd.lib
optimized ${LIBDIR}/embree/lib/sys.lib
optimized ${LIBDIR}/embree/lib/tasking.lib
debug ${LIBDIR}/embree/lib/embree3_d.lib if(EXISTS ${LIBDIR}/embree/include/embree4/rtcore_config.h)
debug ${LIBDIR}/embree/lib/embree_avx2_d.lib set(EMBREE_MAJOR_VERSION 4)
debug ${LIBDIR}/embree/lib/embree_avx_d.lib else()
debug ${LIBDIR}/embree/lib/embree_sse42_d.lib set(EMBREE_MAJOR_VERSION 3)
debug ${LIBDIR}/embree/lib/lexers_d.lib endif()
debug ${LIBDIR}/embree/lib/math_d.lib
debug ${LIBDIR}/embree/lib/simd_d.lib file(READ ${LIBDIR}/embree/include/embree${EMBREE_MAJOR_VERSION}/rtcore_config.h _embree_config_header)
debug ${LIBDIR}/embree/lib/sys_d.lib if(_embree_config_header MATCHES "#define EMBREE_STATIC_LIB")
debug ${LIBDIR}/embree/lib/tasking_d.lib set(EMBREE_STATIC_LIB TRUE)
else()
set(EMBREE_STATIC_LIB FALSE)
endif()
if(_embree_config_header MATCHES "#define EMBREE_SYCL_SUPPORT")
set(EMBREE_SYCL_SUPPORT TRUE)
else()
set(EMBREE_SYCL_SUPPORT FALSE)
endif()
set(EMBREE_LIBRARIES
optimized ${LIBDIR}/embree/lib/embree${EMBREE_MAJOR_VERSION}.lib
debug ${LIBDIR}/embree/lib/embree${EMBREE_MAJOR_VERSION}_d.lib
)
if(EMBREE_SYCL_SUPPORT)
set(EMBREE_LIBRARIES
${EMBREE_LIBRARIES}
optimized ${LIBDIR}/embree/lib/embree4_sycl.lib
debug ${LIBDIR}/embree/lib/embree4_sycl_d.lib
)
endif()
if(EMBREE_STATIC_LIB)
set(EMBREE_LIBRARIES
${EMBREE_LIBRARIES}
optimized ${LIBDIR}/embree/lib/embree_avx2.lib
optimized ${LIBDIR}/embree/lib/embree_avx.lib
optimized ${LIBDIR}/embree/lib/embree_sse42.lib
optimized ${LIBDIR}/embree/lib/lexers.lib
optimized ${LIBDIR}/embree/lib/math.lib
optimized ${LIBDIR}/embree/lib/simd.lib
optimized ${LIBDIR}/embree/lib/sys.lib
optimized ${LIBDIR}/embree/lib/tasking.lib
debug ${LIBDIR}/embree/lib/embree_avx2_d.lib
debug ${LIBDIR}/embree/lib/embree_avx_d.lib
debug ${LIBDIR}/embree/lib/embree_sse42_d.lib
debug ${LIBDIR}/embree/lib/lexers_d.lib
debug ${LIBDIR}/embree/lib/math_d.lib
debug ${LIBDIR}/embree/lib/simd_d.lib
debug ${LIBDIR}/embree/lib/sys_d.lib
debug ${LIBDIR}/embree/lib/tasking_d.lib
)
if(EMBREE_SYCL_SUPPORT)
set(EMBREE_LIBRARIES
${EMBREE_LIBRARIES}
optimized ${LIBDIR}/embree/lib/embree_rthwif.lib
debug ${LIBDIR}/embree/lib/embree_rthwif_d.lib
)
endif()
endif()
endif()
if(NOT EMBREE_STATIC_LIB)
list(APPEND PLATFORM_BUNDLED_LIBRARIES
RELEASE ${EMBREE_ROOT_DIR}/bin/embree${EMBREE_MAJOR_VERSION}.dll
DEBUG ${EMBREE_ROOT_DIR}/bin/embree${EMBREE_MAJOR_VERSION}_d.dll
) )
endif() endif()
endif() endif()
@ -1029,7 +1077,7 @@ endif()
set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include) set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include)
set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib) set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib)
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)))
set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero) set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero)
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler") set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR) if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
@ -1040,7 +1088,7 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
${SYCL_ROOT_DIR}/bin/sycl[0-9].dll ${SYCL_ROOT_DIR}/bin/sycl[0-9].dll
) )
foreach(sycl_runtime_library IN LISTS _sycl_runtime_libraries_glob) foreach(sycl_runtime_library IN LISTS _sycl_runtime_libraries_glob)
string(REPLACE ".dll" "_d.dll" sycl_runtime_library_debug ${sycl_runtime_library}) string(REPLACE ".dll" "d.dll" sycl_runtime_library_debug ${sycl_runtime_library})
list(APPEND _sycl_runtime_libraries RELEASE ${sycl_runtime_library}) list(APPEND _sycl_runtime_libraries RELEASE ${sycl_runtime_library})
list(APPEND _sycl_runtime_libraries DEBUG ${sycl_runtime_library_debug}) list(APPEND _sycl_runtime_libraries DEBUG ${sycl_runtime_library_debug})
endforeach() endforeach()
@ -1055,6 +1103,8 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries}) list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
unset(_sycl_runtime_libraries) unset(_sycl_runtime_libraries)
set(SYCL_LIBRARIES optimized ${SYCL_LIBRARY} debug ${SYCL_LIBRARY_DEBUG})
endif() endif()

View File

@ -112,6 +112,7 @@ def create_manifest(
print(f'Building manifest of files: "{outpath}"...', end="", flush=True) print(f'Building manifest of files: "{outpath}"...', end="", flush=True)
with outpath.open("w", encoding="utf-8") as outfile: with outpath.open("w", encoding="utf-8") as outfile:
main_files_to_manifest(blender_srcdir, outfile) main_files_to_manifest(blender_srcdir, outfile)
assets_to_manifest(blender_srcdir, outfile)
submodules_to_manifest(blender_srcdir, version, outfile) submodules_to_manifest(blender_srcdir, version, outfile)
if packages_dir: if packages_dir:
@ -140,6 +141,18 @@ def submodules_to_manifest(
print(path, file=outfile) print(path, file=outfile)
def assets_to_manifest(blender_srcdir: Path, outfile: TextIO) -> None:
assert not blender_srcdir.is_absolute()
assets_dir = blender_srcdir.parent / "lib" / "assets"
for path in assets_dir.glob("*"):
if path.name == "working":
continue
if path.name in SKIP_NAMES:
continue
print(path, file=outfile)
def packages_to_manifest(outfile: TextIO, packages_dir: Path) -> None: def packages_to_manifest(outfile: TextIO, packages_dir: Path) -> None:
for path in packages_dir.glob("*"): for path in packages_dir.glob("*"):
if not path.is_file(): if not path.is_file():
@ -170,7 +183,9 @@ def create_tarball(
command += [ command += [
"--transform", "--transform",
f"s,^{blender_srcdir.name}/,blender-{version}/,g", f"s,^{blender_srcdir.name}/,blender-{version}/,g",
"--use-compress-program=xz -9", "--transform",
f"s,^lib/assets/,blender-{version}/release/datafiles/assets/,g",
"--use-compress-program=xz -1",
"--create", "--create",
f"--file={tarball}", f"--file={tarball}",
f"--files-from={manifest}", f"--files-from={manifest}",

View File

@ -1853,8 +1853,6 @@ def pyrna2sphinx(basepath):
fw(" %s\n\n" % operator_description) fw(" %s\n\n" % operator_description)
for prop in op.args: for prop in op.args:
write_param(" ", fw, prop) write_param(" ", fw, prop)
if op.args:
fw("\n")
location = op.get_location() location = op.get_location()
if location != (None, None): if location != (None, None):
@ -1865,9 +1863,12 @@ def pyrna2sphinx(basepath):
else: else:
url_base = API_BASEURL url_base = API_BASEURL
fw(" :file:`%s\\:%d <%s/%s#L%d>`_\n\n" % fw(" :File: `%s\\:%d <%s/%s#L%d>`__\n\n" %
(location[0], location[1], url_base, location[0], location[1])) (location[0], location[1], url_base, location[0], location[1]))
if op.args:
fw("\n")
file.close() file.close()
if "bpy.ops" not in EXCLUDE_MODULES: if "bpy.ops" not in EXCLUDE_MODULES:

View File

@ -14,3 +14,13 @@ The first three of them were employed by the Blender Foundation during that time
Some features (random sounds, dynamic music, playback manager, convolution and HRTFs support) were added as part of the VALS (Virtual Alliances for Learning Society) project by Some features (random sounds, dynamic music, playback manager, convolution and HRTFs support) were added as part of the VALS (Virtual Alliances for Learning Society) project by
- Juan Francisco Crespo Galán <dethon_5@outlook.com> - Juan Francisco Crespo Galán <dethon_5@outlook.com>
The Equalizer sound effect has been added by
- Marcos Perez
Several people provided fixes:
- Aaron Carlisle
- Sebastian Parborg
- Leon Zandman

View File

@ -1,3 +1,104 @@
Audaspace 1.4
- Support for OS specific/native audio devices/backends has been added, that is PulseAudio (Linux), WASAPI (Windows) and CoreAudio (MacOS).
- New sound effects have been added, namely Modulator and Equalizer. Thanks to Marcos Perez for contributing the Equalizer.
- File stream info: if an audio file contains multiple streams you can choose which one to process instead of taking the first one (this feature is only supported by ffmpeg, not libsndfile).
- API Change: double instead of float for time values for more precise timing control.
- There have been lots of bugfixes, which are basically the majority of all changes.
- And some other minor improvements were implemented as well.
Detailed list of changes:
d4042d9 Port changes in Blender to upstream.
b60fb45 Equalizer
ab04e84 Fixes
8f0c305 Fix build error with MSVC 17.4+ ported from Blender.
ce44342 Minor documentation update.
cdcb3f4 Migrate from distuils to setuptools for python module.
21eccef Fix FindFFTW to find the float version fftw3f.
ab15e2f Bugfix: API change in new ffmpeg version.
a097be8 Clang format file added, valid from now on.
2fc9fb7 Porting bugfix from Blender upstream.
bb655b7 Bugfix: wrong sample size computation for PulseAudio.
a150495 Bugfix: Buffer did not support buffers > 2 GB.
034645c Update for ffmpeg 5.
932739c Bugfix: WASAPI hangs.
4fcd47c WASAPI: fix bug when switching the default device while there is no playback.
a16fbd2 Python API: fix to get convolution in the python API.
27ac5c1 WASAPI: always switch to default audio device.
1b03e6c Bugfix: catch exception if file cannot be read.
369ff6e PulseAudio: remove unused underflow callback.
2d8bf3a PulseAudio: improve synchronization accuracy.
4868e14 Revert PulseAudioDevice back from ThreadedDevice to threaded mainloop.
6a04446 Adding a jack style mixing thread with a ring buffer for pulseaudio.
5d4b57b Implement RingBuffer class.
e02d3aa FFMPEG: fix seeking and duration calculation.
07b9fa0 Adding file stream functionality.
5a8ad27 Porting changes from Blender.
fa47258 Bugfix: PulseAudio writing to little data on request.
ca3edb5 PulseAudio: increase buffersize.
6d36f3e Pulseaudio: may fix crackling playback start bug.
dbeac4b WASAPI: reinitialize device when lost.
0cba4d3 Bugfix Pulseaudio: might hang.
b73dc6d Bugfix: ffmpeg 4.4 requires channels to be set.
f1ecbe0 Fixed typo.
09e4f27 Rewrite PulseAudioDevice to use ThreadedDevice.
9516924 WASAPI: refactor to simplify and use ThreadedDevice.
749c974 Add ThreadedDevice.
e68b355 Fix some locks in SoftwareDevice.
44b57af Bugfix for deadlock in WASAPIDevice.
8c4b266 CMake: fix ERROR to FATAL_ERROR in MESSAGE.
5a17338 Rename NullDevice's reported name to None.
cd138d7 PulseAudio: add dynamic loading and threading fixes.
6e0250f CoreAudio: add CoreAudioClock as synchronizer.
43aff35 Fix leakage in CoreAudioDevice.cpp
7f6f059 Remove unnecessary cmake code.
a5c1a02 Add CoreAudio device for Apple.
af96f67 Indentation fix.
eec8fd5 WASAPI: use padding also for first buffer submission.
c63bd9b WASAPI: deal with IsFormatSupported case.
079cccb Hide WITH_PULSEAUDIO when not on Linux.
67b5013 Add mingw64 cross compilation toolchain on Linux.
a7bfa58 Add WASAPI backend for Windows.
be1cb25 Allow AUD_init with nullptr to use default device.
fc68868 Compilation fix for mingw.
bb79d25 Add a PulseAudio output device.
a11f593 Bugfix for unwanted volume fading at the beginning of sounds.
8510acf Bugfix: more accurate positioning of sequences.
cb816c1 Fix API docs for python playback manager play function
d125fa2 Add callback for mixing down audio.
789832e Fix numpy import.
9a6a802 Bugfix: JOS resampling type bugfix caused integer underflow.
ece0842 Fix corrupted document in python bindings
28b2ea2 SDL 2: support more audio formats.
a39b7e3 Trying to fix Travis CI build for OS X.
c924007 Some more changes of times from flaot to double.
659afd4 Porting fixes from blender.
8e5e2e6 Fix documentation warnings.
7a6054f API: All times are now double instead of float.
452a724 Mixer sample buffer added channels twice
8ddb6c1 Docs: Cleanup Line Wrapping for python examples
a0c37b2 Docs: Use class methods for api docs
2f8b2e3 Bugfix for invalid offsets provided by ffmpeg's seeking code.
20a7a28 Bug fixes for files with more than 8 channels.
94dc527 Bugfix: Fading from full volume.
2fb9862 Fix: Missing include in FileManager.h.
afadb94 Minor CMakeLists.txt formatting fixes.
734ef03 Add sample rate parameter to silence generation.
ed50f3b Bugfix: Return correct length for modulator and superpose.
cb7a314 Adding a modulator sound effect.
101c714 Bugfix: don't add non-existing devices to the device manager.
7ad99df OpenAL: recreate device if disconnected.
a2ff4e8 Bugfix: memory leak in python API.
5fb21bb Silence some warnings.
9b38605 Some fixes backported from Blender.
40a0a34 Udpate for travis.ci.
212b4b6 Support newer ffmpeg versions.
d27746c Build option: configure whether to build versioned plugins.
19c8d9f Make fftw3 optional.
aa11968 Bugfix for building with gcc7.
10413c5 Fix for seeking with modified pitch.
Audaspace 1.3 Audaspace 1.3
============= =============
@ -10,6 +111,8 @@ Audaspace 1.3
- filter python API parameter check - filter python API parameter check
- finding ffmpeg with pkgconfig - finding ffmpeg with pkgconfig
Detailed list of changes:
64884a7 Windows fixes. 64884a7 Windows fixes.
53ba3e6 Implemented JACK dynamic loading. 53ba3e6 Implemented JACK dynamic loading.
5ee0ee1 Continues last commit. 5ee0ee1 Continues last commit.
@ -46,6 +149,8 @@ Audaspace 1.2
- assuring numpy is installed - assuring numpy is installed
- building the Python module on Mac OS X with CMake - building the Python module on Mac OS X with CMake
Detailed list of changes:
a6b6e70 Changing default sample rate from 44.1 to 48 kHz. a6b6e70 Changing default sample rate from 44.1 to 48 kHz.
20f0164 Bugfix: CMake custom command for python module on OS X. 20f0164 Bugfix: CMake custom command for python module on OS X.
98679a2 Bugfix: using standard library (s)rand. 98679a2 Bugfix: using standard library (s)rand.

View File

@ -23,7 +23,7 @@ endif()
project(audaspace) project(audaspace)
set(AUDASPACE_VERSION 1.3) set(AUDASPACE_VERSION 1.4)
set(AUDASPACE_LONG_VERSION ${AUDASPACE_VERSION}.0) set(AUDASPACE_LONG_VERSION ${AUDASPACE_VERSION}.0)
if(DEFINED AUDASPACE_CMAKE_CFG) if(DEFINED AUDASPACE_CMAKE_CFG)

View File

@ -15,7 +15,7 @@ Audaspace is written in C++ 11 so a fairly recent compiler (g++ 4.8.2, clang 3.3
- Jack (output device) - Jack (output device)
- libsndfile (file access) - libsndfile (file access)
- ffmpeg (file access) - ffmpeg (file access)
- Python (language binding) - Python (language binding, needs NumPy as well)
Getting the Code Getting the Code
---------------- ----------------

View File

@ -32,7 +32,7 @@ The following (probably incomplete) features are supported by audaspace:
License License
------- -------
> Copyright © 2009-2015 Jörg Müller. All rights reserved. > Copyright © 2009-2023 Jörg Müller. All rights reserved.
> >
> Licensed under the Apache License, Version 2.0 (the "License"); > Licensed under the Apache License, Version 2.0 (the "License");
> you may not use this file except in compliance with the License. > you may not use this file except in compliance with the License.

View File

@ -165,6 +165,12 @@ AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, double begin, doub
(*entry)->move(begin, end, skip); (*entry)->move(begin, end, skip);
} }
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data)
{
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));
prop->writeConstantRange(data, frame_start, frame_end);
}
AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated) AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
{ {
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type)); AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));

View File

@ -68,6 +68,16 @@ extern AUD_API void AUD_Sequence_remove(AUD_Sound* sequence, AUD_SequenceEntry*
* Writes animation data to a sequence. * Writes animation data to a sequence.
* \param sequence The sound scene. * \param sequence The sound scene.
* \param type The type of animation data. * \param type The type of animation data.
* \param frame_start Start of the frame range.
* \param frame_end End of the frame range.
* \param data The data to write.
*/
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data);
/**
* Writes animation data to a sequenced entry.
* \param entry The sequenced entry.
* \param type The type of animation data.
* \param frame The frame this data is for. * \param frame The frame this data is for.
* \param data The data to write. * \param data The data to write.
* \param animated Whether the attribute is animated. * \param animated Whether the attribute is animated.

View File

@ -112,6 +112,14 @@ public:
*/ */
void write(const float* data, int position, int count); void write(const float* data, int position, int count);
/**
* Fills the properties frame range with constant value and marks it animated.
* \param data The new value.
* \param position_start The start position in the animation in frames.
* \param position_end The end position in the animation in frames.
*/
void writeConstantRange(const float* data, int position_start, int position_end);
/** /**
* Reads the properties value. * Reads the properties value.
* \param position The position in the animation in frames. * \param position The position in the animation in frames.

View File

@ -198,12 +198,13 @@ public:
/** /**
* Adds a new entry to the scene. * Adds a new entry to the scene.
* \param sound The sound this entry should play. * \param sound The sound this entry should play.
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
* \param begin The start time. * \param begin The start time.
* \param end The end time or a negative value if determined by the sound. * \param end The end time or a negative value if determined by the sound.
* \param skip How much seconds should be skipped at the beginning. * \param skip How much seconds should be skipped at the beginning.
* \return The entry added. * \return The entry added.
*/ */
std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, double begin, double end, double skip); std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip);
/** /**
* Removes an entry from the scene. * Removes an entry from the scene.

View File

@ -23,6 +23,7 @@
*/ */
#include "sequence/AnimateableProperty.h" #include "sequence/AnimateableProperty.h"
#include "sequence/SequenceData.h"
#include "util/ILockable.h" #include "util/ILockable.h"
#include <mutex> #include <mutex>
@ -63,6 +64,9 @@ private:
/// How many seconds are skipped at the beginning. /// How many seconds are skipped at the beginning.
double m_skip; double m_skip;
/// reference to sequence_data. Mainly needed to get the FPS of the scene.
std::shared_ptr<SequenceData> m_sequence_data;
/// Whether the entry is muted. /// Whether the entry is muted.
bool m_muted; bool m_muted;
@ -122,9 +126,10 @@ public:
* \param begin The start time. * \param begin The start time.
* \param end The end time or a negative value if determined by the sound. * \param end The end time or a negative value if determined by the sound.
* \param skip How much seconds should be skipped at the beginning. * \param skip How much seconds should be skipped at the beginning.
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
* \param id The ID of the entry. * \param id The ID of the entry.
*/ */
SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id); SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id);
virtual ~SequenceEntry(); virtual ~SequenceEntry();
/** /**

View File

@ -65,6 +65,19 @@ void AnimateableProperty::write(const float* data)
std::memcpy(getBuffer(), data, m_count * sizeof(float)); std::memcpy(getBuffer(), data, m_count * sizeof(float));
} }
void AnimateableProperty::writeConstantRange(const float* data, int position_start, int position_end)
{
assureSize(position_end * m_count * sizeof(float), true);
float* buffer = getBuffer();
for(int i = position_start; i < position_end; i++)
{
std::memcpy(buffer + i * m_count, data, m_count * sizeof(float));
}
m_isAnimated = true;
}
void AnimateableProperty::write(const float* data, int position, int count) void AnimateableProperty::write(const float* data, int position, int count)
{ {
std::lock_guard<std::recursive_mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);

View File

@ -92,7 +92,7 @@ AnimateableProperty* Sequence::getAnimProperty(AnimateablePropertyType type)
std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, double begin, double end, double skip) std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, double begin, double end, double skip)
{ {
return m_sequence->add(sound, begin, end, skip); return m_sequence->add(sound, m_sequence, begin, end, skip);
} }
void Sequence::remove(std::shared_ptr<SequenceEntry> entry) void Sequence::remove(std::shared_ptr<SequenceEntry> entry)

View File

@ -149,11 +149,11 @@ AnimateableProperty* SequenceData::getAnimProperty(AnimateablePropertyType type)
} }
} }
std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, double begin, double end, double skip) std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip)
{ {
std::lock_guard<std::recursive_mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, m_id++)); std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, sequence_data, m_id++));
m_entries.push_back(entry); m_entries.push_back(entry);
m_entry_status++; m_entry_status++;

View File

@ -22,7 +22,7 @@
AUD_NAMESPACE_BEGIN AUD_NAMESPACE_BEGIN
SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id) : SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id) :
m_status(0), m_status(0),
m_pos_status(1), m_pos_status(1),
m_sound_status(0), m_sound_status(0),
@ -31,6 +31,7 @@ SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double
m_begin(begin), m_begin(begin),
m_end(end), m_end(end),
m_skip(skip), m_skip(skip),
m_sequence_data(sequence_data),
m_muted(false), m_muted(false),
m_relative(true), m_relative(true),
m_volume_max(1.0f), m_volume_max(1.0f),

View File

@ -241,10 +241,38 @@ bool SequenceHandle::seek(double position)
return false; return false;
std::lock_guard<ILockable> lock(*m_entry); std::lock_guard<ILockable> lock(*m_entry);
double seekpos = position - m_entry->m_begin;
if(seekpos < 0) double seek_frame = (position - m_entry->m_begin) * m_entry->m_sequence_data->getFPS();
seekpos = 0;
seekpos += m_entry->m_skip; if(seek_frame < 0)
seek_frame = 0;
seek_frame += m_entry->m_skip * m_entry->m_sequence_data->getFPS();
AnimateableProperty* pitch_property = m_entry->getAnimProperty(AP_PITCH);
double target_frame = 0;
if(pitch_property != nullptr)
{
int frame_start = (m_entry->m_begin - m_entry->m_skip) * m_entry->m_sequence_data->getFPS();
for(int i = 0; seek_frame > 0; i++)
{
float pitch;
pitch_property->read(frame_start + i, &pitch);
const double factor = seek_frame > 1.0 ? 1.0 : seek_frame;
target_frame += pitch * factor;
seek_frame--;
}
}
else
{
target_frame = seek_frame;
}
double seekpos = target_frame / m_entry->m_sequence_data->getFPS();
m_handle->setPitch(1.0f); m_handle->setPitch(1.0f);
m_handle->seek(seekpos); m_handle->seek(seekpos);

View File

@ -127,7 +127,7 @@ typedef uint32_t cuuint32_t;
typedef uint64_t cuuint64_t; typedef uint64_t cuuint64_t;
#endif #endif
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) || defined(__ppc64__) || defined(__PPC64__)
typedef unsigned long long CUdeviceptr; typedef unsigned long long CUdeviceptr;
#else #else
typedef unsigned int CUdeviceptr; typedef unsigned int CUdeviceptr;

View File

@ -84,7 +84,7 @@ typedef uint32_t hipuint32_t;
typedef uint64_t hipuint64_t; typedef uint64_t hipuint64_t;
#endif #endif
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) || defined(__ppc64__) || defined(__PPC64__)
typedef unsigned long long hipDeviceptr_t; typedef unsigned long long hipDeviceptr_t;
#else #else
typedef unsigned int hipDeviceptr_t; typedef unsigned int hipDeviceptr_t;

View File

@ -281,6 +281,7 @@ endif()
if(WITH_CYCLES_EMBREE) if(WITH_CYCLES_EMBREE)
add_definitions(-DWITH_EMBREE) add_definitions(-DWITH_EMBREE)
add_definitions(-DEMBREE_MAJOR_VERSION=${EMBREE_MAJOR_VERSION})
include_directories( include_directories(
SYSTEM SYSTEM
${EMBREE_INCLUDE_DIRS} ${EMBREE_INCLUDE_DIRS}

View File

@ -51,6 +51,12 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
endif() endif()
if(WITH_USD) if(WITH_USD)
# Silence warning from USD headers using deprecated TBB header.
add_definitions(
-D__TBB_show_deprecation_message_atomic_H
-D__TBB_show_deprecation_message_task_H
)
list(APPEND INC_SYS list(APPEND INC_SYS
${USD_INCLUDE_DIRS} ${USD_INCLUDE_DIRS}
) )

View File

@ -403,7 +403,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
time_limit: FloatProperty( time_limit: FloatProperty(
name="Time Limit", name="Time Limit",
description="Limit the render time (excluding synchronization time)." description="Limit the render time (excluding synchronization time). "
"Zero disables the limit", "Zero disables the limit",
min=0.0, min=0.0,
default=0.0, default=0.0,

View File

@ -609,59 +609,60 @@ void BlenderSync::sync_particle_hair(
} }
} }
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves) static const float *find_radius_attribute(BL::Curves b_curves)
{ {
for (BL::Attribute &b_attribute : b_curves.attributes) { for (BL::Attribute &b_attribute : b_curves.attributes) {
if (b_attribute.name() != "radius") { if (b_attribute.name() != "radius") {
continue; continue;
} }
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) { if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue; continue;
} }
return BL::FloatAttribute{b_attribute}; BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
} }
return std::nullopt; return nullptr;
} }
static BL::FloatVectorAttribute find_curves_position_attribute(BL::Curves b_curves) static const float (*find_position_attribute(BL::Curves b_curves))[3]
{ {
for (BL::Attribute &b_attribute : b_curves.attributes) { for (BL::Attribute &b_attribute : b_curves.attributes) {
if (b_attribute.name() != "position") { if (b_attribute.name() != "position") {
continue; continue;
} }
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) { if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
continue; continue;
} }
return BL::FloatVectorAttribute{b_attribute}; BL::FloatVectorAttribute b_float3_attribute{b_attribute};
if (b_float3_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
} }
/* The position attribute must exist. */ /* The position attribute must exist. */
assert(false); assert(false);
return BL::FloatVectorAttribute{b_curves.attributes[0]}; return nullptr;
} }
template<typename TypeInCycles, typename GetValueAtIndex> template<typename TypeInCycles, typename GetValueAtIndex>
static void fill_generic_attribute(BL::Curves &b_curves, static void fill_generic_attribute(const int num_curves,
const int num_points,
TypeInCycles *data, TypeInCycles *data,
const AttributeElement element, const AttributeElement element,
const GetValueAtIndex &get_value_at_index) const GetValueAtIndex &get_value_at_index)
{ {
switch (element) { switch (element) {
case ATTR_ELEMENT_CURVE_KEY: { case ATTR_ELEMENT_CURVE_KEY: {
const int num_points = b_curves.points.length();
for (int i = 0; i < num_points; i++) { for (int i = 0; i < num_points; i++) {
data[i] = get_value_at_index(i); data[i] = get_value_at_index(i);
} }
break; break;
} }
case ATTR_ELEMENT_CURVE: { case ATTR_ELEMENT_CURVE: {
const int num_verts = b_curves.curves.length(); for (int i = 0; i < num_curves; i++) {
for (int i = 0; i < num_verts; i++) {
data[i] = get_value_at_index(i); data[i] = get_value_at_index(i);
} }
break; break;
@ -681,6 +682,7 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
} }
BL::FloatVectorAttribute b_vector_attribute(b_attribute); BL::FloatVectorAttribute b_vector_attribute(b_attribute);
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
const int num_curve_keys = hair->get_curve_keys().size(); const int num_curve_keys = hair->get_curve_keys().size();
/* Find or add attribute */ /* Find or add attribute */
@ -698,23 +700,24 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
float3 *mP = attr_mP->data_float3() + step * num_curve_keys; float3 *mP = attr_mP->data_float3() + step * num_curve_keys;
for (int i = 0; i < num_curve_keys; i++) { for (int i = 0; i < num_curve_keys; i++) {
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time; mP[i] = P[i] + make_float3(src[i][0], src[i][1], src[i][2]) * relative_time;
} }
} }
} }
static void attr_create_uv(AttributeSet &attributes, static void attr_create_uv(AttributeSet &attributes,
BL::Curves &b_curves, const int num_curves,
const int num_points,
BL::Attribute &b_attribute, BL::Attribute &b_attribute,
const ustring name) const ustring name)
{ {
BL::Float2Attribute b_float2_attribute{b_attribute}; BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(ATTR_STD_UV, name); Attribute *attr = attributes.add(ATTR_STD_UV, name);
float2 *data = attr->data_float2(); float2 *data = attr->data_float2();
fill_generic_attribute(b_curves, data, ATTR_ELEMENT_CURVE, [&](int i) { fill_generic_attribute(num_curves, num_points, data, ATTR_ELEMENT_CURVE, [&](int i) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector(); return make_float2(src[i][0], src[i][1]);
return make_float2(v[0], v[1]);
}); });
} }
@ -724,6 +727,9 @@ static void attr_create_generic(Scene *scene,
const bool need_motion, const bool need_motion,
const float motion_scale) const float motion_scale)
{ {
const int num_keys = b_curves.points.length();
const int num_curves = b_curves.curves.length();
AttributeSet &attributes = hair->attributes; AttributeSet &attributes = hair->attributes;
static const ustring u_velocity("velocity"); static const ustring u_velocity("velocity");
const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV); const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV);
@ -743,7 +749,7 @@ static void attr_create_generic(Scene *scene,
/* Weak, use first float2 attribute as standard UV. */ /* Weak, use first float2 attribute as standard UV. */
if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 && if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 &&
b_domain == BL::Attribute::domain_CURVE) { b_domain == BL::Attribute::domain_CURVE) {
attr_create_uv(attributes, b_curves, b_attribute, name); attr_create_uv(attributes, num_curves, num_keys, b_attribute, name);
have_uv = true; have_uv = true;
continue; continue;
} }
@ -773,57 +779,70 @@ static void attr_create_generic(Scene *scene,
switch (b_data_type) { switch (b_data_type) {
case BL::Attribute::data_type_FLOAT: { case BL::Attribute::data_type_FLOAT: {
BL::FloatAttribute b_float_attribute{b_attribute}; BL::FloatAttribute b_float_attribute{b_attribute};
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute( fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) { return src[i]; });
b_curves, data, element, [&](int i) { return b_float_attribute.data[i].value(); });
break; break;
} }
case BL::Attribute::data_type_BOOLEAN: { case BL::Attribute::data_type_BOOLEAN: {
BL::BoolAttribute b_bool_attribute{b_attribute}; BL::BoolAttribute b_bool_attribute{b_attribute};
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute(b_curves, data, element, [&](int i) { fill_generic_attribute(
return (float)b_bool_attribute.data[i].value(); num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
});
break; break;
} }
case BL::Attribute::data_type_INT: { case BL::Attribute::data_type_INT: {
BL::IntAttribute b_int_attribute{b_attribute}; BL::IntAttribute b_int_attribute{b_attribute};
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute(b_curves, data, element, [&](int i) { fill_generic_attribute(
return (float)b_int_attribute.data[i].value(); num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
});
break; break;
} }
case BL::Attribute::data_type_FLOAT_VECTOR: { case BL::Attribute::data_type_FLOAT_VECTOR: {
BL::FloatVectorAttribute b_vector_attribute{b_attribute}; BL::FloatVectorAttribute b_vector_attribute{b_attribute};
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeVector, element); Attribute *attr = attributes.add(name, TypeVector, element);
float3 *data = attr->data_float3(); float3 *data = attr->data_float3();
fill_generic_attribute(b_curves, data, element, [&](int i) { fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
BL::Array<float, 3> v = b_vector_attribute.data[i].vector(); return make_float3(src[i][0], src[i][1], src[i][2]);
return make_float3(v[0], v[1], v[2]); });
break;
}
case BL::Attribute::data_type_BYTE_COLOR: {
BL::ByteColorAttribute b_color_attribute{b_attribute};
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
return make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
color_srgb_to_linear(byte_to_float(src[i][1])),
color_srgb_to_linear(byte_to_float(src[i][2])),
color_srgb_to_linear(byte_to_float(src[i][3])));
}); });
break; break;
} }
case BL::Attribute::data_type_FLOAT_COLOR: { case BL::Attribute::data_type_FLOAT_COLOR: {
BL::FloatColorAttribute b_color_attribute{b_attribute}; BL::FloatColorAttribute b_color_attribute{b_attribute};
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element); Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4(); float4 *data = attr->data_float4();
fill_generic_attribute(b_curves, data, element, [&](int i) { fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
BL::Array<float, 4> v = b_color_attribute.data[i].color(); return make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
return make_float4(v[0], v[1], v[2], v[3]);
}); });
break; break;
} }
case BL::Attribute::data_type_FLOAT2: { case BL::Attribute::data_type_FLOAT2: {
BL::Float2Attribute b_float2_attribute{b_attribute}; BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat2, element); Attribute *attr = attributes.add(name, TypeFloat2, element);
float2 *data = attr->data_float2(); float2 *data = attr->data_float2();
fill_generic_attribute(b_curves, data, element, [&](int i) { fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector(); return make_float2(src[i][0], src[i][1]);
return make_float2(v[0], v[1]);
}); });
break; break;
} }
@ -834,27 +853,28 @@ static void attr_create_generic(Scene *scene,
} }
} }
static float4 hair_point_as_float4(BL::FloatVectorAttribute b_attr_position, static float4 curve_point_as_float4(const float (*b_attr_position)[3],
std::optional<BL::FloatAttribute> b_attr_radius, const float *b_attr_radius,
const int index) const int index)
{ {
float4 mP = float3_to_float4(get_float3(b_attr_position.data[index].vector())); float4 mP = make_float4(
mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.005f; b_attr_position[index][0], b_attr_position[index][1], b_attr_position[index][2], 0.0f);
mP.w = b_attr_radius ? b_attr_radius[index] : 0.005f;
return mP; return mP;
} }
static float4 interpolate_hair_points(BL::FloatVectorAttribute b_attr_position, static float4 interpolate_curve_points(const float (*b_attr_position)[3],
std::optional<BL::FloatAttribute> b_attr_radius, const float *b_attr_radius,
const int first_point_index, const int first_point_index,
const int num_points, const int num_points,
const float step) const float step)
{ {
const float curve_t = step * (num_points - 1); const float curve_t = step * (num_points - 1);
const int point_a = clamp((int)curve_t, 0, num_points - 1); const int point_a = clamp((int)curve_t, 0, num_points - 1);
const int point_b = min(point_a + 1, num_points - 1); const int point_b = min(point_a + 1, num_points - 1);
const float t = curve_t - (float)point_a; const float t = curve_t - (float)point_a;
return lerp(hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a), return lerp(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b), curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
t); t);
} }
@ -864,8 +884,6 @@ static void export_hair_curves(Scene *scene,
const bool need_motion, const bool need_motion,
const float motion_scale) const float motion_scale)
{ {
/* TODO: optimize so we can straight memcpy arrays from Blender? */
const int num_keys = b_curves.points.length(); const int num_keys = b_curves.points.length();
const int num_curves = b_curves.curves.length(); const int num_curves = b_curves.curves.length();
@ -879,7 +897,6 @@ static void export_hair_curves(Scene *scene,
/* Add requested attributes. */ /* Add requested attributes. */
float *attr_intercept = NULL; float *attr_intercept = NULL;
float *attr_length = NULL; float *attr_length = NULL;
float *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) { if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float(); attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float();
@ -888,28 +905,40 @@ static void export_hair_curves(Scene *scene,
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH)->data_float(); attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH)->data_float();
} }
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) { if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float(); float *attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
for (int i = 0; i < num_curves; i++) {
attr_random[i] = hash_uint2_to_float(i, 0);
}
} }
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves); const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves); const float(*b_attr_position)[3] = find_position_attribute(b_curves);
const float *b_attr_radius = find_radius_attribute(b_curves);
std::copy(point_offsets, point_offsets + num_curves, curve_first_key);
std::fill(curve_shader, curve_shader + num_curves, 0);
if (b_attr_radius) {
std::copy(b_attr_radius, b_attr_radius + num_keys, curve_radius);
}
else {
std::fill(curve_radius, curve_radius + num_curves, 0.005f);
}
/* Export curves and points. */ /* Export curves and points. */
for (int i = 0; i < num_curves; i++) { for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_curves.curve_offset_data[i].value(); const int first_point_index = point_offsets[i];
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index; const int num_points = point_offsets[i + 1] - first_point_index;
float3 prev_co = zero_float3(); float3 prev_co = zero_float3();
float length = 0.0f; float length = 0.0f;
/* Position and radius. */ /* Position and radius. */
for (int j = 0; j < num_points; j++) { for (int j = 0; j < num_points; j++) {
const int point_offset = first_point_index + j; const int point = first_point_index + j;
const float3 co = get_float3(b_attr_position.data[point_offset].vector()); const float3 co = make_float3(
const float radius = b_attr_radius ? b_attr_radius->data[point_offset].value() : 0.005f; b_attr_position[point][0], b_attr_position[point][1], b_attr_position[point][2]);
curve_keys[point_offset] = co; curve_keys[point] = co;
curve_radius[point_offset] = radius;
if (attr_length || attr_intercept) { if (attr_length || attr_intercept) {
if (j > 0) { if (j > 0) {
@ -918,7 +947,7 @@ static void export_hair_curves(Scene *scene,
prev_co = co; prev_co = co;
if (attr_intercept) { if (attr_intercept) {
attr_intercept[point_offset] = length; attr_intercept[point] = length;
} }
} }
} }
@ -926,8 +955,8 @@ static void export_hair_curves(Scene *scene,
/* Normalized 0..1 attribute along curve. */ /* Normalized 0..1 attribute along curve. */
if (attr_intercept && length > 0.0f) { if (attr_intercept && length > 0.0f) {
for (int j = 1; j < num_points; j++) { for (int j = 1; j < num_points; j++) {
const int point_offset = first_point_index + j; const int point = first_point_index + j;
attr_intercept[point_offset] /= length; attr_intercept[point] /= length;
} }
} }
@ -935,15 +964,6 @@ static void export_hair_curves(Scene *scene,
if (attr_length) { if (attr_length) {
attr_length[i] = length; attr_length[i] = length;
} }
/* Random number per curve. */
if (attr_random != NULL) {
attr_random[i] = hash_uint2_to_float(i, 0);
}
/* Curve. */
curve_shader[i] = 0;
curve_first_key[i] = first_point_index;
} }
attr_create_generic(scene, hair, b_curves, need_motion, motion_scale); attr_create_generic(scene, hair, b_curves, need_motion, motion_scale);
@ -968,12 +988,13 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
int num_motion_keys = 0; int num_motion_keys = 0;
int curve_index = 0; int curve_index = 0;
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves); const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves); const float(*b_attr_position)[3] = find_position_attribute(b_curves);
const float *b_attr_radius = find_radius_attribute(b_curves);
for (int i = 0; i < num_curves; i++) { for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_curves.curve_offset_data[i].value(); const int first_point_index = point_offsets[i];
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index; const int num_points = point_offsets[i + 1] - first_point_index;
Hair::Curve curve = hair->get_curve(curve_index); Hair::Curve curve = hair->get_curve(curve_index);
curve_index++; curve_index++;
@ -981,10 +1002,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
if (num_points == curve.num_keys) { if (num_points == curve.num_keys) {
/* Number of keys matches. */ /* Number of keys matches. */
for (int i = 0; i < num_points; i++) { for (int i = 0; i < num_points; i++) {
int point_index = first_point_index + i; int point = first_point_index + i;
if (point_index < num_keys) { if (point < num_keys) {
mP[num_motion_keys] = hair_point_as_float4(b_attr_position, b_attr_radius, point_index); mP[num_motion_keys] = curve_point_as_float4(b_attr_position, b_attr_radius, point);
num_motion_keys++; num_motion_keys++;
if (!have_motion) { if (!have_motion) {
@ -1003,7 +1024,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f; const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
for (int i = 0; i < curve.num_keys; i++) { for (int i = 0; i < curve.num_keys; i++) {
const float step = i * step_size; const float step = i * step_size;
mP[num_motion_keys] = interpolate_hair_points( mP[num_motion_keys] = interpolate_curve_points(
b_attr_position, b_attr_radius, first_point_index, num_points, step); b_attr_position, b_attr_radius, first_point_index, num_points, step);
num_motion_keys++; num_motion_keys++;
} }

View File

@ -10,22 +10,12 @@
#include "blender/sync.h" #include "blender/sync.h"
#include "blender/util.h" #include "blender/util.h"
#include "util/color.h"
#include "util/foreach.h" #include "util/foreach.h"
#include "util/hash.h" #include "util/hash.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
template<typename TypeInCycles, typename GetValueAtIndex>
static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
TypeInCycles *data,
const GetValueAtIndex &get_value_at_index)
{
const int num_points = b_pointcloud.points.length();
for (int i = 0; i < num_points; i++) {
data[i] = get_value_at_index(i);
}
}
static void attr_create_motion(PointCloud *pointcloud, static void attr_create_motion(PointCloud *pointcloud,
BL::Attribute &b_attribute, BL::Attribute &b_attribute,
const float motion_scale) const float motion_scale)
@ -63,6 +53,11 @@ static void copy_attributes(PointCloud *pointcloud,
const bool need_motion, const bool need_motion,
const float motion_scale) const float motion_scale)
{ {
const int num_points = b_pointcloud.points.length();
if (num_points == 0) {
return;
}
AttributeSet &attributes = pointcloud->attributes; AttributeSet &attributes = pointcloud->attributes;
static const ustring u_velocity("velocity"); static const ustring u_velocity("velocity");
for (BL::Attribute &b_attribute : b_pointcloud.attributes) { for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
@ -81,56 +76,73 @@ static void copy_attributes(PointCloud *pointcloud,
switch (b_data_type) { switch (b_data_type) {
case BL::Attribute::data_type_FLOAT: { case BL::Attribute::data_type_FLOAT: {
BL::FloatAttribute b_float_attribute{b_attribute}; BL::FloatAttribute b_float_attribute{b_attribute};
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute( std::copy(src, src + num_points, data);
b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); });
break; break;
} }
case BL::Attribute::data_type_BOOLEAN: { case BL::Attribute::data_type_BOOLEAN: {
BL::BoolAttribute b_bool_attribute{b_attribute}; BL::BoolAttribute b_bool_attribute{b_attribute};
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute( for (int i = 0; i < num_points; i++) {
b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); }); data[i] = float(src[i]);
}
break; break;
} }
case BL::Attribute::data_type_INT: { case BL::Attribute::data_type_INT: {
BL::IntAttribute b_int_attribute{b_attribute}; BL::IntAttribute b_int_attribute{b_attribute};
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element); Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float(); float *data = attr->data_float();
fill_generic_attribute( for (int i = 0; i < num_points; i++) {
b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); }); data[i] = float(src[i]);
}
break; break;
} }
case BL::Attribute::data_type_FLOAT_VECTOR: { case BL::Attribute::data_type_FLOAT_VECTOR: {
BL::FloatVectorAttribute b_vector_attribute{b_attribute}; BL::FloatVectorAttribute b_vector_attribute{b_attribute};
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeVector, element); Attribute *attr = attributes.add(name, TypeVector, element);
float3 *data = attr->data_float3(); float3 *data = attr->data_float3();
fill_generic_attribute(b_pointcloud, data, [&](int i) { for (int i = 0; i < num_points; i++) {
BL::Array<float, 3> v = b_vector_attribute.data[i].vector(); data[i] = make_float3(src[i][0], src[i][1], src[i][2]);
return make_float3(v[0], v[1], v[2]); }
}); break;
}
case BL::Attribute::data_type_BYTE_COLOR: {
BL::ByteColorAttribute b_color_attribute{b_attribute};
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
for (int i = 0; i < num_points; i++) {
data[i] = make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
color_srgb_to_linear(byte_to_float(src[i][1])),
color_srgb_to_linear(byte_to_float(src[i][2])),
color_srgb_to_linear(byte_to_float(src[i][3])));
}
break; break;
} }
case BL::Attribute::data_type_FLOAT_COLOR: { case BL::Attribute::data_type_FLOAT_COLOR: {
BL::FloatColorAttribute b_color_attribute{b_attribute}; BL::FloatColorAttribute b_color_attribute{b_attribute};
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element); Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4(); float4 *data = attr->data_float4();
fill_generic_attribute(b_pointcloud, data, [&](int i) { for (int i = 0; i < num_points; i++) {
BL::Array<float, 4> v = b_color_attribute.data[i].color(); data[i] = make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
return make_float4(v[0], v[1], v[2], v[3]); }
});
break; break;
} }
case BL::Attribute::data_type_FLOAT2: { case BL::Attribute::data_type_FLOAT2: {
BL::Float2Attribute b_float2_attribute{b_attribute}; BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat2, element); Attribute *attr = attributes.add(name, TypeFloat2, element);
float2 *data = attr->data_float2(); float2 *data = attr->data_float2();
fill_generic_attribute(b_pointcloud, data, [&](int i) { for (int i = 0; i < num_points; i++) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector(); data[i] = make_float2(src[i][0], src[i][1]);
return make_float2(v[0], v[1]); }
});
break; break;
} }
default: default:
@ -140,7 +152,7 @@ static void copy_attributes(PointCloud *pointcloud,
} }
} }
static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_pointcloud) static const float *find_radius_attribute(BL::PointCloud b_pointcloud)
{ {
for (BL::Attribute &b_attribute : b_pointcloud.attributes) { for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
if (b_attribute.name() != "radius") { if (b_attribute.name() != "radius") {
@ -149,12 +161,16 @@ static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) { if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue; continue;
} }
return BL::FloatAttribute{b_attribute}; BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
} }
return std::nullopt; return nullptr;
} }
static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcloud) static const float (*find_position_attribute(BL::PointCloud b_pointcloud))[3]
{ {
for (BL::Attribute &b_attribute : b_pointcloud.attributes) { for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
if (b_attribute.name() != "position") { if (b_attribute.name() != "position") {
@ -163,11 +179,15 @@ static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcl
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) { if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
continue; continue;
} }
return BL::FloatVectorAttribute{b_attribute}; BL::FloatVectorAttribute b_float3_attribute{b_attribute};
if (b_float3_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
} }
/* The position attribute must exist. */ /* The position attribute must exist. */
assert(false); assert(false);
return BL::FloatVectorAttribute{b_pointcloud.attributes[0]}; return nullptr;
} }
static void export_pointcloud(Scene *scene, static void export_pointcloud(Scene *scene,
@ -176,34 +196,36 @@ static void export_pointcloud(Scene *scene,
const bool need_motion, const bool need_motion,
const float motion_scale) const float motion_scale)
{ {
/* TODO: optimize so we can straight memcpy arrays from Blender? */ const int num_points = b_pointcloud.points.length();
pointcloud->resize(num_points);
/* Add requested attributes. */ const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
Attribute *attr_random = NULL; float3 *points = pointcloud->get_points().data();
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM); for (int i = 0; i < num_points; i++) {
points[i] = make_float3(b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
} }
/* Reserve memory. */ const float *b_attr_radius = find_radius_attribute(b_pointcloud);
const int num_points = b_pointcloud.points.length(); float *radius = pointcloud->get_radius().data();
pointcloud->reserve(num_points); if (b_attr_radius) {
std::copy(b_attr_radius, b_attr_radius + num_points, radius);
}
else {
std::fill(radius, radius + num_points, 0.01f);
}
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud); int *shader = pointcloud->get_shader().data();
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud); std::fill(shader, shader + num_points, 0);
/* Export points. */ if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
for (int i = 0; i < num_points; i++) { Attribute *attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
const float3 co = get_float3(b_attr_position.data[i].vector()); float *data = attr_random->data_float();
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f; for (int i = 0; i < num_points; i++) {
pointcloud->add_point(co, radius); data[i] = hash_uint2_to_float(i, 0);
/* Random number per point. */
if (attr_random != NULL) {
attr_random->add(hash_uint2_to_float(i, 0));
} }
} }
/* Export attributes */
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale); copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
} }
@ -220,22 +242,22 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
new_attribute = true; new_attribute = true;
} }
/* Export motion points. */
const int num_points = pointcloud->num_points(); const int num_points = pointcloud->num_points();
// Point cloud attributes are stored as float4 with the radius /* Point cloud attributes are stored as float4 with the radius in the w element.
// in the w element. This is explict now as float3 is no longer * This is explict now as float3 is no longer interchangeable with float4 as it
// interchangeable with float4 as it is packed now. * is packed now. */
float4 *mP = attr_mP->data_float4() + motion_step * num_points; float4 *mP = attr_mP->data_float4() + motion_step * num_points;
bool have_motion = false; bool have_motion = false;
const array<float3> &pointcloud_points = pointcloud->get_points(); const array<float3> &pointcloud_points = pointcloud->get_points();
const int b_points_num = b_pointcloud.points.length(); const int b_points_num = b_pointcloud.points.length();
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud); const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud); const float *b_attr_radius = find_radius_attribute(b_pointcloud);
for (int i = 0; i < std::min(num_points, b_points_num); i++) { for (int i = 0; i < std::min(num_points, b_points_num); i++) {
const float3 P = get_float3(b_attr_position.data[i].vector()); const float3 P = make_float3(
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f; b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
const float radius = b_attr_radius ? b_attr_radius[i] : 0.01f;
mP[i] = make_float4(P.x, P.y, P.z, radius); mP[i] = make_float4(P.x, P.y, P.z, radius);
have_motion = have_motion || (P != pointcloud_points[i]); have_motion = have_motion || (P != pointcloud_points[i]);
} }
@ -277,7 +299,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
0.0f; 0.0f;
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale); export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
/* update original sockets */ /* Update original sockets. */
for (const SocketType &socket : new_pointcloud.type->inputs) { for (const SocketType &socket : new_pointcloud.type->inputs) {
/* Those sockets are updated in sync_object, so do not modify them. */ /* Those sockets are updated in sync_object, so do not modify them. */
if (socket.name == "use_motion_blur" || socket.name == "motion_steps" || if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
@ -292,7 +314,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
pointcloud->attributes.attributes.push_back(std::move(attr)); pointcloud->attributes.attributes.push_back(std::move(attr));
} }
/* tag update */ /* Tag update. */
const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points()); const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points());
pointcloud->tag_update(scene, rebuild); pointcloud->tag_update(scene, rebuild);
} }

View File

@ -61,6 +61,11 @@ if(WITH_CYCLES_EMBREE)
list(APPEND LIB list(APPEND LIB
${EMBREE_LIBRARIES} ${EMBREE_LIBRARIES}
) )
if(EMBREE_SYCL_SUPPORT)
list(APPEND LIB
${SYCL_LIBRARIES}
)
endif()
endif() endif()
cycles_add_library(cycles_bvh "${LIB}" ${SRC} ${SRC_HEADERS}) cycles_add_library(cycles_bvh "${LIB}" ${SRC} ${SRC_HEADERS})

View File

@ -17,7 +17,11 @@
#ifdef WITH_EMBREE #ifdef WITH_EMBREE
# include <embree3/rtcore_geometry.h> # if EMBREE_MAJOR_VERSION >= 4
# include <embree4/rtcore_geometry.h>
# else
# include <embree3/rtcore_geometry.h>
# endif
# include "bvh/embree.h" # include "bvh/embree.h"
@ -128,7 +132,11 @@ void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
scene = rtcNewScene(rtc_device); scene = rtcNewScene(rtc_device);
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) | const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
(compact ? RTC_SCENE_FLAG_COMPACT : RTC_SCENE_FLAG_NONE) | (compact ? RTC_SCENE_FLAG_COMPACT : RTC_SCENE_FLAG_NONE) |
RTC_SCENE_FLAG_ROBUST; RTC_SCENE_FLAG_ROBUST
# if EMBREE_MAJOR_VERSION >= 4
| RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS
# endif
;
rtcSetSceneFlags(scene, scene_flags); rtcSetSceneFlags(scene, scene_flags);
build_quality = dynamic ? RTC_BUILD_QUALITY_LOW : build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
(params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH : (params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
@ -226,6 +234,9 @@ void BVHEmbree::add_instance(Object *ob, int i)
rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene); rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
# if EMBREE_MAJOR_VERSION >= 4
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
# endif
rtcCommitGeometry(geom_id); rtcCommitGeometry(geom_id);
rtcAttachGeometryByID(scene, geom_id, i * 2); rtcAttachGeometryByID(scene, geom_id, i * 2);
@ -267,9 +278,13 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
set_tri_vertex_buffer(geom_id, mesh, false); set_tri_vertex_buffer(geom_id, mesh, false);
rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
# if EMBREE_MAJOR_VERSION >= 4
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
# else
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func); rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func);
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func); rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); # endif
rtcCommitGeometry(geom_id); rtcCommitGeometry(geom_id);
rtcAttachGeometryByID(scene, geom_id, i * 2); rtcAttachGeometryByID(scene, geom_id, i * 2);
@ -494,9 +509,13 @@ void BVHEmbree::add_points(const Object *ob, const PointCloud *pointcloud, int i
set_point_vertex_buffer(geom_id, pointcloud, false); set_point_vertex_buffer(geom_id, pointcloud, false);
rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
# if EMBREE_MAJOR_VERSION >= 4
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
# else
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_func_backface_cull); rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_func_backface_cull);
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func_backface_cull); rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func_backface_cull);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); # endif
rtcCommitGeometry(geom_id); rtcCommitGeometry(geom_id);
rtcAttachGeometryByID(scene, geom_id, i * 2); rtcAttachGeometryByID(scene, geom_id, i * 2);
@ -553,6 +572,10 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
set_curve_vertex_buffer(geom_id, hair, false); set_curve_vertex_buffer(geom_id, hair, false);
rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
# if EMBREE_MAJOR_VERSION >= 4
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
# else
if (hair->curve_shape == CURVE_RIBBON) { if (hair->curve_shape == CURVE_RIBBON) {
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func); rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func);
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func); rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func);
@ -562,7 +585,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
rtcSetGeometryOccludedFilterFunction(geom_id, rtcSetGeometryOccludedFilterFunction(geom_id,
kernel_embree_filter_occluded_func_backface_cull); kernel_embree_filter_occluded_func_backface_cull);
} }
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); # endif
rtcCommitGeometry(geom_id); rtcCommitGeometry(geom_id);
rtcAttachGeometryByID(scene, geom_id, i * 2 + 1); rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);

View File

@ -6,8 +6,13 @@
#ifdef WITH_EMBREE #ifdef WITH_EMBREE
# include <embree3/rtcore.h> # if EMBREE_MAJOR_VERSION >= 4
# include <embree3/rtcore_scene.h> # include <embree4/rtcore.h>
# include <embree4/rtcore_scene.h>
# else
# include <embree3/rtcore.h>
# include <embree3/rtcore_scene.h>
# endif
# include "bvh/bvh.h" # include "bvh/bvh.h"
# include "bvh/params.h" # include "bvh/params.h"

View File

@ -176,12 +176,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
else() else()
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so) set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
endif() endif()
list(APPEND LIB ${cycles_kernel_oneapi_lib}) list(APPEND LIB
if(WIN32) ${cycles_kernel_oneapi_lib}
list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY}) ${SYCL_LIBRARIES}
else() )
list(APPEND LIB ${SYCL_LIBRARY})
endif()
list(APPEND SRC list(APPEND SRC
${SRC_ONEAPI} ${SRC_ONEAPI}
) )

View File

@ -14,7 +14,11 @@
#endif #endif
#ifdef WITH_EMBREE #ifdef WITH_EMBREE
# include <embree3/rtcore.h> # if EMBREE_MAJOR_VERSION >= 4
# include <embree4/rtcore.h>
# else
# include <embree3/rtcore.h>
# endif
#endif #endif
#include "device/cpu/kernel.h" #include "device/cpu/kernel.h"

View File

@ -11,7 +11,11 @@
#endif #endif
#ifdef WITH_EMBREE #ifdef WITH_EMBREE
# include <embree3/rtcore.h> # if EMBREE_MAJOR_VERSION >= 4
# include <embree4/rtcore.h>
# else
# include <embree3/rtcore.h>
# endif
#endif #endif
#include "device/cpu/kernel.h" #include "device/cpu/kernel.h"

View File

@ -445,12 +445,10 @@ void MetalKernelPipeline::compile()
const std::string function_name = std::string("cycles_metal_") + const std::string function_name = std::string("cycles_metal_") +
device_kernel_as_string(device_kernel); device_kernel_as_string(device_kernel);
NSString *entryPoint = [@(function_name.c_str()) copy];
NSError *error = NULL; NSError *error = NULL;
if (@available(macOS 11.0, *)) { if (@available(macOS 11.0, *)) {
MTLFunctionDescriptor *func_desc = [MTLIntersectionFunctionDescriptor functionDescriptor]; MTLFunctionDescriptor *func_desc = [MTLIntersectionFunctionDescriptor functionDescriptor];
func_desc.name = entryPoint; func_desc.name = [@(function_name.c_str()) copy];
if (pso_type != PSO_GENERIC) { if (pso_type != PSO_GENERIC) {
func_desc.constantValues = GetConstantValues(&kernel_data_); func_desc.constantValues = GetConstantValues(&kernel_data_);
@ -462,8 +460,6 @@ void MetalKernelPipeline::compile()
function = [mtlLibrary newFunctionWithDescriptor:func_desc error:&error]; function = [mtlLibrary newFunctionWithDescriptor:func_desc error:&error];
} }
[entryPoint release];
if (function == nil) { if (function == nil) {
NSString *err = [error localizedDescription]; NSString *err = [error localizedDescription];
string errors = [err UTF8String]; string errors = [err UTF8String];
@ -471,7 +467,7 @@ void MetalKernelPipeline::compile()
return; return;
} }
function.label = [entryPoint copy]; function.label = [@(function_name.c_str()) copy];
if (use_metalrt) { if (use_metalrt) {
if (@available(macOS 11.0, *)) { if (@available(macOS 11.0, *)) {

View File

@ -80,6 +80,12 @@ if(EXISTS ${USD_INCLUDE_DIR}/pxr/imaging/hgiGL)
list(APPEND SRC_HD_CYCLES_HEADERS display_driver.h) list(APPEND SRC_HD_CYCLES_HEADERS display_driver.h)
endif() endif()
# Silence warning from USD headers using deprecated TBB header.
add_definitions(
-D__TBB_show_deprecation_message_atomic_H
-D__TBB_show_deprecation_message_task_H
)
include_directories(${INC}) include_directories(${INC})
include_directories(SYSTEM ${INC_SYS}) include_directories(SYSTEM ${INC_SYS})

View File

@ -4,6 +4,12 @@
#ifdef _WIN32 #ifdef _WIN32
// Include first to avoid "NOGDI" definition set in Cycles headers // Include first to avoid "NOGDI" definition set in Cycles headers
# ifndef NOMINMAX
# define NOMINMAX
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <Windows.h> # include <Windows.h>
#endif #endif

View File

@ -370,6 +370,16 @@ VtValue convertFromCyclesArray(const array<SrcType> &value)
return VtValue(convertedValue); return VtValue(convertedValue);
} }
template<> VtValue convertFromCyclesArray<float2, GfVec2f>(const array<float2> &value)
{
VtVec2fArray convertedValue;
convertedValue.reserve(value.size());
for (const auto &element : value) {
convertedValue.push_back(GfVec2f(element.x, element.y));
}
return VtValue(convertedValue);
}
template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value) template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
{ {
VtVec3fArray convertedValue; VtVec3fArray convertedValue;

View File

@ -7,6 +7,7 @@
#include "device/device.h" #include "device/device.h"
#include "device/memory.h" #include "device/memory.h"
#include "device/queue.h" #include "device/queue.h"
#include "integrator/pass_accessor_gpu.h"
#include "session/buffers.h" #include "session/buffers.h"
#include "util/log.h" #include "util/log.h"
#include "util/progress.h" #include "util/progress.h"
@ -105,4 +106,220 @@ Device *DenoiserGPU::ensure_denoiser_device(Progress *progress)
return denoiser_device; return denoiser_device;
} }
DenoiserGPU::DenoiseContext::DenoiseContext(Device *device, const DenoiseTask &task)
: denoise_params(task.params),
render_buffers(task.render_buffers),
buffer_params(task.buffer_params),
guiding_buffer(device, "denoiser guiding passes buffer", true),
num_samples(task.num_samples)
{
num_input_passes = 1;
if (denoise_params.use_pass_albedo) {
num_input_passes += 1;
use_pass_albedo = true;
pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO);
if (denoise_params.use_pass_normal) {
num_input_passes += 1;
use_pass_normal = true;
pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL);
}
}
if (denoise_params.temporally_stable) {
prev_output.device_pointer = render_buffers->buffer.device_pointer;
prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS);
prev_output.stride = buffer_params.stride;
prev_output.pass_stride = buffer_params.pass_stride;
num_input_passes += 1;
use_pass_motion = true;
pass_motion = buffer_params.get_pass_offset(PASS_MOTION);
}
use_guiding_passes = (num_input_passes - 1) > 0;
if (use_guiding_passes) {
if (task.allow_inplace_modification) {
guiding_params.device_pointer = render_buffers->buffer.device_pointer;
guiding_params.pass_albedo = pass_denoising_albedo;
guiding_params.pass_normal = pass_denoising_normal;
guiding_params.pass_flow = pass_motion;
guiding_params.stride = buffer_params.stride;
guiding_params.pass_stride = buffer_params.pass_stride;
}
else {
guiding_params.pass_stride = 0;
if (use_pass_albedo) {
guiding_params.pass_albedo = guiding_params.pass_stride;
guiding_params.pass_stride += 3;
}
if (use_pass_normal) {
guiding_params.pass_normal = guiding_params.pass_stride;
guiding_params.pass_stride += 3;
}
if (use_pass_motion) {
guiding_params.pass_flow = guiding_params.pass_stride;
guiding_params.pass_stride += 2;
}
guiding_params.stride = buffer_params.width;
guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
guiding_params.pass_stride);
guiding_params.device_pointer = guiding_buffer.device_pointer;
}
}
pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
}
bool DenoiserGPU::denoise_filter_color_postprocess(const DenoiseContext &context,
const DenoisePass &pass)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
&buffer_params.full_x,
&buffer_params.full_y,
&buffer_params.width,
&buffer_params.height,
&buffer_params.offset,
&buffer_params.stride,
&buffer_params.pass_stride,
&context.num_samples,
&pass.noisy_offset,
&pass.denoised_offset,
&context.pass_sample_count,
&pass.num_components,
&pass.use_compositing);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS, work_size, args);
}
bool DenoiserGPU::denoise_filter_color_preprocess(const DenoiseContext &context,
const DenoisePass &pass)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
&buffer_params.full_x,
&buffer_params.full_y,
&buffer_params.width,
&buffer_params.height,
&buffer_params.offset,
&buffer_params.stride,
&buffer_params.pass_stride,
&pass.denoised_offset);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_PREPROCESS, work_size, args);
}
bool DenoiserGPU::denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.guiding_params.device_pointer,
&context.guiding_params.pass_stride,
&context.guiding_params.pass_albedo,
&buffer_params.width,
&buffer_params.height);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO, work_size, args);
}
void DenoiserGPU::denoise_color_read(const DenoiseContext &context, const DenoisePass &pass)
{
PassAccessor::PassAccessInfo pass_access_info;
pass_access_info.type = pass.type;
pass_access_info.mode = PassMode::NOISY;
pass_access_info.offset = pass.noisy_offset;
/* Denoiser operates on passes which are used to calculate the approximation, and is never used
* on the approximation. The latter is not even possible because OptiX does not support
* denoising of semi-transparent pixels. */
pass_access_info.use_approximate_shadow_catcher = false;
pass_access_info.use_approximate_shadow_catcher_background = false;
pass_access_info.show_active_pixels = false;
/* TODO(sergey): Consider adding support of actual exposure, to avoid clamping in extreme cases.
*/
const PassAccessorGPU pass_accessor(
denoiser_queue_.get(), pass_access_info, 1.0f, context.num_samples);
PassAccessor::Destination destination(pass_access_info.type);
destination.d_pixels = context.render_buffers->buffer.device_pointer +
pass.denoised_offset * sizeof(float);
destination.num_components = 3;
destination.pixel_stride = context.buffer_params.pass_stride;
BufferParams buffer_params = context.buffer_params;
buffer_params.window_x = 0;
buffer_params.window_y = 0;
buffer_params.window_width = buffer_params.width;
buffer_params.window_height = buffer_params.height;
pass_accessor.get_render_tile_pixels(context.render_buffers, buffer_params, destination);
}
void DenoiserGPU::denoise_pass(DenoiseContext &context, PassType pass_type)
{
const BufferParams &buffer_params = context.buffer_params;
const DenoisePass pass(pass_type, buffer_params);
if (pass.noisy_offset == PASS_UNUSED) {
return;
}
if (pass.denoised_offset == PASS_UNUSED) {
LOG(DFATAL) << "Missing denoised pass " << pass_type_as_string(pass_type);
return;
}
if (pass.use_denoising_albedo) {
if (context.albedo_replaced_with_fake) {
LOG(ERROR) << "Pass which requires albedo is denoised after fake albedo has been set.";
return;
}
}
else if (context.use_guiding_passes && !context.albedo_replaced_with_fake) {
context.albedo_replaced_with_fake = true;
if (!denoise_filter_guiding_set_fake_albedo(context)) {
LOG(ERROR) << "Error replacing real albedo with the fake one.";
return;
}
}
/* Read and preprocess noisy color input pass. */
denoise_color_read(context, pass);
if (!denoise_filter_color_preprocess(context, pass)) {
LOG(ERROR) << "Error converting denoising passes to RGB buffer.";
return;
}
if (!denoise_run(context, pass)) {
LOG(ERROR) << "Error running denoiser.";
return;
}
/* Store result in the combined pass of the render buffer.
*
* This will scale the denoiser result up to match the number of, possibly per-pixel, samples. */
if (!denoise_filter_color_postprocess(context, pass)) {
LOG(ERROR) << "Error copying denoiser result to the denoised pass.";
return;
}
denoiser_queue_->synchronize();
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -21,6 +21,9 @@ class DenoiserGPU : public Denoiser {
bool allow_inplace_modification) override; bool allow_inplace_modification) override;
protected: protected:
class DenoisePass;
class DenoiseContext;
/* All the parameters needed to perform buffer denoising on a device. /* All the parameters needed to perform buffer denoising on a device.
* Is not really a task in its canonical terms (as in, is not an asynchronous running task). Is * Is not really a task in its canonical terms (as in, is not an asynchronous running task). Is
* more like a wrapper for all the arguments and parameters needed to perform denoising. Is a * more like a wrapper for all the arguments and parameters needed to perform denoising. Is a
@ -41,12 +44,105 @@ class DenoiserGPU : public Denoiser {
bool allow_inplace_modification; bool allow_inplace_modification;
}; };
/* Read input color pass from the render buffer into the memory which corresponds to the noisy
* input within the given context. Pixels are scaled to the number of samples, but are not
* preprocessed yet. */
void denoise_color_read(const DenoiseContext &context, const DenoisePass &pass);
/* Run corresponding filter kernels, preparing data for the denoiser or copying data from the
* denoiser result to the render buffer. */
bool denoise_filter_color_preprocess(const DenoiseContext &context, const DenoisePass &pass);
bool denoise_filter_color_postprocess(const DenoiseContext &context, const DenoisePass &pass);
bool denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context);
void denoise_pass(DenoiseContext &context, PassType pass_type);
/* Returns true if task is fully handled. */ /* Returns true if task is fully handled. */
virtual bool denoise_buffer(const DenoiseTask & /*task*/) = 0; virtual bool denoise_buffer(const DenoiseTask & /*task*/) = 0;
virtual bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) = 0;
virtual Device *ensure_denoiser_device(Progress *progress) override; virtual Device *ensure_denoiser_device(Progress *progress) override;
unique_ptr<DeviceQueue> denoiser_queue_; unique_ptr<DeviceQueue> denoiser_queue_;
class DenoisePass {
public:
DenoisePass(const PassType type, const BufferParams &buffer_params) : type(type)
{
noisy_offset = buffer_params.get_pass_offset(type, PassMode::NOISY);
denoised_offset = buffer_params.get_pass_offset(type, PassMode::DENOISED);
const PassInfo pass_info = Pass::get_info(type);
num_components = pass_info.num_components;
use_compositing = pass_info.use_compositing;
use_denoising_albedo = pass_info.use_denoising_albedo;
}
PassType type;
int noisy_offset;
int denoised_offset;
int num_components;
bool use_compositing;
bool use_denoising_albedo;
};
class DenoiseContext {
public:
explicit DenoiseContext(Device *device, const DenoiseTask &task);
const DenoiseParams &denoise_params;
RenderBuffers *render_buffers = nullptr;
const BufferParams &buffer_params;
/* Previous output. */
struct {
device_ptr device_pointer = 0;
int offset = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
} prev_output;
/* Device-side storage of the guiding passes. */
device_only_memory<float> guiding_buffer;
struct {
device_ptr device_pointer = 0;
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_albedo = PASS_UNUSED;
int pass_normal = PASS_UNUSED;
int pass_flow = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
} guiding_params;
/* Number of input passes. Including the color and extra auxiliary passes. */
int num_input_passes = 0;
bool use_guiding_passes = false;
bool use_pass_albedo = false;
bool use_pass_normal = false;
bool use_pass_motion = false;
int num_samples = 0;
int pass_sample_count = PASS_UNUSED;
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_denoising_albedo = PASS_UNUSED;
int pass_denoising_normal = PASS_UNUSED;
int pass_motion = PASS_UNUSED;
/* For passes which don't need albedo channel for denoising we replace the actual albedo with
* the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
* the fake values and denoising of passes which do need albedo can no longer happen. */
bool albedo_replaced_with_fake = false;
};
}; };
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -218,154 +218,6 @@ uint OptiXDenoiser::get_device_type_mask() const
return DEVICE_MASK_OPTIX; return DEVICE_MASK_OPTIX;
} }
class OptiXDenoiser::DenoiseContext {
public:
explicit DenoiseContext(OptiXDevice *device, const DenoiseTask &task)
: denoise_params(task.params),
render_buffers(task.render_buffers),
buffer_params(task.buffer_params),
guiding_buffer(device, "denoiser guiding passes buffer", true),
num_samples(task.num_samples)
{
num_input_passes = 1;
if (denoise_params.use_pass_albedo) {
num_input_passes += 1;
use_pass_albedo = true;
pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO);
if (denoise_params.use_pass_normal) {
num_input_passes += 1;
use_pass_normal = true;
pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL);
}
}
if (denoise_params.temporally_stable) {
prev_output.device_pointer = render_buffers->buffer.device_pointer;
prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS);
prev_output.stride = buffer_params.stride;
prev_output.pass_stride = buffer_params.pass_stride;
num_input_passes += 1;
use_pass_motion = true;
pass_motion = buffer_params.get_pass_offset(PASS_MOTION);
}
use_guiding_passes = (num_input_passes - 1) > 0;
if (use_guiding_passes) {
if (task.allow_inplace_modification) {
guiding_params.device_pointer = render_buffers->buffer.device_pointer;
guiding_params.pass_albedo = pass_denoising_albedo;
guiding_params.pass_normal = pass_denoising_normal;
guiding_params.pass_flow = pass_motion;
guiding_params.stride = buffer_params.stride;
guiding_params.pass_stride = buffer_params.pass_stride;
}
else {
guiding_params.pass_stride = 0;
if (use_pass_albedo) {
guiding_params.pass_albedo = guiding_params.pass_stride;
guiding_params.pass_stride += 3;
}
if (use_pass_normal) {
guiding_params.pass_normal = guiding_params.pass_stride;
guiding_params.pass_stride += 3;
}
if (use_pass_motion) {
guiding_params.pass_flow = guiding_params.pass_stride;
guiding_params.pass_stride += 2;
}
guiding_params.stride = buffer_params.width;
guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
guiding_params.pass_stride);
guiding_params.device_pointer = guiding_buffer.device_pointer;
}
}
pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
}
const DenoiseParams &denoise_params;
RenderBuffers *render_buffers = nullptr;
const BufferParams &buffer_params;
/* Previous output. */
struct {
device_ptr device_pointer = 0;
int offset = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
} prev_output;
/* Device-side storage of the guiding passes. */
device_only_memory<float> guiding_buffer;
struct {
device_ptr device_pointer = 0;
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_albedo = PASS_UNUSED;
int pass_normal = PASS_UNUSED;
int pass_flow = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
} guiding_params;
/* Number of input passes. Including the color and extra auxiliary passes. */
int num_input_passes = 0;
bool use_guiding_passes = false;
bool use_pass_albedo = false;
bool use_pass_normal = false;
bool use_pass_motion = false;
int num_samples = 0;
int pass_sample_count = PASS_UNUSED;
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_denoising_albedo = PASS_UNUSED;
int pass_denoising_normal = PASS_UNUSED;
int pass_motion = PASS_UNUSED;
/* For passes which don't need albedo channel for denoising we replace the actual albedo with
* the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
* the fake values and denoising of passes which do need albedo can no longer happen. */
bool albedo_replaced_with_fake = false;
};
class OptiXDenoiser::DenoisePass {
public:
DenoisePass(const PassType type, const BufferParams &buffer_params) : type(type)
{
noisy_offset = buffer_params.get_pass_offset(type, PassMode::NOISY);
denoised_offset = buffer_params.get_pass_offset(type, PassMode::DENOISED);
const PassInfo pass_info = Pass::get_info(type);
num_components = pass_info.num_components;
use_compositing = pass_info.use_compositing;
use_denoising_albedo = pass_info.use_denoising_albedo;
}
PassType type;
int noisy_offset;
int denoised_offset;
int num_components;
bool use_compositing;
bool use_denoising_albedo;
};
bool OptiXDenoiser::denoise_buffer(const DenoiseTask &task) bool OptiXDenoiser::denoise_buffer(const DenoiseTask &task)
{ {
OptiXDevice *const optix_device = static_cast<OptiXDevice *>(denoiser_device_); OptiXDevice *const optix_device = static_cast<OptiXDevice *>(denoiser_device_);
@ -421,151 +273,6 @@ bool OptiXDenoiser::denoise_filter_guiding_preprocess(const DenoiseContext &cont
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args); return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args);
} }
bool OptiXDenoiser::denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.guiding_params.device_pointer,
&context.guiding_params.pass_stride,
&context.guiding_params.pass_albedo,
&buffer_params.width,
&buffer_params.height);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO, work_size, args);
}
void OptiXDenoiser::denoise_pass(DenoiseContext &context, PassType pass_type)
{
const BufferParams &buffer_params = context.buffer_params;
const DenoisePass pass(pass_type, buffer_params);
if (pass.noisy_offset == PASS_UNUSED) {
return;
}
if (pass.denoised_offset == PASS_UNUSED) {
LOG(DFATAL) << "Missing denoised pass " << pass_type_as_string(pass_type);
return;
}
if (pass.use_denoising_albedo) {
if (context.albedo_replaced_with_fake) {
LOG(ERROR) << "Pass which requires albedo is denoised after fake albedo has been set.";
return;
}
}
else if (context.use_guiding_passes && !context.albedo_replaced_with_fake) {
context.albedo_replaced_with_fake = true;
if (!denoise_filter_guiding_set_fake_albedo(context)) {
LOG(ERROR) << "Error replacing real albedo with the fake one.";
return;
}
}
/* Read and preprocess noisy color input pass. */
denoise_color_read(context, pass);
if (!denoise_filter_color_preprocess(context, pass)) {
LOG(ERROR) << "Error converting denoising passes to RGB buffer.";
return;
}
if (!denoise_run(context, pass)) {
LOG(ERROR) << "Error running OptiX denoiser.";
return;
}
/* Store result in the combined pass of the render buffer.
*
* This will scale the denoiser result up to match the number of, possibly per-pixel, samples. */
if (!denoise_filter_color_postprocess(context, pass)) {
LOG(ERROR) << "Error copying denoiser result to the denoised pass.";
return;
}
denoiser_queue_->synchronize();
}
void OptiXDenoiser::denoise_color_read(const DenoiseContext &context, const DenoisePass &pass)
{
PassAccessor::PassAccessInfo pass_access_info;
pass_access_info.type = pass.type;
pass_access_info.mode = PassMode::NOISY;
pass_access_info.offset = pass.noisy_offset;
/* Denoiser operates on passes which are used to calculate the approximation, and is never used
* on the approximation. The latter is not even possible because OptiX does not support
* denoising of semi-transparent pixels. */
pass_access_info.use_approximate_shadow_catcher = false;
pass_access_info.use_approximate_shadow_catcher_background = false;
pass_access_info.show_active_pixels = false;
/* TODO(sergey): Consider adding support of actual exposure, to avoid clamping in extreme cases.
*/
const PassAccessorGPU pass_accessor(
denoiser_queue_.get(), pass_access_info, 1.0f, context.num_samples);
PassAccessor::Destination destination(pass_access_info.type);
destination.d_pixels = context.render_buffers->buffer.device_pointer +
pass.denoised_offset * sizeof(float);
destination.num_components = 3;
destination.pixel_stride = context.buffer_params.pass_stride;
BufferParams buffer_params = context.buffer_params;
buffer_params.window_x = 0;
buffer_params.window_y = 0;
buffer_params.window_width = buffer_params.width;
buffer_params.window_height = buffer_params.height;
pass_accessor.get_render_tile_pixels(context.render_buffers, buffer_params, destination);
}
bool OptiXDenoiser::denoise_filter_color_preprocess(const DenoiseContext &context,
const DenoisePass &pass)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
&buffer_params.full_x,
&buffer_params.full_y,
&buffer_params.width,
&buffer_params.height,
&buffer_params.offset,
&buffer_params.stride,
&buffer_params.pass_stride,
&pass.denoised_offset);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_PREPROCESS, work_size, args);
}
bool OptiXDenoiser::denoise_filter_color_postprocess(const DenoiseContext &context,
const DenoisePass &pass)
{
const BufferParams &buffer_params = context.buffer_params;
const int work_size = buffer_params.width * buffer_params.height;
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
&buffer_params.full_x,
&buffer_params.full_y,
&buffer_params.width,
&buffer_params.height,
&buffer_params.offset,
&buffer_params.stride,
&buffer_params.pass_stride,
&context.num_samples,
&pass.noisy_offset,
&pass.denoised_offset,
&context.pass_sample_count,
&pass.num_components,
&pass.use_compositing);
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS, work_size, args);
}
bool OptiXDenoiser::denoise_ensure(DenoiseContext &context) bool OptiXDenoiser::denoise_ensure(DenoiseContext &context)
{ {
if (!denoise_create_if_needed(context)) { if (!denoise_create_if_needed(context)) {

View File

@ -21,9 +21,6 @@ class OptiXDenoiser : public DenoiserGPU {
virtual uint get_device_type_mask() const override; virtual uint get_device_type_mask() const override;
private: private:
class DenoiseContext;
class DenoisePass;
virtual bool denoise_buffer(const DenoiseTask &task) override; virtual bool denoise_buffer(const DenoiseTask &task) override;
/* Read guiding passes from the render buffers, preprocess them in a way which is expected by /* Read guiding passes from the render buffers, preprocess them in a way which is expected by
@ -36,19 +33,6 @@ class OptiXDenoiser : public DenoiserGPU {
/* Set fake albedo pixels in the albedo guiding pass storage. /* Set fake albedo pixels in the albedo guiding pass storage.
* After this point only passes which do not need albedo for denoising can be processed. */ * After this point only passes which do not need albedo for denoising can be processed. */
bool denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context); bool denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context);
void denoise_pass(DenoiseContext &context, PassType pass_type);
/* Read input color pass from the render buffer into the memory which corresponds to the noisy
* input within the given context. Pixels are scaled to the number of samples, but are not
* preprocessed yet. */
void denoise_color_read(const DenoiseContext &context, const DenoisePass &pass);
/* Run corresponding filter kernels, preparing data for the denoiser or copying data from the
* denoiser result to the render buffer. */
bool denoise_filter_color_preprocess(const DenoiseContext &context, const DenoisePass &pass);
bool denoise_filter_color_postprocess(const DenoiseContext &context, const DenoisePass &pass);
/* Make sure the OptiX denoiser is created and configured. */ /* Make sure the OptiX denoiser is created and configured. */
bool denoise_ensure(DenoiseContext &context); bool denoise_ensure(DenoiseContext &context);
@ -61,7 +45,7 @@ class OptiXDenoiser : public DenoiserGPU {
bool denoise_configure_if_needed(DenoiseContext &context); bool denoise_configure_if_needed(DenoiseContext &context);
/* Run configured denoiser. */ /* Run configured denoiser. */
bool denoise_run(const DenoiseContext &context, const DenoisePass &pass); bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) override;
OptixDenoiser optix_denoiser_ = nullptr; OptixDenoiser optix_denoiser_ = nullptr;

View File

@ -109,6 +109,11 @@ class PassAccessor {
/* Set pass data for the given render buffers. Used for baking to read from passes. */ /* Set pass data for the given render buffers. Used for baking to read from passes. */
bool set_render_tile_pixels(RenderBuffers *render_buffers, const Source &source); bool set_render_tile_pixels(RenderBuffers *render_buffers, const Source &source);
const PassAccessInfo &get_pass_access_info() const
{
return pass_access_info_;
}
protected: protected:
virtual void init_kernel_film_convert(KernelFilmConvert *kfilm_convert, virtual void init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
const BufferParams &buffer_params, const BufferParams &buffer_params,

View File

@ -1036,7 +1036,12 @@ bool PathTrace::get_render_tile_pixels(const PassAccessor &pass_accessor,
} }
if (big_tile_denoise_work_ && render_state_.has_denoised_result) { if (big_tile_denoise_work_ && render_state_.has_denoised_result) {
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination); /* Only use the big tile denoised buffer to access the denoised passes.
* The guiding passes are allowed to be modified in-place for the needs of the denoiser,
* so copy those from the original devices buffers. */
if (pass_accessor.get_pass_access_info().mode == PassMode::DENOISED) {
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination);
}
} }
bool success = true; bool success = true;

View File

@ -362,7 +362,7 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
# endif # endif
# ifdef WITH_CYCLES_DEBUG # ifdef WITH_CYCLES_DEBUG
/* Check if the training/radiance samples generated py the path segment storage are valid.*/ /* Check if the training/radiance samples generated by the path segment storage are valid. */
if (VLOG_WORK_IS_ON) { if (VLOG_WORK_IS_ON) {
const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples(); const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
if (!validSamples) { if (!validSamples) {

View File

@ -5,8 +5,13 @@
#pragma once #pragma once
#include <embree3/rtcore_ray.h> #if EMBREE_MAJOR_VERSION >= 4
#include <embree3/rtcore_scene.h> # include <embree4/rtcore_ray.h>
# include <embree4/rtcore_scene.h>
#else
# include <embree3/rtcore_ray.h>
# include <embree3/rtcore_scene.h>
#endif
#include "kernel/device/cpu/compat.h" #include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/globals.h" #include "kernel/device/cpu/globals.h"
@ -28,11 +33,84 @@ using numhit_t = uint8_t;
using numhit_t = uint32_t; using numhit_t = uint32_t;
#endif #endif
#define CYCLES_EMBREE_USED_FEATURES \
(RTCFeatureFlags)(RTC_FEATURE_FLAG_TRIANGLE | RTC_FEATURE_FLAG_INSTANCE | \
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_FEATURE_FLAG_POINT | \
RTC_FEATURE_FLAG_MOTION_BLUR | RTC_FEATURE_FLAG_ROUND_CATMULL_ROM_CURVE | \
RTC_FEATURE_FLAG_FLAT_CATMULL_ROM_CURVE)
#define EMBREE_IS_HAIR(x) (x & 1) #define EMBREE_IS_HAIR(x) (x & 1)
#if EMBREE_MAJOR_VERSION < 4
# define rtcGetGeometryUserDataFromScene(scene, id) \
(rtcGetGeometryUserData(rtcGetGeometry(scene, id)))
#endif
/* Intersection context. */ /* Intersection context. */
struct CCLIntersectContext { struct CCLFirstHitContext
#if EMBREE_MAJOR_VERSION >= 4
: public RTCRayQueryContext
#endif
{
KernelGlobals kg;
/* For avoiding self intersections */
const Ray *ray;
};
struct CCLShadowContext
#if EMBREE_MAJOR_VERSION >= 4
: public RTCRayQueryContext
#endif
{
#if EMBREE_MAJOR_VERSION >= 4
KernelGlobals kg;
const Ray *ray;
#endif
IntegratorShadowState isect_s;
float throughput;
bool opaque_hit;
numhit_t max_hits;
numhit_t num_hits;
numhit_t num_recorded_hits;
};
struct CCLLocalContext
#if EMBREE_MAJOR_VERSION >= 4
: public RTCRayQueryContext
#endif
{
#if EMBREE_MAJOR_VERSION >= 4
KernelGlobals kg;
const Ray *ray;
numhit_t max_hits;
#endif
int local_object_id;
LocalIntersection *local_isect;
uint *lcg_state;
bool is_sss;
};
struct CCLVolumeContext
#if EMBREE_MAJOR_VERSION >= 4
: public RTCRayQueryContext
#endif
{
#if EMBREE_MAJOR_VERSION >= 4
KernelGlobals kg;
const Ray *ray;
numhit_t max_hits;
numhit_t num_hits;
#endif
Intersection *vol_isect;
};
#if EMBREE_MAJOR_VERSION < 4
struct CCLIntersectContext : public RTCIntersectContext,
public CCLFirstHitContext,
public CCLShadowContext,
public CCLLocalContext,
public CCLVolumeContext {
typedef enum { typedef enum {
RAY_REGULAR = 0, RAY_REGULAR = 0,
RAY_SHADOW_ALL = 1, RAY_SHADOW_ALL = 1,
@ -41,28 +119,8 @@ struct CCLIntersectContext {
RAY_VOLUME_ALL = 4, RAY_VOLUME_ALL = 4,
} RayType; } RayType;
KernelGlobals kg;
RayType type; RayType type;
/* For avoiding self intersections */
const Ray *ray;
/* for shadow rays */
IntegratorShadowState isect_s;
numhit_t max_hits;
numhit_t num_hits;
numhit_t num_recorded_hits;
float throughput;
bool opaque_hit;
/* for SSS Rays: */
LocalIntersection *local_isect;
int local_object_id;
uint *lcg_state;
/* for Volume */
Intersection *vol_isect;
CCLIntersectContext(KernelGlobals kg_, RayType type_) CCLIntersectContext(KernelGlobals kg_, RayType type_)
{ {
kg = kg_; kg = kg_;
@ -79,17 +137,7 @@ struct CCLIntersectContext {
lcg_state = NULL; lcg_state = NULL;
} }
}; };
#endif
class IntersectContext {
public:
IntersectContext(CCLIntersectContext *ctx)
{
rtcInitIntersectContext(&context);
userRayExt = ctx;
}
RTCIntersectContext context;
CCLIntersectContext *userRayExt;
};
/* Utilities. */ /* Utilities. */
@ -173,13 +221,12 @@ ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg,
{ {
intptr_t prim_offset; intptr_t prim_offset;
if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) { if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData( RTCScene inst_scene = (RTCScene)rtcGetGeometryUserDataFromScene(kernel_data.device_bvh,
rtcGetGeometry(kernel_data.device_bvh, hit->instID[0])); hit->instID[0]);
prim_offset = intptr_t(rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID))); prim_offset = intptr_t(rtcGetGeometryUserDataFromScene(inst_scene, hit->geomID));
} }
else { else {
prim_offset = intptr_t( prim_offset = intptr_t(rtcGetGeometryUserDataFromScene(kernel_data.device_bvh, hit->geomID));
rtcGetGeometryUserData(rtcGetGeometry(kernel_data.device_bvh, hit->geomID)));
} }
kernel_embree_convert_hit(kg, ray, hit, isect, prim_offset); kernel_embree_convert_hit(kg, ray, hit, isect, prim_offset);
} }
@ -211,7 +258,11 @@ ccl_device void kernel_embree_filter_intersection_func(const RTCFilterFunctionNA
assert(args->N == 1); assert(args->N == 1);
RTCHit *hit = (RTCHit *)args->hit; RTCHit *hit = (RTCHit *)args->hit;
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; #if EMBREE_MAJOR_VERSION >= 4
CCLFirstHitContext *ctx = (CCLFirstHitContext *)(args->context);
#else
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
#endif
const KernelGlobalsCPU *kg = ctx->kg; const KernelGlobalsCPU *kg = ctx->kg;
const Ray *cray = ctx->ray; const Ray *cray = ctx->ray;
@ -226,205 +277,257 @@ ccl_device void kernel_embree_filter_intersection_func(const RTCFilterFunctionNA
* as well as filtering for volume objects happen here. * as well as filtering for volume objects happen here.
* Cycles' own BVH does that directly inside the traversal calls. * Cycles' own BVH does that directly inside the traversal calls.
*/ */
ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArguments *args) ccl_device void kernel_embree_filter_occluded_shadow_all_func(
const RTCFilterFunctionNArguments *args)
{ {
/* Current implementation in Cycles assumes only single-ray intersection queries. */ /* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1); assert(args->N == 1);
RTCRay *ray = (RTCRay *)args->ray; RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit; RTCHit *hit = (RTCHit *)args->hit;
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; #if EMBREE_MAJOR_VERSION >= 4
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
#else
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
#endif
const KernelGlobalsCPU *kg = ctx->kg; const KernelGlobalsCPU *kg = ctx->kg;
const Ray *cray = ctx->ray; const Ray *cray = ctx->ray;
Intersection current_isect;
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
*args->valid = 0;
return;
}
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
ctx->opaque_hit = true;
return;
}
++ctx->num_hits;
/* Always use baked shadow transparency for curves. */
if (current_isect.type & PRIMITIVE_CURVE) {
ctx->throughput *= intersection_curve_shadow_transparency(
kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
ctx->opaque_hit = true;
return;
}
else {
*args->valid = 0;
return;
}
}
/* Test if we need to record this transparent intersection. */
const numhit_t max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
if (ctx->num_recorded_hits < max_record_hits) {
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
numhit_t isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= max_record_hits) {
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
numhit_t max_recorded_hit = numhit_t(0);
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
max_t = isect_t;
}
}
if (num_recorded_hits >= max_record_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
ray->tfar = max(current_isect.t, max_t);
}
integrator_state_write_shadow_isect(ctx->isect_s, &current_isect, isect_index);
}
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed. */
++ctx->num_recorded_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
ccl_device_forceinline void kernel_embree_filter_occluded_local_func(
const RTCFilterFunctionNArguments *args)
{
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
#if EMBREE_MAJOR_VERSION >= 4
CCLLocalContext *ctx = (CCLLocalContext *)(args->context);
#else
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
#endif
const KernelGlobalsCPU *kg = ctx->kg;
const Ray *cray = ctx->ray;
/* Check if it's hitting the correct object. */
Intersection current_isect;
if (ctx->is_sss) {
kernel_embree_convert_sss_hit(kg,
ray,
hit,
&current_isect,
ctx->local_object_id,
reinterpret_cast<intptr_t>(args->geometryUserPtr));
}
else {
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (ctx->local_object_id != current_isect.object) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
}
if (intersection_skip_self_local(cray->self, current_isect.prim)) {
*args->valid = 0;
return;
}
/* No intersection information requested, just return a hit. */
if (ctx->max_hits == 0) {
return;
}
/* Ignore curves. */
if (EMBREE_IS_HAIR(hit->geomID)) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
LocalIntersection *local_isect = ctx->local_isect;
int hit_idx = 0;
if (ctx->lcg_state) {
/* See triangle_intersect_subsurface() for the native equivalent. */
for (int i = min((int)ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if (local_isect->hits[i].t == ray->tfar) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
}
local_isect->num_hits++;
if (local_isect->num_hits <= ctx->max_hits) {
hit_idx = local_isect->num_hits - 1;
}
else {
/* reservoir sampling: if we are at the maximum number of
* hits, randomly replace element or skip it */
hit_idx = lcg_step_uint(ctx->lcg_state) % local_isect->num_hits;
if (hit_idx >= ctx->max_hits) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
}
}
else {
/* Record closest intersection only. */
if (local_isect->num_hits && current_isect.t > local_isect->hits[0].t) {
*args->valid = 0;
return;
}
local_isect->num_hits = 1;
}
/* record intersection */
local_isect->hits[hit_idx] = current_isect;
local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
ccl_device_forceinline void kernel_embree_filter_occluded_volume_all_func(
const RTCFilterFunctionNArguments *args)
{
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
#if EMBREE_MAJOR_VERSION >= 4
CCLVolumeContext *ctx = (CCLVolumeContext *)(args->context);
#else
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
#endif
const KernelGlobalsCPU *kg = ctx->kg;
const Ray *cray = ctx->ray;
/* Append the intersection to the end of the array. */
if (ctx->num_hits < ctx->max_hits) {
Intersection current_isect;
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
*args->valid = 0;
return;
}
Intersection *isect = &ctx->vol_isect[ctx->num_hits];
++ctx->num_hits;
*isect = current_isect;
/* Only primitives from volume object. */
uint tri_object = isect->object;
int object_flag = kernel_data_fetch(object_flag, tri_object);
if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
--ctx->num_hits;
}
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
}
#if EMBREE_MAJOR_VERSION < 4
ccl_device_forceinline void kernel_embree_filter_occluded_func(
const RTCFilterFunctionNArguments *args)
{
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
switch (ctx->type) { switch (ctx->type) {
case CCLIntersectContext::RAY_SHADOW_ALL: { case CCLIntersectContext::RAY_SHADOW_ALL:
Intersection current_isect; kernel_embree_filter_occluded_shadow_all_func(args);
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
*args->valid = 0;
return;
}
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
ctx->opaque_hit = true;
return;
}
++ctx->num_hits;
/* Always use baked shadow transparency for curves. */
if (current_isect.type & PRIMITIVE_CURVE) {
ctx->throughput *= intersection_curve_shadow_transparency(
kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
ctx->opaque_hit = true;
return;
}
else {
*args->valid = 0;
return;
}
}
/* Test if we need to record this transparent intersection. */
const numhit_t max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
if (ctx->num_recorded_hits < max_record_hits) {
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
numhit_t isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= max_record_hits) {
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
numhit_t max_recorded_hit = numhit_t(0);
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
max_t = isect_t;
}
}
if (num_recorded_hits >= max_record_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
ray->tfar = max(current_isect.t, max_t);
}
integrator_state_write_shadow_isect(ctx->isect_s, &current_isect, isect_index);
}
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed. */
++ctx->num_recorded_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
break; break;
}
case CCLIntersectContext::RAY_LOCAL: case CCLIntersectContext::RAY_LOCAL:
case CCLIntersectContext::RAY_SSS: { case CCLIntersectContext::RAY_SSS:
/* Check if it's hitting the correct object. */ kernel_embree_filter_occluded_local_func(args);
Intersection current_isect;
if (ctx->type == CCLIntersectContext::RAY_SSS) {
kernel_embree_convert_sss_hit(kg,
ray,
hit,
&current_isect,
ctx->local_object_id,
reinterpret_cast<intptr_t>(args->geometryUserPtr));
}
else {
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (ctx->local_object_id != current_isect.object) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
break;
}
}
if (intersection_skip_self_local(cray->self, current_isect.prim)) {
*args->valid = 0;
return;
}
/* No intersection information requested, just return a hit. */
if (ctx->max_hits == 0) {
break;
}
/* Ignore curves. */
if (EMBREE_IS_HAIR(hit->geomID)) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
break;
}
LocalIntersection *local_isect = ctx->local_isect;
int hit_idx = 0;
if (ctx->lcg_state) {
/* See triangle_intersect_subsurface() for the native equivalent. */
for (int i = min((int)ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if (local_isect->hits[i].t == ray->tfar) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
}
local_isect->num_hits++;
if (local_isect->num_hits <= ctx->max_hits) {
hit_idx = local_isect->num_hits - 1;
}
else {
/* reservoir sampling: if we are at the maximum number of
* hits, randomly replace element or skip it */
hit_idx = lcg_step_uint(ctx->lcg_state) % local_isect->num_hits;
if (hit_idx >= ctx->max_hits) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
return;
}
}
}
else {
/* Record closest intersection only. */
if (local_isect->num_hits && current_isect.t > local_isect->hits[0].t) {
*args->valid = 0;
return;
}
local_isect->num_hits = 1;
}
/* record intersection */
local_isect->hits[hit_idx] = current_isect;
local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
/* This tells Embree to continue tracing. */
*args->valid = 0;
break; break;
} case CCLIntersectContext::RAY_VOLUME_ALL:
case CCLIntersectContext::RAY_VOLUME_ALL: { kernel_embree_filter_occluded_volume_all_func(args);
/* Append the intersection to the end of the array. */
if (ctx->num_hits < ctx->max_hits) {
Intersection current_isect;
kernel_embree_convert_hit(
kg, ray, hit, &current_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
*args->valid = 0;
return;
}
Intersection *isect = &ctx->vol_isect[ctx->num_hits];
++ctx->num_hits;
*isect = current_isect;
/* Only primitives from volume object. */
uint tri_object = isect->object;
int object_flag = kernel_data_fetch(object_flag, tri_object);
if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
--ctx->num_hits;
}
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
break; break;
}
case CCLIntersectContext::RAY_REGULAR: case CCLIntersectContext::RAY_REGULAR:
default: default:
if (kernel_embree_is_self_intersection( /* We should never reach this point, because
kg, hit, cray, reinterpret_cast<intptr_t>(args->geometryUserPtr))) { * REGULAR intersection is handled in intersection filter. */
*args->valid = 0; kernel_assert(false);
return;
}
break; break;
} }
} }
@ -441,7 +544,7 @@ ccl_device void kernel_embree_filter_func_backface_cull(const RTCFilterFunctionN
return; return;
} }
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; CCLIntersectContext *ctx = ((CCLIntersectContext *)args->context);
const KernelGlobalsCPU *kg = ctx->kg; const KernelGlobalsCPU *kg = ctx->kg;
const Ray *cray = ctx->ray; const Ray *cray = ctx->ray;
@ -467,6 +570,8 @@ ccl_device void kernel_embree_filter_occluded_func_backface_cull(
kernel_embree_filter_occluded_func(args); kernel_embree_filter_occluded_func(args);
} }
#endif
/* Scene intersection. */ /* Scene intersection. */
ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg, ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg,
@ -475,12 +580,29 @@ ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg,
ccl_private Intersection *isect) ccl_private Intersection *isect)
{ {
isect->t = ray->tmax; isect->t = ray->tmax;
#if EMBREE_MAJOR_VERSION >= 4
CCLFirstHitContext ctx;
rtcInitRayQueryContext(&ctx);
ctx.kg = kg;
#else
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_REGULAR); CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_REGULAR);
IntersectContext rtc_ctx(&ctx); rtcInitIntersectContext(&ctx);
#endif
RTCRayHit ray_hit; RTCRayHit ray_hit;
ctx.ray = ray; ctx.ray = ray;
kernel_embree_setup_rayhit(*ray, ray_hit, visibility); kernel_embree_setup_rayhit(*ray, ray_hit, visibility);
rtcIntersect1(kernel_data.device_bvh, &rtc_ctx.context, &ray_hit);
#if EMBREE_MAJOR_VERSION >= 4
RTCIntersectArguments args;
rtcInitIntersectArguments(&args);
args.filter = (RTCFilterFunctionN)kernel_embree_filter_intersection_func;
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
args.context = &ctx;
rtcIntersect1(kernel_data.device_bvh, &ray_hit, &args);
#else
rtcIntersect1(kernel_data.device_bvh, &ctx, &ray_hit);
#endif
if (ray_hit.hit.geomID == RTC_INVALID_GEOMETRY_ID || if (ray_hit.hit.geomID == RTC_INVALID_GEOMETRY_ID ||
ray_hit.hit.primID == RTC_INVALID_GEOMETRY_ID) { ray_hit.hit.primID == RTC_INVALID_GEOMETRY_ID) {
return false; return false;
@ -500,8 +622,16 @@ ccl_device_intersect bool kernel_embree_intersect_local(KernelGlobals kg,
{ {
const bool has_bvh = !(kernel_data_fetch(object_flag, local_object) & const bool has_bvh = !(kernel_data_fetch(object_flag, local_object) &
SD_OBJECT_TRANSFORM_APPLIED); SD_OBJECT_TRANSFORM_APPLIED);
# if EMBREE_MAJOR_VERSION >= 4
CCLLocalContext ctx;
rtcInitRayQueryContext(&ctx);
ctx.kg = kg;
# else
CCLIntersectContext ctx(kg, CCLIntersectContext ctx(kg,
has_bvh ? CCLIntersectContext::RAY_SSS : CCLIntersectContext::RAY_LOCAL); has_bvh ? CCLIntersectContext::RAY_SSS : CCLIntersectContext::RAY_LOCAL);
rtcInitIntersectContext(&ctx);
# endif
ctx.is_sss = has_bvh;
ctx.lcg_state = lcg_state; ctx.lcg_state = lcg_state;
ctx.max_hits = max_hits; ctx.max_hits = max_hits;
ctx.ray = ray; ctx.ray = ray;
@ -510,36 +640,49 @@ ccl_device_intersect bool kernel_embree_intersect_local(KernelGlobals kg,
local_isect->num_hits = 0; local_isect->num_hits = 0;
} }
ctx.local_object_id = local_object; ctx.local_object_id = local_object;
IntersectContext rtc_ctx(&ctx);
RTCRay rtc_ray; RTCRay rtc_ray;
kernel_embree_setup_ray(*ray, rtc_ray, PATH_RAY_ALL_VISIBILITY); kernel_embree_setup_ray(*ray, rtc_ray, PATH_RAY_ALL_VISIBILITY);
# if EMBREE_MAJOR_VERSION >= 4
RTCOccludedArguments args;
rtcInitOccludedArguments(&args);
args.filter = (RTCFilterFunctionN)(kernel_embree_filter_occluded_local_func);
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
args.context = &ctx;
# endif
/* If this object has its own BVH, use it. */ /* If this object has its own BVH, use it. */
if (has_bvh) { if (has_bvh) {
RTCGeometry geom = rtcGetGeometry(kernel_data.device_bvh, local_object * 2); float3 P = ray->P;
if (geom) { float3 dir = ray->D;
float3 P = ray->P; float3 idir = ray->D;
float3 dir = ray->D; bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
float3 idir = ray->D;
bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
rtc_ray.org_x = P.x; rtc_ray.org_x = P.x;
rtc_ray.org_y = P.y; rtc_ray.org_y = P.y;
rtc_ray.org_z = P.z; rtc_ray.org_z = P.z;
rtc_ray.dir_x = dir.x; rtc_ray.dir_x = dir.x;
rtc_ray.dir_y = dir.y; rtc_ray.dir_y = dir.y;
rtc_ray.dir_z = dir.z; rtc_ray.dir_z = dir.z;
rtc_ray.tnear = ray->tmin; rtc_ray.tnear = ray->tmin;
rtc_ray.tfar = ray->tmax; rtc_ray.tfar = ray->tmax;
RTCScene scene = (RTCScene)rtcGetGeometryUserData(geom); RTCScene scene = (RTCScene)rtcGetGeometryUserDataFromScene(kernel_data.device_bvh,
kernel_assert(scene); local_object * 2);
if (scene) { kernel_assert(scene);
rtcOccluded1(scene, &rtc_ctx.context, &rtc_ray); if (scene) {
} # if EMBREE_MAJOR_VERSION >= 4
rtcOccluded1(scene, &rtc_ray, &args);
# else
rtcOccluded1(scene, &ctx, &rtc_ray);
# endif
} }
} }
else { else {
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray); # if EMBREE_MAJOR_VERSION >= 4
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
# else
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
# endif
} }
/* rtcOccluded1 sets tfar to -inf if a hit was found. */ /* rtcOccluded1 sets tfar to -inf if a hit was found. */
@ -556,14 +699,32 @@ ccl_device_intersect bool kernel_embree_intersect_shadow_all(KernelGlobals kg,
ccl_private uint *num_recorded_hits, ccl_private uint *num_recorded_hits,
ccl_private float *throughput) ccl_private float *throughput)
{ {
# if EMBREE_MAJOR_VERSION >= 4
CCLShadowContext ctx;
rtcInitRayQueryContext(&ctx);
ctx.kg = kg;
# else
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL); CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL);
rtcInitIntersectContext(&ctx);
# endif
ctx.num_hits = ctx.num_recorded_hits = numhit_t(0);
ctx.throughput = 1.0f;
ctx.opaque_hit = false;
ctx.isect_s = state; ctx.isect_s = state;
ctx.max_hits = numhit_t(max_hits); ctx.max_hits = numhit_t(max_hits);
ctx.ray = ray; ctx.ray = ray;
IntersectContext rtc_ctx(&ctx);
RTCRay rtc_ray; RTCRay rtc_ray;
kernel_embree_setup_ray(*ray, rtc_ray, visibility); kernel_embree_setup_ray(*ray, rtc_ray, visibility);
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray); # if EMBREE_MAJOR_VERSION >= 4
RTCOccludedArguments args;
rtcInitOccludedArguments(&args);
args.filter = (RTCFilterFunctionN)kernel_embree_filter_occluded_shadow_all_func;
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
args.context = &ctx;
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
# else
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
# endif
*num_recorded_hits = ctx.num_recorded_hits; *num_recorded_hits = ctx.num_recorded_hits;
*throughput = ctx.throughput; *throughput = ctx.throughput;
@ -578,15 +739,30 @@ ccl_device_intersect uint kernel_embree_intersect_volume(KernelGlobals kg,
const uint max_hits, const uint max_hits,
const uint visibility) const uint visibility)
{ {
# if EMBREE_MAJOR_VERSION >= 4
CCLVolumeContext ctx;
rtcInitRayQueryContext(&ctx);
ctx.kg = kg;
# else
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL); CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL);
rtcInitIntersectContext(&ctx);
# endif
ctx.vol_isect = isect; ctx.vol_isect = isect;
ctx.max_hits = numhit_t(max_hits); ctx.max_hits = numhit_t(max_hits);
ctx.num_hits = numhit_t(0); ctx.num_hits = numhit_t(0);
ctx.ray = ray; ctx.ray = ray;
IntersectContext rtc_ctx(&ctx);
RTCRay rtc_ray; RTCRay rtc_ray;
kernel_embree_setup_ray(*ray, rtc_ray, visibility); kernel_embree_setup_ray(*ray, rtc_ray, visibility);
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray); # if EMBREE_MAJOR_VERSION >= 4
RTCOccludedArguments args;
rtcInitOccludedArguments(&args);
args.filter = (RTCFilterFunctionN)kernel_embree_filter_occluded_volume_all_func;
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
args.context = &ctx;
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
# else
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
# endif
return ctx.num_hits; return ctx.num_hits;
} }
#endif #endif

View File

@ -74,57 +74,43 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals kg,
} }
} }
ccl_device_inline void motion_triangle_vertices( ccl_device_inline void motion_triangle_compute_info(KernelGlobals kg,
KernelGlobals kg, int object, int prim, float time, float3 verts[3]) int object,
float time,
int prim,
ccl_private uint3 *tri_vindex,
ccl_private int *numsteps,
ccl_private int *numverts,
ccl_private int *step,
ccl_private float *t)
{ {
/* get motion info */ /* Get object motion info. */
int numsteps, numverts; object_motion_info(kg, object, numsteps, numverts, NULL);
object_motion_info(kg, object, &numsteps, &numverts, NULL);
/* figure out which steps we need to fetch and their interpolation factor */
int maxstep = numsteps * 2;
int step = min((int)(time * maxstep), maxstep - 1);
float t = time * maxstep - step;
/* find attribute */
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* fetch vertex coordinates */
float3 next_verts[3];
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
/* interpolate between steps */
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
}
ccl_device_inline void motion_triangle_vertices_and_normals(
KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
{
/* get motion info */
int numsteps, numverts;
object_motion_info(kg, object, &numsteps, &numverts, NULL);
/* Figure out which steps we need to fetch and their interpolation factor. */ /* Figure out which steps we need to fetch and their interpolation factor. */
int maxstep = numsteps * 2; int maxstep = *numsteps * 2;
int step = min((int)(time * maxstep), maxstep - 1); *step = min((int)(time * maxstep), maxstep - 1);
float t = time * maxstep - step; *t = time * maxstep - *step;
/* Get triangle indices. */
*tri_vindex = kernel_data_fetch(tri_vindex, prim);
}
ccl_device_inline void motion_triangle_vertices(KernelGlobals kg,
int object,
uint3 tri_vindex,
int numsteps,
int numverts,
int step,
float t,
float3 verts[3])
{
/* Find attribute. */ /* Find attribute. */
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION); int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION);
kernel_assert(offset != ATTR_STD_NOT_FOUND); kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */ /* Fetch vertex coordinates. */
float3 next_verts[3]; float3 next_verts[3];
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
@ -132,60 +118,90 @@ ccl_device_inline void motion_triangle_vertices_and_normals(
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0]; verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1]; verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2]; verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
}
/* Compute smooth normal. */ ccl_device_inline void motion_triangle_vertices(
KernelGlobals kg, int object, int prim, float time, float3 verts[3])
{
int numsteps, numverts, step;
float t;
uint3 tri_vindex;
motion_triangle_compute_info(
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
motion_triangle_vertices(kg, object, tri_vindex, numsteps, numverts, step, t, verts);
}
ccl_device_inline void motion_triangle_normals(KernelGlobals kg,
int object,
uint3 tri_vindex,
int numsteps,
int numverts,
int step,
float t,
float3 normals[3])
{
/* Find attribute. */ /* Find attribute. */
offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL); int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
kernel_assert(offset != ATTR_STD_NOT_FOUND); kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */ /* Fetch normals. */
float3 next_normals[3]; float3 next_normals[3];
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals); motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
motion_triangle_normals_for_step( motion_triangle_normals_for_step(
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals); kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
/* Interpolate between steps. */ /* Interpolate between steps. */
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0]; normals[0] = normalize((1.0f - t) * normals[0] + t * next_normals[0]);
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1]; normals[1] = normalize((1.0f - t) * normals[1] + t * next_normals[1]);
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2]; normals[2] = normalize((1.0f - t) * normals[2] + t * next_normals[2]);
}
ccl_device_inline void motion_triangle_vertices_and_normals(
KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
{
int numsteps, numverts, step;
float t;
uint3 tri_vindex;
motion_triangle_compute_info(
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
motion_triangle_vertices(kg, object, tri_vindex, numsteps, numverts, step, t, verts);
motion_triangle_normals(kg, object, tri_vindex, numsteps, numverts, step, t, normals);
}
ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals kg,
float3 Ng,
int object,
uint3 tri_vindex,
int numsteps,
int numverts,
int step,
float t,
float u,
float v)
{
float3 normals[3];
motion_triangle_normals(kg, object, tri_vindex, numsteps, numverts, step, t, normals);
/* Interpolate between normals. */
float w = 1.0f - u - v;
float3 N = safe_normalize(w * normals[0] + u * normals[1] + v * normals[2]);
return is_zero(N) ? Ng : N;
} }
ccl_device_inline float3 motion_triangle_smooth_normal( ccl_device_inline float3 motion_triangle_smooth_normal(
KernelGlobals kg, float3 Ng, int object, int prim, float u, float v, float time) KernelGlobals kg, float3 Ng, int object, int prim, float u, float v, float time)
{ {
/* get motion info */ int numsteps, numverts, step;
int numsteps, numverts; float t;
object_motion_info(kg, object, &numsteps, &numverts, NULL); uint3 tri_vindex;
motion_triangle_compute_info(
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
/* figure out which steps we need to fetch and their interpolation factor */ return motion_triangle_smooth_normal(
int maxstep = numsteps * 2; kg, Ng, object, tri_vindex, numsteps, numverts, step, t, u, v);
int step = min((int)(time * maxstep), maxstep - 1);
float t = time * maxstep - step;
/* find attribute */
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* fetch normals */
float3 normals[3], next_normals[3];
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
motion_triangle_normals_for_step(
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
/* interpolate between steps */
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
/* interpolate between vertices */
float w = 1.0f - u - v;
float3 N = safe_normalize(u * normals[0] + v * normals[1] + w * normals[2]);
return is_zero(N) ? Ng : N;
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -32,30 +32,17 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
{ {
/* Get shader. */ /* Get shader. */
sd->shader = kernel_data_fetch(tri_shader, sd->prim); sd->shader = kernel_data_fetch(tri_shader, sd->prim);
/* Get motion info. */
/* TODO(sergey): This logic is really similar to motion_triangle_vertices(),
* can we de-duplicate something here?
*/
int numsteps, numverts;
object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
/* Figure out which steps we need to fetch and their interpolation factor. */
int maxstep = numsteps * 2;
int step = min((int)(sd->time * maxstep), maxstep - 1);
float t = sd->time * maxstep - step;
/* Find attribute. */
int offset = intersection_find_attribute(kg, sd->object, ATTR_STD_MOTION_VERTEX_POSITION);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */
float3 verts[3], next_verts[3];
uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); /* Compute motion info. */
int numsteps, numverts, step;
float t;
uint3 tri_vindex;
motion_triangle_compute_info(
kg, sd->object, sd->time, sd->prim, &tri_vindex, &numsteps, &numverts, &step, &t);
float3 verts[3];
motion_triangle_vertices(kg, sd->object, tri_vindex, numsteps, numverts, step, t, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
/* Interpolate between steps. */
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
/* Compute refined position. */ /* Compute refined position. */
sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts); sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts);
/* Compute face normal. */ /* Compute face normal. */
@ -75,23 +62,8 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
#endif #endif
/* Compute smooth normal. */ /* Compute smooth normal. */
if (sd->shader & SHADER_SMOOTH_NORMAL) { if (sd->shader & SHADER_SMOOTH_NORMAL) {
/* Find attribute. */ sd->N = motion_triangle_smooth_normal(
int offset = intersection_find_attribute(kg, sd->object, ATTR_STD_MOTION_VERTEX_NORMAL); kg, Ng, sd->object, tri_vindex, numsteps, numverts, step, t, sd->u, sd->v);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */
float3 normals[3], next_normals[3];
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
motion_triangle_normals_for_step(
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
/* Interpolate between steps. */
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
/* Interpolate between vertices. */
float u = sd->u;
float v = sd->v;
float w = 1.0f - u - v;
sd->N = (w * normals[0] + u * normals[1] + v * normals[2]);
} }
} }

View File

@ -18,7 +18,7 @@ ccl_device_noinline int svm_node_tex_coord(KernelGlobals kg,
uint4 node, uint4 node,
int offset) int offset)
{ {
float3 data; float3 data = zero_float3();
uint type = node.y; uint type = node.y;
uint out_offset = node.z; uint out_offset = node.z;
@ -100,7 +100,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
int offset) int offset)
{ {
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
float3 data; float3 data = zero_float3();
uint type = node.y; uint type = node.y;
uint out_offset = node.z; uint out_offset = node.z;
@ -185,7 +185,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
int offset) int offset)
{ {
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
float3 data; float3 data = zero_float3();
uint type = node.y; uint type = node.y;
uint out_offset = node.z; uint out_offset = node.z;

View File

@ -4,8 +4,13 @@
#pragma once #pragma once
#if !defined(__KERNEL_GPU__) && defined(WITH_EMBREE) #if !defined(__KERNEL_GPU__) && defined(WITH_EMBREE)
# include <embree3/rtcore.h> # if EMBREE_MAJOR_VERSION >= 4
# include <embree3/rtcore_scene.h> # include <embree4/rtcore.h>
# include <embree4/rtcore_scene.h>
# else
# include <embree3/rtcore.h>
# include <embree3/rtcore_scene.h>
# endif
# define __EMBREE__ # define __EMBREE__
#endif #endif

View File

@ -247,13 +247,16 @@ size_t CachedData::memory_used() const
static M44d convert_yup_zup(const M44d &mtx, float scale_mult) static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
{ {
V3d scale, shear, rotation, translation; V3d scale, shear, rotation, translation;
extractSHRT(mtx,
scale, if (!extractSHRT(mtx,
shear, scale,
rotation, shear,
translation, rotation,
true, translation,
IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY); true,
IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY)) {
return mtx;
}
M44d rot_mat, scale_mat, trans_mat; M44d rot_mat, scale_mat, trans_mat;
rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y)); rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y));

View File

@ -531,7 +531,7 @@ PrimitiveType Hair::primitive_type() const
/* Fill in coordinates for curve transparency shader evaluation on device. */ /* Fill in coordinates for curve transparency shader evaluation on device. */
static int fill_shader_input(const Hair *hair, static int fill_shader_input(const Hair *hair,
const int object_index, const size_t object_index,
device_vector<KernelShaderEvalInput> &d_input) device_vector<KernelShaderEvalInput> &d_input)
{ {
int d_input_size = 0; int d_input_size = 0;

View File

@ -86,7 +86,7 @@ ImageHandle::ImageHandle(const ImageHandle &other)
: tile_slots(other.tile_slots), manager(other.manager) : tile_slots(other.tile_slots), manager(other.manager)
{ {
/* Increase image user count. */ /* Increase image user count. */
foreach (const int slot, tile_slots) { foreach (const size_t slot, tile_slots) {
manager->add_image_user(slot); manager->add_image_user(slot);
} }
} }
@ -97,7 +97,7 @@ ImageHandle &ImageHandle::operator=(const ImageHandle &other)
manager = other.manager; manager = other.manager;
tile_slots = other.tile_slots; tile_slots = other.tile_slots;
foreach (const int slot, tile_slots) { foreach (const size_t slot, tile_slots) {
manager->add_image_user(slot); manager->add_image_user(slot);
} }
@ -111,7 +111,7 @@ ImageHandle::~ImageHandle()
void ImageHandle::clear() void ImageHandle::clear()
{ {
foreach (const int slot, tile_slots) { foreach (const size_t slot, tile_slots) {
manager->remove_image_user(slot); manager->remove_image_user(slot);
} }
@ -165,7 +165,7 @@ vector<int4> ImageHandle::get_svm_slots() const
for (size_t i = 0; i < num_nodes; i++) { for (size_t i = 0; i < num_nodes; i++) {
int4 node; int4 node;
int slot = tile_slots[2 * i]; size_t slot = tile_slots[2 * i];
node.x = manager->images[slot]->loader->get_tile_number(); node.x = manager->images[slot]->loader->get_tile_number();
node.y = slot; node.y = slot;
@ -387,7 +387,7 @@ void ImageManager::load_image_metadata(Image *img)
ImageHandle ImageManager::add_image(const string &filename, const ImageParams &params) ImageHandle ImageManager::add_image(const string &filename, const ImageParams &params)
{ {
const int slot = add_image_slot(new OIIOImageLoader(filename), params, false); const size_t slot = add_image_slot(new OIIOImageLoader(filename), params, false);
ImageHandle handle; ImageHandle handle;
handle.tile_slots.push_back(slot); handle.tile_slots.push_back(slot);
@ -408,13 +408,13 @@ ImageHandle ImageManager::add_image(const string &filename,
/* Since we don't have information about the exact tile format used in this code location, /* Since we don't have information about the exact tile format used in this code location,
* just attempt all replacement patterns that Blender supports. */ * just attempt all replacement patterns that Blender supports. */
if (tile != 0) { if (tile != 0) {
string_replace(tile_filename, "<UDIM>", string_printf("%04d", tile)); string_replace(tile_filename, "<UDIM>", string_printf("%04d", (int)tile));
int u = ((tile - 1001) % 10); int u = ((tile - 1001) % 10);
int v = ((tile - 1001) / 10); int v = ((tile - 1001) / 10);
string_replace(tile_filename, "<UVTILE>", string_printf("u%d_v%d", u + 1, v + 1)); string_replace(tile_filename, "<UVTILE>", string_printf("u%d_v%d", u + 1, v + 1));
} }
const int slot = add_image_slot(new OIIOImageLoader(tile_filename), params, false); const size_t slot = add_image_slot(new OIIOImageLoader(tile_filename), params, false);
handle.tile_slots.push_back(slot); handle.tile_slots.push_back(slot);
} }
@ -425,7 +425,7 @@ ImageHandle ImageManager::add_image(ImageLoader *loader,
const ImageParams &params, const ImageParams &params,
const bool builtin) const bool builtin)
{ {
const int slot = add_image_slot(loader, params, builtin); const size_t slot = add_image_slot(loader, params, builtin);
ImageHandle handle; ImageHandle handle;
handle.tile_slots.push_back(slot); handle.tile_slots.push_back(slot);
@ -438,7 +438,7 @@ ImageHandle ImageManager::add_image(const vector<ImageLoader *> &loaders,
{ {
ImageHandle handle; ImageHandle handle;
for (ImageLoader *loader : loaders) { for (ImageLoader *loader : loaders) {
const int slot = add_image_slot(loader, params, true); const size_t slot = add_image_slot(loader, params, true);
handle.tile_slots.push_back(slot); handle.tile_slots.push_back(slot);
} }
@ -446,9 +446,9 @@ ImageHandle ImageManager::add_image(const vector<ImageLoader *> &loaders,
return handle; return handle;
} }
int ImageManager::add_image_slot(ImageLoader *loader, size_t ImageManager::add_image_slot(ImageLoader *loader,
const ImageParams &params, const ImageParams &params,
const bool builtin) const bool builtin)
{ {
Image *img; Image *img;
size_t slot; size_t slot;
@ -492,7 +492,7 @@ int ImageManager::add_image_slot(ImageLoader *loader,
return slot; return slot;
} }
void ImageManager::add_image_user(int slot) void ImageManager::add_image_user(size_t slot)
{ {
thread_scoped_lock device_lock(images_mutex); thread_scoped_lock device_lock(images_mutex);
Image *image = images[slot]; Image *image = images[slot];
@ -501,7 +501,7 @@ void ImageManager::add_image_user(int slot)
image->users++; image->users++;
} }
void ImageManager::remove_image_user(int slot) void ImageManager::remove_image_user(size_t slot)
{ {
thread_scoped_lock device_lock(images_mutex); thread_scoped_lock device_lock(images_mutex);
Image *image = images[slot]; Image *image = images[slot];
@ -682,7 +682,7 @@ bool ImageManager::file_load_image(Image *img, int texture_limit)
return true; return true;
} }
void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Progress *progress) void ImageManager::device_load_image(Device *device, Scene *scene, size_t slot, Progress *progress)
{ {
if (progress->get_cancel()) { if (progress->get_cancel()) {
return; return;
@ -698,7 +698,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
ImageDataType type = img->metadata.type; ImageDataType type = img->metadata.type;
/* Name for debugging. */ /* Name for debugging. */
img->mem_name = string_printf("tex_image_%s_%03d", name_from_type(type), slot); img->mem_name = string_printf("tex_image_%s_%03d", name_from_type(type), (int)slot);
/* Free previous texture in slot. */ /* Free previous texture in slot. */
if (img->mem) { if (img->mem) {
@ -819,7 +819,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
img->need_load = false; img->need_load = false;
} }
void ImageManager::device_free_image(Device *, int slot) void ImageManager::device_free_image(Device *, size_t slot)
{ {
Image *img = images[slot]; Image *img = images[slot];
if (img == NULL) { if (img == NULL) {
@ -874,7 +874,10 @@ void ImageManager::device_update(Device *device, Scene *scene, Progress &progres
need_update_ = false; need_update_ = false;
} }
void ImageManager::device_update_slot(Device *device, Scene *scene, int slot, Progress *progress) void ImageManager::device_update_slot(Device *device,
Scene *scene,
size_t slot,
Progress *progress)
{ {
Image *img = images[slot]; Image *img = images[slot];
assert(img != NULL); assert(img != NULL);

View File

@ -156,7 +156,7 @@ class ImageHandle {
ImageManager *get_manager() const; ImageManager *get_manager() const;
protected: protected:
vector<int> tile_slots; vector<size_t> tile_slots;
ImageManager *manager; ImageManager *manager;
friend class ImageManager; friend class ImageManager;
@ -179,7 +179,7 @@ class ImageManager {
ImageHandle add_image(const vector<ImageLoader *> &loaders, const ImageParams &params); ImageHandle add_image(const vector<ImageLoader *> &loaders, const ImageParams &params);
void device_update(Device *device, Scene *scene, Progress &progress); void device_update(Device *device, Scene *scene, Progress &progress);
void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress); void device_update_slot(Device *device, Scene *scene, size_t slot, Progress *progress);
void device_free(Device *device); void device_free(Device *device);
void device_load_builtin(Device *device, Scene *scene, Progress &progress); void device_load_builtin(Device *device, Scene *scene, Progress &progress);
@ -223,17 +223,17 @@ class ImageManager {
vector<Image *> images; vector<Image *> images;
void *osl_texture_system; void *osl_texture_system;
int add_image_slot(ImageLoader *loader, const ImageParams &params, const bool builtin); size_t add_image_slot(ImageLoader *loader, const ImageParams &params, const bool builtin);
void add_image_user(int slot); void add_image_user(size_t slot);
void remove_image_user(int slot); void remove_image_user(size_t slot);
void load_image_metadata(Image *img); void load_image_metadata(Image *img);
template<TypeDesc::BASETYPE FileFormat, typename StorageType> template<TypeDesc::BASETYPE FileFormat, typename StorageType>
bool file_load_image(Image *img, int texture_limit); bool file_load_image(Image *img, int texture_limit);
void device_load_image(Device *device, Scene *scene, int slot, Progress *progress); void device_load_image(Device *device, Scene *scene, size_t slot, Progress *progress);
void device_free_image(Device *device, int slot); void device_free_image(Device *device, size_t slot);
friend class ImageHandle; friend class ImageHandle;
}; };

View File

@ -264,9 +264,9 @@ void LightManager::device_update_distribution(Device *,
/* Count emissive triangles. */ /* Count emissive triangles. */
Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
size_t mesh_num_triangles = mesh->num_triangles(); int mesh_num_triangles = static_cast<int>(mesh->num_triangles());
for (size_t i = 0; i < mesh_num_triangles; i++) { for (int i = 0; i < mesh_num_triangles; i++) {
int shader_index = mesh->get_shader()[i]; int shader_index = mesh->get_shader()[i];
Shader *shader = (shader_index < mesh->get_used_shaders().size()) ? Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) : static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :

View File

@ -370,9 +370,11 @@ bool LightTree::should_split(LightTreeEmitter *emitters,
int &split_dim) int &split_dim)
{ {
const int num_emitters = end - start; const int num_emitters = end - start;
if (num_emitters == 1) { if (num_emitters < 2) {
/* Do not try to split if there is only one emitter. */ if (num_emitters) {
measure = (emitters + start)->measure; /* Do not try to split if there is only one emitter. */
measure = (emitters + start)->measure;
}
return false; return false;
} }

View File

@ -35,7 +35,7 @@ static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
/* Fill in coordinates for mesh displacement shader evaluation on device. */ /* Fill in coordinates for mesh displacement shader evaluation on device. */
static int fill_shader_input(const Scene *scene, static int fill_shader_input(const Scene *scene,
const Mesh *mesh, const Mesh *mesh,
const int object_index, const size_t object_index,
device_vector<KernelShaderEvalInput> &d_input) device_vector<KernelShaderEvalInput> &d_input)
{ {
int d_input_size = 0; int d_input_size = 0;

View File

@ -40,7 +40,7 @@ ccl_device_inline float half_to_float(half h_in)
* unsigned shorts. */ * unsigned shorts. */
class half { class half {
public: public:
half() : v(0) {} half() = default;
half(const unsigned short &i) : v(i) {} half(const unsigned short &i) : v(i) {}
operator unsigned short() operator unsigned short()
{ {

View File

@ -14,62 +14,62 @@ set(INC_SYS
) )
set(SRC set(SRC
intern/GHOST_Buttons.cpp intern/GHOST_Buttons.cc
intern/GHOST_C-api.cpp intern/GHOST_C-api.cc
intern/GHOST_CallbackEventConsumer.cpp intern/GHOST_CallbackEventConsumer.cc
intern/GHOST_Context.cpp intern/GHOST_Context.cc
intern/GHOST_ContextNone.cpp intern/GHOST_ContextNone.cc
intern/GHOST_DisplayManager.cpp intern/GHOST_DisplayManager.cc
intern/GHOST_EventManager.cpp intern/GHOST_EventManager.cc
intern/GHOST_ISystem.cpp intern/GHOST_ISystem.cc
intern/GHOST_ISystemPaths.cpp intern/GHOST_ISystemPaths.cc
intern/GHOST_ModifierKeys.cpp intern/GHOST_ModifierKeys.cc
intern/GHOST_Path-api.cpp intern/GHOST_Path-api.cc
intern/GHOST_PathUtils.cpp intern/GHOST_PathUtils.cc
intern/GHOST_Rect.cpp intern/GHOST_Rect.cc
intern/GHOST_System.cpp intern/GHOST_System.cc
intern/GHOST_TimerManager.cpp intern/GHOST_TimerManager.cc
intern/GHOST_Window.cpp intern/GHOST_Window.cc
intern/GHOST_WindowManager.cpp intern/GHOST_WindowManager.cc
GHOST_C-api.h GHOST_C-api.h
GHOST_IContext.h GHOST_IContext.hh
GHOST_IEvent.h GHOST_IEvent.hh
GHOST_IEventConsumer.h GHOST_IEventConsumer.hh
GHOST_ISystem.h GHOST_ISystem.hh
GHOST_ISystemPaths.h GHOST_ISystemPaths.hh
GHOST_ITimerTask.h GHOST_ITimerTask.hh
GHOST_IWindow.h GHOST_IWindow.hh
GHOST_Path-api.h GHOST_Path-api.hh
GHOST_Rect.h GHOST_Rect.hh
GHOST_Types.h GHOST_Types.h
intern/GHOST_Buttons.h intern/GHOST_Buttons.hh
intern/GHOST_CallbackEventConsumer.h intern/GHOST_CallbackEventConsumer.hh
intern/GHOST_Context.h intern/GHOST_Context.hh
intern/GHOST_ContextNone.h intern/GHOST_ContextNone.hh
intern/GHOST_Debug.h intern/GHOST_Debug.hh
intern/GHOST_DisplayManager.h intern/GHOST_DisplayManager.hh
intern/GHOST_Event.h intern/GHOST_Event.hh
intern/GHOST_EventButton.h intern/GHOST_EventButton.hh
intern/GHOST_EventCursor.h intern/GHOST_EventCursor.hh
intern/GHOST_EventDragnDrop.h intern/GHOST_EventDragnDrop.hh
intern/GHOST_EventKey.h intern/GHOST_EventKey.hh
intern/GHOST_EventManager.h intern/GHOST_EventManager.hh
intern/GHOST_EventString.h intern/GHOST_EventString.hh
intern/GHOST_EventTrackpad.h intern/GHOST_EventTrackpad.hh
intern/GHOST_EventWheel.h intern/GHOST_EventWheel.hh
intern/GHOST_ModifierKeys.h intern/GHOST_ModifierKeys.hh
intern/GHOST_PathUtils.h intern/GHOST_PathUtils.hh
intern/GHOST_System.h intern/GHOST_System.hh
intern/GHOST_SystemPaths.h intern/GHOST_SystemPaths.hh
intern/GHOST_TimerManager.h intern/GHOST_TimerManager.hh
intern/GHOST_TimerTask.h intern/GHOST_TimerTask.hh
intern/GHOST_Util.h intern/GHOST_Util.hh
intern/GHOST_Window.h intern/GHOST_Window.hh
intern/GHOST_WindowManager.h intern/GHOST_WindowManager.hh
intern/GHOST_utildefines.h intern/GHOST_utildefines.hh
intern/GHOST_utildefines_variadic.h intern/GHOST_utildefines_variadic.hh
) )
set(LIB set(LIB
@ -78,9 +78,9 @@ set(LIB
if(WITH_VULKAN_BACKEND) if(WITH_VULKAN_BACKEND)
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextVK.cpp intern/GHOST_ContextVK.cc
intern/GHOST_ContextVK.h intern/GHOST_ContextVK.hh
) )
list(APPEND INC_SYS list(APPEND INC_SYS
@ -98,9 +98,9 @@ endif()
if(WITH_GHOST_DEBUG) if(WITH_GHOST_DEBUG)
list(APPEND SRC list(APPEND SRC
intern/GHOST_EventPrinter.cpp intern/GHOST_EventPrinter.cc
intern/GHOST_EventPrinter.h intern/GHOST_EventPrinter.hh
) )
add_definitions(-DWITH_GHOST_DEBUG) add_definitions(-DWITH_GHOST_DEBUG)
endif() endif()
@ -109,10 +109,10 @@ if(WITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF) add_definitions(-DWITH_INPUT_NDOF)
list(APPEND SRC list(APPEND SRC
intern/GHOST_NDOFManager.cpp intern/GHOST_NDOFManager.cc
intern/GHOST_EventNDOF.h intern/GHOST_EventNDOF.hh
intern/GHOST_NDOFManager.h intern/GHOST_NDOFManager.hh
) )
list(APPEND INC_SYS list(APPEND INC_SYS
@ -124,24 +124,24 @@ if(WITH_INPUT_NDOF)
endif() endif()
list(APPEND SRC list(APPEND SRC
intern/GHOST_DisplayManagerNULL.h intern/GHOST_DisplayManagerNULL.hh
intern/GHOST_SystemHeadless.h intern/GHOST_SystemHeadless.hh
intern/GHOST_WindowNULL.h intern/GHOST_WindowNULL.hh
) )
if(WITH_HEADLESS) if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS) add_definitions(-DWITH_HEADLESS)
elseif(WITH_GHOST_SDL) elseif(WITH_GHOST_SDL)
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextSDL.cpp intern/GHOST_ContextSDL.cc
intern/GHOST_DisplayManagerSDL.cpp intern/GHOST_DisplayManagerSDL.cc
intern/GHOST_SystemSDL.cpp intern/GHOST_SystemSDL.cc
intern/GHOST_WindowSDL.cpp intern/GHOST_WindowSDL.cc
intern/GHOST_ContextSDL.h intern/GHOST_ContextSDL.hh
intern/GHOST_DisplayManagerSDL.h intern/GHOST_DisplayManagerSDL.hh
intern/GHOST_SystemSDL.h intern/GHOST_SystemSDL.hh
intern/GHOST_WindowSDL.h intern/GHOST_WindowSDL.hh
) )
add_definitions(-DWITH_GHOST_SDL) add_definitions(-DWITH_GHOST_SDL)
@ -167,23 +167,23 @@ elseif(APPLE AND NOT WITH_GHOST_X11)
intern/GHOST_SystemCocoa.mm intern/GHOST_SystemCocoa.mm
intern/GHOST_WindowCocoa.mm intern/GHOST_WindowCocoa.mm
intern/GHOST_DisplayManagerCocoa.h intern/GHOST_DisplayManagerCocoa.hh
intern/GHOST_SystemCocoa.h intern/GHOST_SystemCocoa.hh
intern/GHOST_WindowCocoa.h intern/GHOST_WindowCocoa.hh
intern/GHOST_WindowViewCocoa.h intern/GHOST_WindowViewCocoa.hh
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextCGL.mm intern/GHOST_ContextCGL.mm
intern/GHOST_ContextCGL.h intern/GHOST_ContextCGL.hh
) )
if(WITH_INPUT_NDOF) if(WITH_INPUT_NDOF)
list(APPEND SRC list(APPEND SRC
intern/GHOST_NDOFManagerCocoa.mm intern/GHOST_NDOFManagerCocoa.mm
intern/GHOST_NDOFManagerCocoa.h intern/GHOST_NDOFManagerCocoa.hh
) )
endif() endif()
@ -199,22 +199,22 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_DisplayManagerX11.cpp intern/GHOST_DisplayManagerX11.cc
intern/GHOST_SystemX11.cpp intern/GHOST_SystemX11.cc
intern/GHOST_TaskbarX11.cpp intern/GHOST_TaskbarX11.cc
intern/GHOST_WindowX11.cpp intern/GHOST_WindowX11.cc
intern/GHOST_DisplayManagerX11.h intern/GHOST_DisplayManagerX11.hh
intern/GHOST_IconX11.h intern/GHOST_IconX11.hh
intern/GHOST_SystemX11.h intern/GHOST_SystemX11.hh
intern/GHOST_TaskbarX11.h intern/GHOST_TaskbarX11.hh
intern/GHOST_WindowX11.h intern/GHOST_WindowX11.hh
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextGLX.cpp intern/GHOST_ContextGLX.cc
intern/GHOST_ContextGLX.h intern/GHOST_ContextGLX.hh
) )
if(WITH_GHOST_XDND) if(WITH_GHOST_XDND)
@ -229,9 +229,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_DropTargetX11.cpp intern/GHOST_DropTargetX11.cc
intern/GHOST_DropTargetX11.h intern/GHOST_DropTargetX11.hh
) )
endif() endif()
@ -336,13 +336,13 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
endif() endif()
list(APPEND SRC list(APPEND SRC
intern/GHOST_SystemWayland.cpp intern/GHOST_SystemWayland.cc
intern/GHOST_WindowWayland.cpp intern/GHOST_WindowWayland.cc
intern/GHOST_SystemWayland.h intern/GHOST_SystemWayland.hh
intern/GHOST_WaylandCursorSettings.h intern/GHOST_WaylandCursorSettings.hh
intern/GHOST_WaylandUtils.h intern/GHOST_WaylandUtils.hh
intern/GHOST_WindowWayland.h intern/GHOST_WindowWayland.hh
) )
set(INC_DST ${CMAKE_CURRENT_BINARY_DIR}/libwayland) set(INC_DST ${CMAKE_CURRENT_BINARY_DIR}/libwayland)
@ -441,9 +441,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
if(WITH_INPUT_NDOF) if(WITH_INPUT_NDOF)
list(APPEND SRC list(APPEND SRC
intern/GHOST_NDOFManagerUnix.cpp intern/GHOST_NDOFManagerUnix.cc
intern/GHOST_NDOFManagerUnix.h intern/GHOST_NDOFManagerUnix.hh
) )
endif() endif()
@ -463,67 +463,67 @@ elseif(WIN32)
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextD3D.cpp intern/GHOST_ContextD3D.cc
intern/GHOST_DisplayManagerWin32.cpp intern/GHOST_DisplayManagerWin32.cc
intern/GHOST_DropTargetWin32.cpp intern/GHOST_DropTargetWin32.cc
intern/GHOST_SystemWin32.cpp intern/GHOST_SystemWin32.cc
intern/GHOST_TrackpadWin32.cpp intern/GHOST_TrackpadWin32.cc
intern/GHOST_WindowWin32.cpp intern/GHOST_WindowWin32.cc
intern/GHOST_Wintab.cpp intern/GHOST_Wintab.cc
intern/GHOST_ContextD3D.h intern/GHOST_ContextD3D.hh
intern/GHOST_DisplayManagerWin32.h intern/GHOST_DisplayManagerWin32.hh
intern/GHOST_DropTargetWin32.h intern/GHOST_DropTargetWin32.hh
intern/GHOST_SystemWin32.h intern/GHOST_SystemWin32.hh
intern/GHOST_TaskbarWin32.h intern/GHOST_TaskbarWin32.hh
intern/GHOST_TrackpadWin32.h intern/GHOST_TrackpadWin32.hh
intern/GHOST_WindowWin32.h intern/GHOST_WindowWin32.hh
intern/GHOST_Wintab.h intern/GHOST_Wintab.hh
) )
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextWGL.cpp intern/GHOST_ContextWGL.cc
intern/GHOST_ContextWGL.h intern/GHOST_ContextWGL.hh
) )
if(WITH_INPUT_IME) if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME)
list(APPEND SRC list(APPEND SRC
intern/GHOST_ImeWin32.cpp intern/GHOST_ImeWin32.cc
intern/GHOST_ImeWin32.h intern/GHOST_ImeWin32.hh
) )
endif() endif()
if(WITH_INPUT_NDOF) if(WITH_INPUT_NDOF)
list(APPEND SRC list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp intern/GHOST_NDOFManagerWin32.cc
intern/GHOST_NDOFManagerWin32.h intern/GHOST_NDOFManagerWin32.hh
) )
endif() endif()
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
list(APPEND SRC list(APPEND SRC
intern/GHOST_ContextEGL.cpp intern/GHOST_ContextEGL.cc
intern/GHOST_ContextEGL.h intern/GHOST_ContextEGL.hh
) )
endif() endif()
if(APPLE) if(APPLE)
list(APPEND SRC list(APPEND SRC
intern/GHOST_SystemPathsCocoa.h intern/GHOST_SystemPathsCocoa.hh
intern/GHOST_SystemPathsCocoa.mm intern/GHOST_SystemPathsCocoa.mm
) )
elseif(UNIX) elseif(UNIX)
list(APPEND SRC list(APPEND SRC
intern/GHOST_SystemPathsUnix.cpp intern/GHOST_SystemPathsUnix.cc
intern/GHOST_SystemPathsUnix.h intern/GHOST_SystemPathsUnix.hh
) )
if(NOT WITH_INSTALL_PORTABLE) if(NOT WITH_INSTALL_PORTABLE)
@ -532,8 +532,8 @@ elseif(UNIX)
elseif(WIN32) elseif(WIN32)
list(APPEND SRC list(APPEND SRC
intern/GHOST_SystemPathsWin32.cpp intern/GHOST_SystemPathsWin32.cc
intern/GHOST_SystemPathsWin32.h intern/GHOST_SystemPathsWin32.hh
) )
list(APPEND INC list(APPEND INC
@ -544,25 +544,25 @@ endif()
if(WITH_XR_OPENXR) if(WITH_XR_OPENXR)
list(APPEND SRC list(APPEND SRC
intern/GHOST_Xr.cpp intern/GHOST_Xr.cc
intern/GHOST_XrAction.cpp intern/GHOST_XrAction.cc
intern/GHOST_XrContext.cpp intern/GHOST_XrContext.cc
intern/GHOST_XrControllerModel.cpp intern/GHOST_XrControllerModel.cc
intern/GHOST_XrEvent.cpp intern/GHOST_XrEvent.cc
intern/GHOST_XrGraphicsBinding.cpp intern/GHOST_XrGraphicsBinding.cc
intern/GHOST_XrSession.cpp intern/GHOST_XrSession.cc
intern/GHOST_XrSwapchain.cpp intern/GHOST_XrSwapchain.cc
GHOST_IXrContext.h GHOST_IXrContext.hh
intern/GHOST_IXrGraphicsBinding.h intern/GHOST_IXrGraphicsBinding.hh
intern/GHOST_XrAction.h intern/GHOST_XrAction.hh
intern/GHOST_XrContext.h intern/GHOST_XrContext.hh
intern/GHOST_XrControllerModel.h intern/GHOST_XrControllerModel.hh
intern/GHOST_XrException.h intern/GHOST_XrException.hh
intern/GHOST_XrSession.h intern/GHOST_XrSession.hh
intern/GHOST_XrSwapchain.h intern/GHOST_XrSwapchain.hh
intern/GHOST_Xr_intern.h intern/GHOST_Xr_intern.hh
intern/GHOST_Xr_openxr_includes.h intern/GHOST_Xr_openxr_includes.hh
# Header only library. # Header only library.
../../extern/tinygltf/tiny_gltf.h ../../extern/tinygltf/tiny_gltf.h

View File

@ -8,7 +8,7 @@
#pragma once #pragma once
#include "GHOST_IEvent.h" #include "GHOST_IEvent.hh"
/** /**
* Interface class for objects interested in receiving events. * Interface class for objects interested in receiving events.

View File

@ -12,9 +12,9 @@
#include <stdlib.h> #include <stdlib.h>
#include "GHOST_IContext.h" #include "GHOST_IContext.hh"
#include "GHOST_ITimerTask.h" #include "GHOST_ITimerTask.hh"
#include "GHOST_IWindow.h" #include "GHOST_IWindow.hh"
#include "GHOST_Types.h" #include "GHOST_Types.h"
class GHOST_IEventConsumer; class GHOST_IEventConsumer;
@ -77,12 +77,12 @@ class GHOST_IEventConsumer;
* *
* \subsection cplusplus_api The C++ API consists of the following files: * \subsection cplusplus_api The C++ API consists of the following files:
* *
* - GHOST_IEvent.h * - GHOST_IEvent.hh
* - GHOST_IEventConsumer.h * - GHOST_IEventConsumer.hh
* - GHOST_ISystem.h * - GHOST_ISystem.hh
* - GHOST_ITimerTask.h * - GHOST_ITimerTask.hh
* - GHOST_IWindow.h * - GHOST_IWindow.hh
* - GHOST_Rect.h * - GHOST_Rect.hh
* - GHOST_Types.h * - GHOST_Types.h
* *
* For an example of using the C++-API, have a look at the GHOST_C-Test.cpp * For an example of using the C++-API, have a look at the GHOST_C-Test.cpp

View File

@ -8,7 +8,7 @@
#pragma once #pragma once
#include "GHOST_Rect.h" #include "GHOST_Rect.hh"
#include "GHOST_Types.h" #include "GHOST_Types.h"
#include <stdlib.h> #include <stdlib.h>

View File

@ -5,7 +5,7 @@
* \ingroup GHOST * \ingroup GHOST
*/ */
#include "GHOST_Buttons.h" #include "GHOST_Buttons.hh"
GHOST_Buttons::GHOST_Buttons() GHOST_Buttons::GHOST_Buttons()
{ {

View File

@ -11,16 +11,16 @@
#include <cstring> #include <cstring>
#include "GHOST_C-api.h" #include "GHOST_C-api.h"
#include "GHOST_IEvent.h" #include "GHOST_IEvent.hh"
#include "GHOST_IEventConsumer.h" #include "GHOST_IEventConsumer.hh"
#include "GHOST_ISystem.h" #include "GHOST_ISystem.hh"
#include "intern/GHOST_Debug.h" #include "intern/GHOST_Debug.hh"
#ifdef WITH_XR_OPENXR #ifdef WITH_XR_OPENXR
# include "GHOST_IXrContext.h" # include "GHOST_IXrContext.hh"
# include "intern/GHOST_XrSession.h" # include "intern/GHOST_XrSession.hh"
#endif #endif
#include "intern/GHOST_CallbackEventConsumer.h" #include "intern/GHOST_CallbackEventConsumer.hh"
#include "intern/GHOST_XrException.h" #include "intern/GHOST_XrException.hh"
GHOST_SystemHandle GHOST_CreateSystem(void) GHOST_SystemHandle GHOST_CreateSystem(void)
{ {

View File

@ -9,9 +9,9 @@
* Copyright (C) 2001 NaN Technologies B.V. * Copyright (C) 2001 NaN Technologies B.V.
*/ */
#include "GHOST_CallbackEventConsumer.h" #include "GHOST_CallbackEventConsumer.hh"
#include "GHOST_C-api.h" #include "GHOST_C-api.h"
#include "GHOST_Debug.h" #include "GHOST_Debug.hh"
GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
GHOST_TUserDataPtr userData) GHOST_TUserDataPtr userData)

View File

@ -9,7 +9,7 @@
#pragma once #pragma once
#include "GHOST_C-api.h" #include "GHOST_C-api.h"
#include "GHOST_IEventConsumer.h" #include "GHOST_IEventConsumer.hh"
/** /**
* Event consumer that will forward events to a call-back routine. * Event consumer that will forward events to a call-back routine.

View File

@ -7,7 +7,7 @@
* Definition of GHOST_Context class. * Definition of GHOST_Context class.
*/ */
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#ifdef _WIN32 #ifdef _WIN32
# include <epoxy/wgl.h> # include <epoxy/wgl.h>

View File

@ -8,7 +8,7 @@
#pragma once #pragma once
#include "GHOST_IContext.h" #include "GHOST_IContext.hh"
#include "GHOST_Types.h" #include "GHOST_Types.h"
#include <epoxy/gl.h> #include <epoxy/gl.h>

View File

@ -7,7 +7,7 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <Metal/Metal.h> #include <Metal/Metal.h>

View File

@ -13,7 +13,7 @@
# pragma clang diagnostic ignored "-Wdeprecated-declarations" # pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif #endif
#include "GHOST_ContextCGL.h" #include "GHOST_ContextCGL.hh"
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <Metal/Metal.h> #include <Metal/Metal.h>

View File

@ -12,8 +12,8 @@
#include <epoxy/wgl.h> #include <epoxy/wgl.h>
#include "GHOST_ContextD3D.h" #include "GHOST_ContextD3D.hh"
#include "GHOST_ContextWGL.h" /* For shared drawing */ #include "GHOST_ContextWGL.hh" /* For shared drawing */
HMODULE GHOST_ContextD3D::s_d3d_lib = NULL; HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL; PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL;

View File

@ -12,7 +12,7 @@
#include <D3D11.h> #include <D3D11.h>
#include "GHOST_Context.h" #include "GHOST_Context.hh"
class GHOST_ContextD3D : public GHOST_Context { class GHOST_ContextD3D : public GHOST_Context {
/* XR code needs low level graphics data to send to OpenXR. */ /* XR code needs low level graphics data to send to OpenXR. */

View File

@ -7,7 +7,7 @@
* Definition of GHOST_ContextEGL class. * Definition of GHOST_ContextEGL class.
*/ */
#include "GHOST_ContextEGL.h" #include "GHOST_ContextEGL.hh"
#include <set> #include <set>
#include <sstream> #include <sstream>

View File

@ -7,8 +7,8 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#include "GHOST_System.h" #include "GHOST_System.hh"
#include <epoxy/egl.h> #include <epoxy/egl.h>
#include <epoxy/gl.h> #include <epoxy/gl.h>

View File

@ -7,8 +7,8 @@
* Definition of GHOST_ContextGLX class. * Definition of GHOST_ContextGLX class.
*/ */
#include "GHOST_ContextGLX.h" #include "GHOST_ContextGLX.hh"
#include "GHOST_SystemX11.h" #include "GHOST_SystemX11.hh"
#include <vector> #include <vector>

View File

@ -7,7 +7,7 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#include <epoxy/glx.h> #include <epoxy/glx.h>

View File

@ -7,7 +7,7 @@
* Definition of GHOST_ContextNone class. * Definition of GHOST_ContextNone class.
*/ */
#include "GHOST_ContextNone.h" #include "GHOST_ContextNone.hh"
GHOST_TSuccess GHOST_ContextNone::swapBuffers() GHOST_TSuccess GHOST_ContextNone::swapBuffers()
{ {

View File

@ -9,7 +9,7 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
class GHOST_ContextNone : public GHOST_Context { class GHOST_ContextNone : public GHOST_Context {
public: public:

View File

@ -7,7 +7,7 @@
* Definition of GHOST_ContextSDL class. * Definition of GHOST_ContextSDL class.
*/ */
#include "GHOST_ContextSDL.h" #include "GHOST_ContextSDL.hh"
#include <vector> #include <vector>

View File

@ -7,7 +7,7 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
extern "C" { extern "C" {
#include "SDL.h" #include "SDL.h"

View File

@ -4,7 +4,7 @@
* \ingroup GHOST * \ingroup GHOST
*/ */
#include "GHOST_ContextVK.h" #include "GHOST_ContextVK.hh"
#ifdef _WIN32 #ifdef _WIN32
# include <vulkan/vulkan_win32.h> # include <vulkan/vulkan_win32.h>

View File

@ -6,16 +6,16 @@
#pragma once #pragma once
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#ifdef _WIN32 #ifdef _WIN32
# include "GHOST_SystemWin32.h" # include "GHOST_SystemWin32.hh"
#elif defined(__APPLE__) #elif defined(__APPLE__)
# include "GHOST_SystemCocoa.h" # include "GHOST_SystemCocoa.hh"
#else #else
# include "GHOST_SystemX11.h" # include "GHOST_SystemX11.hh"
# ifdef WITH_GHOST_WAYLAND # ifdef WITH_GHOST_WAYLAND
# include "GHOST_SystemWayland.h" # include "GHOST_SystemWayland.hh"
# else # else
# define wl_surface void # define wl_surface void
# define wl_display void # define wl_display void

View File

@ -7,7 +7,7 @@
* Definition of GHOST_ContextWGL class. * Definition of GHOST_ContextWGL class.
*/ */
#include "GHOST_ContextWGL.h" #include "GHOST_ContextWGL.hh"
#include <tchar.h> #include <tchar.h>

View File

@ -9,7 +9,7 @@
//#define WIN32_COMPOSITING //#define WIN32_COMPOSITING
#include "GHOST_Context.h" #include "GHOST_Context.hh"
#include <epoxy/wgl.h> #include <epoxy/wgl.h>

View File

@ -9,8 +9,8 @@
* Copyright (C) 2001 NaN Technologies B.V. * Copyright (C) 2001 NaN Technologies B.V.
*/ */
#include "GHOST_DisplayManager.h" #include "GHOST_DisplayManager.hh"
#include "GHOST_Debug.h" #include "GHOST_Debug.hh"
GHOST_DisplayManager::GHOST_DisplayManager() : m_settingsInitialized(false) {} GHOST_DisplayManager::GHOST_DisplayManager() : m_settingsInitialized(false) {}

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