diff --git a/.clang-format b/.clang-format
index bf20a4e4c4a..41f828787b2 100644
--- a/.clang-format
+++ b/.clang-format
@@ -180,6 +180,7 @@ ForEachMacros:
- CTX_DATA_BEGIN_WITH_ID
- DEG_OBJECT_ITER_BEGIN
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN
+ - DRW_ENABLED_ENGINE_ITER
- DRIVER_TARGETS_LOOPER_BEGIN
- DRIVER_TARGETS_USED_LOOPER_BEGIN
- FOREACH_BASE_IN_EDIT_MODE_BEGIN
@@ -267,3 +268,6 @@ ForEachMacros:
StatementMacros:
- PyObject_HEAD
- PyObject_VAR_HEAD
+
+MacroBlockBegin: "^BSDF_CLOSURE_CLASS_BEGIN$"
+MacroBlockEnd: "^BSDF_CLOSURE_CLASS_END$"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000000..93a29565e54
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,5 @@
+This repository is only used as a mirror of git.blender.org. Blender development happens on
+https://developer.blender.org.
+
+To get started with contributing code, please see:
+https://wiki.blender.org/wiki/Process/Contributing_Code
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 47712f0ac1e..62e7d9b2941 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
"CMake generation for blender is not allowed within the source directory!"
"\n Remove \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" and try again from another folder, e.g.:"
"\n "
- "\n rm CMakeCache.txt"
+ "\n rm -rf CMakeCache.txt CMakeFiles"
"\n cd .."
"\n mkdir cmake-make"
"\n cd cmake-make"
@@ -156,6 +156,15 @@ get_blender_version()
option(WITH_BLENDER "Build blender (disable to build only the blender player)" ON)
mark_as_advanced(WITH_BLENDER)
+if(APPLE)
+ # Currently this causes a build error linking, disable.
+ set(WITH_BLENDER_THUMBNAILER OFF)
+elseif(WIN32)
+ option(WITH_BLENDER_THUMBNAILER "Build \"BlendThumb.dll\" helper for Windows explorer integration" ON)
+else()
+ option(WITH_BLENDER_THUMBNAILER "Build \"blender-thumbnailer\" thumbnail extraction utility" ON)
+endif()
+
option(WITH_INTERNATIONAL "Enable I18N (International fonts and text)" ON)
option(WITH_PYTHON "Enable Embedded Python API (only disable for development)" ON)
@@ -388,46 +397,55 @@ if(WITH_PYTHON_INSTALL)
set(PYTHON_REQUESTS_PATH "" CACHE PATH "Path to python site-packages or dist-packages containing 'requests' module")
mark_as_advanced(PYTHON_REQUESTS_PATH)
endif()
+
+ option(WITH_PYTHON_INSTALL_ZSTANDARD "Copy zstandard into the blender install folder" ON)
+ set(PYTHON_ZSTANDARD_PATH "" CACHE PATH "Path to python site-packages or dist-packages containing 'zstandard' module")
+ mark_as_advanced(PYTHON_ZSTANDARD_PATH)
endif()
option(WITH_CPU_SIMD "Enable SIMD instruction if they're detected on the host machine" ON)
mark_as_advanced(WITH_CPU_SIMD)
# Cycles
-option(WITH_CYCLES "Enable Cycles Render Engine" ON)
-option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
-option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
-option(WITH_CYCLES_OSL "Build Cycles with OSL support" ON)
-option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
-option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF)
-option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
-option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
-mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
-set(CYCLES_TEST_DEVICES CPU CACHE STRING "Run regression tests on the specified device types (CPU CUDA OPTIX OPENCL)" )
-set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
-mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
-unset(PLATFORM_DEFAULT)
-option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
-option(WITH_CYCLES_DEBUG_NAN "Build Cycles with additional asserts for detecting NaNs and invalid values" OFF)
-option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" OFF)
-option(WITH_CYCLES_KERNEL_ASAN "Build Cycles kernels with address sanitizer when WITH_COMPILER_ASAN is on, even if it's very slow" OFF)
+option(WITH_CYCLES "Enable Cycles Render Engine" ON)
+option(WITH_CYCLES_OSL "Build Cycles with OpenShadingLanguage support" ON)
+option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
+option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
+
+option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
+option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
+
+option(WITH_CYCLES_DEBUG_NAN "Build Cycles with additional asserts for detecting NaNs and invalid values" OFF)
+option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" OFF)
+option(WITH_CYCLES_KERNEL_ASAN "Build Cycles kernels with address sanitizer when WITH_COMPILER_ASAN is on, even if it's very slow" OFF)
+set(CYCLES_TEST_DEVICES CPU CACHE STRING "Run regression tests on the specified device types (CPU CUDA OPTIX HIP)" )
mark_as_advanced(WITH_CYCLES_KERNEL_ASAN)
-mark_as_advanced(WITH_CYCLES_CUBIN_COMPILER)
mark_as_advanced(WITH_CYCLES_LOGGING)
mark_as_advanced(WITH_CYCLES_DEBUG_NAN)
mark_as_advanced(WITH_CYCLES_NATIVE_ONLY)
-option(WITH_CYCLES_DEVICE_CUDA "Enable Cycles CUDA compute support" ON)
-option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles OptiX support" OFF)
-option(WITH_CYCLES_DEVICE_OPENCL "Enable Cycles OpenCL compute support" ON)
-option(WITH_CYCLES_NETWORK "Enable Cycles compute over network support (EXPERIMENTAL and unfinished)" OFF)
+# NVIDIA CUDA & OptiX
+option(WITH_CYCLES_DEVICE_CUDA "Enable Cycles NVIDIA CUDA compute support" ON)
+option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles NVIDIA OptiX support" ON)
mark_as_advanced(WITH_CYCLES_DEVICE_CUDA)
-mark_as_advanced(WITH_CYCLES_DEVICE_OPENCL)
-mark_as_advanced(WITH_CYCLES_NETWORK)
-option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime" ON)
+option(WITH_CYCLES_CUDA_BINARIES "Build Cycles NVIDIA CUDA binaries" OFF)
+set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
+option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
+option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
+option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime (for developers, makes cuda-gdb work)" ON)
+mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
+mark_as_advanced(WITH_CYCLES_CUBIN_COMPILER)
+mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
mark_as_advanced(WITH_CUDA_DYNLOAD)
+# AMD HIP
+option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" OFF)
+option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
+set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
+mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
+mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
+
# Draw Manager
option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF)
mark_as_advanced(WITH_DRAW_DEBUG)
@@ -825,6 +843,11 @@ if(NOT WITH_CUDA_DYNLOAD)
endif()
endif()
+if(WITH_CYCLES_DEVICE_HIP)
+ # Currently HIP must be dynamically loaded, this may change in future toolkits
+ set(WITH_HIP_DYNLOAD ON)
+endif()
+
#-----------------------------------------------------------------------------
# Check check if submodules are cloned
@@ -1720,6 +1743,12 @@ if(WITH_PYTHON)
elseif(WITH_PYTHON_INSTALL_REQUESTS)
find_python_package(requests "")
endif()
+
+ if(WIN32 OR APPLE)
+ # pass, we have this in lib/python/site-packages
+ elseif(WITH_PYTHON_INSTALL_ZSTANDARD)
+ find_python_package(zstandard "")
+ endif()
endif()
# Select C++17 as the standard for C++ projects.
@@ -1854,6 +1883,9 @@ elseif(WITH_CYCLES_STANDALONE)
if(WITH_CUDA_DYNLOAD)
add_subdirectory(extern/cuew)
endif()
+ if(WITH_HIP_DYNLOAD)
+ add_subdirectory(extern/hipew)
+ endif()
if(NOT WITH_SYSTEM_GLEW)
add_subdirectory(extern/glew)
endif()
@@ -1988,6 +2020,7 @@ if(FIRST_RUN)
endif()
info_cfg_option(WITH_PYTHON_INSTALL)
info_cfg_option(WITH_PYTHON_INSTALL_NUMPY)
+ info_cfg_option(WITH_PYTHON_INSTALL_ZSTANDARD)
info_cfg_option(WITH_PYTHON_MODULE)
info_cfg_option(WITH_PYTHON_SAFETY)
diff --git a/GNUmakefile b/GNUmakefile
index d620e5c4363..57892959d2a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -27,7 +27,7 @@
define HELP_TEXT
Blender Convenience Targets
- Provided for building Blender, (multiple at once can be used).
+ Provided for building Blender (multiple targets can be used at once).
* debug: Build a debug binary.
* full: Enable all supported dependencies & options.
@@ -40,6 +40,8 @@ Blender Convenience Targets
* ninja: Use ninja build tool for faster builds.
* ccache: Use ccache for faster rebuilds.
+ Note: when passing in multiple targets their order is not important.
+ So for a fast build you can for e.g. run 'make lite ccache ninja'.
Note: passing the argument 'BUILD_DIR=path' when calling make will override the default build dir.
Note: passing the argument 'BUILD_CMAKE_ARGS=args' lets you add cmake arguments.
diff --git a/build_files/build_environment/cmake/numpy.cmake b/build_files/build_environment/cmake/numpy.cmake
index 73fa6e75556..1b58fd6aee9 100644
--- a/build_files/build_environment/cmake/numpy.cmake
+++ b/build_files/build_environment/cmake/numpy.cmake
@@ -38,7 +38,6 @@ ExternalProject_Add(external_numpy
PREFIX ${BUILD_DIR}/numpy
PATCH_COMMAND ${NUMPY_PATCH}
CONFIGURE_COMMAND ""
- PATCH_COMMAND COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/numpy/src/external_numpy < ${PATCH_DIR}/numpy.diff
LOG_BUILD 1
BUILD_COMMAND ${PYTHON_BINARY} ${BUILD_DIR}/numpy/src/external_numpy/setup.py build ${NUMPY_BUILD_OPTION} install --old-and-unmanageable
INSTALL_COMMAND ""
diff --git a/build_files/build_environment/cmake/python_site_packages.cmake b/build_files/build_environment/cmake/python_site_packages.cmake
index 2b75a6a244f..a8918fdb784 100644
--- a/build_files/build_environment/cmake/python_site_packages.cmake
+++ b/build_files/build_environment/cmake/python_site_packages.cmake
@@ -18,14 +18,20 @@
if(WIN32 AND BUILD_MODE STREQUAL Debug)
set(SITE_PACKAGES_EXTRA --global-option build --global-option --debug)
+ # zstandard is determined to build and link release mode libs in a debug
+ # configuration, the only way to make it happy is to bend to its will
+ # and give it a library to link with.
+ set(PIP_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/python/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}_d.lib ${LIBDIR}/python/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}.lib)
+else()
+ set(PIP_CONFIGURE_COMMAND echo ".")
endif()
ExternalProject_Add(external_python_site_packages
DOWNLOAD_COMMAND ""
- CONFIGURE_COMMAND ""
+ CONFIGURE_COMMAND ${PIP_CONFIGURE_COMMAND}
BUILD_COMMAND ""
PREFIX ${BUILD_DIR}/site_packages
- INSTALL_COMMAND ${PYTHON_BINARY} -m pip install ${SITE_PACKAGES_EXTRA} cython==${CYTHON_VERSION} idna==${IDNA_VERSION} chardet==${CHARDET_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} --no-binary :all:
+ INSTALL_COMMAND ${PYTHON_BINARY} -m pip install ${SITE_PACKAGES_EXTRA} cython==${CYTHON_VERSION} idna==${IDNA_VERSION} charset-normalizer==${CHARSET_NORMALIZER_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} zstandard==${ZSTANDARD_VERSION} --no-binary :all:
)
if(USE_PIP_NUMPY)
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index d1675bdddfd..f2c245dc380 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -189,11 +189,11 @@ set(OSL_HASH 1abd7ce40481771a9fa937f19595d2f2)
set(OSL_HASH_TYPE MD5)
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
-set(PYTHON_VERSION 3.9.2)
+set(PYTHON_VERSION 3.9.7)
set(PYTHON_SHORT_VERSION 3.9)
set(PYTHON_SHORT_VERSION_NO_DOTS 39)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
-set(PYTHON_HASH f0dc9000312abeb16de4eccce9a870ab)
+set(PYTHON_HASH fddb060b483bc01850a3f412eea1d954)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
@@ -215,17 +215,18 @@ set(NANOVDB_HASH e7b9e863ec2f3b04ead171dec2322807)
set(NANOVDB_HASH_TYPE MD5)
set(NANOVDB_FILE nano-vdb-${NANOVDB_GIT_UID}.tar.gz)
-set(IDNA_VERSION 2.10)
-set(CHARDET_VERSION 4.0.0)
-set(URLLIB3_VERSION 1.26.3)
-set(CERTIFI_VERSION 2020.12.5)
-set(REQUESTS_VERSION 2.25.1)
-set(CYTHON_VERSION 0.29.21)
+set(IDNA_VERSION 3.2)
+set(CHARSET_NORMALIZER_VERSION 2.0.6)
+set(URLLIB3_VERSION 1.26.7)
+set(CERTIFI_VERSION 2021.10.8)
+set(REQUESTS_VERSION 2.26.0)
+set(CYTHON_VERSION 0.29.24)
+set(ZSTANDARD_VERSION 0.15.2 )
-set(NUMPY_VERSION 1.19.5)
-set(NUMPY_SHORT_VERSION 1.19)
+set(NUMPY_VERSION 1.21.2)
+set(NUMPY_SHORT_VERSION 1.21)
set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}/numpy-${NUMPY_VERSION}.zip)
-set(NUMPY_HASH f6a1b48717c552bbc18f1adc3cc1fe0e)
+set(NUMPY_HASH 5638d5dae3ca387be562912312db842e)
set(NUMPY_HASH_TYPE MD5)
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index ecaff307885..2bb7175da00 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -371,71 +371,78 @@ NO_BUILD=false
NO_CONFIRM=false
USE_CXX11=true
-# Note about versions: Min is inclusive, Max is exclusive (i.e. XXX_VERSION_MIN <= ACTUAL_VERSION < XXX_VERSION_MAX)
+# Note about versions: Min is inclusive, Mex is 'minimum exclusive' (i.e. XXX_VERSION_MIN <= ACTUAL_VERSION < XXX_VERSION_MEX)
# XXX_VERSION is officially supported/used version in official builds.
# XXX_VERSION_SHORT is used for various things, like preferred version (when distribution provides several of them),
# and to name shortcuts to built libraries' installation directories...
CLANG_FORMAT_VERSION_MIN="6.0"
-CLANG_FORMAT_VERSION_MAX="10.0"
+CLANG_FORMAT_VERSION_MEX="10.0"
-PYTHON_VERSION="3.9.2"
+PYTHON_VERSION="3.9.7"
PYTHON_VERSION_SHORT="3.9"
PYTHON_VERSION_MIN="3.7"
-PYTHON_VERSION_MAX="3.11"
+PYTHON_VERSION_MEX="3.11"
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT
PYTHON_FORCE_BUILD=false
PYTHON_FORCE_REBUILD=false
PYTHON_SKIP=false
# Additional Python modules.
-PYTHON_IDNA_VERSION="2.9"
+PYTHON_IDNA_VERSION="3.2"
PYTHON_IDNA_VERSION_MIN="2.0"
-PYTHON_IDNA_VERSION_MAX="3.0"
+PYTHON_IDNA_VERSION_MEX="4.0"
PYTHON_IDNA_NAME="idna"
-PYTHON_CHARDET_VERSION="3.0.4"
-PYTHON_CHARDET_VERSION_MIN="3.0"
-PYTHON_CHARDET_VERSION_MAX="5.0"
-PYTHON_CHARDET_NAME="chardet"
+PYTHON_CHARSET_NORMALIZER_VERSION="2.0.6"
+PYTHON_CHARSET_NORMALIZER_VERSION_MIN="2.0.6"
+PYTHON_CHARSET_NORMALIZER_VERSION_MEX="2.1.0" # requests uses `charset_normalizer~=2.0.0`
+PYTHON_CHARSET_NORMALIZER_NAME="charset-normalizer"
-PYTHON_URLLIB3_VERSION="1.25.9"
+PYTHON_URLLIB3_VERSION="1.26.7"
PYTHON_URLLIB3_VERSION_MIN="1.0"
-PYTHON_URLLIB3_VERSION_MAX="2.0"
+PYTHON_URLLIB3_VERSION_MEX="2.0"
PYTHON_URLLIB3_NAME="urllib3"
-PYTHON_CERTIFI_VERSION="2020.4.5.2"
-PYTHON_CERTIFI_VERSION_MIN="2020.0"
-PYTHON_CERTIFI_VERSION_MAX="2021.0"
+PYTHON_CERTIFI_VERSION="2021.10.8"
+PYTHON_CERTIFI_VERSION_MIN="2021.0"
+PYTHON_CERTIFI_VERSION_MEX="2023.0"
PYTHON_CERTIFI_NAME="certifi"
PYTHON_REQUESTS_VERSION="2.23.0"
PYTHON_REQUESTS_VERSION_MIN="2.0"
-PYTHON_REQUESTS_VERSION_MAX="3.0"
+PYTHON_REQUESTS_VERSION_MEX="3.0"
PYTHON_REQUESTS_NAME="requests"
-PYTHON_NUMPY_VERSION="1.19.5"
+PYTHON_ZSTANDARD_VERSION="0.15.2"
+PYTHON_ZSTANDARD_VERSION_MIN="0.15.2"
+PYTHON_ZSTANDARD_VERSION_MEX="0.16.0"
+PYTHON_ZSTANDARD_NAME="zstandard"
+
+PYTHON_NUMPY_VERSION="1.21.2"
PYTHON_NUMPY_VERSION_MIN="1.14"
-PYTHON_NUMPY_VERSION_MAX="2.0"
+PYTHON_NUMPY_VERSION_MEX="2.0"
PYTHON_NUMPY_NAME="numpy"
# As package-ready parameters (only used with distro packages).
PYTHON_MODULES_PACKAGES=(
- "$PYTHON_IDNA_NAME $PYTHON_IDNA_VERSION_MIN $PYTHON_IDNA_VERSION_MAX"
- "$PYTHON_CHARDET_NAME $PYTHON_CHARDET_VERSION_MIN $PYTHON_CHARDET_VERSION_MAX"
- "$PYTHON_URLLIB3_NAME $PYTHON_URLLIB3_VERSION_MIN $PYTHON_URLLIB3_VERSION_MAX"
- "$PYTHON_CERTIFI_NAME $PYTHON_CERTIFI_VERSION_MIN $PYTHON_CERTIFI_VERSION_MAX"
- "$PYTHON_REQUESTS_NAME $PYTHON_REQUESTS_VERSION_MIN $PYTHON_REQUESTS_VERSION_MAX"
- "$PYTHON_NUMPY_NAME $PYTHON_NUMPY_VERSION_MIN $PYTHON_NUMPY_VERSION_MAX"
+ "$PYTHON_IDNA_NAME $PYTHON_IDNA_VERSION_MIN $PYTHON_IDNA_VERSION_MEX"
+ "$PYTHON_CHARSET_NORMALIZER_NAME $PYTHON_CHARSET_NORMALIZER_VERSION_MIN $PYTHON_CHARSET_NORMALIZER_VERSION_MEX"
+ "$PYTHON_URLLIB3_NAME $PYTHON_URLLIB3_VERSION_MIN $PYTHON_URLLIB3_VERSION_MEX"
+ "$PYTHON_CERTIFI_NAME $PYTHON_CERTIFI_VERSION_MIN $PYTHON_CERTIFI_VERSION_MEX"
+ "$PYTHON_REQUESTS_NAME $PYTHON_REQUESTS_VERSION_MIN $PYTHON_REQUESTS_VERSION_MEX"
+ "$PYTHON_ZSTANDARD_NAME $PYTHON_ZSTANDARD_VERSION_MIN $PYTHON_ZSTANDARD_VERSION_MEX"
+ "$PYTHON_NUMPY_NAME $PYTHON_NUMPY_VERSION_MIN $PYTHON_NUMPY_VERSION_MEX"
)
# As pip-ready parameters (only used when building python).
PYTHON_MODULES_PIP=(
"$PYTHON_IDNA_NAME==$PYTHON_IDNA_VERSION"
- "$PYTHON_CHARDET_NAME==$PYTHON_CHARDET_VERSION"
+ "$PYTHON_CHARSET_NORMALIZER_NAME==$PYTHON_CHARSET_NORMALIZER_VERSION"
"$PYTHON_URLLIB3_NAME==$PYTHON_URLLIB3_VERSION"
"$PYTHON_CERTIFI_NAME==$PYTHON_CERTIFI_VERSION"
"$PYTHON_REQUESTS_NAME==$PYTHON_REQUESTS_VERSION"
+ "$PYTHON_ZSTANDARD_NAME==$PYTHON_ZSTANDARD_VERSION"
"$PYTHON_NUMPY_NAME==$PYTHON_NUMPY_VERSION"
)
@@ -443,7 +450,7 @@ PYTHON_MODULES_PIP=(
BOOST_VERSION="1.73.0"
BOOST_VERSION_SHORT="1.73"
BOOST_VERSION_MIN="1.49"
-BOOST_VERSION_MAX="2.0"
+BOOST_VERSION_MEX="2.0"
BOOST_FORCE_BUILD=false
BOOST_FORCE_REBUILD=false
BOOST_SKIP=false
@@ -452,7 +459,7 @@ TBB_VERSION="2020"
TBB_VERSION_SHORT="2020"
TBB_VERSION_UPDATE="_U2" # Used for source packages...
TBB_VERSION_MIN="2018"
-TBB_VERSION_MAX="2022"
+TBB_VERSION_MEX="2022"
TBB_FORCE_BUILD=false
TBB_FORCE_REBUILD=false
TBB_SKIP=false
@@ -460,7 +467,7 @@ TBB_SKIP=false
OCIO_VERSION="2.0.0"
OCIO_VERSION_SHORT="2.0"
OCIO_VERSION_MIN="2.0"
-OCIO_VERSION_MAX="3.0"
+OCIO_VERSION_MEX="3.0"
OCIO_FORCE_BUILD=false
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
@@ -468,7 +475,7 @@ OCIO_SKIP=false
OPENEXR_VERSION="2.5.5"
OPENEXR_VERSION_SHORT="2.5"
OPENEXR_VERSION_MIN="2.4"
-OPENEXR_VERSION_MAX="3.0"
+OPENEXR_VERSION_MEX="3.0"
OPENEXR_FORCE_BUILD=false
OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
@@ -477,7 +484,7 @@ _with_built_openexr=false
OIIO_VERSION="2.2.15.1"
OIIO_VERSION_SHORT="2.2"
OIIO_VERSION_MIN="2.1.12"
-OIIO_VERSION_MAX="2.3.0"
+OIIO_VERSION_MEX="2.3.0"
OIIO_FORCE_BUILD=false
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
@@ -485,7 +492,7 @@ OIIO_SKIP=false
LLVM_VERSION="12.0.0"
LLVM_VERSION_SHORT="12.0"
LLVM_VERSION_MIN="11.0"
-LLVM_VERSION_MAX="13.0"
+LLVM_VERSION_MEX="13.0"
LLVM_VERSION_FOUND=""
LLVM_FORCE_BUILD=false
LLVM_FORCE_REBUILD=false
@@ -495,7 +502,7 @@ LLVM_SKIP=false
OSL_VERSION="1.11.14.1"
OSL_VERSION_SHORT="1.11"
OSL_VERSION_MIN="1.11"
-OSL_VERSION_MAX="2.0"
+OSL_VERSION_MEX="2.0"
OSL_FORCE_BUILD=false
OSL_FORCE_REBUILD=false
OSL_SKIP=false
@@ -504,7 +511,7 @@ OSL_SKIP=false
OSD_VERSION="3.4.3"
OSD_VERSION_SHORT="3.4"
OSD_VERSION_MIN="3.4"
-OSD_VERSION_MAX="4.0"
+OSD_VERSION_MEX="4.0"
OSD_FORCE_BUILD=false
OSD_FORCE_REBUILD=false
OSD_SKIP=false
@@ -515,7 +522,7 @@ OPENVDB_BLOSC_VERSION="1.5.0"
OPENVDB_VERSION="8.0.1"
OPENVDB_VERSION_SHORT="8.0"
OPENVDB_VERSION_MIN="8.0"
-OPENVDB_VERSION_MAX="8.1"
+OPENVDB_VERSION_MEX="8.1"
OPENVDB_FORCE_BUILD=false
OPENVDB_FORCE_REBUILD=false
OPENVDB_SKIP=false
@@ -524,7 +531,7 @@ OPENVDB_SKIP=false
ALEMBIC_VERSION="1.7.16"
ALEMBIC_VERSION_SHORT="1.7"
ALEMBIC_VERSION_MIN="1.7"
-ALEMBIC_VERSION_MAX="2.0"
+ALEMBIC_VERSION_MEX="2.0"
ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
ALEMBIC_SKIP=false
@@ -532,7 +539,7 @@ ALEMBIC_SKIP=false
USD_VERSION="21.02"
USD_VERSION_SHORT="21.02"
USD_VERSION_MIN="20.05"
-USD_VERSION_MAX="22.00"
+USD_VERSION_MEX="22.00"
USD_FORCE_BUILD=false
USD_FORCE_REBUILD=false
USD_SKIP=false
@@ -540,7 +547,7 @@ USD_SKIP=false
OPENCOLLADA_VERSION="1.6.68"
OPENCOLLADA_VERSION_SHORT="1.6"
OPENCOLLADA_VERSION_MIN="1.6.68"
-OPENCOLLADA_VERSION_MAX="1.7"
+OPENCOLLADA_VERSION_MEX="1.7"
OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
@@ -548,7 +555,7 @@ OPENCOLLADA_SKIP=false
EMBREE_VERSION="3.10.0"
EMBREE_VERSION_SHORT="3.10"
EMBREE_VERSION_MIN="3.10"
-EMBREE_VERSION_MAX="4.0"
+EMBREE_VERSION_MEX="4.0"
EMBREE_FORCE_BUILD=false
EMBREE_FORCE_REBUILD=false
EMBREE_SKIP=false
@@ -556,7 +563,7 @@ EMBREE_SKIP=false
OIDN_VERSION="1.4.1"
OIDN_VERSION_SHORT="1.4"
OIDN_VERSION_MIN="1.4.0"
-OIDN_VERSION_MAX="1.5"
+OIDN_VERSION_MEX="1.5"
OIDN_FORCE_BUILD=false
OIDN_FORCE_REBUILD=false
OIDN_SKIP=false
@@ -566,7 +573,7 @@ ISPC_VERSION="1.16.0"
FFMPEG_VERSION="4.4"
FFMPEG_VERSION_SHORT="4.4"
FFMPEG_VERSION_MIN="3.0"
-FFMPEG_VERSION_MAX="5.0"
+FFMPEG_VERSION_MEX="5.0"
FFMPEG_FORCE_BUILD=false
FFMPEG_FORCE_REBUILD=false
FFMPEG_SKIP=false
@@ -575,7 +582,7 @@ _ffmpeg_list_sep=";"
XR_OPENXR_VERSION="1.0.17"
XR_OPENXR_VERSION_SHORT="1.0"
XR_OPENXR_VERSION_MIN="1.0.8"
-XR_OPENXR_VERSION_MAX="2.0"
+XR_OPENXR_VERSION_MEX="2.0"
XR_OPENXR_FORCE_BUILD=false
XR_OPENXR_FORCE_REBUILD=false
XR_OPENXR_SKIP=false
@@ -1141,10 +1148,11 @@ You may also want to build them yourself (optional ones are [between brackets]):
* Python $PYTHON_VERSION (from $PYTHON_SOURCE).
** [IDNA $PYTHON_IDNA_VERSION] (use pip).
- ** [Chardet $PYTHON_CHARDET_VERSION] (use pip).
+ ** [Charset Normalizer $PYTHON_CHARSET_NORMALIZER_VERSION] (use pip).
** [Urllib3 $PYTHON_URLLIB3_VERSION] (use pip).
** [Certifi $PYTHON_CERTIFI_VERSION] (use pip).
** [Requests $PYTHON_REQUESTS_VERSION] (use pip).
+ ** [ZStandard $PYTHON_ZSTANDARD_VERSION] (use pip).
** [NumPy $PYTHON_NUMPY_VERSION] (use pip).
* Boost $BOOST_VERSION (from $BOOST_SOURCE, modules: $BOOST_BUILD_MODULES).
* TBB $TBB_VERSION (from $TBB_SOURCE).
@@ -2013,7 +2021,7 @@ compile_OIIO() {
fi
# To be changed each time we make edits that would modify the compiled result!
- oiio_magic=17
+ oiio_magic=18
_init_oiio
# Force having own builds for the dependencies.
@@ -2088,6 +2096,7 @@ compile_OIIO() {
cmake_d="$cmake_d -D USE_PYTHON=OFF"
cmake_d="$cmake_d -D USE_FFMPEG=OFF"
cmake_d="$cmake_d -D USE_OPENCV=OFF"
+ cmake_d="$cmake_d -D USE_OPENVDB=OFF"
cmake_d="$cmake_d -D BUILD_TESTING=OFF"
cmake_d="$cmake_d -D OIIO_BUILD_TESTS=OFF"
cmake_d="$cmake_d -D OIIO_BUILD_TOOLS=OFF"
@@ -4027,7 +4036,7 @@ install_DEB() {
INFO "Forced Python building, as requested..."
_do_compile_python=true
else
- check_package_version_ge_lt_DEB python3-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX
+ check_package_version_ge_lt_DEB python3-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python3-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
@@ -4040,8 +4049,8 @@ install_DEB() {
module=($module)
package="python3-${module[0]}"
package_vmin=${module[1]}
- package_vmax=${module[2]}
- check_package_version_ge_lt_DEB "$package" $package_vmin $package_vmax
+ package_vmex=${module[2]}
+ check_package_version_ge_lt_DEB "$package" $package_vmin $package_vmex
if [ $? -eq 0 ]; then
install_packages_DEB "$package"
else
@@ -4067,7 +4076,7 @@ install_DEB() {
INFO "Forced Boost building, as requested..."
compile_Boost
else
- check_package_version_ge_lt_DEB libboost-dev $BOOST_VERSION_MIN $BOOST_VERSION_MAX
+ check_package_version_ge_lt_DEB libboost-dev $BOOST_VERSION_MIN $BOOST_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libboost-dev
@@ -4088,7 +4097,7 @@ install_DEB() {
INFO "Forced TBB building, as requested..."
compile_TBB
else
- check_package_version_ge_lt_DEB libtbb-dev $TBB_VERSION_MIN $TBB_VERSION_MAX
+ check_package_version_ge_lt_DEB libtbb-dev $TBB_VERSION_MIN $TBB_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libtbb-dev
clean_TBB
@@ -4105,7 +4114,7 @@ install_DEB() {
INFO "Forced OpenColorIO building, as requested..."
compile_OCIO
else
- check_package_version_ge_lt_DEB libopencolorio-dev $OCIO_VERSION_MIN $OCIO_VERSION_MAX
+ check_package_version_ge_lt_DEB libopencolorio-dev $OCIO_VERSION_MIN $OCIO_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libopencolorio-dev
clean_OCIO
@@ -4122,7 +4131,7 @@ install_DEB() {
INFO "Forced ILMBase/OpenEXR building, as requested..."
compile_OPENEXR
else
- check_package_version_ge_lt_DEB libopenexr-dev $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MAX
+ check_package_version_ge_lt_DEB libopenexr-dev $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libopenexr-dev
OPENEXR_VERSION=`get_package_version_DEB libopenexr-dev`
@@ -4143,7 +4152,7 @@ install_DEB() {
INFO "Forced OpenImageIO building, as requested..."
compile_OIIO
else
- check_package_version_ge_lt_DEB libopenimageio-dev $OIIO_VERSION_MIN $OIIO_VERSION_MAX
+ check_package_version_ge_lt_DEB libopenimageio-dev $OIIO_VERSION_MIN $OIIO_VERSION_MEX
if [ $? -eq 0 -a "$_with_built_openexr" = false ]; then
install_packages_DEB libopenimageio-dev openimageio-tools
clean_OIIO
@@ -4163,7 +4172,7 @@ install_DEB() {
INFO "Forced LLVM building, as requested..."
_do_compile_llvm=true
else
- check_package_version_ge_lt_DEB llvm-dev $LLVM_VERSION_MIN $LLVM_VERSION_MAX
+ check_package_version_ge_lt_DEB llvm-dev $LLVM_VERSION_MIN $LLVM_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB llvm-dev clang libclang-dev
have_llvm=true
@@ -4194,7 +4203,7 @@ install_DEB() {
INFO "Forced OpenShadingLanguage building, as requested..."
_do_compile_osl=true
else
- check_package_version_ge_lt_DEB libopenshadinglanguage-dev $OSL_VERSION_MIN $OSL_VERSION_MAX
+ check_package_version_ge_lt_DEB libopenshadinglanguage-dev $OSL_VERSION_MIN $OSL_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libopenshadinglanguage-dev
clean_OSL
@@ -4232,7 +4241,7 @@ install_DEB() {
INFO "Forced OpenVDB building, as requested..."
compile_OPENVDB
else
- check_package_version_ge_lt_DEB libopenvdb-dev $OPENVDB_VERSION_MIN $OPENVDB_VERSION_MAX
+ check_package_version_ge_lt_DEB libopenvdb-dev $OPENVDB_VERSION_MIN $OPENVDB_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libopenvdb-dev libblosc-dev
clean_OPENVDB
@@ -4294,7 +4303,7 @@ install_DEB() {
_do_compile_embree=true
else
# There is a package, but it does not provide everything that Blender needs...
- #~ check_package_version_ge_lt_DEB libembree-dev $EMBREE_VERSION_MIN $EMBREE_VERSION_MAX
+ #~ check_package_version_ge_lt_DEB libembree-dev $EMBREE_VERSION_MIN $EMBREE_VERSION_MEX
#~ if [ $? -eq 0 ]; then
#~ install_packages_DEB libembree-dev
#~ clean_Embree
@@ -4336,7 +4345,7 @@ install_DEB() {
# XXX Debian Testing / Ubuntu 16.04 finally includes FFmpeg, so check as usual
check_package_DEB ffmpeg
if [ $? -eq 0 ]; then
- check_package_version_ge_lt_DEB ffmpeg $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MAX
+ check_package_version_ge_lt_DEB ffmpeg $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_DEB libavdevice-dev
clean_FFmpeg
@@ -4670,7 +4679,7 @@ install_RPM() {
INFO "Forced Python building, as requested..."
_do_compile_python=true
else
- check_package_version_ge_lt_RPM python3-devel $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX
+ check_package_version_ge_lt_RPM python3-devel $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
@@ -4682,8 +4691,8 @@ install_RPM() {
module=($module)
package="python3-${module[0]}"
package_vmin=${module[1]}
- package_vmax=${module[2]}
- check_package_version_ge_lt_RPM "$package" $package_vmin $package_vmax
+ package_vmex=${module[2]}
+ check_package_version_ge_lt_RPM "$package" $package_vmin $package_vmex
if [ $? -eq 0 ]; then
install_packages_RPM "$package"
else
@@ -4710,7 +4719,7 @@ install_RPM() {
INFO "Forced Boost building, as requested..."
_do_compile_boost=true
else
- check_package_version_ge_lt_RPM boost-devel $BOOST_VERSION_MIN $BOOST_VERSION_MAX
+ check_package_version_ge_lt_RPM boost-devel $BOOST_VERSION_MIN $BOOST_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM boost-devel
clean_Boost
@@ -4737,7 +4746,7 @@ install_RPM() {
INFO "Forced TBB building, as requested..."
compile_TBB
else
- check_package_version_ge_lt_RPM tbb-devel $TBB_VERSION_MIN $TBB_VERSION_MAX
+ check_package_version_ge_lt_RPM tbb-devel $TBB_VERSION_MIN $TBB_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM tbb-devel
clean_TBB
@@ -4755,7 +4764,7 @@ install_RPM() {
compile_OCIO
else
if [ "$RPM" = "SUSE" ]; then
- check_package_version_ge_lt_RPM OpenColorIO-devel $OCIO_VERSION_MIN $OCIO_VERSION_MAX
+ check_package_version_ge_lt_RPM OpenColorIO-devel $OCIO_VERSION_MIN $OCIO_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM OpenColorIO-devel
clean_OCIO
@@ -4775,7 +4784,7 @@ install_RPM() {
INFO "Forced ILMBase/OpenEXR building, as requested..."
compile_OPENEXR
else
- check_package_version_ge_lt_RPM openexr-devel $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MAX
+ check_package_version_ge_lt_RPM openexr-devel $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM openexr-devel
OPENEXR_VERSION=`get_package_version_RPM openexr-devel`
@@ -4793,7 +4802,7 @@ install_RPM() {
INFO "Forced OpenImageIO building, as requested..."
compile_OIIO
else
- check_package_version_ge_lt_RPM OpenImageIO-devel $OIIO_VERSION_MIN $OIIO_VERSION_MAX
+ check_package_version_ge_lt_RPM OpenImageIO-devel $OIIO_VERSION_MIN $OIIO_VERSION_MEX
if [ $? -eq 0 -a $_with_built_openexr == false ]; then
install_packages_RPM OpenImageIO-devel OpenImageIO-utils
clean_OIIO
@@ -4818,7 +4827,7 @@ install_RPM() {
else
CLANG_DEV="clang-devel"
fi
- check_package_version_ge_lt_RPM llvm-devel $LLVM_VERSION_MIN $LLVM_VERSION_MAX
+ check_package_version_ge_lt_RPM llvm-devel $LLVM_VERSION_MIN $LLVM_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM llvm-devel $CLANG_DEV
have_llvm=true
@@ -4854,7 +4863,7 @@ install_RPM() {
else
OSL_DEV="openshadinglanguage-devel"
fi
- check_package_version_ge_lt_RPM $OSL_DEV $OSL_VERSION_MIN $OSL_VERSION_MAX
+ check_package_version_ge_lt_RPM $OSL_DEV $OSL_VERSION_MIN $OSL_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM $OSL_DEV
clean_OSL
@@ -4949,7 +4958,7 @@ install_RPM() {
_do_compile_embree=true
else
# There is a package, but it does not provide everything that Blender needs...
- #~ check_package_version_ge_lt_RPM embree-devel $EMBREE_VERSION_MIN $EMBREE_VERSION_MAX
+ #~ check_package_version_ge_lt_RPM embree-devel $EMBREE_VERSION_MIN $EMBREE_VERSION_MEX
#~ if [ $? -eq 0 ]; then
#~ install_packages_RPM embree-devel
#~ clean_Embree
@@ -4988,7 +4997,7 @@ install_RPM() {
INFO "Forced FFMpeg building, as requested..."
compile_FFmpeg
else
- check_package_version_ge_lt_RPM ffmpeg-devel $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MAX
+ check_package_version_ge_lt_RPM ffmpeg-devel $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_RPM ffmpeg ffmpeg-devel
clean_FFmpeg
@@ -5213,7 +5222,7 @@ install_ARCH() {
INFO "Forced Python building, as requested..."
_do_compile_python=true
else
- check_package_version_ge_lt_ARCH python $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX
+ check_package_version_ge_lt_ARCH python $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
@@ -5226,8 +5235,8 @@ install_ARCH() {
module=($module)
package="python-${module[0]}"
package_vmin=${module[1]}
- package_vmax=${module[2]}
- check_package_version_ge_lt_ARCH "$package" $package_vmin $package_vmax
+ package_vmex=${module[2]}
+ check_package_version_ge_lt_ARCH "$package" $package_vmin $package_vmex
if [ $? -eq 0 ]; then
install_packages_ARCH "$package"
else
@@ -5253,7 +5262,7 @@ install_ARCH() {
INFO "Forced Boost building, as requested..."
compile_Boost
else
- check_package_version_ge_lt_ARCH boost $BOOST_VERSION_MIN $BOOST_VERSION_MAX
+ check_package_version_ge_lt_ARCH boost $BOOST_VERSION_MIN $BOOST_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH boost
clean_Boost
@@ -5270,7 +5279,7 @@ install_ARCH() {
INFO "Forced TBB building, as requested..."
compile_TBB
else
- check_package_version_ge_lt_ARCH intel-tbb $TBB_VERSION_MIN $TBB_VERSION_MAX
+ check_package_version_ge_lt_ARCH intel-tbb $TBB_VERSION_MIN $TBB_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH intel-tbb
clean_TBB
@@ -5287,7 +5296,7 @@ install_ARCH() {
INFO "Forced OpenColorIO building, as requested..."
compile_OCIO
else
- check_package_version_ge_lt_ARCH opencolorio $OCIO_VERSION_MIN $OCIO_VERSION_MAX
+ check_package_version_ge_lt_ARCH opencolorio $OCIO_VERSION_MIN $OCIO_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH opencolorio
clean_OCIO
@@ -5304,7 +5313,7 @@ install_ARCH() {
INFO "Forced ILMBase/OpenEXR building, as requested..."
compile_OPENEXR
else
- check_package_version_ge_lt_ARCH openexr $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MAX
+ check_package_version_ge_lt_ARCH openexr $OPENEXR_VERSION_MIN $OPENEXR_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH openexr
OPENEXR_VERSION=`get_package_version_ARCH openexr`
@@ -5323,7 +5332,7 @@ install_ARCH() {
INFO "Forced OpenImageIO building, as requested..."
compile_OIIO
else
- check_package_version_ge_lt_ARCH openimageio $OIIO_VERSION_MIN $OIIO_VERSION_MAX
+ check_package_version_ge_lt_ARCH openimageio $OIIO_VERSION_MIN $OIIO_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH openimageio
clean_OIIO
@@ -5343,7 +5352,7 @@ install_ARCH() {
INFO "Forced LLVM building, as requested..."
_do_compile_llvm=true
else
- check_package_version_ge_lt_ARCH llvm $LLVM_VERSION_MIN $LLVM_VERSION_MAX
+ check_package_version_ge_lt_ARCH llvm $LLVM_VERSION_MIN $LLVM_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH llvm clang
have_llvm=true
@@ -5374,7 +5383,7 @@ install_ARCH() {
INFO "Forced OpenShadingLanguage building, as requested..."
_do_compile_osl=true
else
- check_package_version_ge_lt_ARCH openshadinglanguage $OSL_VERSION_MIN $OSL_VERSION_MAX
+ check_package_version_ge_lt_ARCH openshadinglanguage $OSL_VERSION_MIN $OSL_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH openshadinglanguage
clean_OSL
@@ -5400,7 +5409,7 @@ install_ARCH() {
INFO "Forced OpenSubdiv building, as requested..."
compile_OSD
else
- check_package_version_ge_lt_ARCH opensubdiv $OSD_VERSION_MIN $OSD_VERSION_MAX
+ check_package_version_ge_lt_ARCH opensubdiv $OSD_VERSION_MIN $OSD_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH opensubdiv
clean_OSD
@@ -5417,7 +5426,7 @@ install_ARCH() {
INFO "Forced OpenVDB building, as requested..."
compile_OPENVDB
else
- check_package_version_ge_lt_ARCH openvdb $OPENVDB_VERSION_MIN $OPENVDB_VERSION_MAX
+ check_package_version_ge_lt_ARCH openvdb $OPENVDB_VERSION_MIN $OPENVDB_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH openvdb
clean_OPENVDB
@@ -5483,7 +5492,7 @@ install_ARCH() {
_do_compile_embree=true
else
# There is a package, but it does not provide everything that Blender needs...
- #~ check_package_version_ge_lt_ARCH embree $EMBREE_VERSION_MIN $EMBREE_VERSION_MAX
+ #~ check_package_version_ge_lt_ARCH embree $EMBREE_VERSION_MIN $EMBREE_VERSION_MEX
#~ if [ $? -eq 0 ]; then
#~ install_packages_ARCH embree
#~ clean_Embree
@@ -5522,7 +5531,7 @@ install_ARCH() {
INFO "Forced FFMpeg building, as requested..."
compile_FFmpeg
else
- check_package_version_ge_lt_ARCH ffmpeg $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MAX
+ check_package_version_ge_lt_ARCH ffmpeg $FFMPEG_VERSION_MIN $FFMPEG_VERSION_MEX
if [ $? -eq 0 ]; then
install_packages_ARCH ffmpeg
clean_FFmpeg
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
index 5a50a3f8756..c255f7c37a3 100644
--- a/build_files/build_environment/patches/ffmpeg.diff
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -70,16 +70,18 @@
}
--- a/libavcodec/rl.c
+++ b/libavcodec/rl.c
-@@ -71,7 +71,7 @@ av_cold void ff_rl_init(RLTable *rl,
+@@ -71,17 +71,19 @@
av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
{
int i, q;
- VLC_TYPE table[1500][2] = {{0}};
+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2);
VLC vlc = { .table = table, .table_allocated = static_size };
- av_assert0(static_size <= FF_ARRAY_ELEMS(table));
+- av_assert0(static_size <= FF_ARRAY_ELEMS(table));
++ av_assert0(static_size < 1500);
init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC);
-@@ -80,8 +80,10 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
+
+ for (q = 0; q < 32; q++) {
int qmul = q * 2;
int qadd = (q - 1) | 1;
@@ -91,7 +93,7 @@
if (q == 0) {
qmul = 1;
-@@ -113,4 +115,5 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
+@@ -113,4 +115,5 @@
rl->rl_vlc[q][i].run = run;
}
}
diff --git a/build_files/build_environment/patches/numpy.diff b/build_files/build_environment/patches/numpy.diff
deleted file mode 100644
index a9b783dd856..00000000000
--- a/build_files/build_environment/patches/numpy.diff
+++ /dev/null
@@ -1,27 +0,0 @@
-diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py
-index ba2b1f4..b10f7df 100644
---- a/numpy/distutils/system_info.py
-+++ b/numpy/distutils/system_info.py
-@@ -2164,8 +2164,8 @@ class accelerate_info(system_info):
- 'accelerate' in libraries):
- if intel:
- args.extend(['-msse3'])
-- else:
-- args.extend(['-faltivec'])
-+# else:
-+# args.extend(['-faltivec'])
- args.extend([
- '-I/System/Library/Frameworks/vecLib.framework/Headers'])
- link_args.extend(['-Wl,-framework', '-Wl,Accelerate'])
-@@ -2174,8 +2174,8 @@ class accelerate_info(system_info):
- 'veclib' in libraries):
- if intel:
- args.extend(['-msse3'])
-- else:
-- args.extend(['-faltivec'])
-+# else:
-+# args.extend(['-faltivec'])
- args.extend([
- '-I/System/Library/Frameworks/vecLib.framework/Headers'])
- link_args.extend(['-Wl,-framework', '-Wl,vecLib'])
-
diff --git a/build_files/build_environment/windows/build_deps.cmd b/build_files/build_environment/windows/build_deps.cmd
index 2159055f3bd..5174af8e20d 100644
--- a/build_files/build_environment/windows/build_deps.cmd
+++ b/build_files/build_environment/windows/build_deps.cmd
@@ -79,6 +79,9 @@ set STAGING=%BUILD_DIR%\S
rem for python module build
set MSSdk=1
set DISTUTILS_USE_SDK=1
+rem if you let pip pick its own build dirs, it'll stick it somewhere deep inside the user profile
+rem and cython will refuse to link due to a path that gets too long.
+set TMPDIR=c:\t\
rem for python externals source to be shared between the various archs and compilers
mkdir %BUILD_DIR%\downloads\externals
diff --git a/build_files/cmake/Modules/FindHIP.cmake b/build_files/cmake/Modules/FindHIP.cmake
new file mode 100644
index 00000000000..c331a19eb33
--- /dev/null
+++ b/build_files/cmake/Modules/FindHIP.cmake
@@ -0,0 +1,81 @@
+# - Find HIP compiler
+#
+# This module defines
+# HIP_HIPCC_EXECUTABLE, the full path to the hipcc executable
+# HIP_VERSION, the HIP compiler version
+#
+# HIP_FOUND, if the HIP toolkit is found.
+
+#=============================================================================
+# Copyright 2021 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
+#=============================================================================
+
+# If HIP_ROOT_DIR was defined in the environment, use it.
+if(NOT HIP_ROOT_DIR AND NOT $ENV{HIP_ROOT_DIR} STREQUAL "")
+ set(HIP_ROOT_DIR $ENV{HIP_ROOT_DIR})
+endif()
+
+set(_hip_SEARCH_DIRS
+ ${HIP_ROOT_DIR}
+)
+
+find_program(HIP_HIPCC_EXECUTABLE
+ NAMES
+ hipcc
+ HINTS
+ ${_hip_SEARCH_DIRS}
+ PATH_SUFFIXES
+ bin
+)
+
+if(HIP_HIPCC_EXECUTABLE AND NOT EXISTS ${HIP_HIPCC_EXECUTABLE})
+ message(WARNING "Cached or directly specified hipcc executable does not exist.")
+ set(HIP_FOUND FALSE)
+elseif(HIP_HIPCC_EXECUTABLE)
+ set(HIP_FOUND TRUE)
+
+ set(HIP_VERSION_MAJOR 0)
+ set(HIP_VERSION_MINOR 0)
+ set(HIP_VERSION_PATCH 0)
+
+ # Get version from the output.
+ execute_process(COMMAND ${HIP_HIPCC_EXECUTABLE} --version
+ OUTPUT_VARIABLE HIP_VERSION_RAW
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ # Parse parts.
+ if(HIP_VERSION_RAW MATCHES "HIP version: .*")
+ # Strip the HIP prefix and get list of individual version components.
+ string(REGEX REPLACE
+ ".*HIP version: ([.0-9]+).*" "\\1"
+ HIP_SEMANTIC_VERSION "${HIP_VERSION_RAW}")
+ string(REPLACE "." ";" HIP_VERSION_PARTS "${HIP_SEMANTIC_VERSION}")
+ list(LENGTH HIP_VERSION_PARTS NUM_HIP_VERSION_PARTS)
+
+ # Extract components into corresponding variables.
+ if(NUM_HIP_VERSION_PARTS GREATER 0)
+ list(GET HIP_VERSION_PARTS 0 HIP_VERSION_MAJOR)
+ endif()
+ if(NUM_HIP_VERSION_PARTS GREATER 1)
+ list(GET HIP_VERSION_PARTS 1 HIP_VERSION_MINOR)
+ endif()
+ if(NUM_HIP_VERSION_PARTS GREATER 2)
+ list(GET HIP_VERSION_PARTS 2 HIP_VERSION_PATCH)
+ endif()
+
+ # Unset temp variables.
+ unset(NUM_HIP_VERSION_PARTS)
+ unset(HIP_SEMANTIC_VERSION)
+ unset(HIP_VERSION_PARTS)
+ endif()
+
+ # Construct full semantic version.
+ set(HIP_VERSION "${HIP_VERSION_MAJOR}.${HIP_VERSION_MINOR}.${HIP_VERSION_PATCH}")
+ unset(HIP_VERSION_RAW)
+else()
+ set(HIP_FOUND FALSE)
+endif()
diff --git a/build_files/cmake/Modules/FindOptiX.cmake b/build_files/cmake/Modules/FindOptiX.cmake
index cfcdd9cd23b..67106740f57 100644
--- a/build_files/cmake/Modules/FindOptiX.cmake
+++ b/build_files/cmake/Modules/FindOptiX.cmake
@@ -33,11 +33,23 @@ FIND_PATH(OPTIX_INCLUDE_DIR
include
)
+IF(EXISTS "${OPTIX_INCLUDE_DIR}/optix.h")
+ FILE(STRINGS "${OPTIX_INCLUDE_DIR}/optix.h" _optix_version REGEX "^#define OPTIX_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _optix_version ${_optix_version})
+
+ MATH(EXPR _optix_version_major "${_optix_version} / 10000")
+ MATH(EXPR _optix_version_minor "(${_optix_version} % 10000) / 100")
+ MATH(EXPR _optix_version_patch "${_optix_version} % 100")
+
+ SET(OPTIX_VERSION "${_optix_version_major}.${_optix_version_minor}.${_optix_version_patch}")
+ENDIF()
+
# handle the QUIETLY and REQUIRED arguments and set OPTIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(OptiX DEFAULT_MSG
- OPTIX_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OptiX
+ REQUIRED_VARS OPTIX_INCLUDE_DIR
+ VERSION_VAR OPTIX_VERSION)
IF(OPTIX_FOUND)
SET(OPTIX_INCLUDE_DIRS ${OPTIX_INCLUDE_DIR})
@@ -45,6 +57,7 @@ ENDIF()
MARK_AS_ADVANCED(
OPTIX_INCLUDE_DIR
+ OPTIX_VERSION
)
UNSET(_optix_SEARCH_DIRS)
diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py
index 1eef2efe2b5..0e37b9ba468 100644
--- a/build_files/cmake/cmake_static_check_cppcheck.py
+++ b/build_files/cmake/cmake_static_check_cppcheck.py
@@ -24,6 +24,7 @@ import project_source_info
import subprocess
import sys
import os
+import tempfile
from typing import (
Any,
@@ -35,7 +36,6 @@ USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [
"extern",
- "intern/moto",
]
CHECKER_BIN = "cppcheck"
@@ -47,13 +47,19 @@ CHECKER_ARGS = [
"--max-configs=1", # speeds up execution
# "--check-config", # when includes are missing
"--enable=all", # if you want sixty hundred pedantic suggestions
+
+ # Quiet output, otherwise all defines/includes are printed (overly verbose).
+ # Only enable this for troubleshooting (if defines are not set as expected for example).
+ "--quiet",
+
+ # NOTE: `--cppcheck-build-dir=
` is added later as a temporary directory.
]
if USE_QUIET:
CHECKER_ARGS.append("--quiet")
-def main() -> None:
+def cppcheck() -> None:
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
source_defines = project_source_info.build_defines_as_args()
@@ -78,7 +84,10 @@ def main() -> None:
percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:"
sys.stdout.flush()
- sys.stdout.write("%s " % percent_str)
+ sys.stdout.write("%s %s\n" % (
+ percent_str,
+ os.path.relpath(c, project_source_info.SOURCE_DIR)
+ ))
return subprocess.Popen(cmd)
@@ -90,5 +99,11 @@ def main() -> None:
print("Finished!")
+def main() -> None:
+ with tempfile.TemporaryDirectory() as temp_dir:
+ CHECKER_ARGS.append("--cppcheck-build-dir=" + temp_dir)
+ cppcheck()
+
+
if __name__ == "__main__":
main()
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 0cd886e67d7..89bd46ecd7d 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -9,6 +9,7 @@ set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
+set(WITH_BLENDER_THUMBNAILER OFF CACHE BOOL "" FORCE)
set(WITH_BOOST OFF CACHE BOOL "" FORCE)
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py
index d2ed80022ca..c2ba7e5b11c 100644
--- a/build_files/cmake/project_source_info.py
+++ b/build_files/cmake/project_source_info.py
@@ -243,7 +243,9 @@ def build_defines_as_args() -> List[str]:
# use this module.
def queue_processes(
process_funcs: Sequence[Tuple[Callable[..., subprocess.Popen[Any]], Tuple[Any, ...]]],
+ *,
job_total: int =-1,
+ sleep: float = 0.1,
) -> None:
""" Takes a list of function arg pairs, each function must return a process
"""
@@ -271,14 +273,20 @@ def queue_processes(
if len(processes) <= job_total:
break
- else:
- time.sleep(0.1)
+ time.sleep(sleep)
sys.stdout.flush()
sys.stderr.flush()
processes.append(func(*args))
+ # Don't return until all jobs have finished.
+ while 1:
+ processes[:] = [p for p in processes if p.poll() is None]
+ if not processes:
+ break
+ time.sleep(sleep)
+
def main() -> None:
if not os.path.exists(join(CMAKE_DIR, "CMakeCache.txt")):
diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml
index 5d1a24a30f1..8222f2ff0b9 100644
--- a/build_files/config/pipeline_config.yaml
+++ b/build_files/config/pipeline_config.yaml
@@ -55,7 +55,7 @@ buildbot:
cuda11:
version: '11.4.1'
optix:
- version: '7.1.0'
+ version: '7.3.0'
cmake:
default:
version: any
diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py
index a6399790bc9..30ef090efbb 100755
--- a/build_files/utils/make_update.py
+++ b/build_files/utils/make_update.py
@@ -200,15 +200,20 @@ def submodules_update(args, release_version, branch):
if msg:
skip_msg += submodule_path + " skipped: " + msg + "\n"
else:
- if make_utils.git_branch(args.git_command) != submodule_branch:
- call([args.git_command, "fetch", "origin"])
- call([args.git_command, "checkout", submodule_branch])
- call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
- # If we cannot find the specified branch for this submodule, fallback to default one (aka master).
- if make_utils.git_branch(args.git_command) != submodule_branch:
- call([args.git_command, "fetch", "origin"])
- call([args.git_command, "checkout", submodule_branch_fallback])
- call([args.git_command, "pull", "--rebase", "origin", submodule_branch_fallback])
+ # Find a matching branch that exists.
+ call([args.git_command, "fetch", "origin"])
+ if make_utils.git_branch_exists(args.git_command, submodule_branch):
+ pass
+ elif make_utils.git_branch_exists(args.git_command, submodule_branch_fallback):
+ submodule_branch = submodule_branch_fallback
+ else:
+ submodule_branch = None
+
+ # Switch to branch and pull.
+ if submodule_branch:
+ if make_utils.git_branch(args.git_command) != submodule_branch:
+ call([args.git_command, "checkout", submodule_branch])
+ call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
finally:
os.chdir(cwd)
diff --git a/build_files/utils/make_utils.py b/build_files/utils/make_utils.py
index db352ff7e16..9def0059ceb 100755
--- a/build_files/utils/make_utils.py
+++ b/build_files/utils/make_utils.py
@@ -8,14 +8,19 @@ import subprocess
import sys
-def call(cmd, exit_on_error=True):
- print(" ".join(cmd))
+def call(cmd, exit_on_error=True, silent=False):
+ if not silent:
+ print(" ".join(cmd))
# Flush to ensure correct order output on Windows.
sys.stdout.flush()
sys.stderr.flush()
- retcode = subprocess.call(cmd)
+ if silent:
+ retcode = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ else:
+ retcode = subprocess.call(cmd)
+
if exit_on_error and retcode != 0:
sys.exit(retcode)
return retcode
@@ -38,6 +43,11 @@ def check_output(cmd, exit_on_error=True):
return output.strip()
+def git_branch_exists(git_command, branch):
+ return call([git_command, "rev-parse", "--verify", branch], exit_on_error=False, silent=True) == 0 or \
+ call([git_command, "rev-parse", "--verify", "remotes/origin/" + branch], exit_on_error=False, silent=True) == 0
+
+
def git_branch(git_command):
# Get current branch name.
try:
diff --git a/build_files/windows/find_dependencies.cmd b/build_files/windows/find_dependencies.cmd
index 0b6ae2d3c32..9fa3b156a4f 100644
--- a/build_files/windows/find_dependencies.cmd
+++ b/build_files/windows/find_dependencies.cmd
@@ -3,7 +3,7 @@ for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
-set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\37\bin\python.exe
+set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
if NOT "%verbose%" == "" (
echo svn : "%SVN%"
echo cmake : "%CMAKE%"
diff --git a/build_files/windows/format.cmd b/build_files/windows/format.cmd
index d19595bf042..d5003c9f8d8 100644
--- a/build_files/windows/format.cmd
+++ b/build_files/windows/format.cmd
@@ -10,7 +10,7 @@ exit /b 1
echo found clang-format in %CF_PATH%
if EXIST %PYTHON% (
- set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\37\bin\python.exe
+ set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
goto detect_python_done
)
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
index c63f062dfef..dcef46c2c9a 100644
--- a/build_files/windows/parse_arguments.cmd
+++ b/build_files/windows/parse_arguments.cmd
@@ -116,6 +116,9 @@ if NOT "%1" == "" (
) else if "%1" == "doc_py" (
set DOC_PY=1
goto EOF
+ ) else if "%1" == "svnfix" (
+ set SVN_FIX=1
+ goto EOF
) else (
echo Command "%1" unknown, aborting!
goto ERR
diff --git a/build_files/windows/svn_fix.cmd b/build_files/windows/svn_fix.cmd
new file mode 100644
index 00000000000..a9dcdf36847
--- /dev/null
+++ b/build_files/windows/svn_fix.cmd
@@ -0,0 +1,26 @@
+if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
+if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
+if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
+
+set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
+set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
+
+echo Starting cleanup in %BUILD_VS_LIBDIR%.
+cd %BUILD_VS_LIBDIR%
+:RETRY
+"%SVN%" cleanup
+"%SVN%" update
+if errorlevel 1 (
+ set /p LibRetry= "Error during update, retry? y/n"
+ if /I "!LibRetry!"=="Y" (
+ goto RETRY
+ )
+ echo.
+ echo Error: Download of external libraries failed.
+ echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
+ echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
+ echo.
+ exit /b 1
+)
+echo Cleanup complete
+
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 96eb30a852e..89954d8a155 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = V3.0
+PROJECT_NUMBER = V3.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/doc/python_api/examples/aud.py b/doc/python_api/examples/aud.py
index a52258c1a45..0eb27647671 100644
--- a/doc/python_api/examples/aud.py
+++ b/doc/python_api/examples/aud.py
@@ -14,7 +14,7 @@ sound = aud.Sound('music.ogg')
# play the audio, this return a handle to control play/pause
handle = device.play(sound)
# if the audio is not too big and will be used often you can buffer it
-sound_buffered = aud.Sound.buffer(sound)
+sound_buffered = aud.Sound.cache(sound)
handle_buffered = device.play(sound_buffered)
# stop the sounds (otherwise they play until their ends)
diff --git a/doc/python_api/examples/bpy.types.Bone.convert_local_to_pose.py b/doc/python_api/examples/bpy.types.Bone.convert_local_to_pose.py
new file mode 100644
index 00000000000..f3cc95dec61
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Bone.convert_local_to_pose.py
@@ -0,0 +1,40 @@
+"""
+This method enables conversions between Local and Pose space for bones in
+the middle of updating the armature without having to update dependencies
+after each change, by manually carrying updated matrices in a recursive walk.
+"""
+
+def set_pose_matrices(obj, matrix_map):
+ "Assign pose space matrices of all bones at once, ignoring constraints."
+
+ def rec(pbone, parent_matrix):
+ matrix = matrix_map[pbone.name]
+
+ ## Instead of:
+ # pbone.matrix = matrix
+ # bpy.context.view_layer.update()
+
+ # Compute and assign local matrix, using the new parent matrix
+ if pbone.parent:
+ pbone.matrix_basis = pbone.bone.convert_local_to_pose(
+ matrix,
+ pbone.bone.matrix_local,
+ parent_matrix=parent_matrix,
+ parent_matrix_local=pbone.parent.bone.matrix_local,
+ invert=True
+ )
+ else:
+ pbone.matrix_basis = pbone.bone.convert_local_to_pose(
+ matrix,
+ pbone.bone.matrix_local,
+ invert=True
+ )
+
+ # Recursively process children, passing the new matrix through
+ for child in pbone.children:
+ rec(child, matrix)
+
+ # Scan all bone trees from their roots
+ for pbone in obj.pose.bones:
+ if not pbone.parent:
+ rec(pbone, None)
diff --git a/doc/python_api/examples/gpu.9.py b/doc/python_api/examples/gpu.9.py
index b0400ce7809..318c0a74ceb 100644
--- a/doc/python_api/examples/gpu.9.py
+++ b/doc/python_api/examples/gpu.9.py
@@ -32,7 +32,7 @@ def draw():
context.region,
view_matrix,
projection_matrix,
- True)
+ do_color_management=True)
gpu.state.depth_mask_set(False)
draw_texture_2d(offscreen.texture_color, (10, 10), WIDTH, HEIGHT)
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index aa0f79646e6..04efe49f778 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -1101,14 +1101,18 @@ context_type_map = {
"scene": ("Scene", False),
"sculpt_object": ("Object", False),
"selectable_objects": ("Object", True),
+ "selected_asset_files": ("FileSelectEntry", True),
"selected_bones": ("EditBone", True),
"selected_editable_bones": ("EditBone", True),
"selected_editable_fcurves": ("FCurve", True),
"selected_editable_keyframes": ("Keyframe", True),
"selected_editable_objects": ("Object", True),
"selected_editable_sequences": ("Sequence", True),
+ "selected_ids": ("ID", True),
"selected_files": ("FileSelectEntry", True),
+ "selected_ids": ("ID", True),
"selected_nla_strips": ("NlaStrip", True),
+ "selected_movieclip_tracks": ("MovieTrackingTrack", True),
"selected_nodes": ("Node", True),
"selected_objects": ("Object", True),
"selected_pose_bones": ("PoseBone", True),
@@ -1220,7 +1224,10 @@ def pycontext2sphinx(basepath):
while char_array[i] is not None:
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
fw(".. data:: %s\n\n" % member)
- member_type, is_seq = context_type_map[member]
+ try:
+ member_type, is_seq = context_type_map[member]
+ except KeyError:
+ raise SystemExit("Error: context key %r not found in context_type_map; update %s" % (member, __file__)) from None
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
unique.add(member)
i += 1
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 7f7d91f0765..1fdc8e60167 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -67,9 +67,12 @@ endif()
if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
add_subdirectory(clew)
- if(WITH_CUDA_DYNLOAD)
+ if((WITH_CYCLES_DEVICE_CUDA OR WITH_CYCLES_DEVICE_OPTIX) AND WITH_CUDA_DYNLOAD)
add_subdirectory(cuew)
endif()
+ if(WITH_CYCLES_DEVICE_HIP AND WITH_HIP_DYNLOAD)
+ add_subdirectory(hipew)
+ endif()
endif()
if(WITH_GHOST_X11 AND WITH_GHOST_XDND)
diff --git a/extern/audaspace/CMakeLists.txt b/extern/audaspace/CMakeLists.txt
index 1599c03cbad..8493fe3e67d 100644
--- a/extern/audaspace/CMakeLists.txt
+++ b/extern/audaspace/CMakeLists.txt
@@ -129,6 +129,7 @@ set(SRC
src/util/Barrier.cpp
src/util/Buffer.cpp
src/util/BufferReader.cpp
+ src/util/RingBuffer.cpp
src/util/StreamBuffer.cpp
src/util/ThreadPool.cpp
)
@@ -152,6 +153,7 @@ set(PUBLIC_HDR
include/devices/ThreadedDevice.h
include/Exception.h
include/file/File.h
+ include/file/FileInfo.h
include/file/FileManager.h
include/file/FileWriter.h
include/file/IFileInput.h
@@ -244,6 +246,7 @@ set(PUBLIC_HDR
include/util/BufferReader.h
include/util/ILockable.h
include/util/Math3D.h
+ include/util/RingBuffer.h
include/util/StreamBuffer.h
include/util/ThreadPool.h
)
@@ -960,7 +963,10 @@ endif()
if(BUILD_DEMOS)
include_directories(${INCLUDE})
- set(DEMOS audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
+ set(DEMOS audainfo audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
+
+ add_executable(audainfo demos/audainfo.cpp)
+ target_link_libraries(audainfo audaspace)
add_executable(audaplay demos/audaplay.cpp)
target_link_libraries(audaplay audaspace)
diff --git a/extern/audaspace/bindings/C/AUD_PlaybackManager.h b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
index 0fa8171599d..a2f5134602a 100644
--- a/extern/audaspace/bindings/C/AUD_PlaybackManager.h
+++ b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
@@ -39,7 +39,7 @@ extern AUD_API void AUD_PlaybackManager_free(AUD_PlaybackManager* manager);
* Plays a sound through the playback manager, adding it into a category.
* \param manager The PlaybackManager object.
* \param sound The sound to be played.
-* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be creatd.
+* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be created.
*/
extern AUD_API void AUD_PlaybackManager_play(AUD_PlaybackManager* manager, AUD_Sound* sound, unsigned int catKey);
diff --git a/extern/audaspace/bindings/C/AUD_Sound.cpp b/extern/audaspace/bindings/C/AUD_Sound.cpp
index 8c99ce2341f..8a3c9d1bbc9 100644
--- a/extern/audaspace/bindings/C/AUD_Sound.cpp
+++ b/extern/audaspace/bindings/C/AUD_Sound.cpp
@@ -94,6 +94,40 @@ AUD_API int AUD_Sound_getLength(AUD_Sound* sound)
return (*sound)->createReader()->getLength();
}
+AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo **stream_infos)
+{
+ assert(sound);
+
+ std::shared_ptr file = std::dynamic_pointer_cast(*sound);
+
+ if(file)
+ {
+ try
+ {
+ auto streams = file->queryStreams();
+
+ size_t size = sizeof(AUD_StreamInfo) * streams.size();
+
+ if(!size)
+ {
+ *stream_infos = nullptr;
+ return 0;
+ }
+
+ *stream_infos = reinterpret_cast(std::malloc(size));
+ std::memcpy(*stream_infos, streams.data(), size);
+
+ return streams.size();
+ }
+ catch(Exception&)
+ {
+ }
+ }
+
+ *stream_infos = nullptr;
+ return 0;
+}
+
AUD_API sample_t* AUD_Sound_data(AUD_Sound* sound, int* length, AUD_Specs* specs)
{
assert(sound);
@@ -252,6 +286,12 @@ AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size)
return new AUD_Sound(new File(buffer, size));
}
+AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream)
+{
+ assert(buffer);
+ return new AUD_Sound(new File(buffer, size, stream));
+}
+
AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound)
{
assert(sound);
@@ -272,6 +312,12 @@ AUD_API AUD_Sound* AUD_Sound_file(const char* filename)
return new AUD_Sound(new File(filename));
}
+AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream)
+{
+ assert(filename);
+ return new AUD_Sound(new File(filename, stream));
+}
+
AUD_API AUD_Sound* AUD_Sound_sawtooth(float frequency, AUD_SampleRate rate)
{
return new AUD_Sound(new Sawtooth(frequency, rate));
diff --git a/extern/audaspace/bindings/C/AUD_Sound.h b/extern/audaspace/bindings/C/AUD_Sound.h
index 53172616781..fc73a31e15c 100644
--- a/extern/audaspace/bindings/C/AUD_Sound.h
+++ b/extern/audaspace/bindings/C/AUD_Sound.h
@@ -36,7 +36,15 @@ extern AUD_API AUD_Specs AUD_Sound_getSpecs(AUD_Sound* sound);
* \return The length of the sound in samples.
* \note This function creates a reader from the sound and deletes it again.
*/
-extern AUD_API int AUD_getLength(AUD_Sound* sound);
+extern AUD_API int AUD_Sound_getLength(AUD_Sound* sound);
+
+/**
+ * Retrieves the stream infos of a sound file.
+ * \param sound The sound to retrieve from which must be a file sound.
+ * \param infos A pointer to a AUD_StreamInfo array that will be allocated and must afterwards be freed by the caller.
+ * \return The number of items in the infos array.
+ */
+extern AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo** stream_infos);
/**
* Reads a sound's samples into memory.
@@ -89,6 +97,15 @@ extern AUD_API AUD_Sound* AUD_Sound_buffer(sample_t* data, int length, AUD_Specs
*/
extern AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size);
+/**
+ * Loads a sound file from a memory buffer.
+ * \param buffer The buffer which contains the sound file.
+ * \param size The size of the buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream);
+
/**
* Caches a sound into a memory buffer.
* \param sound The sound to cache.
@@ -103,6 +120,14 @@ extern AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound);
*/
extern AUD_API AUD_Sound* AUD_Sound_file(const char* filename);
+/**
+ * Loads a sound file.
+ * \param filename The filename of the sound file.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream);
+
/**
* Creates a sawtooth sound.
* \param frequency The frequency of the generated sawtooth sound.
diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp
index 5cc33525d1d..1ce25dcd41c 100644
--- a/extern/audaspace/bindings/C/AUD_Special.cpp
+++ b/extern/audaspace/bindings/C/AUD_Special.cpp
@@ -86,7 +86,6 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0f;
- info.start_offset = 0.0f;
try
{
@@ -96,7 +95,6 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
{
info.specs = convSpecToC(reader->getSpecs());
info.length = reader->getLength() / (float) info.specs.rate;
- info.start_offset = reader->getStartOffset();
}
}
catch(Exception&)
@@ -109,7 +107,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int accumulate, int additive, int square,
- float sthreshold, double samplerate, int* length)
+ float sthreshold, double samplerate, int* length, int stream)
{
Buffer buffer;
DeviceSpecs specs;
@@ -117,7 +115,7 @@ AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
specs.rate = (SampleRate)samplerate;
std::shared_ptr sound;
- std::shared_ptr file = std::shared_ptr(new File(filename));
+ std::shared_ptr file = std::shared_ptr(new File(filename, stream));
int position = 0;
@@ -247,7 +245,7 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
buffer[i * 3] = min;
buffer[i * 3 + 1] = max;
- buffer[i * 3 + 2] = sqrt(power / len); // RMS
+ buffer[i * 3 + 2] = std::sqrt(power / len);
if(overallmax < max)
overallmax = max;
diff --git a/extern/audaspace/bindings/C/AUD_Special.h b/extern/audaspace/bindings/C/AUD_Special.h
index ce51fa2e04e..2f5d13c6fd9 100644
--- a/extern/audaspace/bindings/C/AUD_Special.h
+++ b/extern/audaspace/bindings/C/AUD_Special.h
@@ -37,7 +37,7 @@ extern AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float
float attack, float release, float threshold,
int accumulate, int additive, int square,
float sthreshold, double samplerate,
- int* length);
+ int* length, int stream);
/**
* Pauses a playing sound after a specific amount of time.
diff --git a/extern/audaspace/bindings/C/AUD_Types.h b/extern/audaspace/bindings/C/AUD_Types.h
index c6a96d30d3f..0f95366bc27 100644
--- a/extern/audaspace/bindings/C/AUD_Types.h
+++ b/extern/audaspace/bindings/C/AUD_Types.h
@@ -176,5 +176,17 @@ typedef struct
{
AUD_Specs specs;
float length;
- double start_offset;
} AUD_SoundInfo;
+
+/// Specification of a sound source.
+typedef struct
+{
+ /// Start time in seconds.
+ double start;
+
+ /// Duration in seconds. May be estimated or 0 if unknown.
+ double duration;
+
+ /// Audio data parameters.
+ AUD_DeviceSpecs specs;
+} AUD_StreamInfo;
diff --git a/extern/audaspace/bindings/python/PySound.cpp b/extern/audaspace/bindings/python/PySound.cpp
index 33628307249..1f149482914 100644
--- a/extern/audaspace/bindings/python/PySound.cpp
+++ b/extern/audaspace/bindings/python/PySound.cpp
@@ -89,10 +89,11 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
self = (Sound*)type->tp_alloc(type, 0);
if(self != nullptr)
{
- static const char* kwlist[] = {"filename", nullptr};
+ static const char* kwlist[] = {"filename", "stream", nullptr};
const char* filename = nullptr;
+ int stream = 0;
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Sound", const_cast(kwlist), &filename))
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:Sound", const_cast(kwlist), &filename, &stream))
{
Py_DECREF(self);
return nullptr;
@@ -100,7 +101,7 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
try
{
- self->sound = new std::shared_ptr(new File(filename));
+ self->sound = new std::shared_ptr(new File(filename, stream));
}
catch(Exception& e)
{
@@ -289,7 +290,7 @@ PyDoc_STRVAR(M_aud_Sound_buffer_doc,
".. classmethod:: buffer(data, rate)\n\n"
" Creates a sound from a data buffer.\n\n"
" :arg data: The data as two dimensional numpy array.\n"
- " :type data: numpy.ndarray\n"
+ " :type data: :class:`numpy.ndarray`\n"
" :arg rate: The sample rate.\n"
" :type rate: double\n"
" :return: The created :class:`Sound` object.\n"
@@ -407,8 +408,9 @@ static PyObject *
Sound_file(PyTypeObject* type, PyObject* args)
{
const char* filename = nullptr;
+ int stream = 0;
- if(!PyArg_ParseTuple(args, "s:file", &filename))
+ if(!PyArg_ParseTuple(args, "s|i:file", &filename, &stream))
return nullptr;
Sound* self;
@@ -418,7 +420,7 @@ Sound_file(PyTypeObject* type, PyObject* args)
{
try
{
- self->sound = new std::shared_ptr(new File(filename));
+ self->sound = new std::shared_ptr(new File(filename, stream));
}
catch(Exception& e)
{
diff --git a/extern/audaspace/include/IReader.h b/extern/audaspace/include/IReader.h
index f6070b0f23b..c29900ca579 100644
--- a/extern/audaspace/include/IReader.h
+++ b/extern/audaspace/include/IReader.h
@@ -70,12 +70,6 @@ public:
*/
virtual int getPosition() const=0;
- /**
- * Returns the start offset the sound should have to line up with related sources.
- * \return The required start offset in seconds.
- */
- virtual double getStartOffset() const { return 0.0;}
-
/**
* Returns the specification of the reader.
* \return The Specs structure.
diff --git a/extern/audaspace/include/file/File.h b/extern/audaspace/include/file/File.h
index 24745a757e8..ac490acba38 100644
--- a/extern/audaspace/include/file/File.h
+++ b/extern/audaspace/include/file/File.h
@@ -23,9 +23,11 @@
*/
#include "ISound.h"
+#include "FileInfo.h"
#include
#include
+#include
AUD_NAMESPACE_BEGIN
@@ -48,6 +50,14 @@ private:
*/
std::shared_ptr m_buffer;
+ /**
+ * The index of the stream within the file if it contains multiple.
+ * The first audio stream in the file has index 0 and the index increments by one
+ * for every other audio stream in the file. Other types of streams in the file
+ * do not count.
+ */
+ int m_stream;
+
// delete copy constructor and operator=
File(const File&) = delete;
File& operator=(const File&) = delete;
@@ -57,16 +67,25 @@ public:
* Creates a new sound.
* The file is read from the file system using the given path.
* \param filename The sound file path.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
- File(std::string filename);
+ File(std::string filename, int stream = 0);
/**
* Creates a new sound.
* The file is read from memory using the supplied buffer.
* \param buffer The buffer to read from.
* \param size The size of the buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
- File(const data_t* buffer, int size);
+ File(const data_t* buffer, int size, int stream = 0);
+
+ /**
+ * Queries the streams of the file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ std::vector queryStreams();
virtual std::shared_ptr createReader();
};
diff --git a/extern/audaspace/include/file/FileInfo.h b/extern/audaspace/include/file/FileInfo.h
new file mode 100644
index 00000000000..53ba99a5f67
--- /dev/null
+++ b/extern/audaspace/include/file/FileInfo.h
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+/**
+ * @file FileInfo.h
+ * @ingroup file
+ * The FileInfo data structures.
+ */
+
+#include "respec/Specification.h"
+
+AUD_NAMESPACE_BEGIN
+
+/// Specification of a sound source.
+struct StreamInfo
+{
+ /// Start time in seconds.
+ double start;
+
+ /// Duration in seconds. May be estimated or 0 if unknown.
+ double duration;
+
+ /// Audio data parameters.
+ DeviceSpecs specs;
+};
+
+AUD_NAMESPACE_END
diff --git a/extern/audaspace/include/file/FileManager.h b/extern/audaspace/include/file/FileManager.h
index 56708607ea6..e19eef65b1c 100644
--- a/extern/audaspace/include/file/FileManager.h
+++ b/extern/audaspace/include/file/FileManager.h
@@ -22,12 +22,14 @@
* The FileManager class.
*/
+#include "FileInfo.h"
#include "respec/Specification.h"
#include "IWriter.h"
#include
#include
#include
+#include
AUD_NAMESPACE_BEGIN
@@ -66,18 +68,36 @@ public:
/**
* Creates a file reader for the given filename if a registed IFileInput is able to read it.
* @param filename The path to the file.
+ * @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
- static std::shared_ptr createReader(std::string filename);
+ static std::shared_ptr createReader(std::string filename, int stream = 0);
/**
* Creates a file reader for the given buffer if a registed IFileInput is able to read it.
* @param buffer The buffer to read the file from.
+ * @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
- static std::shared_ptr createReader(std::shared_ptr buffer);
+ static std::shared_ptr createReader(std::shared_ptr buffer, int stream = 0);
+
+ /**
+ * Queries the streams of a sound file.
+ * \param filename Path to the file to be read.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ static std::vector queryStreams(std::string filename);
+
+ /**
+ * Queries the streams of a sound file.
+ * \param buffer The in-memory file buffer.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ static std::vector queryStreams(std::shared_ptr buffer);
/**
* Creates a file writer that writes a sound to the given file path.
diff --git a/extern/audaspace/include/file/IFileInput.h b/extern/audaspace/include/file/IFileInput.h
index 64074910d13..4a3fe446852 100644
--- a/extern/audaspace/include/file/IFileInput.h
+++ b/extern/audaspace/include/file/IFileInput.h
@@ -23,9 +23,11 @@
*/
#include "Audaspace.h"
+#include "FileInfo.h"
#include
#include
+#include
AUD_NAMESPACE_BEGIN
@@ -48,18 +50,36 @@ public:
/**
* Creates a reader for a file to be read.
* \param filename Path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
- virtual std::shared_ptr createReader(std::string filename)=0;
+ virtual std::shared_ptr createReader(std::string filename, int stream = 0)=0;
/**
* Creates a reader for a file to be read from memory.
* \param buffer The in-memory file buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
- virtual std::shared_ptr createReader(std::shared_ptr buffer)=0;
+ virtual std::shared_ptr createReader(std::shared_ptr buffer, int stream = 0)=0;
+
+ /**
+ * Queries the streams of a sound file.
+ * \param filename Path to the file to be read.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector queryStreams(std::string filename)=0;
+
+ /**
+ * Queries the streams of a sound file.
+ * \param buffer The in-memory file buffer.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector queryStreams(std::shared_ptr buffer)=0;
};
AUD_NAMESPACE_END
diff --git a/extern/audaspace/include/fx/VolumeReader.h b/extern/audaspace/include/fx/VolumeReader.h
index f7169f4c78b..13b6845e931 100644
--- a/extern/audaspace/include/fx/VolumeReader.h
+++ b/extern/audaspace/include/fx/VolumeReader.h
@@ -67,4 +67,4 @@ public:
virtual void read(int& length, bool& eos, sample_t* buffer);
};
-AUD_NAMESPACE_END
+AUD_NAMESPACE_END
\ No newline at end of file
diff --git a/extern/audaspace/include/util/RingBuffer.h b/extern/audaspace/include/util/RingBuffer.h
new file mode 100644
index 00000000000..67bd1cc8640
--- /dev/null
+++ b/extern/audaspace/include/util/RingBuffer.h
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright 2009-2021 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+/**
+ * @file RingBuffer.h
+ * @ingroup util
+ * The RingBuffer class.
+ */
+
+#include "Audaspace.h"
+#include "Buffer.h"
+
+#include
+
+AUD_NAMESPACE_BEGIN
+
+/**
+ * This class is a simple ring buffer in RAM which is 32 Byte aligned and provides
+ * functionality for concurrent reading and writting without locks.
+ */
+class AUD_API RingBuffer
+{
+private:
+ /// The buffer storing the actual data.
+ Buffer m_buffer;
+
+ /// The reading pointer.
+ volatile size_t m_read;
+
+ /// The writing pointer.
+ volatile size_t m_write;
+
+ // delete copy constructor and operator=
+ RingBuffer(const RingBuffer&) = delete;
+ RingBuffer& operator=(const RingBuffer&) = delete;
+
+public:
+ /**
+ * Creates a new ring buffer.
+ * \param size The size of the buffer in bytes.
+ */
+ RingBuffer(int size = 0);
+
+ /**
+ * Returns the pointer to the ring buffer in memory.
+ */
+ sample_t* getBuffer() const;
+
+ /**
+ * Returns the size of the ring buffer in bytes.
+ */
+ int getSize() const;
+
+ size_t getReadSize() const;
+
+ size_t getWriteSize() const;
+
+ size_t read(data_t* target, size_t size);
+
+ size_t write(data_t* source, size_t size);
+
+ /**
+ * Resets the ring buffer to a state where nothing has been written or read.
+ */
+ void reset();
+
+ /**
+ * Resizes the ring buffer.
+ * \param size The new size of the ring buffer, measured in bytes.
+ */
+ void resize(int size);
+
+ /**
+ * Makes sure the ring buffer has a minimum size.
+ * If size is >= current size, nothing will happen.
+ * Otherwise the ring buffer is resized with keep as parameter.
+ * \param size The new minimum size of the ring buffer, measured in bytes.
+ */
+ void assureSize(int size);
+};
+
+AUD_NAMESPACE_END
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
index 3ffe963b2b9..07c0fee691a 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
@@ -35,14 +35,24 @@ void FFMPEG::registerPlugin()
FileManager::registerOutput(plugin);
}
-std::shared_ptr FFMPEG::createReader(std::string filename)
+std::shared_ptr FFMPEG::createReader(std::string filename, int stream)
{
- return std::shared_ptr(new FFMPEGReader(filename));
+ return std::shared_ptr(new FFMPEGReader(filename, stream));
}
-std::shared_ptr FFMPEG::createReader(std::shared_ptr buffer)
+std::shared_ptr FFMPEG::createReader(std::shared_ptr buffer, int stream)
{
- return std::shared_ptr(new FFMPEGReader(buffer));
+ return std::shared_ptr(new FFMPEGReader(buffer, stream));
+}
+
+std::vector FFMPEG::queryStreams(std::string filename)
+{
+ return FFMPEGReader(filename).queryStreams();
+}
+
+std::vector FFMPEG::queryStreams(std::shared_ptr buffer)
+{
+ return FFMPEGReader(buffer).queryStreams();
}
std::shared_ptr FFMPEG::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEG.h b/extern/audaspace/plugins/ffmpeg/FFMPEG.h
index 108ba547e0f..fb40ba05573 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEG.h
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEG.h
@@ -52,8 +52,10 @@ public:
*/
static void registerPlugin();
- virtual std::shared_ptr createReader(std::string filename);
- virtual std::shared_ptr createReader(std::shared_ptr buffer);
+ virtual std::shared_ptr createReader(std::string filename, int stream = 0);
+ virtual std::shared_ptr createReader(std::shared_ptr buffer, int stream = 0);
+ virtual std::vector queryStreams(std::string filename);
+ virtual std::vector queryStreams(std::shared_ptr buffer);
virtual std::shared_ptr createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
index afdc7fcfcc6..de3ca099696 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
@@ -31,6 +31,25 @@ AUD_NAMESPACE_BEGIN
#define FFMPEG_OLD_CODE
#endif
+SampleFormat FFMPEGReader::convertSampleFormat(AVSampleFormat format)
+{
+ switch(av_get_packed_sample_fmt(format))
+ {
+ case AV_SAMPLE_FMT_U8:
+ return FORMAT_U8;
+ case AV_SAMPLE_FMT_S16:
+ return FORMAT_S16;
+ case AV_SAMPLE_FMT_S32:
+ return FORMAT_S32;
+ case AV_SAMPLE_FMT_FLT:
+ return FORMAT_FLOAT32;
+ case AV_SAMPLE_FMT_DBL:
+ return FORMAT_FLOAT64;
+ default:
+ AUD_THROW(FileException, "FFMPEG sample format unknown.");
+ }
+}
+
int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
{
int buf_size = buffer.getSize();
@@ -68,7 +87,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -109,7 +128,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -123,13 +142,10 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
return buf_pos;
}
-void FFMPEGReader::init()
+void FFMPEGReader::init(int stream)
{
m_position = 0;
- m_start_offset = 0.0f;
m_pkgbuf_left = 0;
- m_st_time = 0;
- m_duration = 0;
if(avformat_find_stream_info(m_formatCtx, nullptr) < 0)
AUD_THROW(FileException, "File couldn't be read, ffmpeg couldn't find the stream info.");
@@ -137,43 +153,22 @@ void FFMPEGReader::init()
// find audio stream and codec
m_stream = -1;
- double dur_sec = 0;
-
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
{
#ifdef FFMPEG_OLD_CODE
- if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#else
- if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+ if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
+ && (m_stream < 0))
{
- AVStream *audio_stream = m_formatCtx->streams[i];
- double audio_timebase = av_q2d(audio_stream->time_base);
-
- if (audio_stream->start_time != AV_NOPTS_VALUE)
+ if(stream == 0)
{
- m_st_time = audio_stream->start_time;
- }
-
- int64_t ctx_start_time = 0;
- if (m_formatCtx->start_time != AV_NOPTS_VALUE) {
- ctx_start_time = m_formatCtx->start_time;
- }
-
- m_start_offset = m_st_time * audio_timebase - (double)ctx_start_time / AV_TIME_BASE;
-
- if(audio_stream->duration != AV_NOPTS_VALUE)
- {
- dur_sec = audio_stream->duration * audio_timebase;
+ m_stream=i;
+ break;
}
else
- {
- /* If the audio starts after the stream start time, subract this from the total duration. */
- dur_sec = (double)m_formatCtx->duration / AV_TIME_BASE - m_start_offset;
- }
-
- m_stream=i;
- break;
+ stream--;
}
}
@@ -242,10 +237,9 @@ void FFMPEGReader::init()
}
m_specs.rate = (SampleRate) m_codecCtx->sample_rate;
- m_duration = lround(dur_sec * m_codecCtx->sample_rate);
}
-FFMPEGReader::FFMPEGReader(std::string filename) :
+FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
m_pkgbuf(),
m_formatCtx(nullptr),
m_codecCtx(nullptr),
@@ -259,7 +253,7 @@ FFMPEGReader::FFMPEGReader(std::string filename) :
try
{
- init();
+ init(stream);
}
catch(Exception&)
{
@@ -268,7 +262,7 @@ FFMPEGReader::FFMPEGReader(std::string filename) :
}
}
-FFMPEGReader::FFMPEGReader(std::shared_ptr buffer) :
+FFMPEGReader::FFMPEGReader(std::shared_ptr buffer, int stream) :
m_pkgbuf(),
m_codecCtx(nullptr),
m_frame(nullptr),
@@ -295,7 +289,7 @@ FFMPEGReader::FFMPEGReader(std::shared_ptr buffer) :
try
{
- init();
+ init(stream);
}
catch(Exception&)
{
@@ -318,6 +312,51 @@ FFMPEGReader::~FFMPEGReader()
avformat_close_input(&m_formatCtx);
}
+std::vector FFMPEGReader::queryStreams()
+{
+ std::vector result;
+
+ for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
+ {
+#ifdef FFMPEG_OLD_CODE
+ if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+#else
+ if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+#endif
+ {
+ StreamInfo info;
+
+ double time_base = av_q2d(m_formatCtx->streams[i]->time_base);
+
+ if(m_formatCtx->streams[i]->start_time != AV_NOPTS_VALUE)
+ info.start = m_formatCtx->streams[i]->start_time * time_base;
+ else
+ info.start = 0;
+
+ if(m_formatCtx->streams[i]->duration != AV_NOPTS_VALUE)
+ info.duration = m_formatCtx->streams[i]->duration * time_base;
+ else if(m_formatCtx->duration != AV_NOPTS_VALUE)
+ info.duration = double(m_formatCtx->duration) / AV_TIME_BASE - info.start;
+ else
+ info.duration = 0;
+
+#ifdef FFMPEG_OLD_CODE
+ info.specs.channels = Channels(m_formatCtx->streams[i]->codec->channels);
+ info.specs.rate = m_formatCtx->streams[i]->codec->sample_rate;
+ info.specs.format = convertSampleFormat(m_formatCtx->streams[i]->codec->sample_fmt);
+#else
+ info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->channels);
+ info.specs.rate = m_formatCtx->streams[i]->codecpar->sample_rate;
+ info.specs.format = convertSampleFormat(AVSampleFormat(m_formatCtx->streams[i]->codecpar->format));
+#endif
+
+ result.emplace_back(info);
+ }
+ }
+
+ return result;
+}
+
int FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
{
FFMPEGReader* reader = reinterpret_cast(opaque);
@@ -368,18 +407,16 @@ void FFMPEGReader::seek(int position)
{
if(position >= 0)
{
- double pts_time_base =
- av_q2d(m_formatCtx->streams[m_stream]->time_base);
+ double pts_time_base = av_q2d(m_formatCtx->streams[m_stream]->time_base);
- uint64_t seek_pts = (((uint64_t)position) / ((uint64_t)m_specs.rate)) / pts_time_base;
+ uint64_t st_time = m_formatCtx->streams[m_stream]->start_time;
+ uint64_t seek_pos = (uint64_t)(position / (pts_time_base * m_specs.rate));
- if(m_st_time != AV_NOPTS_VALUE) {
- seek_pts += m_st_time;
- }
+ if(st_time != AV_NOPTS_VALUE)
+ seek_pos += st_time;
// a value < 0 tells us that seeking failed
- if(av_seek_frame(m_formatCtx, m_stream, seek_pts,
- AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
+ if(av_seek_frame(m_formatCtx, m_stream, seek_pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
{
avcodec_flush_buffers(m_codecCtx);
m_position = position;
@@ -400,7 +437,7 @@ void FFMPEGReader::seek(int position)
if(packet.pts != AV_NOPTS_VALUE)
{
// calculate real position, and read to frame!
- m_position = (packet.pts - m_st_time) * pts_time_base * m_specs.rate;
+ m_position = (packet.pts - (st_time != AV_NOPTS_VALUE ? st_time : 0)) * pts_time_base * m_specs.rate;
if(m_position < position)
{
@@ -430,8 +467,25 @@ void FFMPEGReader::seek(int position)
int FFMPEGReader::getLength() const
{
+ auto stream = m_formatCtx->streams[m_stream];
+
+ double time_base = av_q2d(stream->time_base);
+ double duration;
+
+ if(stream->duration != AV_NOPTS_VALUE)
+ duration = stream->duration * time_base;
+ else if(m_formatCtx->duration != AV_NOPTS_VALUE)
+ {
+ duration = float(m_formatCtx->duration) / AV_TIME_BASE;
+
+ if(stream->start_time != AV_NOPTS_VALUE)
+ duration -= stream->start_time * time_base;
+ }
+ else
+ duration = -1;
+
// return approximated remaning size
- return m_duration - m_position;
+ return (int)(duration * m_codecCtx->sample_rate) - m_position;
}
int FFMPEGReader::getPosition() const
@@ -439,11 +493,6 @@ int FFMPEGReader::getPosition() const
return m_position;
}
-double FFMPEGReader::getStartOffset() const
-{
- return m_start_offset;
-}
-
Specs FFMPEGReader::getSpecs() const
{
return m_specs.specs;
@@ -480,13 +529,11 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
// decode the package
pkgbuf_pos = decode(packet, m_pkgbuf);
- if (packet.pts >= m_st_time) {
- // copy to output buffer
- data_size = std::min(pkgbuf_pos, left * sample_size);
- m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
- buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
- left -= data_size / sample_size;
- }
+ // copy to output buffer
+ data_size = std::min(pkgbuf_pos, left * sample_size);
+ m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
+ buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
+ left -= data_size / sample_size;
}
av_packet_unref(&packet);
}
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
index d613457c220..70f13911eca 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
@@ -29,9 +29,11 @@
#include "respec/ConverterFunctions.h"
#include "IReader.h"
#include "util/Buffer.h"
+#include "file/FileInfo.h"
#include
#include
+#include
struct AVCodecContext;
extern "C" {
@@ -54,22 +56,6 @@ private:
*/
int m_position;
- /**
- * The start offset in seconds relative to the media container start time.
- * IE how much the sound should be delayed to be kept in sync with the rest of the containter streams.
- */
- double m_start_offset;
-
- /**
- * The start time pts of the stream. All packets before this timestamp shouldn't be played back (only decoded).
- */
- int64_t m_st_time;
-
- /**
- * The duration of the audio stream in samples.
- */
- int64_t m_duration;
-
/**
* The specification of the audio data.
*/
@@ -135,6 +121,13 @@ private:
*/
bool m_tointerleave;
+ /**
+ * Converts an ffmpeg sample format to an audaspace one.
+ * \param format The AVSampleFormat sample format.
+ * \return The sample format as SampleFormat.
+ */
+ AUD_LOCAL static SampleFormat convertSampleFormat(AVSampleFormat format);
+
/**
* Decodes a packet into the given buffer.
* \param packet The AVPacket to decode.
@@ -145,8 +138,9 @@ private:
/**
* Initializes the object.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
- AUD_LOCAL void init();
+ AUD_LOCAL void init(int stream);
// delete copy constructor and operator=
FFMPEGReader(const FFMPEGReader&) = delete;
@@ -156,24 +150,33 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with ffmpeg.
*/
- FFMPEGReader(std::string filename);
+ FFMPEGReader(std::string filename, int stream = 0);
/**
* Creates a new reader.
* \param buffer The buffer to read from.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with ffmpeg.
*/
- FFMPEGReader(std::shared_ptr buffer);
+ FFMPEGReader(std::shared_ptr buffer, int stream = 0);
/**
* Destroys the reader and closes the file.
*/
virtual ~FFMPEGReader();
+ /**
+ * Queries the streams of a sound file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector queryStreams();
+
/**
* Reads data to a memory buffer.
* This function is used for avio only.
@@ -198,7 +201,6 @@ public:
virtual void seek(int position);
virtual int getLength() const;
virtual int getPosition() const;
- virtual double getStartOffset() const;
virtual Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};
diff --git a/extern/audaspace/plugins/libsndfile/SndFile.cpp b/extern/audaspace/plugins/libsndfile/SndFile.cpp
index ba4ff24ad68..39335de9a1a 100644
--- a/extern/audaspace/plugins/libsndfile/SndFile.cpp
+++ b/extern/audaspace/plugins/libsndfile/SndFile.cpp
@@ -32,16 +32,26 @@ void SndFile::registerPlugin()
FileManager::registerOutput(plugin);
}
-std::shared_ptr SndFile::createReader(std::string filename)
+std::shared_ptr SndFile::createReader(std::string filename, int stream)
{
return std::shared_ptr(new SndFileReader(filename));
}
-std::shared_ptr SndFile::createReader(std::shared_ptr buffer)
+std::shared_ptr SndFile::createReader(std::shared_ptr buffer, int stream)
{
return std::shared_ptr(new SndFileReader(buffer));
}
+std::vector SndFile::queryStreams(std::string filename)
+{
+ return SndFileReader(filename).queryStreams();
+}
+
+std::vector SndFile::queryStreams(std::shared_ptr buffer)
+{
+ return SndFileReader(buffer).queryStreams();
+}
+
std::shared_ptr SndFile::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
{
return std::shared_ptr(new SndFileWriter(filename, specs, format, codec, bitrate));
diff --git a/extern/audaspace/plugins/libsndfile/SndFile.h b/extern/audaspace/plugins/libsndfile/SndFile.h
index 61afed1d564..10a7391180f 100644
--- a/extern/audaspace/plugins/libsndfile/SndFile.h
+++ b/extern/audaspace/plugins/libsndfile/SndFile.h
@@ -52,8 +52,10 @@ public:
*/
static void registerPlugin();
- virtual std::shared_ptr createReader(std::string filename);
- virtual std::shared_ptr createReader(std::shared_ptr buffer);
+ virtual std::shared_ptr createReader(std::string filename, int stream = 0);
+ virtual std::shared_ptr createReader(std::shared_ptr buffer, int stream = 0);
+ virtual std::vector queryStreams(std::string filename);
+ virtual std::vector queryStreams(std::shared_ptr buffer);
virtual std::shared_ptr createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};
diff --git a/extern/audaspace/plugins/libsndfile/SndFileReader.cpp b/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
index d2d89814c07..21c733d8117 100644
--- a/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
+++ b/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
@@ -118,6 +118,21 @@ SndFileReader::~SndFileReader()
sf_close(m_sndfile);
}
+std::vector SndFileReader::queryStreams()
+{
+ std::vector result;
+
+ StreamInfo info;
+ info.start = 0;
+ info.duration = double(getLength()) / m_specs.rate;
+ info.specs.specs = m_specs;
+ info.specs.format = FORMAT_FLOAT32;
+
+ result.emplace_back(info);
+
+ return result;
+}
+
bool SndFileReader::isSeekable() const
{
return m_seekable;
diff --git a/extern/audaspace/plugins/libsndfile/SndFileReader.h b/extern/audaspace/plugins/libsndfile/SndFileReader.h
index 081c29c686c..b4158d9091a 100644
--- a/extern/audaspace/plugins/libsndfile/SndFileReader.h
+++ b/extern/audaspace/plugins/libsndfile/SndFileReader.h
@@ -28,9 +28,12 @@
* The SndFileReader class.
*/
+#include "file/FileInfo.h"
+
#include
#include
#include
+#include
AUD_NAMESPACE_BEGIN
@@ -96,6 +99,7 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with libsndfile.
*/
@@ -104,6 +108,7 @@ public:
/**
* Creates a new reader.
* \param buffer The buffer to read from.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with libsndfile.
*/
@@ -114,6 +119,13 @@ public:
*/
virtual ~SndFileReader();
+ /**
+ * Queries the streams of a sound file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector queryStreams();
+
virtual bool isSeekable() const;
virtual void seek(int position);
virtual int getLength() const;
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
index bf3fad82620..cddc411cfc6 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
@@ -23,95 +23,121 @@
AUD_NAMESPACE_BEGIN
+PulseAudioDevice::PulseAudioSynchronizer::PulseAudioSynchronizer(PulseAudioDevice *device) :
+ m_device(device)
+{
+}
+
+double PulseAudioDevice::PulseAudioSynchronizer::getPosition(std::shared_ptr handle)
+{
+ pa_usec_t latency;
+ int negative;
+ AUD_pa_stream_get_latency(m_device->m_stream, &latency, &negative);
+
+ double delay = m_device->m_ring_buffer.getReadSize() / (AUD_SAMPLE_SIZE(m_device->m_specs) * m_device->m_specs.rate) + latency * 1.0e-6;
+
+ return handle->getPosition() - delay;
+}
+
+void PulseAudioDevice::updateRingBuffer()
+{
+ unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
+
+ std::unique_lock lock(m_mixingLock);
+
+ Buffer buffer;
+
+ while(m_valid)
+ {
+ size_t size = m_ring_buffer.getWriteSize();
+
+ size_t sample_count = size / samplesize;
+
+ if(sample_count > 0)
+ {
+ size = sample_count * samplesize;
+
+ buffer.assureSize(size);
+
+ mix(reinterpret_cast(buffer.getBuffer()), sample_count);
+
+ m_ring_buffer.write(reinterpret_cast(buffer.getBuffer()), size);
+ }
+
+ m_mixingCondition.wait(lock);
+ }
+}
+
void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data)
{
PulseAudioDevice* device = (PulseAudioDevice*)data;
- std::lock_guard lock(*device);
-
device->m_state = AUD_pa_context_get_state(context);
+
+ AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0);
}
void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t total_bytes, void *data)
{
PulseAudioDevice* device = (PulseAudioDevice*)data;
- void* buffer;
+ data_t* buffer;
+
+ size_t sample_size = AUD_DEVICE_SAMPLE_SIZE(device->m_specs);
while(total_bytes > 0)
{
size_t num_bytes = total_bytes;
- AUD_pa_stream_begin_write(stream, &buffer, &num_bytes);
+ AUD_pa_stream_begin_write(stream, reinterpret_cast(&buffer), &num_bytes);
- device->mix((data_t*)buffer, num_bytes / AUD_DEVICE_SAMPLE_SIZE(device->m_specs));
+ size_t readsamples = device->m_ring_buffer.getReadSize();
- AUD_pa_stream_write(stream, buffer, num_bytes, nullptr, 0, PA_SEEK_RELATIVE);
+ readsamples = std::min(readsamples, size_t(num_bytes)) / sample_size;
+
+ device->m_ring_buffer.read(buffer, readsamples * sample_size);
+
+ if(readsamples * sample_size < num_bytes)
+ std::memset(buffer + readsamples * sample_size, 0, num_bytes - readsamples * sample_size);
+
+ if(device->m_mixingLock.try_lock())
+ {
+ device->m_mixingCondition.notify_all();
+ device->m_mixingLock.unlock();
+ }
+
+ AUD_pa_stream_write(stream, reinterpret_cast(buffer), num_bytes, nullptr, 0, PA_SEEK_RELATIVE);
total_bytes -= num_bytes;
}
}
-void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
+void PulseAudioDevice::playing(bool playing)
{
- PulseAudioDevice* device = (PulseAudioDevice*)data;
+ m_playback = playing;
- DeviceSpecs specs = device->getSpecs();
-
- if(++device->m_underflows > 4 && device->m_buffersize < AUD_DEVICE_SAMPLE_SIZE(specs) * specs.rate * 2)
- {
- device->m_buffersize <<= 1;
- device->m_underflows = 0;
-
- pa_buffer_attr buffer_attr;
-
- buffer_attr.fragsize = -1U;
- buffer_attr.maxlength = -1U;
- buffer_attr.minreq = -1U;
- buffer_attr.prebuf = -1U;
- buffer_attr.tlength = device->m_buffersize;
-
- AUD_pa_stream_set_buffer_attr(stream, &buffer_attr, nullptr, nullptr);
- }
-}
-
-void PulseAudioDevice::runMixingThread()
-{
- for(;;)
- {
- {
- std::lock_guard lock(*this);
-
- if(shouldStop())
- {
- AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
- AUD_pa_stream_flush(m_stream, nullptr, nullptr);
- doStop();
- return;
- }
- }
-
- if(AUD_pa_stream_is_corked(m_stream))
- AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
-
- // similar to AUD_pa_mainloop_iterate(m_mainloop, false, nullptr); except with a longer timeout
- AUD_pa_mainloop_prepare(m_mainloop, 1 << 14);
- AUD_pa_mainloop_poll(m_mainloop);
- AUD_pa_mainloop_dispatch(m_mainloop);
- }
+ AUD_pa_threaded_mainloop_lock(m_mainloop);
+ AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
}
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
+ m_synchronizer(this),
+ m_playback(false),
m_state(PA_CONTEXT_UNCONNECTED),
+ m_valid(true),
m_underflows(0)
{
- m_mainloop = AUD_pa_mainloop_new();
+ m_mainloop = AUD_pa_threaded_mainloop_new();
- m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str());
+ AUD_pa_threaded_mainloop_lock(m_mainloop);
+
+ m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str());
if(!m_context)
{
- AUD_pa_mainloop_free(m_mainloop);
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
+ AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
}
@@ -120,21 +146,26 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
+ AUD_pa_threaded_mainloop_start(m_mainloop);
+
while(m_state != PA_CONTEXT_READY)
{
switch(m_state)
{
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
+ AUD_pa_threaded_mainloop_stop(m_mainloop);
+
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_mainloop_free(m_mainloop);
+ AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
break;
default:
- AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
+ AUD_pa_threaded_mainloop_wait(m_mainloop);
break;
}
}
@@ -182,16 +213,18 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
if(!m_stream)
{
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
+ AUD_pa_threaded_mainloop_stop(m_mainloop);
+
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_mainloop_free(m_mainloop);
+ AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not create PulseAudio stream.");
}
AUD_pa_stream_set_write_callback(m_stream, PulseAudio_request, this);
- AUD_pa_stream_set_underflow_callback(m_stream, PulseAudio_underflow, this);
buffersize *= AUD_DEVICE_SAMPLE_SIZE(m_specs);
m_buffersize = buffersize;
@@ -204,31 +237,53 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
buffer_attr.prebuf = -1U;
buffer_attr.tlength = buffersize;
- if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
+ m_ring_buffer.resize(buffersize);
+
+ if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
{
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
+ AUD_pa_threaded_mainloop_stop(m_mainloop);
+
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_mainloop_free(m_mainloop);
+ AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect PulseAudio stream.");
}
+ AUD_pa_threaded_mainloop_unlock(m_mainloop);
+
create();
+
+ m_mixingThread = std::thread(&PulseAudioDevice::updateRingBuffer, this);
}
PulseAudioDevice::~PulseAudioDevice()
{
- stopMixingThread();
+ m_valid = false;
+
+ m_mixingLock.lock();
+ m_mixingCondition.notify_all();
+ m_mixingLock.unlock();
+
+ m_mixingThread.join();
+
+ AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_mainloop_free(m_mainloop);
+ AUD_pa_threaded_mainloop_free(m_mainloop);
destroy();
}
+ISynchronizer *PulseAudioDevice::getSynchronizer()
+{
+ return &m_synchronizer;
+}
+
class PulseAudioDeviceFactory : public IDeviceFactory
{
private:
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
index 45b813a5755..57359110633 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
@@ -26,7 +26,11 @@
* The PulseAudioDevice class.
*/
-#include "devices/ThreadedDevice.h"
+#include "devices/SoftwareDevice.h"
+#include "util/RingBuffer.h"
+
+#include
+#include
#include
@@ -35,17 +39,65 @@ AUD_NAMESPACE_BEGIN
/**
* This device plays back through PulseAudio, the simple direct media layer.
*/
-class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice
+class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice
{
private:
- pa_mainloop* m_mainloop;
+ class PulseAudioSynchronizer : public DefaultSynchronizer
+ {
+ PulseAudioDevice* m_device;
+
+ public:
+ PulseAudioSynchronizer(PulseAudioDevice* device);
+
+ virtual double getPosition(std::shared_ptr handle);
+ };
+
+ /// Synchronizer.
+ PulseAudioSynchronizer m_synchronizer;
+
+ /**
+ * Whether there is currently playback.
+ */
+ volatile bool m_playback;
+
+ pa_threaded_mainloop* m_mainloop;
pa_context* m_context;
pa_stream* m_stream;
pa_context_state_t m_state;
+ /**
+ * The mixing ring buffer.
+ */
+ RingBuffer m_ring_buffer;
+
+ /**
+ * Whether the device is valid.
+ */
+ bool m_valid;
+
int m_buffersize;
uint32_t m_underflows;
+ /**
+ * The mixing thread.
+ */
+ std::thread m_mixingThread;
+
+ /**
+ * Mutex for mixing.
+ */
+ std::mutex m_mixingLock;
+
+ /**
+ * Condition for mixing.
+ */
+ std::condition_variable m_mixingCondition;
+
+ /**
+ * Updates the ring buffer.
+ */
+ AUD_LOCAL void updateRingBuffer();
+
/**
* Reports the state of the PulseAudio server connection.
* \param context The PulseAudio context.
@@ -61,23 +113,13 @@ private:
*/
AUD_LOCAL static void PulseAudio_request(pa_stream* stream, size_t total_bytes, void* data);
- /**
- * Reports an underflow from the PulseAudio server.
- * Automatically adjusts the latency if this happens too often.
- * @param stream The PulseAudio stream.
- * \param data The PulseAudio device.
- */
- AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
-
- /**
- * Streaming thread main function.
- */
- AUD_LOCAL void runMixingThread();
-
// delete copy constructor and operator=
PulseAudioDevice(const PulseAudioDevice&) = delete;
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
+protected:
+ virtual void playing(bool playing);
+
public:
/**
* Opens the PulseAudio audio device for playback.
@@ -93,6 +135,8 @@ public:
*/
virtual ~PulseAudioDevice();
+ virtual ISynchronizer* getSynchronizer();
+
/**
* Registers this plugin.
*/
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
index 361aa518087..a33135b6e25 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
@@ -25,6 +25,7 @@ PULSEAUDIO_SYMBOL(pa_stream_begin_write);
PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork);
PULSEAUDIO_SYMBOL(pa_stream_flush);
+PULSEAUDIO_SYMBOL(pa_stream_get_latency);
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
@@ -39,3 +40,13 @@ PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
PULSEAUDIO_SYMBOL(pa_mainloop_prepare);
PULSEAUDIO_SYMBOL(pa_mainloop_poll);
PULSEAUDIO_SYMBOL(pa_mainloop_dispatch);
+
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock);
+PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait);
diff --git a/extern/audaspace/src/file/File.cpp b/extern/audaspace/src/file/File.cpp
index 0cdecb03657..5d4bae482d6 100644
--- a/extern/audaspace/src/file/File.cpp
+++ b/extern/audaspace/src/file/File.cpp
@@ -23,23 +23,31 @@
AUD_NAMESPACE_BEGIN
-File::File(std::string filename) :
- m_filename(filename)
+File::File(std::string filename, int stream) :
+ m_filename(filename), m_stream(stream)
{
}
-File::File(const data_t* buffer, int size) :
- m_buffer(new Buffer(size))
+File::File(const data_t* buffer, int size, int stream) :
+ m_buffer(new Buffer(size)), m_stream(stream)
{
std::memcpy(m_buffer->getBuffer(), buffer, size);
}
+std::vector File::queryStreams()
+{
+ if(m_buffer.get())
+ return FileManager::queryStreams(m_buffer);
+ else
+ return FileManager::queryStreams(m_filename);
+}
+
std::shared_ptr File::createReader()
{
if(m_buffer.get())
- return FileManager::createReader(m_buffer);
+ return FileManager::createReader(m_buffer, m_stream);
else
- return FileManager::createReader(m_filename);
+ return FileManager::createReader(m_filename, m_stream);
}
AUD_NAMESPACE_END
diff --git a/extern/audaspace/src/file/FileManager.cpp b/extern/audaspace/src/file/FileManager.cpp
index f8ef8deb409..7cbc0318f8c 100644
--- a/extern/audaspace/src/file/FileManager.cpp
+++ b/extern/audaspace/src/file/FileManager.cpp
@@ -43,13 +43,13 @@ void FileManager::registerOutput(std::shared_ptr output)
outputs().push_back(output);
}
-std::shared_ptr FileManager::createReader(std::string filename)
+std::shared_ptr FileManager::createReader(std::string filename, int stream)
{
for(std::shared_ptr input : inputs())
{
try
{
- return input->createReader(filename);
+ return input->createReader(filename, stream);
}
catch(Exception&) {}
}
@@ -57,13 +57,41 @@ std::shared_ptr FileManager::createReader(std::string filename)
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
}
-std::shared_ptr FileManager::createReader(std::shared_ptr buffer)
+std::shared_ptr FileManager::createReader(std::shared_ptr buffer, int stream)
{
for(std::shared_ptr input : inputs())
{
try
{
- return input->createReader(buffer);
+ return input->createReader(buffer, stream);
+ }
+ catch(Exception&) {}
+ }
+
+ AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
+}
+
+std::vector FileManager::queryStreams(std::string filename)
+{
+ for(std::shared_ptr input : inputs())
+ {
+ try
+ {
+ return input->queryStreams(filename);
+ }
+ catch(Exception&) {}
+ }
+
+ AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
+}
+
+std::vector FileManager::queryStreams(std::shared_ptr buffer)
+{
+ for(std::shared_ptr input : inputs())
+ {
+ try
+ {
+ return input->queryStreams(buffer);
}
catch(Exception&) {}
}
diff --git a/extern/audaspace/src/fx/VolumeReader.cpp b/extern/audaspace/src/fx/VolumeReader.cpp
index 627acbac9ef..ac1d4882a87 100644
--- a/extern/audaspace/src/fx/VolumeReader.cpp
+++ b/extern/audaspace/src/fx/VolumeReader.cpp
@@ -57,4 +57,4 @@ void VolumeReader::read(int& length, bool& eos, sample_t* buffer)
buffer[i] = buffer[i] * m_volumeStorage->getVolume();
}
-AUD_NAMESPACE_END
+AUD_NAMESPACE_END
\ No newline at end of file
diff --git a/extern/audaspace/src/util/RingBuffer.cpp b/extern/audaspace/src/util/RingBuffer.cpp
new file mode 100644
index 00000000000..3796684aa88
--- /dev/null
+++ b/extern/audaspace/src/util/RingBuffer.cpp
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright 2009-2021 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "util/RingBuffer.h"
+
+#include
+#include
+#include
+
+#define ALIGNMENT 32
+#define ALIGN(a) (a + ALIGNMENT - ((long long)a & (ALIGNMENT-1)))
+
+AUD_NAMESPACE_BEGIN
+
+RingBuffer::RingBuffer(int size) :
+ m_buffer(size),
+ m_read(0),
+ m_write(0)
+{
+}
+
+sample_t* RingBuffer::getBuffer() const
+{
+ return m_buffer.getBuffer();
+}
+
+int RingBuffer::getSize() const
+{
+ return m_buffer.getSize();
+}
+
+size_t RingBuffer::getReadSize() const
+{
+ size_t read = m_read;
+ size_t write = m_write;
+
+ if(read > write)
+ return write + getSize() - read;
+ else
+ return write - read;
+}
+
+size_t RingBuffer::getWriteSize() const
+{
+ size_t read = m_read;
+ size_t write = m_write;
+
+ if(read > write)
+ return read - write - 1;
+ else
+ return read + getSize() - write - 1;
+}
+
+size_t RingBuffer::read(data_t* target, size_t size)
+{
+ size = std::min(size, getReadSize());
+
+ data_t* buffer = reinterpret_cast(m_buffer.getBuffer());
+
+ if(m_read + size > m_buffer.getSize())
+ {
+ size_t read_first = m_buffer.getSize() - m_read;
+ size_t read_second = size - read_first;
+
+ std::memcpy(target, buffer + m_read, read_first);
+ std::memcpy(target + read_first, buffer, read_second);
+
+ m_read = read_second;
+ }
+ else
+ {
+ std::memcpy(target, buffer + m_read, size);
+
+ m_read += size;
+ }
+
+ return size;
+}
+
+size_t RingBuffer::write(data_t* source, size_t size)
+{
+ size = std::min(size, getWriteSize());
+
+ data_t* buffer = reinterpret_cast(m_buffer.getBuffer());
+
+ if(m_write + size > m_buffer.getSize())
+ {
+ size_t write_first = m_buffer.getSize() - m_write;
+ size_t write_second = size - write_first;
+
+ std::memcpy(buffer + m_write, source, write_first);
+ std::memcpy(buffer, source + write_first, write_second);
+
+ m_write = write_second;
+ }
+ else
+ {
+ std::memcpy(buffer + m_write, source, size);
+
+ m_write += size;
+ }
+
+ return size;
+}
+
+void RingBuffer::reset()
+{
+ m_read = 0;
+ m_write = 0;
+}
+
+void RingBuffer::resize(int size)
+{
+ m_buffer.resize(size);
+ reset();
+}
+
+void RingBuffer::assureSize(int size)
+{
+ m_buffer.assureSize(size);
+ reset();
+}
+
+AUD_NAMESPACE_END
diff --git a/extern/cuew/include/cuew.h b/extern/cuew/include/cuew.h
index 0fa0f1291fa..5979f48e43d 100644
--- a/extern/cuew/include/cuew.h
+++ b/extern/cuew/include/cuew.h
@@ -609,6 +609,7 @@ typedef enum cudaError_enum {
CUDA_ERROR_INVALID_GRAPHICS_CONTEXT = 219,
CUDA_ERROR_NVLINK_UNCORRECTABLE = 220,
CUDA_ERROR_JIT_COMPILER_NOT_FOUND = 221,
+ CUDA_ERROR_UNSUPPORTED_PTX_VERSION = 222,
CUDA_ERROR_INVALID_SOURCE = 300,
CUDA_ERROR_FILE_NOT_FOUND = 301,
CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
@@ -645,7 +646,8 @@ typedef enum CUdevice_P2PAttribute_enum {
CU_DEVICE_P2P_ATTRIBUTE_PERFORMANCE_RANK = 0x01,
CU_DEVICE_P2P_ATTRIBUTE_ACCESS_SUPPORTED = 0x02,
CU_DEVICE_P2P_ATTRIBUTE_NATIVE_ATOMIC_SUPPORTED = 0x03,
- CU_DEVICE_P2P_ATTRIBUTE_ARRAY_ACCESS_ACCESS_SUPPORTED = 0x04,
+ CU_DEVICE_P2P_ATTRIBUTE_ACCESS_ACCESS_SUPPORTED = 0x04,
+ CU_DEVICE_P2P_ATTRIBUTE_CUDA_ARRAY_ACCESS_SUPPORTED = 0x04,
} CUdevice_P2PAttribute;
typedef void (CUDA_CB *CUstreamCallback)(CUstream hStream, CUresult status, void* userData);
diff --git a/extern/cuew/src/cuew.c b/extern/cuew/src/cuew.c
index 7a1b0018a24..9eba9306323 100644
--- a/extern/cuew/src/cuew.c
+++ b/extern/cuew/src/cuew.c
@@ -736,6 +736,7 @@ const char *cuewErrorString(CUresult result) {
case CUDA_ERROR_INVALID_GRAPHICS_CONTEXT: return "Invalid graphics context";
case CUDA_ERROR_NVLINK_UNCORRECTABLE: return "Nvlink uncorrectable";
case CUDA_ERROR_JIT_COMPILER_NOT_FOUND: return "Jit compiler not found";
+ case CUDA_ERROR_UNSUPPORTED_PTX_VERSION: return "Unsupported PTX version";
case CUDA_ERROR_INVALID_SOURCE: return "Invalid source";
case CUDA_ERROR_FILE_NOT_FOUND: return "File not found";
case CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND: return "Link to a shared object failed to resolve";
diff --git a/extern/hipew/CMakeLists.txt b/extern/hipew/CMakeLists.txt
new file mode 100644
index 00000000000..d215ea8c691
--- /dev/null
+++ b/extern/hipew/CMakeLists.txt
@@ -0,0 +1,39 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2021, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ include
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ src/hipew.c
+
+ include/hipew.h
+)
+
+set(LIB
+)
+
+blender_add_lib(extern_hipew "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/extern/hipew/include/hipew.h b/extern/hipew/include/hipew.h
new file mode 100644
index 00000000000..d18cf67524d
--- /dev/null
+++ b/extern/hipew/include/hipew.h
@@ -0,0 +1,1352 @@
+/*
+ * Copyright 2011-2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#ifndef __HIPEW_H__
+#define __HIPEW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+#define HIP_IPC_HANDLE_SIZE 64
+#define hipHostMallocDefault 0x00
+#define hipHostMallocPortable 0x01
+#define hipHostMallocMapped 0x02
+#define hipHostMallocWriteCombined 0x04
+#define hipHostMallocNumaUser 0x20000000
+#define hipHostMallocCoherent 0x40000000
+#define hipHostMallocNonCoherent 0x80000000
+#define hipHostRegisterPortable 0x01
+#define hipHostRegisterMapped 0x02
+#define hipHostRegisterIoMemory 0x04
+#define hipCooperativeLaunchMultiDeviceNoPreSync 0x01
+#define hipCooperativeLaunchMultiDeviceNoPostSync 0x02
+#define hipArrayLayered 0x01
+#define hipArraySurfaceLoadStore 0x02
+#define hipArrayCubemap 0x04
+#define hipArrayTextureGather 0x08
+#define HIP_TRSA_OVERRIDE_FORMAT 0x01
+#define HIP_TRSF_READ_AS_INTEGER 0x01
+#define HIP_TRSF_NORMALIZED_COORDINATES 0x02
+#define HIP_LAUNCH_PARAM_END ((void*)0x00)
+#define HIP_LAUNCH_PARAM_BUFFER_POINTER ((void*)0x01)
+#define HIP_LAUNCH_PARAM_BUFFER_SIZE ((void*)0x02)
+
+/* Functions which changed 3.1 -> 3.2 for 64 bit stuff,
+ * the cuda library has both the old ones for compatibility and new
+ * ones with _v2 postfix,
+ */
+#define hipModuleGetGlobal hipModuleGetGlobal
+#define hipMemGetInfo hipMemGetInfo
+#define hipMemAllocPitch hipMemAllocPitch
+#define hipMemGetAddressRange hipMemGetAddressRange
+#define hipMemcpyHtoD hipMemcpyHtoD
+#define hipMemcpyDtoH hipMemcpyDtoH
+#define hipMemcpyDtoD hipMemcpyDtoD
+#define hipMemcpyHtoA hipMemcpyHtoA
+#define hipMemcpyAtoH hipMemcpyAtoH
+#define hipMemcpyHtoDAsync hipMemcpyHtoDAsync
+#define hipMemcpyDtoHAsync hipMemcpyDtoHAsync
+#define hipMemcpyDtoDAsync hipMemcpyDtoDAsync
+#define hipMemsetD8 hipMemsetD8
+#define hipMemsetD16 hipMemsetD16
+#define hipMemsetD32 hipMemsetD32
+#define hipArrayCreate hipArrayCreate
+#define hipArray3DCreate hipArray3DCreate
+#define hipTexRefSetAddress hipTexRefSetAddress
+#define hipTexRefGetAddress hipTexRefGetAddress
+#define hipStreamDestroy hipStreamDestroy
+#define hipEventDestroy hipEventDestroy
+#define hipTexRefSetAddress2D hipTexRefSetAddress2D
+
+/* Types. */
+#ifdef _MSC_VER
+typedef unsigned __int32 hipuint32_t;
+typedef unsigned __int64 hipuint64_t;
+#else
+#include
+typedef uint32_t hipuint32_t;
+typedef uint64_t hipuint64_t;
+#endif
+
+#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__)
+typedef unsigned long long hipDeviceptr_t;
+#else
+typedef unsigned int hipDeviceptr_t;
+#endif
+
+
+#ifdef _WIN32
+# define HIPAPI __stdcall
+# define HIP_CB __stdcall
+#else
+# define HIPAPI
+# define HIP_CB
+#endif
+
+typedef int hipDevice_t;
+typedef struct ihipCtx_t* hipCtx_t;
+typedef struct ihipModule_t* hipModule_t;
+typedef struct ihipModuleSymbol_t* hipFunction_t;
+typedef struct hipArray* hArray;
+typedef struct hipMipmappedArray_st* hipMipmappedArray_t;
+typedef struct ihipEvent_t* hipEvent_t;
+typedef struct ihipStream_t* hipStream_t;
+typedef unsigned long long hipTextureObject_t;
+
+typedef struct HIPuuid_st {
+ char bytes[16];
+} HIPuuid;
+
+typedef enum hipChannelFormatKind {
+ hipChannelFormatKindSigned = 0,
+ hipChannelFormatKindUnsigned = 1,
+ hipChannelFormatKindFloat = 2,
+ hipChannelFormatKindNone = 3,
+}hipChannelFormatKind;
+
+typedef struct hipChannelFormatDesc {
+ int x;
+ int y;
+ int z;
+ int w;
+ enum hipChannelFormatKind f;
+}hipChannelFormatDesc;
+
+typedef enum hipTextureFilterMode {
+ hipFilterModePoint = 0,
+ hipFilterModeLinear = 1,
+} hipTextureFilterMode;
+
+typedef enum hipArray_Format {
+ HIP_AD_FORMAT_UNSIGNED_INT8 = 0x01,
+ HIP_AD_FORMAT_SIGNED_INT8 = 0x08,
+ HIP_AD_FORMAT_UNSIGNED_INT16 = 0x02,
+ HIP_AD_FORMAT_SIGNED_INT16 = 0x09,
+ HIP_AD_FORMAT_UNSIGNED_INT32 = 0x03,
+ HIP_AD_FORMAT_SIGNED_INT32 = 0x0a,
+ HIP_AD_FORMAT_HALF = 0x10,
+ HIP_AD_FORMAT_FLOAT = 0x20,
+} hipArray_Format;
+
+typedef enum hipTextureAddressMode {
+ hipAddressModeWrap = 0,
+ hipAddressModeClamp = 1,
+ hipAddressModeMirror = 2,
+ hipAddressModeBorder = 3,
+} hipTextureAddressMode;
+
+/**
+ * hip texture reference
+ */
+typedef struct textureReference {
+ int normalized;
+ //enum hipTextureReadMode readMode;// used only for driver API's
+ enum hipTextureFilterMode filterMode;
+ enum hipTextureAddressMode addressMode[3]; // Texture address mode for up to 3 dimensions
+ struct hipChannelFormatDesc channelDesc;
+ int sRGB; // Perform sRGB->linear conversion during texture read
+ unsigned int maxAnisotropy; // Limit to the anisotropy ratio
+ enum hipTextureFilterMode mipmapFilterMode;
+ float mipmapLevelBias;
+ float minMipmapLevelClamp;
+ float maxMipmapLevelClamp;
+
+ hipTextureObject_t textureObject;
+ int numChannels;
+ enum hipArray_Format format;
+}textureReference;
+
+typedef textureReference* hipTexRef;
+
+typedef enum hipMemoryType {
+ hipMemoryTypeHost = 0x00,
+ hipMemoryTypeDevice = 0x01,
+ hipMemoryTypeArray = 0x02,
+ hipMemoryTypeUnified = 0x03,
+} hipMemoryType;
+
+/**
+ * Pointer attributes
+ */
+typedef struct hipPointerAttribute_t {
+ enum hipMemoryType memoryType;
+ int device;
+ void* devicePointer;
+ void* hostPointer;
+ int isManaged;
+ unsigned allocationFlags; /* flags specified when memory was allocated*/
+ /* peers? */
+} hipPointerAttribute_t;
+
+typedef struct ihipIpcEventHandle_t {
+ char reserved[HIP_IPC_HANDLE_SIZE];
+} ihipIpcEventHandle_t;
+
+typedef struct hipIpcMemHandle_st {
+ char reserved[HIP_IPC_HANDLE_SIZE];
+} hipIpcMemHandle_t;
+
+typedef enum HIPipcMem_flags_enum {
+ hipIpcMemLazyEnablePeerAccess = 0x1,
+} HIPipcMem_flags;
+
+typedef enum HIPmemAttach_flags_enum {
+ hipMemAttachGlobal = 0x1,
+ hipMemAttachHost = 0x2,
+ HIP_MEM_ATTACH_SINGLE = 0x4,
+} HIPmemAttach_flags;
+
+typedef enum HIPctx_flags_enum {
+ hipDeviceScheduleAuto = 0x00,
+ hipDeviceScheduleSpin = 0x01,
+ hipDeviceScheduleYield = 0x02,
+ hipDeviceScheduleBlockingSync = 0x04,
+ hipDeviceScheduleMask = 0x07,
+ hipDeviceMapHost = 0x08,
+ hipDeviceLmemResizeToMax = 0x10,
+} HIPctx_flags;
+
+typedef enum HIPstream_flags_enum {
+ hipStreamDefault = 0x0,
+ hipStreamNonBlocking = 0x1,
+} HIPstream_flags;
+
+typedef enum HIPevent_flags_enum {
+ hipEventDefault = 0x0,
+ hipEventBlockingSync = 0x1,
+ hipEventDisableTiming = 0x2,
+ hipEventInterprocess = 0x4,
+} HIPevent_flags;
+
+typedef enum HIPstreamWaitValue_flags_enum {
+ HIP_STREAM_WAIT_VALUE_GEQ = 0x0,
+ HIP_STREAM_WAIT_VALUE_EQ = 0x1,
+ HIP_STREAM_WAIT_VALUE_AND = 0x2,
+ HIP_STREAM_WAIT_VALUE_NOR = 0x3,
+ HIP_STREAM_WAIT_VALUE_FLUSH = (1 << 30),
+} HIPstreamWaitValue_flags;
+
+typedef enum HIPstreamWriteValue_flags_enum {
+ HIP_STREAM_WRITE_VALUE_DEFAULT = 0x0,
+ HIP_STREAM_WRITE_VALUE_NO_MEMORY_BARRIER = 0x1,
+} HIPstreamWriteValue_flags;
+
+typedef enum HIPstreamBatchMemOpType_enum {
+ HIP_STREAM_MEM_OP_WAIT_VALUE_32 = 1,
+ HIP_STREAM_MEM_OP_WRITE_VALUE_32 = 2,
+ HIP_STREAM_MEM_OP_WAIT_VALUE_64 = 4,
+ HIP_STREAM_MEM_OP_WRITE_VALUE_64 = 5,
+ HIP_STREAM_MEM_OP_FLUSH_REMOTE_WRITES = 3,
+} HIPstreamBatchMemOpType;
+
+
+typedef union HIPstreamBatchMemOpParams_union {
+ HIPstreamBatchMemOpType operation;
+ struct HIPstreamMemOpWaitValueParams_st {
+ HIPstreamBatchMemOpType operation;
+ hipDeviceptr_t address;
+ union {
+ hipuint32_t value;
+ hipuint64_t value64;
+ };
+ unsigned int flags;
+ hipDeviceptr_t alias;
+ } waitValue;
+ struct HIPstreamMemOpWriteValueParams_st {
+ HIPstreamBatchMemOpType operation;
+ hipDeviceptr_t address;
+ union {
+ hipuint32_t value;
+ hipuint64_t value64;
+ };
+ unsigned int flags;
+ hipDeviceptr_t alias;
+ } writeValue;
+ struct HIPstreamMemOpFlushRemoteWritesParams_st {
+ HIPstreamBatchMemOpType operation;
+ unsigned int flags;
+ } flushRemoteWrites;
+ hipuint64_t pad[6];
+} HIPstreamBatchMemOpParams;
+
+typedef enum HIPoccupancy_flags_enum {
+ hipOccupancyDefault = 0x0,
+ HIP_OCCUPANCY_DISABLE_CACHING_OVERRIDE = 0x1,
+} HIPoccupancy_flags;
+
+typedef enum hipDeviceAttribute_t {
+ hipDeviceAttributeCudaCompatibleBegin = 0,
+ hipDeviceAttributeEccEnabled = hipDeviceAttributeCudaCompatibleBegin, ///< Whether ECC support is enabled.
+ hipDeviceAttributeAccessPolicyMaxWindowSize, ///< Cuda only. The maximum size of the window policy in bytes.
+ hipDeviceAttributeAsyncEngineCount, ///< Cuda only. Asynchronous engines number.
+ hipDeviceAttributeCanMapHostMemory, ///< Whether host memory can be mapped into device address space
+ hipDeviceAttributeCanUseHostPointerForRegisteredMem,///< Cuda only. Device can access host registered memory
+ ///< at the same virtual address as the CPU
+ hipDeviceAttributeClockRate, ///< Peak clock frequency in kilohertz.
+ hipDeviceAttributeComputeMode, ///< Compute mode that device is currently in.
+ hipDeviceAttributeComputePreemptionSupported, ///< Cuda only. Device supports Compute Preemption.
+ hipDeviceAttributeConcurrentKernels, ///< Device can possibly execute multiple kernels concurrently.
+ hipDeviceAttributeConcurrentManagedAccess, ///< Device can coherently access managed memory concurrently with the CPU
+ hipDeviceAttributeCooperativeLaunch, ///< Support cooperative launch
+ hipDeviceAttributeCooperativeMultiDeviceLaunch, ///< Support cooperative launch on multiple devices
+ hipDeviceAttributeDeviceOverlap, ///< Cuda only. Device can concurrently copy memory and execute a kernel.
+ ///< Deprecated. Use instead asyncEngineCount.
+ hipDeviceAttributeDirectManagedMemAccessFromHost, ///< Host can directly access managed memory on
+ ///< the device without migration
+ hipDeviceAttributeGlobalL1CacheSupported, ///< Cuda only. Device supports caching globals in L1
+ hipDeviceAttributeHostNativeAtomicSupported, ///< Cuda only. Link between the device and the host supports native atomic operations
+ hipDeviceAttributeIntegrated, ///< Device is integrated GPU
+ hipDeviceAttributeIsMultiGpuBoard, ///< Multiple GPU devices.
+ hipDeviceAttributeKernelExecTimeout, ///< Run time limit for kernels executed on the device
+ hipDeviceAttributeL2CacheSize, ///< Size of L2 cache in bytes. 0 if the device doesn't have L2 cache.
+ hipDeviceAttributeLocalL1CacheSupported, ///< caching locals in L1 is supported
+ hipDeviceAttributeLuid, ///< Cuda only. 8-byte locally unique identifier in 8 bytes. Undefined on TCC and non-Windows platforms
+ hipDeviceAttributeLuidDeviceNodeMask, ///< Cuda only. Luid device node mask. Undefined on TCC and non-Windows platforms
+ hipDeviceAttributeComputeCapabilityMajor, ///< Major compute capability version number.
+ hipDeviceAttributeManagedMemory, ///< Device supports allocating managed memory on this system
+ hipDeviceAttributeMaxBlocksPerMultiProcessor, ///< Cuda only. Max block size per multiprocessor
+ hipDeviceAttributeMaxBlockDimX, ///< Max block size in width.
+ hipDeviceAttributeMaxBlockDimY, ///< Max block size in height.
+ hipDeviceAttributeMaxBlockDimZ, ///< Max block size in depth.
+ hipDeviceAttributeMaxGridDimX, ///< Max grid size in width.
+ hipDeviceAttributeMaxGridDimY, ///< Max grid size in height.
+ hipDeviceAttributeMaxGridDimZ, ///< Max grid size in depth.
+ hipDeviceAttributeMaxSurface1D, ///< Maximum size of 1D surface.
+ hipDeviceAttributeMaxSurface1DLayered, ///< Cuda only. Maximum dimensions of 1D layered surface.
+ hipDeviceAttributeMaxSurface2D, ///< Maximum dimension (width, height) of 2D surface.
+ hipDeviceAttributeMaxSurface2DLayered, ///< Cuda only. Maximum dimensions of 2D layered surface.
+ hipDeviceAttributeMaxSurface3D, ///< Maximum dimension (width, height, depth) of 3D surface.
+ hipDeviceAttributeMaxSurfaceCubemap, ///< Cuda only. Maximum dimensions of Cubemap surface.
+ hipDeviceAttributeMaxSurfaceCubemapLayered, ///< Cuda only. Maximum dimension of Cubemap layered surface.
+ hipDeviceAttributeMaxTexture1DWidth, ///< Maximum size of 1D texture.
+ hipDeviceAttributeMaxTexture1DLayered, ///< Cuda only. Maximum dimensions of 1D layered texture.
+ hipDeviceAttributeMaxTexture1DLinear, ///< Maximum number of elements allocatable in a 1D linear texture.
+ ///< Use cudaDeviceGetTexture1DLinearMaxWidth() instead on Cuda.
+ hipDeviceAttributeMaxTexture1DMipmap, ///< Cuda only. Maximum size of 1D mipmapped texture.
+ hipDeviceAttributeMaxTexture2DWidth, ///< Maximum dimension width of 2D texture.
+ hipDeviceAttributeMaxTexture2DHeight, ///< Maximum dimension hight of 2D texture.
+ hipDeviceAttributeMaxTexture2DGather, ///< Cuda only. Maximum dimensions of 2D texture if gather operations performed.
+ hipDeviceAttributeMaxTexture2DLayered, ///< Cuda only. Maximum dimensions of 2D layered texture.
+ hipDeviceAttributeMaxTexture2DLinear, ///< Cuda only. Maximum dimensions (width, height, pitch) of 2D textures bound to pitched memory.
+ hipDeviceAttributeMaxTexture2DMipmap, ///< Cuda only. Maximum dimensions of 2D mipmapped texture.
+ hipDeviceAttributeMaxTexture3DWidth, ///< Maximum dimension width of 3D texture.
+ hipDeviceAttributeMaxTexture3DHeight, ///< Maximum dimension height of 3D texture.
+ hipDeviceAttributeMaxTexture3DDepth, ///< Maximum dimension depth of 3D texture.
+ hipDeviceAttributeMaxTexture3DAlt, ///< Cuda only. Maximum dimensions of alternate 3D texture.
+ hipDeviceAttributeMaxTextureCubemap, ///< Cuda only. Maximum dimensions of Cubemap texture
+ hipDeviceAttributeMaxTextureCubemapLayered, ///< Cuda only. Maximum dimensions of Cubemap layered texture.
+ hipDeviceAttributeMaxThreadsDim, ///< Maximum dimension of a block
+ hipDeviceAttributeMaxThreadsPerBlock, ///< Maximum number of threads per block.
+ hipDeviceAttributeMaxThreadsPerMultiProcessor, ///< Maximum resident threads per multiprocessor.
+ hipDeviceAttributeMaxPitch, ///< Maximum pitch in bytes allowed by memory copies
+ hipDeviceAttributeMemoryBusWidth, ///< Global memory bus width in bits.
+ hipDeviceAttributeMemoryClockRate, ///< Peak memory clock frequency in kilohertz.
+ hipDeviceAttributeComputeCapabilityMinor, ///< Minor compute capability version number.
+ hipDeviceAttributeMultiGpuBoardGroupID, ///< Cuda only. Unique ID of device group on the same multi-GPU board
+ hipDeviceAttributeMultiprocessorCount, ///< Number of multiprocessors on the device.
+ hipDeviceAttributeName, ///< Device name.
+ hipDeviceAttributePageableMemoryAccess, ///< Device supports coherently accessing pageable memory
+ ///< without calling hipHostRegister on it
+ hipDeviceAttributePageableMemoryAccessUsesHostPageTables, ///< Device accesses pageable memory via the host's page tables
+ hipDeviceAttributePciBusId, ///< PCI Bus ID.
+ hipDeviceAttributePciDeviceId, ///< PCI Device ID.
+ hipDeviceAttributePciDomainID, ///< PCI Domain ID.
+ hipDeviceAttributePersistingL2CacheMaxSize, ///< Cuda11 only. Maximum l2 persisting lines capacity in bytes
+ hipDeviceAttributeMaxRegistersPerBlock, ///< 32-bit registers available to a thread block. This number is shared
+ ///< by all thread blocks simultaneously resident on a multiprocessor.
+ hipDeviceAttributeMaxRegistersPerMultiprocessor, ///< 32-bit registers available per block.
+ hipDeviceAttributeReservedSharedMemPerBlock, ///< Cuda11 only. Shared memory reserved by CUDA driver per block.
+ hipDeviceAttributeMaxSharedMemoryPerBlock, ///< Maximum shared memory available per block in bytes.
+ hipDeviceAttributeSharedMemPerBlockOptin, ///< Cuda only. Maximum shared memory per block usable by special opt in.
+ hipDeviceAttributeSharedMemPerMultiprocessor, ///< Cuda only. Shared memory available per multiprocessor.
+ hipDeviceAttributeSingleToDoublePrecisionPerfRatio, ///< Cuda only. Performance ratio of single precision to double precision.
+ hipDeviceAttributeStreamPrioritiesSupported, ///< Cuda only. Whether to support stream priorities.
+ hipDeviceAttributeSurfaceAlignment, ///< Cuda only. Alignment requirement for surfaces
+ hipDeviceAttributeTccDriver, ///< Cuda only. Whether device is a Tesla device using TCC driver
+ hipDeviceAttributeTextureAlignment, ///< Alignment requirement for textures
+ hipDeviceAttributeTexturePitchAlignment, ///< Pitch alignment requirement for 2D texture references bound to pitched memory;
+ hipDeviceAttributeTotalConstantMemory, ///< Constant memory size in bytes.
+ hipDeviceAttributeTotalGlobalMem, ///< Global memory available on devicice.
+ hipDeviceAttributeUnifiedAddressing, ///< Cuda only. An unified address space shared with the host.
+ hipDeviceAttributeUuid, ///< Cuda only. Unique ID in 16 byte.
+ hipDeviceAttributeWarpSize, ///< Warp size in threads.
+ hipDeviceAttributeCudaCompatibleEnd = 9999,
+ hipDeviceAttributeAmdSpecificBegin = 10000,
+ hipDeviceAttributeClockInstructionRate = hipDeviceAttributeAmdSpecificBegin, ///< Frequency in khz of the timer used by the device-side "clock*"
+ hipDeviceAttributeArch, ///< Device architecture
+ hipDeviceAttributeMaxSharedMemoryPerMultiprocessor, ///< Maximum Shared Memory PerMultiprocessor.
+ hipDeviceAttributeGcnArch, ///< Device gcn architecture
+ hipDeviceAttributeGcnArchName, ///< Device gcnArch name in 256 bytes
+ hipDeviceAttributeHdpMemFlushCntl, ///< Address of the HDP_MEM_COHERENCY_FLUSH_CNTL register
+ hipDeviceAttributeHdpRegFlushCntl, ///< Address of the HDP_REG_COHERENCY_FLUSH_CNTL register
+ hipDeviceAttributeCooperativeMultiDeviceUnmatchedFunc, ///< Supports cooperative launch on multiple
+ ///< devices with unmatched functions
+ hipDeviceAttributeCooperativeMultiDeviceUnmatchedGridDim, ///< Supports cooperative launch on multiple
+ ///< devices with unmatched grid dimensions
+ hipDeviceAttributeCooperativeMultiDeviceUnmatchedBlockDim, ///< Supports cooperative launch on multiple
+ ///< devices with unmatched block dimensions
+ hipDeviceAttributeCooperativeMultiDeviceUnmatchedSharedMem, ///< Supports cooperative launch on multiple
+ ///< devices with unmatched shared memories
+ hipDeviceAttributeIsLargeBar, ///< Whether it is LargeBar
+ hipDeviceAttributeAsicRevision, ///< Revision of the GPU in this device
+ hipDeviceAttributeCanUseStreamWaitValue, ///< '1' if Device supports hipStreamWaitValue32() and
+ ///< hipStreamWaitValue64() , '0' otherwise.
+ hipDeviceAttributeAmdSpecificEnd = 19999,
+ hipDeviceAttributeVendorSpecificBegin = 20000,
+ // Extended attributes for vendors
+} hipDeviceAttribute_t;
+
+typedef struct HIPdevprop_st {
+ int maxThreadsPerBlock;
+ int maxThreadsDim[3];
+ int maxGridSize[3];
+ int sharedMemPerBlock;
+ int totalConstantMemory;
+ int SIMDWidth;
+ int memPitch;
+ int regsPerBlock;
+ int clockRate;
+ int textureAlign;
+} HIPdevprop;
+
+typedef struct {
+ // 32-bit Atomics
+ unsigned hasGlobalInt32Atomics : 1; ///< 32-bit integer atomics for global memory.
+ unsigned hasGlobalFloatAtomicExch : 1; ///< 32-bit float atomic exch for global memory.
+ unsigned hasSharedInt32Atomics : 1; ///< 32-bit integer atomics for shared memory.
+ unsigned hasSharedFloatAtomicExch : 1; ///< 32-bit float atomic exch for shared memory.
+ unsigned hasFloatAtomicAdd : 1; ///< 32-bit float atomic add in global and shared memory.
+
+ // 64-bit Atomics
+ unsigned hasGlobalInt64Atomics : 1; ///< 64-bit integer atomics for global memory.
+ unsigned hasSharedInt64Atomics : 1; ///< 64-bit integer atomics for shared memory.
+
+ // Doubles
+ unsigned hasDoubles : 1; ///< Double-precision floating point.
+
+ // Warp cross-lane operations
+ unsigned hasWarpVote : 1; ///< Warp vote instructions (__any, __all).
+ unsigned hasWarpBallot : 1; ///< Warp ballot instructions (__ballot).
+ unsigned hasWarpShuffle : 1; ///< Warp shuffle operations. (__shfl_*).
+ unsigned hasFunnelShift : 1; ///< Funnel two words into one with shift&mask caps.
+
+ // Sync
+ unsigned hasThreadFenceSystem : 1; ///< __threadfence_system.
+ unsigned hasSyncThreadsExt : 1; ///< __syncthreads_count, syncthreads_and, syncthreads_or.
+
+ // Misc
+ unsigned hasSurfaceFuncs : 1; ///< Surface functions.
+ unsigned has3dGrid : 1; ///< Grid and group dims are 3D (rather than 2D).
+ unsigned hasDynamicParallelism : 1; ///< Dynamic parallelism.
+} hipDeviceArch_t;
+
+typedef struct hipDeviceProp_t {
+ char name[256]; ///< Device name.
+ size_t totalGlobalMem; ///< Size of global memory region (in bytes).
+ size_t sharedMemPerBlock; ///< Size of shared memory region (in bytes).
+ int regsPerBlock; ///< Registers per block.
+ int warpSize; ///< Warp size.
+ int maxThreadsPerBlock; ///< Max work items per work group or workgroup max size.
+ int maxThreadsDim[3]; ///< Max number of threads in each dimension (XYZ) of a block.
+ int maxGridSize[3]; ///< Max grid dimensions (XYZ).
+ int clockRate; ///< Max clock frequency of the multiProcessors in khz.
+ int memoryClockRate; ///< Max global memory clock frequency in khz.
+ int memoryBusWidth; ///< Global memory bus width in bits.
+ size_t totalConstMem; ///< Size of shared memory region (in bytes).
+ int major; ///< Major compute capability. On HCC, this is an approximation and features may
+ ///< differ from CUDA CC. See the arch feature flags for portable ways to query
+ ///< feature caps.
+ int minor; ///< Minor compute capability. On HCC, this is an approximation and features may
+ ///< differ from CUDA CC. See the arch feature flags for portable ways to query
+ ///< feature caps.
+ int multiProcessorCount; ///< Number of multi-processors (compute units).
+ int l2CacheSize; ///< L2 cache size.
+ int maxThreadsPerMultiProcessor; ///< Maximum resident threads per multi-processor.
+ int computeMode; ///< Compute mode.
+ int clockInstructionRate; ///< Frequency in khz of the timer used by the device-side "clock*"
+ ///< instructions. New for HIP.
+ hipDeviceArch_t arch; ///< Architectural feature flags. New for HIP.
+ int concurrentKernels; ///< Device can possibly execute multiple kernels concurrently.
+ int pciDomainID; ///< PCI Domain ID
+ int pciBusID; ///< PCI Bus ID.
+ int pciDeviceID; ///< PCI Device ID.
+ size_t maxSharedMemoryPerMultiProcessor; ///< Maximum Shared Memory Per Multiprocessor.
+ int isMultiGpuBoard; ///< 1 if device is on a multi-GPU board, 0 if not.
+ int canMapHostMemory; ///< Check whether HIP can map host memory
+ int gcnArch; ///< DEPRECATED: use gcnArchName instead
+ char gcnArchName[256]; ///< AMD GCN Arch Name.
+ int integrated; ///< APU vs dGPU
+ int cooperativeLaunch; ///< HIP device supports cooperative launch
+ int cooperativeMultiDeviceLaunch; ///< HIP device supports cooperative launch on multiple devices
+ int maxTexture1DLinear; ///< Maximum size for 1D textures bound to linear memory
+ int maxTexture1D; ///< Maximum number of elements in 1D images
+ int maxTexture2D[2]; ///< Maximum dimensions (width, height) of 2D images, in image elements
+ int maxTexture3D[3]; ///< Maximum dimensions (width, height, depth) of 3D images, in image elements
+ unsigned int* hdpMemFlushCntl; ///< Addres of HDP_MEM_COHERENCY_FLUSH_CNTL register
+ unsigned int* hdpRegFlushCntl; ///< Addres of HDP_REG_COHERENCY_FLUSH_CNTL register
+ size_t memPitch; ///
+#include
+#include
+#include
+#include
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include
+
+/* Utility macros. */
+
+typedef HMODULE DynamicLibrary;
+
+# define dynamic_library_open(path) LoadLibraryA(path)
+# define dynamic_library_close(lib) FreeLibrary(lib)
+# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
+#else
+# include
+
+typedef void* DynamicLibrary;
+
+# define dynamic_library_open(path) dlopen(path, RTLD_NOW)
+# define dynamic_library_close(lib) dlclose(lib)
+# define dynamic_library_find(lib, symbol) dlsym(lib, symbol)
+#endif
+
+#define _LIBRARY_FIND_CHECKED(lib, name) \
+ name = (t##name *)dynamic_library_find(lib, #name); \
+ assert(name);
+
+#define _LIBRARY_FIND(lib, name) \
+ name = (t##name *)dynamic_library_find(lib, #name);
+
+#define HIP_LIBRARY_FIND_CHECKED(name) \
+ _LIBRARY_FIND_CHECKED(hip_lib, name)
+#define HIP_LIBRARY_FIND(name) _LIBRARY_FIND(hip_lib, name)
+
+
+static DynamicLibrary hip_lib;
+
+/* Function definitions. */
+thipGetErrorName *hipGetErrorName;
+thipInit *hipInit;
+thipDriverGetVersion *hipDriverGetVersion;
+thipGetDevice *hipGetDevice;
+thipGetDeviceCount *hipGetDeviceCount;
+thipGetDeviceProperties *hipGetDeviceProperties;
+thipDeviceGetName *hipDeviceGetName;
+thipDeviceGetAttribute *hipDeviceGetAttribute;
+thipDeviceComputeCapability *hipDeviceComputeCapability;
+thipDevicePrimaryCtxRetain *hipDevicePrimaryCtxRetain;
+thipDevicePrimaryCtxRelease *hipDevicePrimaryCtxRelease;
+thipDevicePrimaryCtxSetFlags *hipDevicePrimaryCtxSetFlags;
+thipDevicePrimaryCtxGetState *hipDevicePrimaryCtxGetState;
+thipDevicePrimaryCtxReset *hipDevicePrimaryCtxReset;
+thipCtxCreate *hipCtxCreate;
+thipCtxDestroy *hipCtxDestroy;
+thipCtxPushCurrent *hipCtxPushCurrent;
+thipCtxPopCurrent *hipCtxPopCurrent;
+thipCtxSetCurrent *hipCtxSetCurrent;
+thipCtxGetCurrent *hipCtxGetCurrent;
+thipCtxGetDevice *hipCtxGetDevice;
+thipCtxGetFlags *hipCtxGetFlags;
+thipCtxSynchronize *hipCtxSynchronize;
+thipDeviceSynchronize *hipDeviceSynchronize;
+thipCtxGetCacheConfig *hipCtxGetCacheConfig;
+thipCtxSetCacheConfig *hipCtxSetCacheConfig;
+thipCtxGetSharedMemConfig *hipCtxGetSharedMemConfig;
+thipCtxSetSharedMemConfig *hipCtxSetSharedMemConfig;
+thipCtxGetApiVersion *hipCtxGetApiVersion;
+thipModuleLoad *hipModuleLoad;
+thipModuleLoadData *hipModuleLoadData;
+thipModuleLoadDataEx *hipModuleLoadDataEx;
+thipModuleUnload *hipModuleUnload;
+thipModuleGetFunction *hipModuleGetFunction;
+thipModuleGetGlobal *hipModuleGetGlobal;
+thipModuleGetTexRef *hipModuleGetTexRef;
+thipMemGetInfo *hipMemGetInfo;
+thipMalloc *hipMalloc;
+thipMemAllocPitch *hipMemAllocPitch;
+thipFree *hipFree;
+thipMemGetAddressRange *hipMemGetAddressRange;
+thipHostMalloc *hipHostMalloc;
+thipHostFree *hipHostFree;
+thipHostGetDevicePointer *hipHostGetDevicePointer;
+thipHostGetFlags *hipHostGetFlags;
+thipMallocManaged *hipMallocManaged;
+thipDeviceGetByPCIBusId *hipDeviceGetByPCIBusId;
+thipDeviceGetPCIBusId *hipDeviceGetPCIBusId;
+thipMemcpyPeer *hipMemcpyPeer;
+thipMemcpyHtoD *hipMemcpyHtoD;
+thipMemcpyDtoH *hipMemcpyDtoH;
+thipMemcpyDtoD *hipMemcpyDtoD;
+thipDrvMemcpy2DUnaligned *hipDrvMemcpy2DUnaligned;
+thipMemcpyParam2D *hipMemcpyParam2D;
+thipDrvMemcpy3D *hipDrvMemcpy3D;
+thipMemcpyHtoDAsync *hipMemcpyHtoDAsync;
+thipMemcpyDtoHAsync *hipMemcpyDtoHAsync;
+thipMemcpyParam2DAsync *hipMemcpyParam2DAsync;
+thipDrvMemcpy3DAsync *hipDrvMemcpy3DAsync;
+thipMemsetD8 *hipMemsetD8;
+thipMemsetD16 *hipMemsetD16;
+thipMemsetD32 *hipMemsetD32;
+thipMemsetD8Async *hipMemsetD8Async;
+thipMemsetD16Async *hipMemsetD16Async;
+thipMemsetD32Async *hipMemsetD32Async;
+thipArrayCreate *hipArrayCreate;
+thipArrayDestroy *hipArrayDestroy;
+thipArray3DCreate *hipArray3DCreate;
+thipStreamCreateWithFlags *hipStreamCreateWithFlags;
+thipStreamCreateWithPriority *hipStreamCreateWithPriority;
+thipStreamGetPriority *hipStreamGetPriority;
+thipStreamGetFlags *hipStreamGetFlags;
+thipStreamWaitEvent *hipStreamWaitEvent;
+thipStreamAddCallback *hipStreamAddCallback;
+thipStreamQuery *hipStreamQuery;
+thipStreamSynchronize *hipStreamSynchronize;
+thipStreamDestroy *hipStreamDestroy;
+thipEventCreateWithFlags *hipEventCreateWithFlags;
+thipEventRecord *hipEventRecord;
+thipEventQuery *hipEventQuery;
+thipEventSynchronize *hipEventSynchronize;
+thipEventDestroy *hipEventDestroy;
+thipEventElapsedTime *hipEventElapsedTime;
+thipFuncGetAttribute *hipFuncGetAttribute;
+thipFuncSetCacheConfig *hipFuncSetCacheConfig;
+thipModuleLaunchKernel *hipModuleLaunchKernel;
+thipDrvOccupancyMaxActiveBlocksPerMultiprocessor *hipDrvOccupancyMaxActiveBlocksPerMultiprocessor;
+thipDrvOccupancyMaxActiveBlocksPerMultiprocessorWithFlags *hipDrvOccupancyMaxActiveBlocksPerMultiprocessorWithFlags;
+thipModuleOccupancyMaxPotentialBlockSize *hipModuleOccupancyMaxPotentialBlockSize;
+thipTexRefSetArray *hipTexRefSetArray;
+thipTexRefSetAddress *hipTexRefSetAddress;
+thipTexRefSetAddress2D *hipTexRefSetAddress2D;
+thipTexRefSetFormat *hipTexRefSetFormat;
+thipTexRefSetAddressMode *hipTexRefSetAddressMode;
+thipTexRefSetFilterMode *hipTexRefSetFilterMode;
+thipTexRefSetFlags *hipTexRefSetFlags;
+thipTexRefGetAddress *hipTexRefGetAddress;
+thipTexRefGetArray *hipTexRefGetArray;
+thipTexRefGetAddressMode *hipTexRefGetAddressMode;
+thipTexObjectCreate *hipTexObjectCreate;
+thipTexObjectDestroy *hipTexObjectDestroy;
+thipDeviceCanAccessPeer *hipDeviceCanAccessPeer;
+
+thipCtxEnablePeerAccess *hipCtxEnablePeerAccess;
+thipCtxDisablePeerAccess *hipCtxDisablePeerAccess;
+thipDeviceGetP2PAttribute *hipDeviceGetP2PAttribute;
+thipGraphicsUnregisterResource *hipGraphicsUnregisterResource;
+thipGraphicsMapResources *hipGraphicsMapResources;
+thipGraphicsUnmapResources *hipGraphicsUnmapResources;
+thipGraphicsResourceGetMappedPointer *hipGraphicsResourceGetMappedPointer;
+
+thipGraphicsGLRegisterBuffer *hipGraphicsGLRegisterBuffer;
+thipGLGetDevices *hipGLGetDevices;
+
+thiprtcGetErrorString* hiprtcGetErrorString;
+thiprtcAddNameExpression* hiprtcAddNameExpression;
+thiprtcCompileProgram* hiprtcCompileProgram;
+thiprtcCreateProgram* hiprtcCreateProgram;
+thiprtcDestroyProgram* hiprtcDestroyProgram;
+thiprtcGetLoweredName* hiprtcGetLoweredName;
+thiprtcGetProgramLog* hiprtcGetProgramLog;
+thiprtcGetProgramLogSize* hiprtcGetProgramLogSize;
+thiprtcGetCode* hiprtcGetCode;
+thiprtcGetCodeSize* hiprtcGetCodeSize;
+
+
+
+static DynamicLibrary dynamic_library_open_find(const char **paths) {
+ int i = 0;
+ while (paths[i] != NULL) {
+ DynamicLibrary lib = dynamic_library_open(paths[i]);
+ if (lib != NULL) {
+ return lib;
+ }
+ ++i;
+ }
+ return NULL;
+}
+
+/* Implementation function. */
+static void hipewHipExit(void) {
+ if (hip_lib != NULL) {
+ /* Ignore errors. */
+ dynamic_library_close(hip_lib);
+ hip_lib = NULL;
+ }
+}
+
+static int hipewHipInit(void) {
+ /* Library paths. */
+#ifdef _WIN32
+ /* Expected in c:/windows/system or similar, no path needed. */
+ const char *hip_paths[] = {"amdhip64.dll", NULL};
+#elif defined(__APPLE__)
+ /* Default installation path. */
+ const char *hip_paths[] = {"", NULL};
+#else
+ const char *hip_paths[] = {"/opt/rocm/hip/lib/libamdhip64.so", NULL};
+#endif
+ static int initialized = 0;
+ static int result = 0;
+ int error, driver_version;
+
+ if (initialized) {
+ return result;
+ }
+
+ initialized = 1;
+
+ error = atexit(hipewHipExit);
+ if (error) {
+ result = HIPEW_ERROR_ATEXIT_FAILED;
+ return result;
+ }
+
+ /* Load library. */
+ hip_lib = dynamic_library_open_find(hip_paths);
+
+ if (hip_lib == NULL) {
+ result = HIPEW_ERROR_OPEN_FAILED;
+ return result;
+ }
+
+ /* Fetch all function pointers. */
+ HIP_LIBRARY_FIND_CHECKED(hipGetErrorName);
+ HIP_LIBRARY_FIND_CHECKED(hipInit);
+ HIP_LIBRARY_FIND_CHECKED(hipDriverGetVersion);
+ HIP_LIBRARY_FIND_CHECKED(hipGetDevice);
+ HIP_LIBRARY_FIND_CHECKED(hipGetDeviceCount);
+ HIP_LIBRARY_FIND_CHECKED(hipGetDeviceProperties);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceGetName);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceGetAttribute);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceComputeCapability);
+ HIP_LIBRARY_FIND_CHECKED(hipDevicePrimaryCtxRetain);
+ HIP_LIBRARY_FIND_CHECKED(hipDevicePrimaryCtxRelease);
+ HIP_LIBRARY_FIND_CHECKED(hipDevicePrimaryCtxSetFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipDevicePrimaryCtxGetState);
+ HIP_LIBRARY_FIND_CHECKED(hipDevicePrimaryCtxReset);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxCreate);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxDestroy);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxPushCurrent);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxPopCurrent);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxSetCurrent);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetCurrent);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetDevice);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxSynchronize);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceSynchronize);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetCacheConfig);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxSetCacheConfig);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetSharedMemConfig);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxSetSharedMemConfig);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxGetApiVersion);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleLoad);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleLoadData);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleLoadDataEx);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleUnload);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleGetFunction);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleGetGlobal);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleGetTexRef);
+ HIP_LIBRARY_FIND_CHECKED(hipMemGetInfo);
+ HIP_LIBRARY_FIND_CHECKED(hipMalloc);
+ HIP_LIBRARY_FIND_CHECKED(hipMemAllocPitch);
+ HIP_LIBRARY_FIND_CHECKED(hipFree);
+ HIP_LIBRARY_FIND_CHECKED(hipMemGetAddressRange);
+ HIP_LIBRARY_FIND_CHECKED(hipHostMalloc);
+ HIP_LIBRARY_FIND_CHECKED(hipHostFree);
+ HIP_LIBRARY_FIND_CHECKED(hipHostGetDevicePointer);
+ HIP_LIBRARY_FIND_CHECKED(hipHostGetFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipMallocManaged);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceGetByPCIBusId);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceGetPCIBusId);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyPeer);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyHtoD);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyDtoH);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyDtoD);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyParam2D);
+ HIP_LIBRARY_FIND_CHECKED(hipDrvMemcpy3D);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyHtoDAsync);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyDtoHAsync);
+ HIP_LIBRARY_FIND_CHECKED(hipDrvMemcpy2DUnaligned);
+ HIP_LIBRARY_FIND_CHECKED(hipMemcpyParam2DAsync);
+ HIP_LIBRARY_FIND_CHECKED(hipDrvMemcpy3DAsync);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD8);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD16);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD32);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD8Async);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD16Async);
+ HIP_LIBRARY_FIND_CHECKED(hipMemsetD32Async);
+ HIP_LIBRARY_FIND_CHECKED(hipArrayCreate);
+ HIP_LIBRARY_FIND_CHECKED(hipArrayDestroy);
+ HIP_LIBRARY_FIND_CHECKED(hipArray3DCreate);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamCreateWithFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamCreateWithPriority);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamGetPriority);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamGetFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamWaitEvent);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamAddCallback);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamQuery);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamSynchronize);
+ HIP_LIBRARY_FIND_CHECKED(hipStreamDestroy);
+ HIP_LIBRARY_FIND_CHECKED(hipEventCreateWithFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipEventRecord);
+ HIP_LIBRARY_FIND_CHECKED(hipEventQuery);
+ HIP_LIBRARY_FIND_CHECKED(hipEventSynchronize);
+ HIP_LIBRARY_FIND_CHECKED(hipEventDestroy);
+ HIP_LIBRARY_FIND_CHECKED(hipEventElapsedTime);
+ HIP_LIBRARY_FIND_CHECKED(hipFuncGetAttribute);
+ HIP_LIBRARY_FIND_CHECKED(hipFuncSetCacheConfig);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleLaunchKernel);
+ HIP_LIBRARY_FIND_CHECKED(hipModuleOccupancyMaxPotentialBlockSize);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetArray);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetAddress);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetAddress2D);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetFormat);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetAddressMode);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetFilterMode);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefSetFlags);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefGetAddress);
+ HIP_LIBRARY_FIND_CHECKED(hipTexRefGetAddressMode);
+ HIP_LIBRARY_FIND_CHECKED(hipTexObjectCreate);
+ HIP_LIBRARY_FIND_CHECKED(hipTexObjectDestroy);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceCanAccessPeer);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxEnablePeerAccess);
+ HIP_LIBRARY_FIND_CHECKED(hipCtxDisablePeerAccess);
+ HIP_LIBRARY_FIND_CHECKED(hipDeviceGetP2PAttribute);
+#ifdef _WIN32
+ HIP_LIBRARY_FIND_CHECKED(hipGraphicsUnregisterResource);
+ HIP_LIBRARY_FIND_CHECKED(hipGraphicsMapResources);
+ HIP_LIBRARY_FIND_CHECKED(hipGraphicsUnmapResources);
+ HIP_LIBRARY_FIND_CHECKED(hipGraphicsResourceGetMappedPointer);
+ HIP_LIBRARY_FIND_CHECKED(hipGraphicsGLRegisterBuffer);
+ HIP_LIBRARY_FIND_CHECKED(hipGLGetDevices);
+#endif
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetErrorString);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcAddNameExpression);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcCompileProgram);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcCreateProgram);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcDestroyProgram);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetLoweredName);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetProgramLog);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetProgramLogSize);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetCode);
+ HIP_LIBRARY_FIND_CHECKED(hiprtcGetCodeSize);
+ result = HIPEW_SUCCESS;
+ return result;
+}
+
+
+
+int hipewInit(hipuint32_t flags) {
+ int result = HIPEW_SUCCESS;
+
+ if (flags & HIPEW_INIT_HIP) {
+ result = hipewHipInit();
+ if (result != HIPEW_SUCCESS) {
+ return result;
+ }
+ }
+
+ return result;
+}
+
+
+const char *hipewErrorString(hipError_t result) {
+ switch (result) {
+ case hipSuccess: return "No errors";
+ case hipErrorInvalidValue: return "Invalid value";
+ case hipErrorOutOfMemory: return "Out of memory";
+ case hipErrorNotInitialized: return "Driver not initialized";
+ case hipErrorDeinitialized: return "Driver deinitialized";
+ case hipErrorProfilerDisabled: return "Profiler disabled";
+ case hipErrorProfilerNotInitialized: return "Profiler not initialized";
+ case hipErrorProfilerAlreadyStarted: return "Profiler already started";
+ case hipErrorProfilerAlreadyStopped: return "Profiler already stopped";
+ case hipErrorNoDevice: return "No HIP-capable device available";
+ case hipErrorInvalidDevice: return "Invalid device";
+ case hipErrorInvalidImage: return "Invalid kernel image";
+ case hipErrorInvalidContext: return "Invalid context";
+ case hipErrorContextAlreadyCurrent: return "Context already current";
+ case hipErrorMapFailed: return "Map failed";
+ case hipErrorUnmapFailed: return "Unmap failed";
+ case hipErrorArrayIsMapped: return "Array is mapped";
+ case hipErrorAlreadyMapped: return "Already mapped";
+ case hipErrorNoBinaryForGpu: return "No binary for GPU";
+ case hipErrorAlreadyAcquired: return "Already acquired";
+ case hipErrorNotMapped: return "Not mapped";
+ case hipErrorNotMappedAsArray: return "Mapped resource not available for access as an array";
+ case hipErrorNotMappedAsPointer: return "Mapped resource not available for access as a pointer";
+ case hipErrorECCNotCorrectable: return "Uncorrectable ECC error detected";
+ case hipErrorUnsupportedLimit: return "hipLimit_t not supported by device";
+ case hipErrorContextAlreadyInUse: return "Context already in use";
+ case hipErrorPeerAccessUnsupported: return "Peer access unsupported";
+ case hipErrorInvalidKernelFile: return "Invalid ptx";
+ case hipErrorInvalidGraphicsContext: return "Invalid graphics context";
+ case hipErrorInvalidSource: return "Invalid source";
+ case hipErrorFileNotFound: return "File not found";
+ case hipErrorSharedObjectSymbolNotFound: return "Link to a shared object failed to resolve";
+ case hipErrorSharedObjectInitFailed: return "Shared object initialization failed";
+ case hipErrorOperatingSystem: return "Operating system";
+ case hipErrorInvalidHandle: return "Invalid handle";
+ case hipErrorNotFound: return "Not found";
+ case hipErrorNotReady: return "HIP not ready";
+ case hipErrorIllegalAddress: return "Illegal address";
+ case hipErrorLaunchOutOfResources: return "Launch exceeded resources";
+ case hipErrorLaunchTimeOut: return "Launch exceeded timeout";
+ case hipErrorPeerAccessAlreadyEnabled: return "Peer access already enabled";
+ case hipErrorPeerAccessNotEnabled: return "Peer access not enabled";
+ case hipErrorSetOnActiveProcess: return "Primary context active";
+ case hipErrorAssert: return "Assert";
+ case hipErrorHostMemoryAlreadyRegistered: return "Host memory already registered";
+ case hipErrorHostMemoryNotRegistered: return "Host memory not registered";
+ case hipErrorLaunchFailure: return "Launch failed";
+ case hipErrorCooperativeLaunchTooLarge: return "Cooperative launch too large";
+ case hipErrorNotSupported: return "Not supported";
+ case hipErrorUnknown: return "Unknown error";
+ default: return "Unknown HIP error value";
+ }
+}
+
+static void path_join(const char *path1,
+ const char *path2,
+ int maxlen,
+ char *result) {
+#if defined(WIN32) || defined(_WIN32)
+ const char separator = '\\';
+#else
+ const char separator = '/';
+#endif
+ int n = snprintf(result, maxlen, "%s%c%s", path1, separator, path2);
+ if (n != -1 && n < maxlen) {
+ result[n] = '\0';
+ }
+ else {
+ result[maxlen - 1] = '\0';
+ }
+}
+
+static int path_exists(const char *path) {
+ struct stat st;
+ if (stat(path, &st)) {
+ return 0;
+ }
+ return 1;
+}
+
+const char *hipewCompilerPath(void) {
+ #ifdef _WIN32
+ const char *hipPath = getenv("HIP_ROCCLR_HOME");
+ const char *windowsCommand = "perl ";
+ const char *executable = "bin/hipcc";
+
+ static char hipcc[65536];
+ static char finalCommand[65536];
+ if(hipPath) {
+ path_join(hipPath, executable, sizeof(hipcc), hipcc);
+ if(path_exists(hipcc)) {
+ snprintf(finalCommand, sizeof(hipcc), "%s %s", windowsCommand, hipcc);
+ return finalCommand;
+ } else {
+ printf("Could not find hipcc. Make sure HIP_ROCCLR_HOME points to the directory holding /bin/hipcc");
+ }
+ }
+ #else
+ const char *hipPath = "opt/rocm/hip/bin";
+ const char *executable = "hipcc";
+
+ static char hipcc[65536];
+ if(hipPath) {
+ path_join(hipPath, executable, sizeof(hipcc), hipcc);
+ if(path_exists(hipcc)){
+ return hipcc;
+ }
+ }
+ #endif
+
+ {
+#ifdef _WIN32
+ FILE *handle = popen("where hipcc", "r");
+#else
+ FILE *handle = popen("which hipcc", "r");
+#endif
+ if (handle) {
+ char buffer[4096] = {0};
+ int len = fread(buffer, 1, sizeof(buffer) - 1, handle);
+ buffer[len] = '\0';
+ pclose(handle);
+ if (buffer[0]) {
+ return "hipcc";
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int hipewCompilerVersion(void) {
+ const char *path = hipewCompilerPath();
+ const char *marker = "Hip compilation tools, release ";
+ FILE *pipe;
+ int major, minor;
+ char *versionstr;
+ char buf[128];
+ char output[65536] = "\0";
+ char command[65536] = "\0";
+
+ if (path == NULL) {
+ return 0;
+ }
+
+ /* get --version output */
+ strcat(command, "\"");
+ strncat(command, path, sizeof(command) - 1);
+ strncat(command, "\" --version", sizeof(command) - strlen(path) - 1);
+ pipe = popen(command, "r");
+ if (!pipe) {
+ fprintf(stderr, "HIP: failed to run compiler to retrieve version");
+ return 0;
+ }
+
+ while (!feof(pipe)) {
+ if (fgets(buf, sizeof(buf), pipe) != NULL) {
+ strncat(output, buf, sizeof(output) - strlen(output) - 1);
+ }
+ }
+
+ pclose(pipe);
+ return 40;
+}
diff --git a/extern/json/README.blender b/extern/json/README.blender
new file mode 100644
index 00000000000..b9d8b02d87e
--- /dev/null
+++ b/extern/json/README.blender
@@ -0,0 +1,5 @@
+Project: JSON
+URL: https://github.com/nlohmann/json/
+License: MIT License
+Upstream version: 3.10.2
+Local modifications: None
diff --git a/extern/json/include/json.hpp b/extern/json/include/json.hpp
new file mode 100644
index 00000000000..8959265daea
--- /dev/null
+++ b/extern/json/include/json.hpp
@@ -0,0 +1,26640 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++
+| | |__ | | | | | | version 3.10.2
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License .
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2019 Niels Lohmann .
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef INCLUDE_NLOHMANN_JSON_HPP_
+#define INCLUDE_NLOHMANN_JSON_HPP_
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3
+#define NLOHMANN_JSON_VERSION_MINOR 10
+#define NLOHMANN_JSON_VERSION_PATCH 2
+
+#include // all_of, find, for_each
+#include // nullptr_t, ptrdiff_t, size_t
+#include // hash, less
+#include // initializer_list
+#ifndef JSON_NO_IO
+ #include // istream, ostream
+#endif // JSON_NO_IO
+#include // random_access_iterator_tag
+#include // unique_ptr
+#include // accumulate
+#include // string, stoi, to_string
+#include // declval, forward, move, pair, swap
+#include // vector
+
+// #include
+
+
+#include
+#include
+
+// #include
+
+
+#include // transform
+#include // array
+#include // forward_list
+#include // inserter, front_inserter, end
+#include