Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
93b96bab9a
|
@ -266,6 +266,7 @@ ForEachMacros:
|
|||
- MAP_SLOT_PROBING_BEGIN
|
||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||
- TGSET_ITER
|
||||
- WL_ARRAY_FOR_EACH
|
||||
|
||||
StatementMacros:
|
||||
- PyObject_HEAD
|
||||
|
|
|
@ -222,6 +222,14 @@ if(UNIX AND NOT (APPLE OR HAIKU))
|
|||
|
||||
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND)
|
||||
|
||||
if (WITH_GHOST_WAYLAND)
|
||||
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
|
||||
option(WITH_GHOST_WAYLAND_DBUS "Optionally build with DBUS support (used for Cursor themes). May hang on startup systems where DBUS is not used." OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_DBUS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
|
@ -255,19 +263,11 @@ if(WITH_GHOST_X11)
|
|||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
|
||||
option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
|
||||
else()
|
||||
# not an option for other OS's
|
||||
set(WITH_SYSTEM_GLEW OFF)
|
||||
set(WITH_SYSTEM_GLES OFF)
|
||||
set(WITH_SYSTEM_FREETYPE OFF)
|
||||
endif()
|
||||
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(WITH_SYSTEM_EIGEN3 "Use the systems Eigen3 library" OFF)
|
||||
else()
|
||||
set(WITH_SYSTEM_FREETYPE OFF)
|
||||
set(WITH_SYSTEM_EIGEN3 OFF)
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -444,7 +444,7 @@ endif()
|
|||
if(NOT APPLE)
|
||||
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
|
||||
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
|
||||
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
|
||||
endif()
|
||||
|
@ -454,6 +454,21 @@ if(APPLE)
|
|||
option(WITH_CYCLES_DEVICE_METAL "Enable Cycles Apple Metal compute support" ON)
|
||||
endif()
|
||||
|
||||
# oneAPI
|
||||
if(NOT APPLE)
|
||||
option(WITH_CYCLES_DEVICE_ONEAPI "Enable Cycles oneAPI compute support" OFF)
|
||||
option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF)
|
||||
option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF)
|
||||
|
||||
# https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html
|
||||
SET (CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for")
|
||||
SET (CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for")
|
||||
|
||||
mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
|
||||
mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES)
|
||||
mark_as_advanced(CYCLES_ONEAPI_SYCL_TARGETS)
|
||||
endif()
|
||||
|
||||
# Draw Manager
|
||||
option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF)
|
||||
mark_as_advanced(WITH_DRAW_DEBUG)
|
||||
|
@ -518,16 +533,40 @@ endif()
|
|||
|
||||
# OpenGL
|
||||
|
||||
# Experimental EGL option.
|
||||
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, GLX or WGL)" OFF)
|
||||
mark_as_advanced(WITH_GL_EGL)
|
||||
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
# Wayland can only use EGL to create OpenGL contexts, not GLX.
|
||||
set(WITH_GL_EGL ON)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(WITH_GL_EGL)
|
||||
# GLEW can only be built with either GLX or EGL support. Most binary distributions are
|
||||
# built with GLX support and we have no automated way to detect this. So always build
|
||||
# GLEW from source to be sure it has EGL support.
|
||||
set(WITH_SYSTEM_GLEW OFF)
|
||||
else()
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
endif()
|
||||
|
||||
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
|
||||
else()
|
||||
# System GLEW and GLES not an option on other platforms.
|
||||
set(WITH_SYSTEM_GLEW OFF)
|
||||
set(WITH_SYSTEM_GLES OFF)
|
||||
endif()
|
||||
|
||||
option(WITH_OPENGL "When off limits visibility of the opengl headers to just bf_gpu and gawain (temporary option for development purposes)" ON)
|
||||
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
|
||||
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
|
||||
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
|
||||
option(WITH_GPU_SHADER_BUILDER "Shader builder is a developer option enabling linting on GLSL during compilation" OFF)
|
||||
|
||||
mark_as_advanced(
|
||||
WITH_OPENGL
|
||||
WITH_GLEW_ES
|
||||
WITH_GL_EGL
|
||||
WITH_GL_PROFILE_ES20
|
||||
WITH_GPU_SHADER_BUILDER
|
||||
)
|
||||
|
|
|
@ -29,10 +29,12 @@ cmake_minimum_required(VERSION 3.5)
|
|||
|
||||
include(ExternalProject)
|
||||
include(cmake/check_software.cmake)
|
||||
include(cmake/versions.cmake)
|
||||
include(cmake/options.cmake)
|
||||
# versions.cmake needs to be included after options.cmake due to the BLENDER_PLATFORM_ARM variable being needed.
|
||||
include(cmake/versions.cmake)
|
||||
include(cmake/boost_build_options.cmake)
|
||||
include(cmake/download.cmake)
|
||||
include(cmake/macros.cmake)
|
||||
|
||||
if(ENABLE_MINGW64)
|
||||
include(cmake/setup_mingw64.cmake)
|
||||
|
@ -57,7 +59,6 @@ include(cmake/alembic.cmake)
|
|||
include(cmake/opensubdiv.cmake)
|
||||
include(cmake/sdl.cmake)
|
||||
include(cmake/opencollada.cmake)
|
||||
include(cmake/llvm.cmake)
|
||||
if(APPLE)
|
||||
include(cmake/openmp.cmake)
|
||||
endif()
|
||||
|
@ -75,6 +76,7 @@ include(cmake/osl.cmake)
|
|||
include(cmake/tbb.cmake)
|
||||
include(cmake/openvdb.cmake)
|
||||
include(cmake/python.cmake)
|
||||
include(cmake/llvm.cmake)
|
||||
option(USE_PIP_NUMPY "Install NumPy using pip wheel instead of building from source" OFF)
|
||||
if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64"))
|
||||
set(USE_PIP_NUMPY ON)
|
||||
|
@ -96,6 +98,15 @@ include(cmake/fmt.cmake)
|
|||
include(cmake/robinmap.cmake)
|
||||
if(NOT APPLE)
|
||||
include(cmake/xr_openxr.cmake)
|
||||
if(NOT WIN32 OR BUILD_MODE STREQUAL Release)
|
||||
include(cmake/dpcpp.cmake)
|
||||
include(cmake/dpcpp_deps.cmake)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
include(cmake/igc.cmake)
|
||||
include(cmake/gmmlib.cmake)
|
||||
include(cmake/ocloc.cmake)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# OpenColorIO and dependencies.
|
||||
|
|
|
@ -56,10 +56,7 @@ if(UNIX)
|
|||
"On Debian and Ubuntu:\n"
|
||||
" apt install autoconf automake libtool yasm tcl ninja-build meson python3-mako\n"
|
||||
"\n"
|
||||
"On macOS Intel (with homebrew):\n"
|
||||
" brew install autoconf automake bison libtool pkg-config yasm\n"
|
||||
"\n"
|
||||
"On macOS ARM (with homebrew):\n"
|
||||
"On macOS (with homebrew):\n"
|
||||
" brew install autoconf automake bison flex libtool pkg-config yasm\n"
|
||||
"\n"
|
||||
"Other platforms:\n"
|
||||
|
|
|
@ -101,3 +101,18 @@ download_source(ROBINMAP)
|
|||
download_source(IMATH)
|
||||
download_source(PYSTRING)
|
||||
download_source(LEVEL_ZERO)
|
||||
download_source(DPCPP)
|
||||
download_source(VCINTRINSICS)
|
||||
download_source(OPENCLHEADERS)
|
||||
download_source(ICDLOADER)
|
||||
download_source(MP11)
|
||||
download_source(SPIRV_HEADERS)
|
||||
download_source(IGC)
|
||||
download_source(IGC_LLVM)
|
||||
download_source(IGC_OPENCL_CLANG)
|
||||
download_source(IGC_VCINTRINSICS)
|
||||
download_source(IGC_SPIRV_HEADERS)
|
||||
download_source(IGC_SPIRV_TOOLS)
|
||||
download_source(IGC_SPIRV_TRANSLATOR)
|
||||
download_source(GMMLIB)
|
||||
download_source(OCLOC)
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(LLVM_GENERATOR "Ninja")
|
||||
else()
|
||||
set(LLVM_GENERATOR "Unix Makefiles")
|
||||
endif()
|
||||
|
||||
set(DPCPP_CONFIGURE_ARGS
|
||||
# When external deps dpcpp needs are not found it will automatically
|
||||
# download the during the configure stage using FetchContent. Given
|
||||
# we need to keep an archive of all source used during build for compliance
|
||||
# reasons it CANNOT download anything we do not know about. By setting
|
||||
# this property to ON, all downloads are disabled, and we will have to
|
||||
# provide the missing deps some other way, a build error beats a compliance
|
||||
# violation
|
||||
--cmake-opt FETCHCONTENT_FULLY_DISCONNECTED=ON
|
||||
)
|
||||
set(DPCPP_SOURCE_ROOT ${BUILD_DIR}/dpcpp/src/external_dpcpp/)
|
||||
set(DPCPP_EXTRA_ARGS
|
||||
# When external deps dpcpp needs are not found it will automatically
|
||||
# download the during the configure stage using FetchContent. Given
|
||||
# we need to keep an archive of all source used during build for compliance
|
||||
# reasons it CANNOT download anything we do not know about. By setting
|
||||
# this property to ON, all downloads are disabled, and we will have to
|
||||
# provide the missing deps some other way, a build or configure error
|
||||
# beats a compliance violation
|
||||
-DFETCHCONTENT_FULLY_DISCONNECTED=ON
|
||||
-DLLVMGenXIntrinsics_SOURCE_DIR=${BUILD_DIR}/vcintrinsics/src/external_vcintrinsics/
|
||||
-DOpenCL_HEADERS=file://${PACKAGE_DIR}/${OPENCLHEADERS_FILE}
|
||||
-DOpenCL_LIBRARY_SRC=file://${PACKAGE_DIR}/${ICDLOADER_FILE}
|
||||
-DBOOST_MP11_SOURCE_DIR=${BUILD_DIR}/mp11/src/external_mp11/
|
||||
-DLEVEL_ZERO_LIBRARY=${LIBDIR}/level-zero/lib/${LIBPREFIX}ze_loader${SHAREDLIBEXT}
|
||||
-DLEVEL_ZERO_INCLUDE_DIR=${LIBDIR}/level-zero/include
|
||||
-DLLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR=${BUILD_DIR}/spirvheaders/src/external_spirvheaders/
|
||||
# Below here is copied from an invocation of buildbot/config.py
|
||||
-DLLVM_ENABLE_ASSERTIONS=ON
|
||||
-DLLVM_TARGETS_TO_BUILD=X86
|
||||
-DLLVM_EXTERNAL_PROJECTS=sycl^^llvm-spirv^^opencl^^libdevice^^xpti^^xptifw
|
||||
-DLLVM_EXTERNAL_SYCL_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/sycl
|
||||
-DLLVM_EXTERNAL_LLVM_SPIRV_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/llvm-spirv
|
||||
-DLLVM_EXTERNAL_XPTI_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/xpti
|
||||
-DXPTI_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/xpti
|
||||
-DLLVM_EXTERNAL_XPTIFW_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/xptifw
|
||||
-DLLVM_EXTERNAL_LIBDEVICE_SOURCE_DIR=${DPCPP_SOURCE_ROOT}/libdevice
|
||||
-DLLVM_ENABLE_PROJECTS=clang^^sycl^^llvm-spirv^^opencl^^libdevice^^xpti^^xptifw
|
||||
-DLIBCLC_TARGETS_TO_BUILD=
|
||||
-DLIBCLC_GENERATE_REMANGLED_VARIANTS=OFF
|
||||
-DSYCL_BUILD_PI_HIP_PLATFORM=AMD
|
||||
-DLLVM_BUILD_TOOLS=ON
|
||||
-DSYCL_ENABLE_WERROR=OFF
|
||||
-DSYCL_INCLUDE_TESTS=ON
|
||||
-DLLVM_ENABLE_DOXYGEN=OFF
|
||||
-DLLVM_ENABLE_SPHINX=OFF
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DSYCL_ENABLE_XPTI_TRACING=ON
|
||||
-DLLVM_ENABLE_LLD=OFF
|
||||
-DXPTI_ENABLE_WERROR=OFF
|
||||
-DSYCL_CLANG_EXTRA_FLAGS=
|
||||
-DSYCL_ENABLE_PLUGINS=level_zero
|
||||
-DCMAKE_INSTALL_RPATH=\$ORIGIN
|
||||
-DPython3_ROOT_DIR=${LIBDIR}/python/
|
||||
-DPython3_EXECUTABLE=${PYTHON_BINARY}
|
||||
-DPYTHON_EXECUTABLE=${PYTHON_BINARY}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND DPCPP_EXTRA_ARGS -DPython3_FIND_REGISTRY=NEVER)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_dpcpp
|
||||
URL file://${PACKAGE_DIR}/${DPCPP_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${DPCPP_HASH_TYPE}=${DPCPP_HASH}
|
||||
PREFIX ${BUILD_DIR}/dpcpp
|
||||
CMAKE_GENERATOR ${LLVM_GENERATOR}
|
||||
SOURCE_SUBDIR llvm
|
||||
LIST_SEPARATOR ^^
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/dpcpp ${DEFAULT_CMAKE_FLAGS} ${DPCPP_EXTRA_ARGS}
|
||||
#CONFIGURE_COMMAND ${PYTHON_BINARY} ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/configure.py ${DPCPP_CONFIGURE_ARGS}
|
||||
#BUILD_COMMAND echo "." #${PYTHON_BINARY} ${BUILD_DIR}/dpcpp/src/external_dpcpp/buildbot/compile.py
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --build . -- deploy-sycl-toolchain
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/dpcpp/src/external_dpcpp < ${PATCH_DIR}/dpcpp.diff
|
||||
INSTALL_DIR ${LIBDIR}/dpcpp
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_dpcpp
|
||||
external_python
|
||||
external_python_site_packages
|
||||
external_vcintrinsics
|
||||
external_openclheaders
|
||||
external_icdloader
|
||||
external_mp11
|
||||
external_level-zero
|
||||
external_spirvheaders
|
||||
)
|
||||
|
||||
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||
ExternalProject_Add_Step(external_dpcpp after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/dpcpp/bin/clang-cl.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/dpcpp/bin/clang-cpp.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/dpcpp/bin/clang.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/dpcpp ${HARVEST_TARGET}/dpcpp
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,61 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# These are build time requirements for dpcpp
|
||||
# We only have to unpack these dpcpp will build
|
||||
# them.
|
||||
|
||||
ExternalProject_Add(external_vcintrinsics
|
||||
URL file://${PACKAGE_DIR}/${VCINTRINSICS_FILE}
|
||||
URL_HASH ${VCINTRINSICS_HASH_TYPE}=${VCINTRINSICS_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/vcintrinsics
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
||||
|
||||
# opencl headers do not have to be unpacked, dpcpp will do it
|
||||
# but it wouldn't hurt to do it anyway as an opertunity to validate
|
||||
# the hash is correct.
|
||||
ExternalProject_Add(external_openclheaders
|
||||
URL file://${PACKAGE_DIR}/${OPENCLHEADERS_FILE}
|
||||
URL_HASH ${OPENCLHEADERS_HASH_TYPE}=${OPENCLHEADERS_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/openclheaders
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
||||
|
||||
# icdloader does not have to be unpacked, dpcpp will do it
|
||||
# but it wouldn't hurt to do it anyway as an opertunity to validate
|
||||
# the hash is correct.
|
||||
ExternalProject_Add(external_icdloader
|
||||
URL file://${PACKAGE_DIR}/${ICDLOADER_FILE}
|
||||
URL_HASH ${ICDLOADER_HASH_TYPE}=${ICDLOADER_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/icdloader
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_mp11
|
||||
URL file://${PACKAGE_DIR}/${MP11_FILE}
|
||||
URL_HASH ${MP11_HASH_TYPE}=${MP11_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/mp11
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_spirvheaders
|
||||
URL file://${PACKAGE_DIR}/${SPIRV_HEADERS_FILE}
|
||||
URL_HASH ${SPIRV_HEADERS_HASH_TYPE}=${SPIRV_HEADERS_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/spirvheaders
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
|
@ -5,6 +5,8 @@ ExternalProject_Add(external_flex
|
|||
URL_HASH ${FLEX_HASH_TYPE}=${FLEX_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/flex
|
||||
# This patch fixes build with some versions of glibc (https://github.com/westes/flex/commit/24fd0551333e7eded87b64dd36062da3df2f6380)
|
||||
PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/flex/src/external_flex < ${PATCH_DIR}/flex.diff
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flex/src/external_flex/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/flex
|
||||
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flex/src/external_flex/ && make -j${MAKE_THREADS}
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/flex/src/external_flex/ && make install
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(GMMLIB_EXTRA_ARGS
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_gmmlib
|
||||
URL file://${PACKAGE_DIR}/${GMMLIB_FILE}
|
||||
URL_HASH ${GMMLIB_HASH_TYPE}=${GMMLIB_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/gmmlib
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/gmmlib ${DEFAULT_CMAKE_FLAGS} ${GMMLIB_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/gmmlib
|
||||
)
|
|
@ -192,6 +192,10 @@ harvest(zstd/lib zstd/lib "*.a")
|
|||
if(UNIX AND NOT APPLE)
|
||||
harvest(libglu/lib mesa/lib "*.so*")
|
||||
harvest(mesa/lib64 mesa/lib "*.so*")
|
||||
endif()
|
||||
|
||||
harvest(dpcpp dpcpp "*")
|
||||
harvest(igc dpcpp/lib/igc "*")
|
||||
harvest(ocloc dpcpp/lib/ocloc "*")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
unpack_only(igc_vcintrinsics)
|
||||
unpack_only(igc_spirv_headers)
|
||||
unpack_only(igc_spirv_tools)
|
||||
|
||||
#
|
||||
# igc_opencl_clang contains patches that need to be applied
|
||||
# to external_igc_llvm and igc_spirv_translator, we unpack
|
||||
# igc_opencl_clang first, then have the patch stages of
|
||||
# external_igc_llvm and igc_spirv_translator apply them.
|
||||
#
|
||||
|
||||
ExternalProject_Add(external_igc_opencl_clang
|
||||
URL file://${PACKAGE_DIR}/${IGC_OPENCL_CLANG_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${IGC_OPENCL_CLANG_HASH_TYPE}=${IGC_OPENCL_CLANG_HASH}
|
||||
PREFIX ${BUILD_DIR}/igc_opencl_clang
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/igc_opencl_clang/src/external_igc_opencl_clang/ < ${PATCH_DIR}/igc_opencl_clang.diff
|
||||
)
|
||||
|
||||
set(IGC_OPENCL_CLANG_PATCH_DIR ${BUILD_DIR}/igc_opencl_clang/src/external_igc_opencl_clang/patches)
|
||||
set(IGC_LLVM_SOURCE_DIR ${BUILD_DIR}/igc_llvm/src/external_igc_llvm)
|
||||
set(IGC_SPIRV_TRANSLATOR_SOURCE_DIR ${BUILD_DIR}/igc_spirv_translator/src/external_igc_spirv_translator)
|
||||
|
||||
ExternalProject_Add(external_igc_llvm
|
||||
URL file://${PACKAGE_DIR}/${IGC_LLVM_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${IGC_LLVM_HASH_TYPE}=${IGC_LLVM_HASH}
|
||||
PREFIX ${BUILD_DIR}/igc_llvm
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0001-OpenCL-3.0-support.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0002-Remove-__IMAGE_SUPPORT__-macro-for-SPIR.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0003-Avoid-calling-ParseCommandLineOptions-in-BackendUtil.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0004-OpenCL-support-cl_ext_float_atomics.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0005-OpenCL-Add-cl_khr_integer_dot_product.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0001-Memory-leak-fix-for-Managed-Static-Mutex.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0002-Remove-repo-name-in-LLVM-IR.patch
|
||||
)
|
||||
add_dependencies(
|
||||
external_igc_llvm
|
||||
external_igc_opencl_clang
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_igc_spirv_translator
|
||||
URL file://${PACKAGE_DIR}/${IGC_SPIRV_TRANSLATOR_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${IGC_SPIRV_TRANSLATOR_HASH_TYPE}=${IGC_SPIRV_TRANSLATOR_HASH}
|
||||
PREFIX ${BUILD_DIR}/igc_spirv_translator
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0001-update-SPIR-V-headers-for-SPV_INTEL_split_barrier.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch &&
|
||||
${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0003-Support-cl_bf16_conversions.patch
|
||||
)
|
||||
add_dependencies(
|
||||
external_igc_spirv_translator
|
||||
external_igc_opencl_clang
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(IGC_GENERATOR "Ninja")
|
||||
set(IGC_TARGET Windows64)
|
||||
else()
|
||||
set(IGC_GENERATOR "Unix Makefiles")
|
||||
set(IGC_TARGET Linux64)
|
||||
endif()
|
||||
|
||||
set(IGC_EXTRA_ARGS
|
||||
-DIGC_OPTION__ARCHITECTURE_TARGET=${IGC_TARGET}
|
||||
-DIGC_OPTION__ARCHITECTURE_HOST=${IGC_TARGET}
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND IGC_EXTRA_ARGS
|
||||
-DFLEX_EXECUTABLE=${LIBDIR}/flex/bin/flex
|
||||
-DFLEX_INCLUDE_DIR=${LIBDIR}/flex/include
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_igc
|
||||
URL file://${PACKAGE_DIR}/${IGC_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${IGC_HASH_TYPE}=${IGC_HASH}
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/igc ${DEFAULT_CMAKE_FLAGS} ${IGC_EXTRA_ARGS}
|
||||
|
||||
# IGC is pretty set in its way where sub projects ought to live, for some it offers
|
||||
# hooks to supply alternatives folders, other are just hardocded with no way to configure
|
||||
# we symlink everything here, since it's less work than trying to convince the cmake
|
||||
# scripts to accept alternative locations.
|
||||
#
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_llvm/src/external_igc_llvm/ ${BUILD_DIR}/igc/src/llvm-project &&
|
||||
${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_opencl_clang/src/external_igc_opencl_clang/ ${BUILD_DIR}/igc/src/llvm-project/llvm/projects/opencl-clang &&
|
||||
${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_spirv_translator/src/external_igc_spirv_translator/ ${BUILD_DIR}/igc/src/llvm-project/llvm/projects/llvm-spirv &&
|
||||
${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_spirv_tools/src/external_igc_spirv_tools/ ${BUILD_DIR}/igc/src/SPIRV-Tools &&
|
||||
${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_spirv_headers/src/external_igc_spirv_headers/ ${BUILD_DIR}/igc/src/SPIRV-Headers &&
|
||||
${CMAKE_COMMAND} -E create_symlink ${BUILD_DIR}/igc_vcintrinsics/src/external_igc_vcintrinsics/ ${BUILD_DIR}/igc/src/vc-intrinsics
|
||||
PREFIX ${BUILD_DIR}/igc
|
||||
INSTALL_DIR ${LIBDIR}/igc
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --install . --strip
|
||||
CMAKE_GENERATOR ${IGC_GENERATOR}
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_igc
|
||||
external_igc_vcintrinsics
|
||||
external_igc_llvm
|
||||
external_igc_opencl_clang
|
||||
external_igc_vcintrinsics
|
||||
external_igc_spirv_headers
|
||||
external_igc_spirv_tools
|
||||
external_igc_spirv_translator
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
add_dependencies(
|
||||
external_igc
|
||||
external_flex
|
||||
)
|
||||
endif()
|
|
@ -6,6 +6,7 @@ if(WIN32)
|
|||
-DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe
|
||||
-DM4_EXECUTABLE=${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/m4.exe
|
||||
-DARM_ENABLED=Off
|
||||
-DPython3_FIND_REGISTRY=NEVER
|
||||
)
|
||||
elseif(APPLE)
|
||||
# Use bison and flex installed via Homebrew.
|
||||
|
@ -27,7 +28,7 @@ elseif(UNIX)
|
|||
set(ISPC_EXTRA_ARGS_UNIX
|
||||
-DCMAKE_C_COMPILER=${LIBDIR}/llvm/bin/clang
|
||||
-DCMAKE_CXX_COMPILER=${LIBDIR}/llvm/bin/clang++
|
||||
-DARM_ENABLED=Off
|
||||
-DARM_ENABLED=${BLENDER_PLATFORM_ARM}
|
||||
-DFLEX_EXECUTABLE=${LIBDIR}/flex/bin/flex
|
||||
)
|
||||
endif()
|
||||
|
@ -43,6 +44,8 @@ set(ISPC_EXTRA_ARGS
|
|||
-DISPC_INCLUDE_TESTS=Off
|
||||
-DCLANG_LIBRARY_DIR=${LIBDIR}/llvm/lib
|
||||
-DCLANG_INCLUDE_DIRS=${LIBDIR}/llvm/include
|
||||
-DPython3_ROOT_DIR=${LIBDIR}/python/
|
||||
-DPython3_EXECUTABLE=${PYTHON_BINARY}
|
||||
${ISPC_EXTRA_ARGS_WIN}
|
||||
${ISPC_EXTRA_ARGS_APPLE}
|
||||
${ISPC_EXTRA_ARGS_UNIX}
|
||||
|
@ -61,6 +64,7 @@ ExternalProject_Add(external_ispc
|
|||
add_dependencies(
|
||||
external_ispc
|
||||
ll
|
||||
external_python
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -25,11 +25,14 @@ set(LLVM_EXTRA_ARGS
|
|||
-DLLVM_BUILD_LLVM_C_DYLIB=OFF
|
||||
-DLLVM_ENABLE_UNWIND_TABLES=OFF
|
||||
-DLLVM_ENABLE_PROJECTS=clang${LLVM_BUILD_CLANG_TOOLS_EXTRA}
|
||||
-DPython3_ROOT_DIR=${LIBDIR}/python/
|
||||
-DPython3_EXECUTABLE=${PYTHON_BINARY}
|
||||
${LLVM_XML2_ARGS}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(LLVM_GENERATOR "Ninja")
|
||||
list(APPEND LLVM_EXTRA_ARGS -DPython3_FIND_REGISTRY=NEVER)
|
||||
else()
|
||||
set(LLVM_GENERATOR "Unix Makefiles")
|
||||
endif()
|
||||
|
@ -74,3 +77,8 @@ if(APPLE)
|
|||
external_xml2
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(
|
||||
ll
|
||||
external_python
|
||||
)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# shorthand to only unpack a certain dependency
|
||||
macro(unpack_only name)
|
||||
string(TOUPPER ${name} UPPER_NAME)
|
||||
set(TARGET_FILE ${${UPPER_NAME}_FILE})
|
||||
set(TARGET_HASH_TYPE ${${UPPER_NAME}_HASH_TYPE})
|
||||
set(TARGET_HASH ${${UPPER_NAME}_HASH})
|
||||
ExternalProject_Add(external_${name}
|
||||
URL file://${PACKAGE_DIR}/${TARGET_FILE}
|
||||
URL_HASH ${TARGET_HASH_TYPE}=${TARGET_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/${name}
|
||||
CONFIGURE_COMMAND echo .
|
||||
BUILD_COMMAND echo .
|
||||
INSTALL_COMMAND echo .
|
||||
)
|
||||
endmacro()
|
|
@ -0,0 +1,24 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(OCLOC_EXTRA_ARGS
|
||||
-DNEO_SKIP_UNIT_TESTS=1
|
||||
-DNEO_BUILD_WITH_OCL=0
|
||||
-DBUILD_WITH_L0=0
|
||||
-DIGC_DIR=${LIBDIR}/igc
|
||||
-DGMM_DIR=${LIBDIR}/gmmlib
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_ocloc
|
||||
URL file://${PACKAGE_DIR}/${OCLOC_FILE}
|
||||
URL_HASH ${OCLOC_HASH_TYPE}=${OCLOC_HASH}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
PREFIX ${BUILD_DIR}/ocloc
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/ocloc ${DEFAULT_CMAKE_FLAGS} ${OCLOC_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/ocloc
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_ocloc
|
||||
external_igc
|
||||
external_gmmlib
|
||||
)
|
|
@ -9,6 +9,7 @@ set(OIDN_EXTRA_ARGS
|
|||
-DOIDN_STATIC_RUNTIME=OFF
|
||||
-DISPC_EXECUTABLE=${LIBDIR}/ispc/bin/ispc
|
||||
-DOIDN_FILTER_RTLIGHTMAP=OFF
|
||||
-DPYTHON_EXECUTABLE=${PYTHON_BINARY}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
@ -38,6 +39,7 @@ add_dependencies(
|
|||
external_openimagedenoise
|
||||
external_tbb
|
||||
external_ispc
|
||||
external_python
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -38,6 +38,7 @@ message("BUILD_DIR = ${BUILD_DIR}")
|
|||
if(WIN32)
|
||||
set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/patch.exe)
|
||||
set(LIBEXT ".lib")
|
||||
set(SHAREDLIBEXT ".lib")
|
||||
set(LIBPREFIX "")
|
||||
|
||||
# For OIIO and OSL
|
||||
|
@ -96,6 +97,7 @@ if(WIN32)
|
|||
else()
|
||||
set(PATCH_CMD patch)
|
||||
set(LIBEXT ".a")
|
||||
set(SHAREDLIBEXT ".so")
|
||||
set(LIBPREFIX "lib")
|
||||
|
||||
if(APPLE)
|
||||
|
|
|
@ -147,7 +147,7 @@ set(OPENIMAGEIO_HASH de45fb38501c4581062b522b53b6141c)
|
|||
set(OPENIMAGEIO_HASH_TYPE MD5)
|
||||
set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz)
|
||||
|
||||
# 8.0.0 is currently oiio's preferred vesion although never versions may be available.
|
||||
# 8.0.0 is currently oiio's preferred version although never versions may be available.
|
||||
# the preferred version can be found in oiio's externalpackages.cmake
|
||||
set(FMT_VERSION 8.0.0)
|
||||
set(FMT_URI https://github.com/fmtlib/fmt/archive/refs/tags/${FMT_VERSION}.tar.gz)
|
||||
|
@ -155,7 +155,7 @@ set(FMT_HASH 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
|
|||
set(FMT_HASH_TYPE SHA256)
|
||||
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
|
||||
|
||||
# 0.6.2 is currently oiio's preferred vesion although never versions may be available.
|
||||
# 0.6.2 is currently oiio's preferred version although never versions may be available.
|
||||
# the preferred version can be found in oiio's externalpackages.cmake
|
||||
set(ROBINMAP_VERSION v0.6.2)
|
||||
set(ROBINMAP_URI https://github.com/Tessil/robin-map/archive/refs/tags/${ROBINMAP_VERSION}.tar.gz)
|
||||
|
@ -502,3 +502,134 @@ set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${
|
|||
set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617)
|
||||
set(LEVEL_ZERO_HASH_TYPE SHA256)
|
||||
set(LEVEL_ZERO_FILE level-zero-${LEVEL_ZERO_VERSION}.tar.gz)
|
||||
|
||||
set(DPCPP_VERSION 20220620)
|
||||
set(DPCPP_URI https://github.com/intel/llvm/archive/refs/tags/sycl-nightly/${DPCPP_VERSION}.tar.gz)
|
||||
set(DPCPP_HASH a5f41abd5229d28afa92cbd8a5d8d786ee698bf239f722929fd686276bad692c)
|
||||
set(DPCPP_HASH_TYPE SHA256)
|
||||
set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz)
|
||||
|
||||
########################
|
||||
### DPCPP DEPS BEGIN ###
|
||||
########################
|
||||
# The following deps are build time requirements for dpcpp, when possible
|
||||
# the source in the dpcpp source tree for the version chosen is documented
|
||||
# by each dep, these will only have to be downloaded and unpacked, dpcpp
|
||||
# will take care of building them, unpack is being done in dpcpp_deps.cmake
|
||||
|
||||
# Source llvm/lib/SYCLLowerIR/CMakeLists.txt
|
||||
set(VCINTRINSICS_VERSION 984bb27baacce6ee5c716c2e64845f2a1928025b)
|
||||
set(VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/${VCINTRINSICS_VERSION}.tar.gz)
|
||||
set(VCINTRINSICS_HASH abea415a15a0dd11fdc94dee8fb462910f2548311b787e02f42509789e1b0d7b)
|
||||
set(VCINTRINSICS_HASH_TYPE SHA256)
|
||||
set(VCINTRINSICS_FILE vc-intrinsics-${VCINTRINSICS_VERSION}.tar.gz)
|
||||
|
||||
# Source opencl/CMakeLists.txt
|
||||
set(OPENCLHEADERS_VERSION dcd5bede6859d26833cd85f0d6bbcee7382dc9b3)
|
||||
set(OPENCLHEADERS_URI https://github.com/KhronosGroup/OpenCL-Headers/archive/${OPENCLHEADERS_VERSION}.tar.gz)
|
||||
set(OPENCLHEADERS_HASH ca8090359654e94f2c41e946b7e9d826253d795ae809ce7c83a7d3c859624693)
|
||||
set(OPENCLHEADERS_HASH_TYPE SHA256)
|
||||
set(OPENCLHEADERS_FILE opencl_headers-${OPENCLHEADERS_VERSION}.tar.gz)
|
||||
|
||||
# Source opencl/CMakeLists.txt
|
||||
set(ICDLOADER_VERSION aec3952654832211636fc4af613710f80e203b0a)
|
||||
set(ICDLOADER_URI https://github.com/KhronosGroup/OpenCL-ICD-Loader/archive/${ICDLOADER_VERSION}.tar.gz)
|
||||
set(ICDLOADER_HASH e1880551d67bd8dc31d13de63b94bbfd6b1f315b6145dad1ffcd159b89bda93c)
|
||||
set(ICDLOADER_HASH_TYPE SHA256)
|
||||
set(ICDLOADER_FILE icdloader-${ICDLOADER_VERSION}.tar.gz)
|
||||
|
||||
# Source sycl/cmake/modules/AddBoostMp11Headers.cmake
|
||||
# Using external MP11 here, getting AddBoostMp11Headers.cmake to recognize
|
||||
# our copy in boost directly was more trouble than it was worth.
|
||||
set(MP11_VERSION 7bc4e1ae9b36ec8ee635c3629b59ec525bbe82b9)
|
||||
set(MP11_URI https://github.com/boostorg/mp11/archive/${MP11_VERSION}.tar.gz)
|
||||
set(MP11_HASH 071ee2bd3952ec89882edb3af25dd1816f6b61723f66e42eea32f4d02ceef426)
|
||||
set(MP11_HASH_TYPE SHA256)
|
||||
set(MP11_FILE mp11-${MP11_VERSION}.tar.gz)
|
||||
|
||||
# Source llvm-spirv/CMakeLists.txt (repo)
|
||||
# Source llvm-spirv/spirv-headers-tag.conf (hash)
|
||||
set(SPIRV_HEADERS_VERSION 36c0c1596225e728bd49abb7ef56a3953e7ed468)
|
||||
set(SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/${SPIRV_HEADERS_VERSION}.tar.gz)
|
||||
set(SPIRV_HEADERS_HASH 7a5c89633f8740456fe8adee052033e134476d267411d1336c0cb1e587a9229a)
|
||||
set(SPIRV_HEADERS_HASH_TYPE SHA256)
|
||||
set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
|
||||
|
||||
######################
|
||||
### DPCPP DEPS END ###
|
||||
######################
|
||||
|
||||
##########################################
|
||||
### Intel Graphics Compiler DEPS BEGIN ###
|
||||
##########################################
|
||||
# The following deps are build time requirements for the intel graphics
|
||||
# compiler, the versions used are taken from the following location
|
||||
# https://github.com/intel/intel-graphics-compiler/releases
|
||||
|
||||
set(IGC_VERSION 1.0.11222)
|
||||
set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz)
|
||||
set(IGC_HASH d92f0608dcbb52690855685f9447282e5c09c0ba98ae35fabf114fcf8b1e9fcf)
|
||||
set(IGC_HASH_TYPE SHA256)
|
||||
set(IGC_FILE igc-${IGC_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_LLVM_VERSION llvmorg-11.1.0)
|
||||
set(IGC_LLVM_URI https://github.com/llvm/llvm-project/archive/refs/tags/${IGC_LLVM_VERSION}.tar.gz)
|
||||
set(IGC_LLVM_HASH 53a0719f3f4b0388013cfffd7b10c7d5682eece1929a9553c722348d1f866e79)
|
||||
set(IGC_LLVM_HASH_TYPE SHA256)
|
||||
set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz)
|
||||
|
||||
# WARNING WARNING WARNING
|
||||
#
|
||||
# IGC_OPENCL_CLANG contains patches for some of its dependencies.
|
||||
#
|
||||
# Whenever IGC_OPENCL_CLANG_VERSION changes, one *MUST* inspect
|
||||
# IGC_OPENCL_CLANG's patches folder and update igc.cmake to account for
|
||||
# any added or removed patches.
|
||||
#
|
||||
# WARNING WARNING WARNING
|
||||
|
||||
set(IGC_OPENCL_CLANG_VERSION bbdd1587f577397a105c900be114b56755d1f7dc)
|
||||
set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz)
|
||||
set(IGC_OPENCL_CLANG_HASH d08315f1b0d8a6fef33de2b3e6aa7356534c324910634962c72523d970773efc)
|
||||
set(IGC_OPENCL_CLANG_HASH_TYPE SHA256)
|
||||
set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_VCINTRINSICS_VERSION v0.4.0)
|
||||
set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz)
|
||||
set(IGC_VCINTRINSICS_HASH c8b92682ad5031cf9d5b82a40e7d5c0e763cd9278660adbcaa69aab988e4b589)
|
||||
set(IGC_VCINTRINSICS_HASH_TYPE SHA256)
|
||||
set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_SPIRV_HEADERS_VERSION sdk-1.3.204.1)
|
||||
set(IGC_SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/refs/tags/${IGC_SPIRV_HEADERS_VERSION}.tar.gz)
|
||||
set(IGC_SPIRV_HEADERS_HASH 262864053968c217d45b24b89044a7736a32361894743dd6cfe788df258c746c)
|
||||
set(IGC_SPIRV_HEADERS_HASH_TYPE SHA256)
|
||||
set(IGC_SPIRV_HEADERS_FILE SPIR-V-Headers-${IGC_SPIRV_HEADERS_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_SPIRV_TOOLS_VERSION sdk-1.3.204.1)
|
||||
set(IGC_SPIRV_TOOLS_URI https://github.com/KhronosGroup/SPIRV-Tools/archive/refs/tags/${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
|
||||
set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc103b087335)
|
||||
set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256)
|
||||
set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_SPIRV_TRANSLATOR_VERSION 99420daab98998a7e36858befac9c5ed109d4920)
|
||||
set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
|
||||
set(IGC_SPIRV_TRANSLATOR_HASH 77dfb4ddb6bfb993535562c02ddea23f0a0d1c5a0258c1afe7e27c894ff783a8)
|
||||
set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256)
|
||||
set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
|
||||
|
||||
########################################
|
||||
### Intel Graphics Compiler DEPS END ###
|
||||
########################################
|
||||
|
||||
set(GMMLIB_VERSION intel-gmmlib-22.1.2)
|
||||
set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz)
|
||||
set(GMMLIB_HASH 3b9a6d5e7e3f5748b3d0a2fb0e980ae943907fece0980bd9c0508e71c838e334)
|
||||
set(GMMLIB_HASH_TYPE SHA256)
|
||||
set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz)
|
||||
|
||||
set(OCLOC_VERSION 22.20.23198)
|
||||
set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz)
|
||||
set(OCLOC_HASH ab22b8bf2560a57fdd3def0e35a62ca75991406f959c0263abb00cd6cd9ae998)
|
||||
set(OCLOC_HASH_TYPE SHA256)
|
||||
set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz)
|
||||
|
|
|
@ -465,7 +465,7 @@ TBB_VERSION="2020"
|
|||
TBB_VERSION_SHORT="2020"
|
||||
TBB_VERSION_UPDATE="_U3" # Used for source packages...
|
||||
TBB_VERSION_MIN="2018"
|
||||
TBB_VERSION_MEX="2022"
|
||||
TBB_VERSION_MEX="2021" # 2021 introduces 'oneTBB', which has lots of compatibility breakage with previous versions
|
||||
TBB_FORCE_BUILD=false
|
||||
TBB_FORCE_REBUILD=false
|
||||
TBB_SKIP=false
|
||||
|
@ -635,9 +635,6 @@ MP3LAME_DEV=""
|
|||
OPENJPEG_USE=false
|
||||
OPENJPEG_DEV=""
|
||||
|
||||
# Whether to use system GLEW or not (OpenSubDiv needs recent glew to work).
|
||||
NO_SYSTEM_GLEW=false
|
||||
|
||||
# Switch to english language, else some things (like check_package_DEB()) won't work!
|
||||
LANG_BACK=$LANG
|
||||
LANG=""
|
||||
|
@ -1193,7 +1190,7 @@ Those libraries should be available as packages in all recent distributions (opt
|
|||
* libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed).
|
||||
* libwayland-client0, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland)
|
||||
* libsqlite3, libzstd, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp, flex.
|
||||
* libsdl2, libglew, libpugixml, libpotrace, [libgmp], [libglewmx], fontconfig, [libharu/libhpdf].\""
|
||||
* libsdl2, libglew, libpugixml, libpotrace, [libgmp], fontconfig, [libharu/libhpdf].\""
|
||||
|
||||
DEPS_SPECIFIC_INFO="\"BUILDABLE DEPENDENCIES:
|
||||
|
||||
|
@ -1687,7 +1684,7 @@ compile_TBB() {
|
|||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
tbb_magic=0
|
||||
tbb_magic=1
|
||||
_init_tbb
|
||||
|
||||
# Force having own builds for the dependencies.
|
||||
|
@ -2696,14 +2693,13 @@ compile_OSD() {
|
|||
mkdir build
|
||||
cd build
|
||||
|
||||
if [ -d $INST/tbb ]; then
|
||||
cmake_d="$cmake_d $cmake_d -D TBB_LOCATION=$INST/tbb"
|
||||
fi
|
||||
cmake_d="-D CMAKE_BUILD_TYPE=Release"
|
||||
if [ -d $INST/tbb ]; then
|
||||
cmake_d="$cmake_d -D TBB_LOCATION=$INST/tbb"
|
||||
fi
|
||||
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
|
||||
# ptex is only needed when nicholas bishop is ready
|
||||
cmake_d="$cmake_d -D NO_PTEX=1"
|
||||
cmake_d="$cmake_d -D NO_CLEW=1 -D NO_CUDA=1 -D NO_OPENCL=1"
|
||||
cmake_d="$cmake_d -D NO_CLEW=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_GLEW=1"
|
||||
# maya plugin, docs, tutorials, regression tests and examples are not needed
|
||||
cmake_d="$cmake_d -D NO_MAYA=1 -D NO_DOC=1 -D NO_TUTORIALS=1 -D NO_REGRESSION=1 -DNO_EXAMPLES=1"
|
||||
|
||||
|
@ -3326,7 +3322,7 @@ compile_Embree() {
|
|||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled results!
|
||||
embree_magic=10
|
||||
embree_magic=11
|
||||
_init_embree
|
||||
|
||||
# Force having own builds for the dependencies.
|
||||
|
@ -3386,7 +3382,7 @@ compile_Embree() {
|
|||
|
||||
cmake_d="$cmake_d -D EMBREE_TASKING_SYSTEM=TBB"
|
||||
if [ -d $INST/tbb ]; then
|
||||
make_d="$make_d EMBREE_TBB_ROOT=$INST/tbb"
|
||||
cmake_d="$cmake_d -D EMBREE_TBB_ROOT=$INST/tbb"
|
||||
fi
|
||||
|
||||
cmake $cmake_d ../
|
||||
|
@ -3525,7 +3521,7 @@ compile_OIDN() {
|
|||
install_ISPC
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled results!
|
||||
oidn_magic=9
|
||||
oidn_magic=10
|
||||
_init_oidn
|
||||
|
||||
# Force having own builds for the dependencies.
|
||||
|
@ -3581,7 +3577,7 @@ compile_OIDN() {
|
|||
cmake_d="$cmake_d -D ISPC_DIR_HINT=$_ispc_path_bin"
|
||||
|
||||
if [ -d $INST/tbb ]; then
|
||||
make_d="$make_d TBB_ROOT=$INST/tbb"
|
||||
cmake_d="$cmake_d -D TBB_ROOT=$INST/tbb"
|
||||
fi
|
||||
|
||||
cmake $cmake_d ../
|
||||
|
@ -4062,7 +4058,6 @@ install_DEB() {
|
|||
libopenal-dev libglew-dev yasm \
|
||||
libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \
|
||||
libgmp-dev libpugixml-dev libpotrace-dev libhpdf-dev libzstd-dev libpystring-dev"
|
||||
# libglewmx-dev (broken in deb testing currently...)
|
||||
|
||||
VORBIS_USE=true
|
||||
OGG_USE=true
|
||||
|
@ -4171,7 +4166,7 @@ install_DEB() {
|
|||
fi
|
||||
fi
|
||||
|
||||
# Check cmake/glew versions and disable features for older distros.
|
||||
# Check cmake version and disable features for older distros.
|
||||
# This is so Blender can at least compile.
|
||||
PRINT ""
|
||||
_cmake=`get_package_version_DEB cmake`
|
||||
|
@ -4188,28 +4183,6 @@ install_DEB() {
|
|||
fi
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
_glew=`get_package_version_DEB libglew-dev`
|
||||
if [ -z $_glew ]; then
|
||||
# Stupid virtual package in Ubuntu 12.04 doesn't show version number...
|
||||
_glew=`apt-cache showpkg libglew-dev|tail -n1|awk '{print $2}'|sed 's/-.*//'`
|
||||
fi
|
||||
version_ge $_glew "1.9.0"
|
||||
if [ $? -eq 1 ]; then
|
||||
version_ge $_glew "1.7.0"
|
||||
if [ $? -eq 1 ]; then
|
||||
WARNING "OpenSubdiv disabled because GLEW-$_glew is not enough"
|
||||
WARNING "Blender will not use system GLEW library"
|
||||
OSD_SKIP=true
|
||||
NO_SYSTEM_GLEW=true
|
||||
else
|
||||
WARNING "OpenSubdiv will compile with GLEW-$_glew but with limited capability"
|
||||
WARNING "Blender will not use system GLEW library"
|
||||
NO_SYSTEM_GLEW=true
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
PRINT ""
|
||||
_do_compile_python=false
|
||||
if [ "$PYTHON_SKIP" = true ]; then
|
||||
|
@ -6290,12 +6263,6 @@ print_info() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ "$NO_SYSTEM_GLEW" = true ]; then
|
||||
_1="-D WITH_SYSTEM_GLEW=OFF"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
|
||||
if [ "$FFMPEG_SKIP" = false ]; then
|
||||
_1="-D WITH_CODEC_FFMPEG=ON"
|
||||
PRINT " $_1"
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
diff -Naur external_dpcpp.orig/sycl/source/CMakeLists.txt external_dpcpp/sycl/source/CMakeLists.txt
|
||||
--- external_dpcpp.orig/sycl/source/CMakeLists.txt 2022-05-20 04:19:45.067771362 +0000
|
||||
+++ external_dpcpp/sycl/source/CMakeLists.txt 2022-05-20 04:21:49.708025048 +0000
|
||||
@@ -66,10 +66,10 @@
|
||||
target_compile_options(${LIB_OBJ_NAME} PUBLIC
|
||||
-fvisibility=hidden -fvisibility-inlines-hidden)
|
||||
set(linker_script "${CMAKE_CURRENT_SOURCE_DIR}/ld-version-script.txt")
|
||||
- set(abi_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/abi_replacements_linux.txt")
|
||||
- target_link_libraries(
|
||||
- ${LIB_NAME} PRIVATE "-Wl,${abi_linker_script}")
|
||||
- set_target_properties(${LIB_NAME} PROPERTIES LINK_DEPENDS ${abi_linker_script})
|
||||
+# set(abi_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/abi_replacements_linux.txt")
|
||||
+# target_link_libraries(
|
||||
+# ${LIB_NAME} PRIVATE "-Wl,${abi_linker_script}")
|
||||
+# set_target_properties(${LIB_NAME} PROPERTIES LINK_DEPENDS ${abi_linker_script})
|
||||
target_link_libraries(
|
||||
${LIB_NAME} PRIVATE "-Wl,--version-script=${linker_script}")
|
||||
set_target_properties(${LIB_NAME} PROPERTIES LINK_DEPENDS ${linker_script})
|
||||
diff -Naur llvm-sycl-nightly-20220501.orig\opencl/CMakeLists.txt llvm-sycl-nightly-20220501\opencl/CMakeLists.txt
|
||||
--- llvm-sycl-nightly-20220501.orig/opencl/CMakeLists.txt 2022-04-29 13:47:11 -0600
|
||||
+++ llvm-sycl-nightly-20220501/opencl/CMakeLists.txt 2022-05-21 15:25:06 -0600
|
||||
@@ -11,6 +11,11 @@
|
||||
)
|
||||
endif()
|
||||
|
||||
+# Blender code below is determined to use FetchContent_Declare
|
||||
+# temporarily allow it (but feed it our downloaded tarball
|
||||
+# in the OpenCL_HEADERS variable
|
||||
+set(FETCHCONTENT_FULLY_DISCONNECTED OFF)
|
||||
+
|
||||
# Repo URLs
|
||||
|
||||
set(OCL_HEADERS_REPO
|
||||
@@ -77,5 +82,6 @@
|
||||
|
||||
FetchContent_MakeAvailable(ocl-icd)
|
||||
add_library(OpenCL-ICD ALIAS OpenCL)
|
||||
+set(FETCHCONTENT_FULLY_DISCONNECTED ON)
|
||||
|
||||
add_subdirectory(opencl-aot)
|
||||
diff -Naur llvm-sycl-nightly-20220208.orig/libdevice/cmake/modules/SYCLLibdevice.cmake llvm-sycl-nightly-20220208/libdevice/cmake/modules/SYCLLibdevice.cmake
|
||||
--- llvm-sycl-nightly-20220208.orig/libdevice/cmake/modules/SYCLLibdevice.cmake 2022-02-08 09:17:24 -0700
|
||||
+++ llvm-sycl-nightly-20220208/libdevice/cmake/modules/SYCLLibdevice.cmake 2022-05-24 11:35:51 -0600
|
||||
@@ -36,7 +36,9 @@
|
||||
add_custom_target(libsycldevice-obj)
|
||||
add_custom_target(libsycldevice-spv)
|
||||
|
||||
-add_custom_target(libsycldevice DEPENDS
|
||||
+# Blender: add ALL here otherwise this target will not build
|
||||
+# and cause an error due to missing files during the install phase.
|
||||
+add_custom_target(libsycldevice ALL DEPENDS
|
||||
libsycldevice-obj
|
||||
libsycldevice-spv)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
diff --git a/configure.ac b/configure.ac
|
||||
index c6f12d644..3c977a4e3 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -25,8 +25,10 @@
|
||||
# autoconf requirements and initialization
|
||||
|
||||
AC_INIT([the fast lexical analyser generator],[2.6.4],[flex-help@lists.sourceforge.net],[flex])
|
||||
+AC_PREREQ([2.60])
|
||||
AC_CONFIG_SRCDIR([src/scan.l])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
+AC_USE_SYSTEM_EXTENSIONS
|
||||
LT_INIT
|
||||
AM_INIT_AUTOMAKE([1.15 -Wno-portability foreign std-options dist-lzip parallel-tests subdir-objects])
|
||||
AC_CONFIG_HEADER([src/config.h])
|
|
@ -0,0 +1,44 @@
|
|||
diff -Naur external_igc_opencl_clang.orig/CMakeLists.txt external_igc_opencl_clang/CMakeLists.txt
|
||||
--- external_igc_opencl_clang.orig/CMakeLists.txt 2022-03-16 05:51:10 -0600
|
||||
+++ external_igc_opencl_clang/CMakeLists.txt 2022-05-23 10:40:09 -0600
|
||||
@@ -126,22 +126,24 @@
|
||||
)
|
||||
endif()
|
||||
|
||||
-
|
||||
- set(SPIRV_BASE_REVISION llvm_release_110)
|
||||
- set(TARGET_BRANCH "ocl-open-110")
|
||||
- get_filename_component(LLVM_MONOREPO_DIR ${LLVM_SOURCE_DIR} DIRECTORY)
|
||||
- set(LLVM_PATCHES_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm
|
||||
- ${CMAKE_CURRENT_SOURCE_DIR}/patches/clang)
|
||||
- apply_patches(${LLVM_MONOREPO_DIR}
|
||||
- "${LLVM_PATCHES_DIRS}"
|
||||
- ${LLVM_BASE_REVISION}
|
||||
- ${TARGET_BRANCH}
|
||||
- ret)
|
||||
- apply_patches(${SPIRV_SOURCE_DIR}
|
||||
- ${CMAKE_CURRENT_SOURCE_DIR}/patches/spirv
|
||||
- ${SPIRV_BASE_REVISION}
|
||||
- ${TARGET_BRANCH}
|
||||
- ret)
|
||||
+ #
|
||||
+ # Blender: Why apply these manually in igc.cmake
|
||||
+ #
|
||||
+ #set(SPIRV_BASE_REVISION llvm_release_110)
|
||||
+ #set(TARGET_BRANCH "ocl-open-110")
|
||||
+ #get_filename_component(LLVM_MONOREPO_DIR ${LLVM_SOURCE_DIR} DIRECTORY)
|
||||
+ #set(LLVM_PATCHES_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm
|
||||
+ # ${CMAKE_CURRENT_SOURCE_DIR}/patches/clang)
|
||||
+ #apply_patches(${LLVM_MONOREPO_DIR}
|
||||
+ # "${LLVM_PATCHES_DIRS}"
|
||||
+ # ${LLVM_BASE_REVISION}
|
||||
+ # ${TARGET_BRANCH}
|
||||
+ # ret)
|
||||
+ #apply_patches(${SPIRV_SOURCE_DIR}
|
||||
+ # ${CMAKE_CURRENT_SOURCE_DIR}/patches/spirv
|
||||
+ # ${SPIRV_BASE_REVISION}
|
||||
+ # ${TARGET_BRANCH}
|
||||
+ # ret)
|
||||
endif(NOT USE_PREBUILT_LLVM)
|
||||
|
||||
#
|
|
@ -48,10 +48,13 @@ if "%4" == "nobuild" set dobuild=0
|
|||
|
||||
REM If Python is be available certain deps may try to
|
||||
REM to use this over the version we build, to prevent that
|
||||
REM make sure python is NOT in the path
|
||||
for %%X in (python.exe) do (set PYTHON=%%~$PATH:X)
|
||||
if EXIST "%PYTHON%" (
|
||||
echo PYTHON found at %PYTHON% dependencies cannot be build with python available in the path
|
||||
REM make sure pythonw is NOT in the path. We look for pythonw.exe
|
||||
REM since windows apparently ships a python.exe that just opens up
|
||||
REM the windows store but does not ship any actual python files that
|
||||
REM could cause issues.
|
||||
for %%X in (pythonw.exe) do (set PYTHONW=%%~$PATH:X)
|
||||
if EXIST "%PYTHONW%" (
|
||||
echo PYTHON found at %PYTHONW% dependencies cannot be build with python available in the path
|
||||
goto exit
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright 2021-2022 Intel Corporation
|
||||
|
||||
# - Find Level Zero library
|
||||
# Find Level Zero headers and libraries needed by oneAPI implementation
|
||||
# This module defines
|
||||
# LEVEL_ZERO_LIBRARY, libraries to link against in order to use L0.
|
||||
# LEVEL_ZERO_INCLUDE_DIR, directories where L0 headers can be found.
|
||||
# LEVEL_ZERO_ROOT_DIR, The base directory to search for L0 files.
|
||||
# This can also be an environment variable.
|
||||
# LEVEL_ZERO_FOUND, If false, then don't try to use L0.
|
||||
|
||||
IF(NOT LEVEL_ZERO_ROOT_DIR AND NOT $ENV{LEVEL_ZERO_ROOT_DIR} STREQUAL "")
|
||||
SET(LEVEL_ZERO_ROOT_DIR $ENV{LEVEL_ZERO_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_level_zero_search_dirs
|
||||
${LEVEL_ZERO_ROOT_DIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
|
||||
FIND_LIBRARY(_LEVEL_ZERO_LIBRARY
|
||||
NAMES
|
||||
ze_loader
|
||||
HINTS
|
||||
${_level_zero_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
FIND_PATH(_LEVEL_ZERO_INCLUDE_DIR
|
||||
NAMES
|
||||
level_zero/ze_api.h
|
||||
HINTS
|
||||
${_level_zero_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LevelZero DEFAULT_MSG _LEVEL_ZERO_LIBRARY _LEVEL_ZERO_INCLUDE_DIR)
|
||||
|
||||
IF(LevelZero_FOUND)
|
||||
SET(LEVEL_ZERO_LIBRARY ${_LEVEL_ZERO_LIBRARY})
|
||||
SET(LEVEL_ZERO_INCLUDE_DIR ${_LEVEL_ZERO_INCLUDE_DIR} ${_LEVEL_ZERO_INCLUDE_PARENT_DIR})
|
||||
SET(LEVEL_ZERO_FOUND TRUE)
|
||||
ELSE()
|
||||
SET(LEVEL_ZERO_FOUND FALSE)
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
LEVEL_ZERO_LIBRARY
|
||||
LEVEL_ZERO_INCLUDE_DIR
|
||||
)
|
|
@ -0,0 +1,88 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright 2021-2022 Intel Corporation
|
||||
|
||||
# - Find SYCL library
|
||||
# Find the native SYCL header and libraries needed by oneAPI implementation
|
||||
# This module defines
|
||||
# SYCL_COMPILER, compiler which will be used for compilation of SYCL code
|
||||
# SYCL_LIBRARY, libraries to link against in order to use SYCL.
|
||||
# SYCL_INCLUDE_DIR, directories where SYCL headers can be found
|
||||
# SYCL_ROOT_DIR, The base directory to search for SYCL files.
|
||||
# This can also be an environment variable.
|
||||
# SYCL_FOUND, If false, then don't try to use SYCL.
|
||||
|
||||
IF(NOT SYCL_ROOT_DIR AND NOT $ENV{SYCL_ROOT_DIR} STREQUAL "")
|
||||
SET(SYCL_ROOT_DIR $ENV{SYCL_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_sycl_search_dirs
|
||||
${SYCL_ROOT_DIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/intel/oneapi/compiler/latest/linux/
|
||||
C:/Program\ Files\ \(x86\)/Intel/oneAPI/compiler/latest/windows
|
||||
)
|
||||
|
||||
# Find DPC++ compiler.
|
||||
# Since the compiler name is possibly conflicting with the system-wide
|
||||
# CLang start with looking for either dpcpp or clang binary in the given
|
||||
# list of search paths only. If that fails, try to look for a system-wide
|
||||
# dpcpp binary.
|
||||
FIND_PROGRAM(SYCL_COMPILER
|
||||
NAMES
|
||||
dpcpp
|
||||
clang++
|
||||
HINTS
|
||||
${_sycl_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
bin
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
NAMES_PER_DIR
|
||||
)
|
||||
|
||||
# NOTE: No clang++ here so that we do not pick up a system-wide CLang
|
||||
# compiler.
|
||||
if(NOT SYCL_COMPILER)
|
||||
FIND_PROGRAM(SYCL_COMPILER
|
||||
NAMES
|
||||
dpcpp
|
||||
HINTS
|
||||
${_sycl_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
bin
|
||||
)
|
||||
endif()
|
||||
|
||||
FIND_LIBRARY(SYCL_LIBRARY
|
||||
NAMES
|
||||
sycl
|
||||
HINTS
|
||||
${_sycl_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
FIND_PATH(SYCL_INCLUDE_DIR
|
||||
NAMES
|
||||
CL/sycl.hpp
|
||||
HINTS
|
||||
${_sycl_search_dirs}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
include/sycl
|
||||
)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR)
|
||||
|
||||
IF(SYCL_FOUND)
|
||||
get_filename_component(_SYCL_INCLUDE_PARENT_DIR ${SYCL_INCLUDE_DIR} DIRECTORY)
|
||||
SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${_SYCL_INCLUDE_PARENT_DIR})
|
||||
ELSE()
|
||||
SET(SYCL_SYCL_FOUND FALSE)
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
_SYCL_INCLUDE_PARENT_DIR
|
||||
)
|
|
@ -70,7 +70,8 @@ if(NOT WIN32)
|
|||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
if(WIN32)
|
||||
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_DEVICE_ONEAPI ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
|
||||
|
@ -78,6 +79,11 @@ if(UNIX AND NOT APPLE)
|
|||
set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
|
||||
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Disable oneAPI on Linux for the time being.
|
||||
# The AoT compilation takes too long to be used officially in the buildbot CI/CD and the JIT
|
||||
# compilation has ABI compatibility issues when running builds made on centOS on Ubuntu.
|
||||
set(WITH_CYCLES_DEVICE_ONEAPI OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
if(NOT APPLE)
|
||||
set(WITH_XR_OPENXR ON CACHE BOOL "" FORCE)
|
||||
|
@ -86,4 +92,7 @@ if(NOT APPLE)
|
|||
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Disable AoT kernels compilations until buildbot can deliver them in a reasonabel time.
|
||||
set(WITH_CYCLES_ONEAPI_BINARIES OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
|
|
@ -38,9 +38,15 @@ if(EXISTS ${LIBDIR})
|
|||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||
|
||||
file(GLOB LIB_SUBDIRS ${LIBDIR}/*)
|
||||
|
||||
# Ignore Mesa software OpenGL libraries, they are not intended to be
|
||||
# linked against but to optionally override at runtime.
|
||||
list(REMOVE_ITEM LIB_SUBDIRS ${LIBDIR}/mesa)
|
||||
|
||||
# Ignore DPC++ as it contains its own copy of LLVM/CLang which we do
|
||||
# not need to be ever discovered for the Blender linking.
|
||||
list(REMOVE_ITEM LIB_SUBDIRS ${LIBDIR}/dpcpp)
|
||||
|
||||
# NOTE: Make sure "proper" compiled zlib comes first before the one
|
||||
# which is a part of OpenCollada. They have different ABI, and we
|
||||
# do need to use the official one.
|
||||
|
@ -271,6 +277,18 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEVICE_ONEAPI)
|
||||
set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation")
|
||||
if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR)
|
||||
set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO})
|
||||
endif()
|
||||
|
||||
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to DPC++ and SYCL installation")
|
||||
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
|
||||
set(SYCL_ROOT_DIR ${CYCLES_SYCL})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENVDB)
|
||||
find_package_wrapper(OpenVDB)
|
||||
find_package_wrapper(Blosc)
|
||||
|
@ -613,17 +631,35 @@ if(WITH_GHOST_WAYLAND)
|
|||
pkg_check_modules(wayland-scanner REQUIRED wayland-scanner)
|
||||
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
||||
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
||||
pkg_check_modules(dbus REQUIRED dbus-1)
|
||||
|
||||
set(WITH_GL_EGL ON)
|
||||
if(WITH_GHOST_WAYLAND_DBUS)
|
||||
pkg_check_modules(dbus REQUIRED dbus-1)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
pkg_check_modules(libdecor REQUIRED libdecor-0>=0.1)
|
||||
endif()
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${wayland-client_LINK_LIBRARIES}
|
||||
${wayland-egl_LINK_LIBRARIES}
|
||||
${xkbcommon_LINK_LIBRARIES}
|
||||
${wayland-cursor_LINK_LIBRARIES}
|
||||
${dbus_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
if(WITH_GHOST_WAYLAND_DBUS)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${dbus_LINK_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_DBUS)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${libdecor_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
|
|
|
@ -950,3 +950,6 @@ endif()
|
|||
|
||||
set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include)
|
||||
set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib)
|
||||
|
||||
set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero)
|
||||
set(SYCL_ROOT_DIR ${LIBDIR}/dpcpp)
|
||||
|
|
|
@ -54,6 +54,8 @@ buildbot:
|
|||
version: '10.1.243'
|
||||
cuda11:
|
||||
version: '11.4.1'
|
||||
hip:
|
||||
version: '5.2.21440'
|
||||
optix:
|
||||
version: '7.3.0'
|
||||
cmake:
|
||||
|
|
|
@ -1,59 +1,111 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
Dump the python API into a text file so we can generate changelogs.
|
||||
---------------
|
||||
|
||||
output from this tool should be added into "doc/python_api/rst/change_log.rst"
|
||||
Dump the python API into a JSON file, or generate changelogs from those JSON API dumps.
|
||||
|
||||
# dump api blender_version.py in CWD
|
||||
blender --background --python doc/python_api/sphinx_changelog_gen.py -- --dump
|
||||
Typically, changelog output from this tool should be added into "doc/python_api/rst/change_log.rst"
|
||||
|
||||
# create changelog
|
||||
API dump files are saved together with the generated API doc on the server, with a general index file.
|
||||
This way the changelog generation simply needs to re-download the previous version's dump for the diffing process.
|
||||
|
||||
---------------
|
||||
|
||||
# Dump api blender_version.json in CWD:
|
||||
blender --background --factory-startup --python doc/python_api/sphinx_changelog_gen.py -- \
|
||||
--indexpath="path/to/api/docs/api_dump_index.json" \
|
||||
dump --filepath-out="path/to/api/docs/<version>/api_dump.json"
|
||||
|
||||
# Create changelog:
|
||||
blender --background --factory-startup --python doc/python_api/sphinx_changelog_gen.py -- \
|
||||
--api_from blender_2_63_0.py \
|
||||
--api_to blender_2_64_0.py \
|
||||
--api_out changes.rst
|
||||
--indexpath="path/to/api/docs/api_dump_index.json" \
|
||||
changelog --filepath-out doc/python_api/rst/change_log.rst
|
||||
|
||||
|
||||
# Api comparison can also run without blender
|
||||
# Api comparison can also run without blender,
|
||||
# will by default generate changeloig between the last two available versions listed in the index,
|
||||
# unless input files are provided explicitely:
|
||||
python doc/python_api/sphinx_changelog_gen.py -- \
|
||||
--api_from blender_api_2_63_0.py \
|
||||
--api_to blender_api_2_64_0.py \
|
||||
--api_out changes.rst
|
||||
--indexpath="path/to/api/docs/api_dump_index.json" \
|
||||
changelog --filepath-in-from blender_api_2_63_0.json \
|
||||
--filepath-in-to blender_api_2_64_0.json \
|
||||
--filepath-out changes.rst
|
||||
|
||||
# Save the latest API dump in this folder, renaming it with its revision.
|
||||
# This way the next person updating it doesn't need to build an old Blender only for that
|
||||
--------------
|
||||
|
||||
API dump index format:
|
||||
|
||||
{[version_main, version_sub]: "<version>/api_dump.json", ...
|
||||
}
|
||||
|
||||
API dump format:
|
||||
|
||||
[
|
||||
[version_main, vserion_sub, version_path],
|
||||
{"module.name":
|
||||
{"parent.class":
|
||||
{"basic_type", "member_name":
|
||||
["Name", type, range, length, default, descr, f_args, f_arg_types, f_ret_types]}, ...
|
||||
}, ...
|
||||
}
|
||||
]
|
||||
|
||||
"""
|
||||
|
||||
# format
|
||||
'''
|
||||
{"module.name":
|
||||
{"parent.class":
|
||||
{"basic_type", "member_name":
|
||||
("Name", type, range, length, default, descr, f_args, f_arg_types, f_ret_types)}, ...
|
||||
}, ...
|
||||
}
|
||||
'''
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
api_names = "basic_type" "name", "type", "range", "length", "default", "descr", "f_args", "f_arg_types", "f_ret_types"
|
||||
|
||||
API_BASIC_TYPE = 0
|
||||
API_F_ARGS = 7
|
||||
|
||||
|
||||
def api_dunp_fname():
|
||||
import bpy
|
||||
return "blender_api_%s.py" % "_".join([str(i) for i in bpy.app.version])
|
||||
def api_version():
|
||||
try:
|
||||
import bpy
|
||||
except:
|
||||
return None, None
|
||||
version = tuple(bpy.app.version[:2])
|
||||
version_key = "%d.%d" % (version[0], version[1])
|
||||
return version, version_key
|
||||
|
||||
|
||||
def api_dump():
|
||||
dump = {}
|
||||
dump_module = dump["bpy.types"] = {}
|
||||
def api_version_previous_in_index(index, version):
|
||||
print("Searching for previous version to %s in %r" % (version, index))
|
||||
version_prev = (version[0], version[1])
|
||||
while True:
|
||||
version_prev = (version_prev[0], version_prev[1] - 1)
|
||||
if version_prev[1] < 0:
|
||||
version_prev = (version_prev[0] - 1, 99)
|
||||
if version_prev[0] < 0:
|
||||
return None, None
|
||||
version_prev_key = "%d.%d" % (version_prev[0], version_prev[1])
|
||||
if version_prev_key in index:
|
||||
print("Found previous version %s: %r" % (version_prev, index[version_prev_key]))
|
||||
return version_prev, version_prev_key
|
||||
|
||||
|
||||
class JSONEncoderAPIDump(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if o is ...:
|
||||
return "..."
|
||||
if isinstance(o, set):
|
||||
return tuple(o)
|
||||
return json.JSONEncoder.default(self, o)
|
||||
|
||||
|
||||
def api_dump(args):
|
||||
import rna_info
|
||||
import inspect
|
||||
|
||||
version, version_key = api_version()
|
||||
if version is None:
|
||||
raise(ValueError("API dumps can only be generated from within Blender."))
|
||||
|
||||
dump = {}
|
||||
dump_module = dump["bpy.types"] = {}
|
||||
|
||||
struct = rna_info.BuildRNAInfo()[0]
|
||||
for struct_id, struct_info in sorted(struct.items()):
|
||||
|
||||
|
@ -155,17 +207,25 @@ def api_dump():
|
|||
)
|
||||
del funcs
|
||||
|
||||
import pprint
|
||||
filepath_out = args.filepath_out
|
||||
with open(filepath_out, 'w', encoding='utf-8') as file_handle:
|
||||
json.dump((version, dump), file_handle, cls=JSONEncoderAPIDump)
|
||||
|
||||
filename = api_dunp_fname()
|
||||
filehandle = open(filename, 'w', encoding='utf-8')
|
||||
tot = filehandle.write(pprint.pformat(dump, width=1))
|
||||
filehandle.close()
|
||||
print("%s, %d bytes written" % (filename, tot))
|
||||
indexpath = args.indexpath
|
||||
rootpath = os.path.dirname(indexpath)
|
||||
if os.path.exists(indexpath):
|
||||
with open(indexpath, 'r', encoding='utf-8') as file_handle:
|
||||
index = json.load(file_handle)
|
||||
else:
|
||||
index = {}
|
||||
index[version_key] = os.path.relpath(filepath_out, rootpath)
|
||||
with open(indexpath, 'w', encoding='utf-8') as file_handle:
|
||||
json.dump(index, file_handle)
|
||||
|
||||
print("API version %s dumped into %r, and index %r has been updated" % (version_key, filepath_out, indexpath))
|
||||
|
||||
|
||||
def compare_props(a, b, fuzz=0.75):
|
||||
|
||||
# must be same basic_type, function != property
|
||||
if a[0] != b[0]:
|
||||
return False
|
||||
|
@ -180,15 +240,44 @@ def compare_props(a, b, fuzz=0.75):
|
|||
return ((tot / totlen) >= fuzz)
|
||||
|
||||
|
||||
def api_changelog(api_from, api_to, api_out):
|
||||
def api_changelog(args):
|
||||
indexpath = args.indexpath
|
||||
filepath_in_from = args.filepath_in_from
|
||||
filepath_in_to = args.filepath_in_to
|
||||
filepath_out = args.filepath_out
|
||||
|
||||
file_handle = open(api_from, 'r', encoding='utf-8')
|
||||
dict_from = eval(file_handle.read())
|
||||
file_handle.close()
|
||||
rootpath = os.path.dirname(indexpath)
|
||||
|
||||
file_handle = open(api_to, 'r', encoding='utf-8')
|
||||
dict_to = eval(file_handle.read())
|
||||
file_handle.close()
|
||||
version, version_key = api_version()
|
||||
if version is None and (filepath_in_from is None or filepath_in_to is None):
|
||||
raise(ValueError("API dumps files must be given when ran outside of Blender."))
|
||||
|
||||
with open(indexpath, 'r', encoding='utf-8') as file_handle:
|
||||
index = json.load(file_handle)
|
||||
|
||||
if filepath_in_to is None:
|
||||
filepath_in_to = index.get(version_key, None)
|
||||
if filepath_in_to is None:
|
||||
raise(ValueError("Cannot find API dump file for Blender version " + str(version) + " in index file."))
|
||||
|
||||
print("Found to file: %r" % filepath_in_to)
|
||||
|
||||
if filepath_in_from is None:
|
||||
version_from, version_from_key = api_version_previous_in_index(index, version)
|
||||
if version_from is None:
|
||||
raise(ValueError("No previous version of Blender could be found in the index."))
|
||||
filepath_in_from = index.get(version_from_key, None)
|
||||
if filepath_in_from is None:
|
||||
raise(ValueError("Cannot find API dump file for previous Blender version " + str(version_from) + " in index file."))
|
||||
|
||||
print("Found from file: %r" % filepath_in_from)
|
||||
|
||||
with open(os.path.join(rootpath, filepath_in_from), 'r', encoding='utf-8') as file_handle:
|
||||
_, dict_from = json.load(file_handle)
|
||||
|
||||
with open(os.path.join(rootpath, filepath_in_to), 'r', encoding='utf-8') as file_handle:
|
||||
dump_version, dict_to = json.load(file_handle)
|
||||
assert(tuple(dump_version) == version)
|
||||
|
||||
api_changes = []
|
||||
|
||||
|
@ -249,63 +338,66 @@ def api_changelog(api_from, api_to, api_out):
|
|||
|
||||
# also document function argument changes
|
||||
|
||||
fout = open(api_out, 'w', encoding='utf-8')
|
||||
fw = fout.write
|
||||
# print(api_changes)
|
||||
with open(filepath_out, 'w', encoding='utf-8') as fout:
|
||||
fw = fout.write
|
||||
|
||||
# :class:`bpy_struct.id_data`
|
||||
# Write header.
|
||||
fw(""
|
||||
":tocdepth: 2\n"
|
||||
"\n"
|
||||
"Blender API Change Log\n"
|
||||
"**********************\n"
|
||||
"\n"
|
||||
".. note, this document is auto generated by sphinx_changelog_gen.py\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"%s to %s\n"
|
||||
"============\n"
|
||||
"\n" % (version_from_key, version_key))
|
||||
|
||||
def write_title(title, title_char):
|
||||
fw("%s\n%s\n\n" % (title, title_char * len(title)))
|
||||
def write_title(title, title_char):
|
||||
fw("%s\n%s\n\n" % (title, title_char * len(title)))
|
||||
|
||||
for mod_id, class_id, props_moved, props_new, props_old, func_args in api_changes:
|
||||
class_name = class_id.split(".")[-1]
|
||||
title = mod_id + "." + class_name
|
||||
write_title(title, "-")
|
||||
for mod_id, class_id, props_moved, props_new, props_old, func_args in api_changes:
|
||||
class_name = class_id.split(".")[-1]
|
||||
title = mod_id + "." + class_name
|
||||
write_title(title, "-")
|
||||
|
||||
if props_new:
|
||||
write_title("Added", "^")
|
||||
for prop_id in props_new:
|
||||
fw("* :class:`%s.%s.%s`\n" % (mod_id, class_name, prop_id))
|
||||
fw("\n")
|
||||
if props_new:
|
||||
write_title("Added", "^")
|
||||
for prop_id in props_new:
|
||||
fw("* :class:`%s.%s.%s`\n" % (mod_id, class_name, prop_id))
|
||||
fw("\n")
|
||||
|
||||
if props_old:
|
||||
write_title("Removed", "^")
|
||||
for prop_id in props_old:
|
||||
fw("* **%s**\n" % prop_id) # can't link to removed docs
|
||||
fw("\n")
|
||||
if props_old:
|
||||
write_title("Removed", "^")
|
||||
for prop_id in props_old:
|
||||
fw("* **%s**\n" % prop_id) # can't link to removed docs
|
||||
fw("\n")
|
||||
|
||||
if props_moved:
|
||||
write_title("Renamed", "^")
|
||||
for prop_id_old, prop_id in props_moved:
|
||||
fw("* **%s** -> :class:`%s.%s.%s`\n" % (prop_id_old, mod_id, class_name, prop_id))
|
||||
fw("\n")
|
||||
if props_moved:
|
||||
write_title("Renamed", "^")
|
||||
for prop_id_old, prop_id in props_moved:
|
||||
fw("* **%s** -> :class:`%s.%s.%s`\n" % (prop_id_old, mod_id, class_name, prop_id))
|
||||
fw("\n")
|
||||
|
||||
if func_args:
|
||||
write_title("Function Arguments", "^")
|
||||
for func_id, args_old, args_new in func_args:
|
||||
args_new = ", ".join(args_new)
|
||||
args_old = ", ".join(args_old)
|
||||
fw("* :class:`%s.%s.%s` (%s), *was (%s)*\n" % (mod_id, class_name, func_id, args_new, args_old))
|
||||
fw("\n")
|
||||
if func_args:
|
||||
write_title("Function Arguments", "^")
|
||||
for func_id, args_old, args_new in func_args:
|
||||
args_new = ", ".join(args_new)
|
||||
args_old = ", ".join(args_old)
|
||||
fw("* :class:`%s.%s.%s` (%s), *was (%s)*\n" % (mod_id, class_name, func_id, args_new, args_old))
|
||||
fw("\n")
|
||||
|
||||
fout.close()
|
||||
|
||||
print("Written: %r" % api_out)
|
||||
print("Written: %r" % filepath_out)
|
||||
|
||||
|
||||
def main():
|
||||
def main(argv=None):
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
|
||||
try:
|
||||
import argparse
|
||||
except ImportError:
|
||||
print("Old Blender, just dumping")
|
||||
api_dump()
|
||||
return
|
||||
|
||||
argv = sys.argv
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
|
||||
if "--" not in argv:
|
||||
argv = [] # as if no args are passed
|
||||
|
@ -316,42 +408,42 @@ def main():
|
|||
usage_text = "Run blender in background mode with this script: "
|
||||
"blender --background --factory-startup --python %s -- [options]" % os.path.basename(__file__)
|
||||
|
||||
epilog = "Run this before releases"
|
||||
|
||||
parser = argparse.ArgumentParser(description=usage_text, epilog=epilog)
|
||||
|
||||
parser = argparse.ArgumentParser(description=usage_text,
|
||||
epilog=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument(
|
||||
"--dump", dest="dump", action='store_true',
|
||||
help="When set the api will be dumped into blender_version.py")
|
||||
"--indexpath", dest="indexpath", metavar='FILE', required=True,
|
||||
help="Path of the JSON file containing the index of all available API dumps.")
|
||||
|
||||
parser.add_argument(
|
||||
"--api_from", dest="api_from", metavar='FILE',
|
||||
help="File to compare from (previous version)")
|
||||
parser.add_argument(
|
||||
"--api_to", dest="api_to", metavar='FILE',
|
||||
help="File to compare from (current)")
|
||||
parser.add_argument(
|
||||
"--api_out", dest="api_out", metavar='FILE',
|
||||
help="Output sphinx changelog")
|
||||
parser_commands = parser.add_subparsers(required=True)
|
||||
|
||||
args = parser.parse_args(argv) # In this example we won't use the args
|
||||
parser_dump = parser_commands.add_parser('dump', help="Dump the current Blender Python API into a JSON file.")
|
||||
parser_dump.add_argument(
|
||||
"--filepath-out", dest="filepath_out", metavar='FILE', required=True,
|
||||
help="Path of the JSON file containing the dump of the API.")
|
||||
parser_dump.set_defaults(func=api_dump)
|
||||
|
||||
if not argv:
|
||||
print("No args given!")
|
||||
parser.print_help()
|
||||
return
|
||||
parser_changelog = parser_commands.add_parser(
|
||||
'changelog',
|
||||
help="Generate the RST changelog page based on two Blender Python API JSON dumps.",
|
||||
)
|
||||
|
||||
if args.dump:
|
||||
api_dump()
|
||||
else:
|
||||
if args.api_from and args.api_to and args.api_out:
|
||||
api_changelog(args.api_from, args.api_to, args.api_out)
|
||||
else:
|
||||
print("Error: --api_from/api_to/api_out args needed")
|
||||
parser.print_help()
|
||||
return
|
||||
parser_changelog.add_argument(
|
||||
"--filepath-in-from", dest="filepath_in_from", metavar='FILE', default=None,
|
||||
help="JSON dump file to compare from (typically, previous version). "
|
||||
"If not given, will be automatically determined from current Blender version and index file.")
|
||||
parser_changelog.add_argument(
|
||||
"--filepath-in-to", dest="filepath_in_to", metavar='FILE', default=None,
|
||||
help="JSON dump file to compare to (typically, current version). "
|
||||
"If not given, will be automatically determined from current Blender version and index file.")
|
||||
parser_changelog.add_argument(
|
||||
"--filepath-out", dest="filepath_out", metavar='FILE', required=True,
|
||||
help="Output sphinx changelog RST file.")
|
||||
parser_changelog.set_defaults(func=api_changelog)
|
||||
|
||||
print("batch job finished, exiting")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
args.func(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -141,6 +141,26 @@ def handle_args():
|
|||
required=False,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--api-changelog-generate",
|
||||
dest="changelog",
|
||||
default=False,
|
||||
action='store_true',
|
||||
help="Generate the API changelog RST file "
|
||||
"(default=False, requires `--api-dump-index-path` parameter)",
|
||||
required=False,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--api-dump-index-path",
|
||||
dest="api_dump_index_path",
|
||||
metavar='FILE',
|
||||
default=None,
|
||||
help="Path to the API dump index JSON file "
|
||||
"(required when `--api-changelog-generate` is True)",
|
||||
required=False,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-o", "--output",
|
||||
dest="output_dir",
|
||||
|
@ -514,6 +534,42 @@ if ARGS.sphinx_build_pdf:
|
|||
sphinx_make_pdf_log = os.path.join(ARGS.output_dir, ".latex_make.log")
|
||||
SPHINX_MAKE_PDF_STDOUT = open(sphinx_make_pdf_log, "w", encoding="utf-8")
|
||||
|
||||
|
||||
# --------------------------------CHANGELOG GENERATION--------------------------------------
|
||||
|
||||
def generate_changelog():
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"sphinx_changelog_gen",
|
||||
os.path.abspath(os.path.join(SCRIPT_DIR, "sphinx_changelog_gen.py")),
|
||||
)
|
||||
sphinx_changelog_gen = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(sphinx_changelog_gen)
|
||||
|
||||
API_DUMP_INDEX_FILEPATH = ARGS.api_dump_index_path
|
||||
API_DUMP_ROOT = os.path.dirname(API_DUMP_INDEX_FILEPATH)
|
||||
API_DUMP_FILEPATH = os.path.abspath(os.path.join(API_DUMP_ROOT, BLENDER_VERSION_DOTS, "api_dump.json"))
|
||||
API_CHANGELOG_FILEPATH = os.path.abspath(os.path.join(SPHINX_IN_TMP, "change_log.rst"))
|
||||
|
||||
sphinx_changelog_gen.main((
|
||||
"--",
|
||||
"--indexpath",
|
||||
API_DUMP_INDEX_FILEPATH,
|
||||
"dump",
|
||||
"--filepath-out",
|
||||
API_DUMP_FILEPATH,
|
||||
))
|
||||
|
||||
sphinx_changelog_gen.main((
|
||||
"--",
|
||||
"--indexpath",
|
||||
API_DUMP_INDEX_FILEPATH,
|
||||
"changelog",
|
||||
"--filepath-out",
|
||||
API_CHANGELOG_FILEPATH,
|
||||
))
|
||||
|
||||
|
||||
# --------------------------------API DUMP--------------------------------------
|
||||
|
||||
# Lame, python won't give some access.
|
||||
|
@ -2473,6 +2529,9 @@ def main():
|
|||
|
||||
rna2sphinx(SPHINX_IN_TMP)
|
||||
|
||||
if ARGS.changelog:
|
||||
generate_changelog()
|
||||
|
||||
if ARGS.full_rebuild:
|
||||
# Only for full updates.
|
||||
shutil.rmtree(SPHINX_IN, True)
|
||||
|
|
|
@ -41,7 +41,7 @@ double PulseAudioDevice::PulseAudioSynchronizer::getPosition(std::shared_ptr<IHa
|
|||
|
||||
void PulseAudioDevice::updateRingBuffer()
|
||||
{
|
||||
unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
unsigned int samplesize = AUD_DEVICE_SAMPLE_SIZE(m_specs);
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mixingLock);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Project: Curve-Fit-nD
|
||||
URL: https://github.com/ideasman42/curve-fit-nd
|
||||
License: BSD 3-Clause
|
||||
Upstream version: ddcd5bd (Last Release)
|
||||
Upstream version: ae32da9de264c3ed399673e2bc1bc09003799416 (Last Release)
|
||||
Local modifications: None
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
* Takes a flat array of points and evaluates that to calculate a bezier spline.
|
||||
*
|
||||
* \param points, points_len: The array of points to calculate a cubics from.
|
||||
* \param dims: The number of dimensions for for each element in \a points.
|
||||
* \param dims: The number of dimensions for each element in \a points.
|
||||
* \param error_threshold: the error threshold to allow for,
|
||||
* the curve will be within this distance from \a points.
|
||||
* \param corners, corners_len: indices for points which will not have aligned tangents (optional).
|
||||
|
@ -47,10 +47,10 @@
|
|||
* to evaluate a line to detect corner indices.
|
||||
*
|
||||
* \param r_cubic_array, r_cubic_array_len: Resulting array of tangents and knots, formatted as follows:
|
||||
* ``r_cubic_array[r_cubic_array_len][3][dims]``,
|
||||
* `r_cubic_array[r_cubic_array_len][3][dims]`,
|
||||
* where each point has 0 and 2 for the tangents and the middle index 1 for the knot.
|
||||
* The size of the *flat* array will be ``r_cubic_array_len * 3 * dims``.
|
||||
* \param r_corner_index_array, r_corner_index_len: Corner indices in in \a r_cubic_array (optional).
|
||||
* The size of the *flat* array will be `r_cubic_array_len * 3 * dims`.
|
||||
* \param r_corner_index_array, r_corner_index_len: Corner indices in \a r_cubic_array (optional).
|
||||
* This allows you to access corners on the resulting curve.
|
||||
*
|
||||
* \returns zero on success, nonzero is reserved for error values.
|
||||
|
@ -85,7 +85,7 @@ int curve_fit_cubic_to_points_fl(
|
|||
* Takes a flat array of points and evaluates that to calculate handle lengths.
|
||||
*
|
||||
* \param points, points_len: The array of points to calculate a cubics from.
|
||||
* \param dims: The number of dimensions for for each element in \a points.
|
||||
* \param dims: The number of dimensions for each element in \a points.
|
||||
* \param points_length_cache: Optional pre-calculated lengths between points.
|
||||
* \param error_threshold: the error threshold to allow for,
|
||||
* \param tan_l, tan_r: Normalized tangents the handles will be aligned to.
|
||||
|
@ -166,7 +166,7 @@ int curve_fit_cubic_to_points_refit_fl(
|
|||
* A helper function that takes a line and outputs its corner indices.
|
||||
*
|
||||
* \param points, points_len: Curve to evaluate.
|
||||
* \param dims: The number of dimensions for for each element in \a points.
|
||||
* \param dims: The number of dimensions for each element in \a points.
|
||||
* \param radius_min: Corners on the curve between points below this radius are ignored.
|
||||
* \param radius_max: Corners on the curve above this radius are ignored.
|
||||
* \param samples_max: Prevent testing corners beyond this many points
|
||||
|
|
|
@ -43,20 +43,24 @@
|
|||
|
||||
#include "../curve_fit_nd.h"
|
||||
|
||||
/* Take curvature into account when calculating the least square solution isn't usable. */
|
||||
/** Take curvature into account when calculating the least square solution isn't usable. */
|
||||
#define USE_CIRCULAR_FALLBACK
|
||||
|
||||
/* Use the maximum distance of any points from the direct line between 2 points
|
||||
/**
|
||||
* Use the maximum distance of any points from the direct line between 2 points
|
||||
* to calculate how long the handles need to be.
|
||||
* Can do a 'perfect' reversal of subdivision when for curve has symmetrical handles and doesn't change direction
|
||||
* (as with an 'S' shape). */
|
||||
* (as with an 'S' shape).
|
||||
*/
|
||||
#define USE_OFFSET_FALLBACK
|
||||
|
||||
/* avoid re-calculating lengths multiple times */
|
||||
/** Avoid re-calculating lengths multiple times. */
|
||||
#define USE_LENGTH_CACHE
|
||||
|
||||
/* store the indices in the cubic data so we can return the original indices,
|
||||
* useful when the caller has data associated with the curve. */
|
||||
/**
|
||||
* Store the indices in the cubic data so we can return the original indices,
|
||||
* useful when the caller has data associated with the curve.
|
||||
*/
|
||||
#define USE_ORIG_INDEX_DATA
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
@ -95,13 +99,15 @@ typedef unsigned int uint;
|
|||
* \{ */
|
||||
|
||||
typedef struct Cubic {
|
||||
/* single linked lists */
|
||||
/** Single linked lists. */
|
||||
struct Cubic *next;
|
||||
#ifdef USE_ORIG_INDEX_DATA
|
||||
uint orig_span;
|
||||
#endif
|
||||
/* 0: point_0, 1: handle_0, 2: handle_1, 3: point_1,
|
||||
* each one is offset by 'dims' */
|
||||
/**
|
||||
* 0: point_0, 1: handle_0, 2: handle_1, 3: point_1,
|
||||
* each one is offset by 'dims'.
|
||||
*/
|
||||
double pt_data[0];
|
||||
} Cubic;
|
||||
|
||||
|
@ -195,7 +201,7 @@ static double *cubic_list_as_array(
|
|||
bool use_orig_index = (r_orig_index != NULL);
|
||||
#endif
|
||||
|
||||
/* fill the array backwards */
|
||||
/* Fill the array backwards. */
|
||||
const size_t array_chunk = 3 * dims;
|
||||
double *array_iter = array + array_flat_len;
|
||||
for (Cubic *citer = clist->items; citer; citer = citer->next) {
|
||||
|
@ -221,15 +227,15 @@ static double *cubic_list_as_array(
|
|||
}
|
||||
#endif
|
||||
|
||||
/* flip tangent for first and last (we could leave at zero, but set to something useful) */
|
||||
/* Flip tangent for first and last (we could leave at zero, but set to something useful). */
|
||||
|
||||
/* first */
|
||||
/* First. */
|
||||
array_iter -= array_chunk;
|
||||
memcpy(&array_iter[dims], handle_prev, sizeof(double) * 2 * dims);
|
||||
flip_vn_vnvn(&array_iter[0 * dims], &array_iter[1 * dims], &array_iter[2 * dims], dims);
|
||||
assert(array == array_iter);
|
||||
|
||||
/* last */
|
||||
/* Last. */
|
||||
array_iter += array_flat_len - (3 * dims);
|
||||
flip_vn_vnvn(&array_iter[2 * dims], &array_iter[1 * dims], &array_iter[0 * dims], dims);
|
||||
|
||||
|
@ -455,7 +461,7 @@ static double points_calc_circumference_factor(
|
|||
const double dot = dot_vnvn(tan_l, tan_r, dims);
|
||||
const double len_tangent = dot < 0.0 ? len_vnvn(tan_l, tan_r, dims) : len_negated_vnvn(tan_l, tan_r, dims);
|
||||
if (len_tangent > DBL_EPSILON) {
|
||||
/* only clamp to avoid precision error */
|
||||
/* Only clamp to avoid precision error. */
|
||||
double angle = acos(max(-fabs(dot), -1.0));
|
||||
/* Angle may be less than the length when the tangents define >180 degrees of the circle,
|
||||
* (tangents that point away from each other).
|
||||
|
@ -466,7 +472,7 @@ static double points_calc_circumference_factor(
|
|||
return factor;
|
||||
}
|
||||
else {
|
||||
/* tangents are exactly aligned (think two opposite sides of a circle). */
|
||||
/* Tangents are exactly aligned (think two opposite sides of a circle). */
|
||||
return (M_PI / 2);
|
||||
}
|
||||
}
|
||||
|
@ -485,18 +491,18 @@ static double points_calc_circle_tangent_factor(
|
|||
const double eps = 1e-8;
|
||||
const double tan_dot = dot_vnvn(tan_l, tan_r, dims);
|
||||
if (tan_dot > 1.0 - eps) {
|
||||
/* no angle difference (use fallback, length wont make any difference) */
|
||||
/* No angle difference (use fallback, length won't make any difference). */
|
||||
return (1.0 / 3.0) * 0.75;
|
||||
}
|
||||
else if (tan_dot < -1.0 + eps) {
|
||||
/* parallel tangents (half-circle) */
|
||||
/* Parallel tangents (half-circle). */
|
||||
return (1.0 / 2.0);
|
||||
}
|
||||
else {
|
||||
/* non-aligned tangents, calculate handle length */
|
||||
/* Non-aligned tangents, calculate handle length. */
|
||||
const double angle = acos(tan_dot) / 2.0;
|
||||
|
||||
/* could also use 'angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0' */
|
||||
/* Could also use `angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0`. */
|
||||
const double angle_sin = sin(angle);
|
||||
const double angle_cos = cos(angle);
|
||||
return ((1.0 - angle_cos) / (angle_sin * 2.0)) / angle_sin;
|
||||
|
@ -516,15 +522,15 @@ static double points_calc_cubic_scale(
|
|||
const double len_direct = len_vnvn(v_l, v_r, dims);
|
||||
const double len_circle_factor = points_calc_circle_tangent_factor(tan_l, tan_r, dims);
|
||||
|
||||
/* if this curve is a circle, this value doesn't need modification */
|
||||
/* If this curve is a circle, this value doesn't need modification. */
|
||||
const double len_circle_handle = (len_direct * (len_circle_factor / 0.75));
|
||||
|
||||
/* scale by the difference from the circumference distance */
|
||||
/* Scale by the difference from the circumference distance. */
|
||||
const double len_circle = len_direct * points_calc_circumference_factor(tan_l, tan_r, dims);
|
||||
double scale_handle = (coords_length / len_circle);
|
||||
|
||||
/* Could investigate an accurate calculation here,
|
||||
* though this gives close results */
|
||||
* though this gives close results. */
|
||||
scale_handle = ((scale_handle - 1.0) * 1.75) + 1.0;
|
||||
|
||||
return len_circle_handle * scale_handle;
|
||||
|
@ -554,9 +560,8 @@ static void cubic_from_points_fallback(
|
|||
r_cubic->orig_span = (points_offset_len - 1);
|
||||
#endif
|
||||
|
||||
/* p1 = p0 - (tan_l * alpha);
|
||||
* p2 = p3 + (tan_r * alpha);
|
||||
*/
|
||||
/* `p1 = p0 - (tan_l * alpha);`
|
||||
* `p2 = p3 + (tan_r * alpha);` */
|
||||
msub_vn_vnvn_fl(p1, p0, tan_l, alpha, dims);
|
||||
madd_vn_vnvn_fl(p2, p3, tan_r, alpha, dims);
|
||||
}
|
||||
|
@ -594,7 +599,7 @@ static void cubic_from_points_offset_fallback(
|
|||
project_plane_vn_vnvn_normalized(a[0], tan_l, dir_unit, dims);
|
||||
project_plane_vn_vnvn_normalized(a[1], tan_r, dir_unit, dims);
|
||||
|
||||
/* only for better accuracy, not essential */
|
||||
/* Only for better accuracy, not essential. */
|
||||
normalize_vn(a[0], dims);
|
||||
normalize_vn(a[1], dims);
|
||||
|
||||
|
@ -620,7 +625,7 @@ static void cubic_from_points_offset_fallback(
|
|||
*
|
||||
* The 'dists[..] + dir_dirs' limit is just a rough approximation.
|
||||
* While a more exact value could be calculated,
|
||||
* in this case the error values approach divide by zero (inf)
|
||||
* in this case the error values approach divide by zero (infinite)
|
||||
* so there is no need to be too precise when checking if limits have been exceeded. */
|
||||
|
||||
double alpha_l = (dists[0] / 0.75) / fabs(dot_vnvn(tan_l, a[0], dims));
|
||||
|
@ -644,9 +649,8 @@ static void cubic_from_points_offset_fallback(
|
|||
r_cubic->orig_span = (points_offset_len - 1);
|
||||
#endif
|
||||
|
||||
/* p1 = p0 - (tan_l * alpha_l);
|
||||
* p2 = p3 + (tan_r * alpha_r);
|
||||
*/
|
||||
/* `p1 = p0 - (tan_l * alpha_l);`
|
||||
* `p2 = p3 + (tan_r * alpha_r);` */
|
||||
msub_vn_vnvn_fl(p1, p0, tan_l, alpha_l, dims);
|
||||
madd_vn_vnvn_fl(p2, p3, tan_r, alpha_r, dims);
|
||||
}
|
||||
|
@ -674,7 +678,7 @@ static void cubic_from_points(
|
|||
const double *p0 = &points_offset[0];
|
||||
const double *p3 = &points_offset[(points_offset_len - 1) * dims];
|
||||
|
||||
/* Point Pairs */
|
||||
/* Point Pairs. */
|
||||
double alpha_l, alpha_r;
|
||||
#ifdef USE_VLA
|
||||
double a[2][dims];
|
||||
|
@ -696,7 +700,7 @@ static void cubic_from_points(
|
|||
const double b0_plus_b1 = B0plusB1(u_prime[i]);
|
||||
const double b2_plus_b3 = B2plusB3(u_prime[i]);
|
||||
|
||||
/* inline dot product */
|
||||
/* Inline dot product. */
|
||||
for (uint j = 0; j < dims; j++) {
|
||||
const double tmp = (pt[j] - (p0[j] * b0_plus_b1)) + (p3[j] * b2_plus_b3);
|
||||
|
||||
|
@ -719,7 +723,7 @@ static void cubic_from_points(
|
|||
det_C0_C1 = c[0][0] * c[1][1] * 10e-12;
|
||||
}
|
||||
|
||||
/* may still divide-by-zero, check below will catch nan values */
|
||||
/* May still divide-by-zero, check below will catch NAN values. */
|
||||
alpha_l = det_X_C1 / det_C0_C1;
|
||||
alpha_r = det_C_0X / det_C0_C1;
|
||||
}
|
||||
|
@ -736,7 +740,7 @@ static void cubic_from_points(
|
|||
|
||||
bool use_clamp = true;
|
||||
|
||||
/* flip check to catch nan values */
|
||||
/* Flip check to catch NAN values. */
|
||||
if (!(alpha_l >= 0.0) ||
|
||||
!(alpha_r >= 0.0))
|
||||
{
|
||||
|
@ -750,7 +754,7 @@ static void cubic_from_points(
|
|||
alpha_l = alpha_r = len_vnvn(p0, p3, dims) / 3.0;
|
||||
#endif
|
||||
|
||||
/* skip clamping when we're using default handles */
|
||||
/* Skip clamping when we're using default handles. */
|
||||
use_clamp = false;
|
||||
}
|
||||
|
||||
|
@ -764,9 +768,8 @@ static void cubic_from_points(
|
|||
r_cubic->orig_span = (points_offset_len - 1);
|
||||
#endif
|
||||
|
||||
/* p1 = p0 - (tan_l * alpha_l);
|
||||
* p2 = p3 + (tan_r * alpha_r);
|
||||
*/
|
||||
/* `p1 = p0 - (tan_l * alpha_l);`
|
||||
* `p2 = p3 + (tan_r * alpha_r);` */
|
||||
msub_vn_vnvn_fl(p1, p0, tan_l, alpha_l, dims);
|
||||
madd_vn_vnvn_fl(p2, p3, tan_r, alpha_r, dims);
|
||||
|
||||
|
@ -781,7 +784,7 @@ static void cubic_from_points(
|
|||
#endif
|
||||
points_calc_center_weighted(points_offset, points_offset_len, dims, center);
|
||||
|
||||
const double clamp_scale = 3.0; /* clamp to 3x */
|
||||
const double clamp_scale = 3.0; /* Clamp to 3x. */
|
||||
double dist_sq_max = 0.0;
|
||||
|
||||
{
|
||||
|
@ -790,7 +793,7 @@ static void cubic_from_points(
|
|||
#if 0
|
||||
double dist_sq_test = sq(len_vnvn(center, pt, dims) * clamp_scale);
|
||||
#else
|
||||
/* do inline */
|
||||
/* Do inline. */
|
||||
double dist_sq_test = 0.0;
|
||||
for (uint j = 0; j < dims; j++) {
|
||||
dist_sq_test += sq((pt[j] - center[j]) * clamp_scale);
|
||||
|
@ -816,10 +819,8 @@ static void cubic_from_points(
|
|||
alpha_l = alpha_r = len_vnvn(p0, p3, dims) / 3.0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* p1 = p0 - (tan_l * alpha_l);
|
||||
* p2 = p3 + (tan_r * alpha_r);
|
||||
*/
|
||||
/* `p1 = p0 - (tan_l * alpha_l);`
|
||||
* `p2 = p3 + (tan_r * alpha_r);` */
|
||||
for (uint j = 0; j < dims; j++) {
|
||||
p1[j] = p0[j] - (tan_l[j] * alpha_l);
|
||||
p2[j] = p3[j] + (tan_r[j] * alpha_r);
|
||||
|
@ -829,7 +830,7 @@ static void cubic_from_points(
|
|||
p2_dist_sq = len_squared_vnvn(center, p2, dims);
|
||||
}
|
||||
|
||||
/* clamp within the 3x radius */
|
||||
/* Clamp within the 3x radius. */
|
||||
if (p1_dist_sq > dist_sq_max) {
|
||||
isub_vnvn(p1, center, dims);
|
||||
imul_vn_fl(p1, sqrt(dist_sq_max) / sqrt(p1_dist_sq), dims);
|
||||
|
@ -841,7 +842,7 @@ static void cubic_from_points(
|
|||
iadd_vnvn(p2, center, dims);
|
||||
}
|
||||
}
|
||||
/* end clamping */
|
||||
/* End clamping. */
|
||||
}
|
||||
|
||||
#ifdef USE_LENGTH_CACHE
|
||||
|
@ -917,7 +918,7 @@ static double cubic_find_root(
|
|||
const uint dims)
|
||||
{
|
||||
/* Newton-Raphson Method. */
|
||||
/* all vectors */
|
||||
/* All vectors. */
|
||||
#ifdef USE_VLA
|
||||
double q0_u[dims];
|
||||
double q1_u[dims];
|
||||
|
@ -932,8 +933,8 @@ static double cubic_find_root(
|
|||
cubic_calc_speed(cubic, u, dims, q1_u);
|
||||
cubic_calc_acceleration(cubic, u, dims, q2_u);
|
||||
|
||||
/* may divide-by-zero, caller must check for that case */
|
||||
/* u - ((q0_u - p) * q1_u) / (q1_u.length_squared() + (q0_u - p) * q2_u) */
|
||||
/* May divide-by-zero, caller must check for that case. */
|
||||
/* `u - ((q0_u - p) * q1_u) / (q1_u.length_squared() + (q0_u - p) * q2_u)` */
|
||||
isub_vnvn(q0_u, p, dims);
|
||||
return u - dot_vnvn(q0_u, q1_u, dims) /
|
||||
(len_squared_vn(q1_u, dims) + dot_vnvn(q0_u, q2_u, dims));
|
||||
|
@ -1032,7 +1033,7 @@ static bool fit_cubic_to_points(
|
|||
double error_max_sq;
|
||||
uint split_index;
|
||||
|
||||
/* Parameterize points, and attempt to fit curve */
|
||||
/* Parameterize points, and attempt to fit curve. */
|
||||
cubic_from_points(
|
||||
points_offset, points_offset_len,
|
||||
#ifdef USE_CIRCULAR_FALLBACK
|
||||
|
@ -1040,7 +1041,7 @@ static bool fit_cubic_to_points(
|
|||
#endif
|
||||
u, tan_l, tan_r, dims, r_cubic);
|
||||
|
||||
/* Find max deviation of points to fitted curve */
|
||||
/* Find max deviation of points to fitted curve. */
|
||||
error_max_sq = cubic_calc_error(
|
||||
r_cubic, points_offset, points_offset_len, u, dims,
|
||||
&split_index);
|
||||
|
@ -1062,7 +1063,7 @@ static bool fit_cubic_to_points(
|
|||
cubic_test, points_offset, points_offset_len, u, dims,
|
||||
&split_index);
|
||||
|
||||
/* intentionally use the newly calculated 'split_index',
|
||||
/* Intentionally use the newly calculated 'split_index',
|
||||
* even if the 'error_max_sq_test' is worse. */
|
||||
if (error_max_sq > error_max_sq_test) {
|
||||
error_max_sq = error_max_sq_test;
|
||||
|
@ -1071,7 +1072,7 @@ static bool fit_cubic_to_points(
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Test the offset fallback */
|
||||
/* Test the offset fallback. */
|
||||
#ifdef USE_OFFSET_FALLBACK
|
||||
if (!(error_max_sq < error_threshold_sq)) {
|
||||
/* Using the offset from the curve to calculate cubic handle length may give better results
|
||||
|
@ -1095,7 +1096,7 @@ static bool fit_cubic_to_points(
|
|||
if (!(error_max_sq < error_threshold_sq)) {
|
||||
cubic_copy(cubic_test, r_cubic, dims);
|
||||
|
||||
/* If error not too large, try some reparameterization and iteration */
|
||||
/* If error not too large, try some re-parameterization and iteration. */
|
||||
double *u_prime = malloc(sizeof(double) * points_offset_len);
|
||||
for (uint iter = 0; iter < iteration_max; iter++) {
|
||||
if (!cubic_reparameterize(
|
||||
|
@ -1123,7 +1124,7 @@ static bool fit_cubic_to_points(
|
|||
}
|
||||
|
||||
if (!(error_max_sq < error_threshold_sq)) {
|
||||
/* continue */
|
||||
/* Continue. */
|
||||
}
|
||||
else {
|
||||
assert((error_max_sq < error_threshold_sq));
|
||||
|
@ -1156,7 +1157,7 @@ static void fit_cubic_to_points_recursive(
|
|||
const double error_threshold_sq,
|
||||
const uint calc_flag,
|
||||
const uint dims,
|
||||
/* fill in the list */
|
||||
/* Fill in the list. */
|
||||
CubicList *clist)
|
||||
{
|
||||
Cubic *cubic = cubic_alloc(dims);
|
||||
|
@ -1180,7 +1181,7 @@ static void fit_cubic_to_points_recursive(
|
|||
cubic_free(cubic);
|
||||
|
||||
|
||||
/* Fitting failed -- split at max error point and fit recursively */
|
||||
/* Fitting failed -- split at max error point and fit recursively. */
|
||||
|
||||
/* Check splinePoint is not an endpoint?
|
||||
*
|
||||
|
@ -1212,7 +1213,7 @@ static void fit_cubic_to_points_recursive(
|
|||
#endif
|
||||
const double *pt = &points_offset[split_index * dims];
|
||||
|
||||
/* tan_center = ((pt_a - pt).normalized() + (pt - pt_b).normalized()).normalized() */
|
||||
/* `tan_center = ((pt_a - pt).normalized() + (pt - pt_b).normalized()).normalized()`. */
|
||||
normalize_vn_vnvn(tan_center_a, pt_a, pt, dims);
|
||||
normalize_vn_vnvn(tan_center_b, pt, pt_b, dims);
|
||||
add_vn_vnvn(tan_center, tan_center_a, tan_center_b, dims);
|
||||
|
@ -1306,9 +1307,8 @@ int curve_fit_cubic_to_points_db(
|
|||
const double *pt_l_next = pt_l + dims;
|
||||
const double *pt_r_prev = pt_r - dims;
|
||||
|
||||
/* tan_l = (pt_l - pt_l_next).normalized()
|
||||
* tan_r = (pt_r_prev - pt_r).normalized()
|
||||
*/
|
||||
/* `tan_l = (pt_l - pt_l_next).normalized();`
|
||||
* `tan_r = (pt_r_prev - pt_r).normalized();` */
|
||||
normalize_vn_vnvn(tan_l, pt_l, pt_l_next, dims);
|
||||
normalize_vn_vnvn(tan_r, pt_r_prev, pt_r, dims);
|
||||
|
||||
|
@ -1362,7 +1362,7 @@ int curve_fit_cubic_to_points_db(
|
|||
*r_cubic_orig_index = NULL;
|
||||
#endif
|
||||
|
||||
/* allocate a contiguous array and free the linked list */
|
||||
/* Allocate a contiguous array and free the linked list. */
|
||||
*r_cubic_array = cubic_list_as_array(
|
||||
&clist
|
||||
#ifdef USE_ORIG_INDEX_DATA
|
||||
|
@ -1454,7 +1454,7 @@ int curve_fit_cubic_to_points_single_db(
|
|||
{
|
||||
Cubic *cubic = alloca(cubic_alloc_size(dims));
|
||||
|
||||
/* in this instance theres no advantage in using length cache,
|
||||
/* In this instance there are no advantage in using length cache,
|
||||
* since we're not recursively calculating values. */
|
||||
#ifdef USE_LENGTH_CACHE
|
||||
double *points_length_cache_alloc = NULL;
|
||||
|
|
|
@ -1490,3 +1490,4 @@ int curve_fit_cubic_to_points_refit_fl(
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* - #TPOOL_STRUCT: Name for pool struct name.
|
||||
* - #TPOOL_CHUNK_SIZE: Chunk size (optional), use 64kb when not defined.
|
||||
*
|
||||
* \note #TPOOL_ALLOC_TYPE must be at least ``sizeof(void *)``.
|
||||
* \note #TPOOL_ALLOC_TYPE must be at least `sizeof(void *)`.
|
||||
*
|
||||
* Defines the API, uses #TPOOL_IMPL_PREFIX to prefix each function.
|
||||
*
|
||||
|
|
|
@ -305,5 +305,3 @@ void *HEAP_node_ptr(HeapNode *node)
|
|||
{
|
||||
return node->ptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Project: Draco
|
||||
URL: https://google.github.io/draco/
|
||||
License: Apache 2.0
|
||||
Upstream version: 1.3.6
|
||||
Local modifications: None
|
||||
Upstream version: 1.5.2
|
||||
Local modifications: Apply patches/blender.patch
|
||||
|
|
|
@ -38,6 +38,46 @@ void AttributeOctahedronTransform::CopyToAttributeTransformData(
|
|||
out_data->AppendParameterValue(quantization_bits_);
|
||||
}
|
||||
|
||||
bool AttributeOctahedronTransform::TransformAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
PointAttribute *target_attribute) {
|
||||
return GeneratePortableAttribute(attribute, point_ids,
|
||||
target_attribute->size(), target_attribute);
|
||||
}
|
||||
|
||||
bool AttributeOctahedronTransform::InverseTransformAttribute(
|
||||
const PointAttribute &attribute, PointAttribute *target_attribute) {
|
||||
if (target_attribute->data_type() != DT_FLOAT32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int num_points = target_attribute->size();
|
||||
const int num_components = target_attribute->num_components();
|
||||
if (num_components != 3) {
|
||||
return false;
|
||||
}
|
||||
constexpr int kEntrySize = sizeof(float) * 3;
|
||||
float att_val[3];
|
||||
const int32_t *source_attribute_data = reinterpret_cast<const int32_t *>(
|
||||
attribute.GetAddress(AttributeValueIndex(0)));
|
||||
uint8_t *target_address =
|
||||
target_attribute->GetAddress(AttributeValueIndex(0));
|
||||
OctahedronToolBox octahedron_tool_box;
|
||||
if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < num_points; ++i) {
|
||||
const int32_t s = *source_attribute_data++;
|
||||
const int32_t t = *source_attribute_data++;
|
||||
octahedron_tool_box.QuantizedOctahedralCoordsToUnitVector(s, t, att_val);
|
||||
|
||||
// Store the decoded floating point values into the attribute buffer.
|
||||
std::memcpy(target_address, att_val, kEntrySize);
|
||||
target_address += kEntrySize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttributeOctahedronTransform::SetParameters(int quantization_bits) {
|
||||
quantization_bits_ = quantization_bits;
|
||||
}
|
||||
|
@ -51,38 +91,55 @@ bool AttributeOctahedronTransform::EncodeParameters(
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<PointAttribute>
|
||||
AttributeOctahedronTransform::GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
int num_points) const {
|
||||
DRACO_DCHECK(is_initialized());
|
||||
bool AttributeOctahedronTransform::DecodeParameters(
|
||||
const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
|
||||
uint8_t quantization_bits;
|
||||
if (!decoder_buffer->Decode(&quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allocate portable attribute.
|
||||
const int num_entries = static_cast<int>(point_ids.size());
|
||||
std::unique_ptr<PointAttribute> portable_attribute =
|
||||
InitPortableAttribute(num_entries, 2, num_points, attribute, true);
|
||||
bool AttributeOctahedronTransform::GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
int num_points, PointAttribute *target_attribute) const {
|
||||
DRACO_DCHECK(is_initialized());
|
||||
|
||||
// Quantize all values in the order given by point_ids into portable
|
||||
// attribute.
|
||||
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
|
||||
portable_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
target_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
float att_val[3];
|
||||
int32_t dst_index = 0;
|
||||
OctahedronToolBox converter;
|
||||
if (!converter.SetQuantizationBits(quantization_bits_)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < point_ids.size(); ++i) {
|
||||
const AttributeValueIndex att_val_id = attribute.mapped_index(point_ids[i]);
|
||||
attribute.GetValue(att_val_id, att_val);
|
||||
// Encode the vector into a s and t octahedral coordinates.
|
||||
int32_t s, t;
|
||||
converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
|
||||
portable_attribute_data[dst_index++] = s;
|
||||
portable_attribute_data[dst_index++] = t;
|
||||
if (!point_ids.empty()) {
|
||||
for (uint32_t i = 0; i < point_ids.size(); ++i) {
|
||||
const AttributeValueIndex att_val_id =
|
||||
attribute.mapped_index(point_ids[i]);
|
||||
attribute.GetValue(att_val_id, att_val);
|
||||
// Encode the vector into a s and t octahedral coordinates.
|
||||
int32_t s, t;
|
||||
converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
|
||||
portable_attribute_data[dst_index++] = s;
|
||||
portable_attribute_data[dst_index++] = t;
|
||||
}
|
||||
} else {
|
||||
for (PointIndex i(0); i < num_points; ++i) {
|
||||
const AttributeValueIndex att_val_id = attribute.mapped_index(i);
|
||||
attribute.GetValue(att_val_id, att_val);
|
||||
// Encode the vector into a s and t octahedral coordinates.
|
||||
int32_t s, t;
|
||||
converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
|
||||
portable_attribute_data[dst_index++] = s;
|
||||
portable_attribute_data[dst_index++] = t;
|
||||
}
|
||||
}
|
||||
|
||||
return portable_attribute;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -37,19 +37,40 @@ class AttributeOctahedronTransform : public AttributeTransform {
|
|||
void CopyToAttributeTransformData(
|
||||
AttributeTransformData *out_data) const override;
|
||||
|
||||
bool TransformAttribute(const PointAttribute &attribute,
|
||||
const std::vector<PointIndex> &point_ids,
|
||||
PointAttribute *target_attribute) override;
|
||||
|
||||
bool InverseTransformAttribute(const PointAttribute &attribute,
|
||||
PointAttribute *target_attribute) override;
|
||||
|
||||
// Set number of quantization bits.
|
||||
void SetParameters(int quantization_bits);
|
||||
|
||||
// Encode relevant parameters into buffer.
|
||||
bool EncodeParameters(EncoderBuffer *encoder_buffer) const;
|
||||
bool EncodeParameters(EncoderBuffer *encoder_buffer) const override;
|
||||
|
||||
bool DecodeParameters(const PointAttribute &attribute,
|
||||
DecoderBuffer *decoder_buffer) override;
|
||||
|
||||
bool is_initialized() const { return quantization_bits_ != -1; }
|
||||
int32_t quantization_bits() const { return quantization_bits_; }
|
||||
|
||||
// Create portable attribute.
|
||||
std::unique_ptr<PointAttribute> GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
int num_points) const;
|
||||
protected:
|
||||
DataType GetTransformedDataType(
|
||||
const PointAttribute &attribute) const override {
|
||||
return DT_UINT32;
|
||||
}
|
||||
int GetTransformedNumComponents(
|
||||
const PointAttribute &attribute) const override {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Perform the actual transformation.
|
||||
bool GeneratePortableAttribute(const PointAttribute &attribute,
|
||||
const std::vector<PointIndex> &point_ids,
|
||||
int num_points,
|
||||
PointAttribute *target_attribute) const;
|
||||
|
||||
private:
|
||||
int32_t quantization_bits_;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright 2017 The Draco Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -51,13 +50,74 @@ void AttributeQuantizationTransform::CopyToAttributeTransformData(
|
|||
out_data->AppendParameterValue(range_);
|
||||
}
|
||||
|
||||
void AttributeQuantizationTransform::SetParameters(int quantization_bits,
|
||||
bool AttributeQuantizationTransform::TransformAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
PointAttribute *target_attribute) {
|
||||
if (point_ids.empty()) {
|
||||
GeneratePortableAttribute(attribute, target_attribute->size(),
|
||||
target_attribute);
|
||||
} else {
|
||||
GeneratePortableAttribute(attribute, point_ids, target_attribute->size(),
|
||||
target_attribute);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AttributeQuantizationTransform::InverseTransformAttribute(
|
||||
const PointAttribute &attribute, PointAttribute *target_attribute) {
|
||||
if (target_attribute->data_type() != DT_FLOAT32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert all quantized values back to floats.
|
||||
const int32_t max_quantized_value =
|
||||
(1u << static_cast<uint32_t>(quantization_bits_)) - 1;
|
||||
const int num_components = target_attribute->num_components();
|
||||
const int entry_size = sizeof(float) * num_components;
|
||||
const std::unique_ptr<float[]> att_val(new float[num_components]);
|
||||
int quant_val_id = 0;
|
||||
int out_byte_pos = 0;
|
||||
Dequantizer dequantizer;
|
||||
if (!dequantizer.Init(range_, max_quantized_value)) {
|
||||
return false;
|
||||
}
|
||||
const int32_t *const source_attribute_data =
|
||||
reinterpret_cast<const int32_t *>(
|
||||
attribute.GetAddress(AttributeValueIndex(0)));
|
||||
|
||||
const int num_values = target_attribute->size();
|
||||
|
||||
for (uint32_t i = 0; i < num_values; ++i) {
|
||||
for (int c = 0; c < num_components; ++c) {
|
||||
float value =
|
||||
dequantizer.DequantizeFloat(source_attribute_data[quant_val_id++]);
|
||||
value = value + min_values_[c];
|
||||
att_val[c] = value;
|
||||
}
|
||||
// Store the floating point value into the attribute buffer.
|
||||
target_attribute->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
|
||||
out_byte_pos += entry_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AttributeQuantizationTransform::IsQuantizationValid(
|
||||
int quantization_bits) {
|
||||
// Currently we allow only up to 30 bit quantization.
|
||||
return quantization_bits >= 1 && quantization_bits <= 30;
|
||||
}
|
||||
|
||||
bool AttributeQuantizationTransform::SetParameters(int quantization_bits,
|
||||
const float *min_values,
|
||||
int num_components,
|
||||
float range) {
|
||||
if (!IsQuantizationValid(quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
min_values_.assign(min_values, min_values + num_components);
|
||||
range_ = range;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AttributeQuantizationTransform::ComputeParameters(
|
||||
|
@ -65,6 +125,9 @@ bool AttributeQuantizationTransform::ComputeParameters(
|
|||
if (quantization_bits_ != -1) {
|
||||
return false; // already initialized.
|
||||
}
|
||||
if (!IsQuantizationValid(quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
|
||||
const int num_components = attribute.num_components();
|
||||
|
@ -121,20 +184,37 @@ bool AttributeQuantizationTransform::EncodeParameters(
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<PointAttribute>
|
||||
AttributeQuantizationTransform::GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, int num_points) const {
|
||||
bool AttributeQuantizationTransform::DecodeParameters(
|
||||
const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
|
||||
min_values_.resize(attribute.num_components());
|
||||
if (!decoder_buffer->Decode(&min_values_[0],
|
||||
sizeof(float) * min_values_.size())) {
|
||||
return false;
|
||||
}
|
||||
if (!decoder_buffer->Decode(&range_)) {
|
||||
return false;
|
||||
}
|
||||
uint8_t quantization_bits;
|
||||
if (!decoder_buffer->Decode(&quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
if (!IsQuantizationValid(quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttributeQuantizationTransform::GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, int num_points,
|
||||
PointAttribute *target_attribute) const {
|
||||
DRACO_DCHECK(is_initialized());
|
||||
|
||||
// Allocate portable attribute.
|
||||
const int num_entries = num_points;
|
||||
const int num_components = attribute.num_components();
|
||||
std::unique_ptr<PointAttribute> portable_attribute =
|
||||
InitPortableAttribute(num_entries, num_components, 0, attribute, true);
|
||||
|
||||
// Quantize all values using the order given by point_ids.
|
||||
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
|
||||
portable_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
target_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1;
|
||||
Quantizer quantizer;
|
||||
quantizer.Init(range(), max_quantized_value);
|
||||
|
@ -149,24 +229,18 @@ AttributeQuantizationTransform::GeneratePortableAttribute(
|
|||
portable_attribute_data[dst_index++] = q_val;
|
||||
}
|
||||
}
|
||||
return portable_attribute;
|
||||
}
|
||||
|
||||
std::unique_ptr<PointAttribute>
|
||||
AttributeQuantizationTransform::GeneratePortableAttribute(
|
||||
void AttributeQuantizationTransform::GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
int num_points) const {
|
||||
int num_points, PointAttribute *target_attribute) const {
|
||||
DRACO_DCHECK(is_initialized());
|
||||
|
||||
// Allocate portable attribute.
|
||||
const int num_entries = static_cast<int>(point_ids.size());
|
||||
const int num_components = attribute.num_components();
|
||||
std::unique_ptr<PointAttribute> portable_attribute = InitPortableAttribute(
|
||||
num_entries, num_components, num_points, attribute, true);
|
||||
|
||||
// Quantize all values using the order given by point_ids.
|
||||
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
|
||||
portable_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
target_attribute->GetAddress(AttributeValueIndex(0)));
|
||||
const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1;
|
||||
Quantizer quantizer;
|
||||
quantizer.Init(range(), max_quantized_value);
|
||||
|
@ -181,7 +255,6 @@ AttributeQuantizationTransform::GeneratePortableAttribute(
|
|||
portable_attribute_data[dst_index++] = q_val;
|
||||
}
|
||||
}
|
||||
return portable_attribute;
|
||||
}
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -37,14 +37,24 @@ class AttributeQuantizationTransform : public AttributeTransform {
|
|||
void CopyToAttributeTransformData(
|
||||
AttributeTransformData *out_data) const override;
|
||||
|
||||
void SetParameters(int quantization_bits, const float *min_values,
|
||||
bool TransformAttribute(const PointAttribute &attribute,
|
||||
const std::vector<PointIndex> &point_ids,
|
||||
PointAttribute *target_attribute) override;
|
||||
|
||||
bool InverseTransformAttribute(const PointAttribute &attribute,
|
||||
PointAttribute *target_attribute) override;
|
||||
|
||||
bool SetParameters(int quantization_bits, const float *min_values,
|
||||
int num_components, float range);
|
||||
|
||||
bool ComputeParameters(const PointAttribute &attribute,
|
||||
const int quantization_bits);
|
||||
|
||||
// Encode relevant parameters into buffer.
|
||||
bool EncodeParameters(EncoderBuffer *encoder_buffer) const;
|
||||
bool EncodeParameters(EncoderBuffer *encoder_buffer) const override;
|
||||
|
||||
bool DecodeParameters(const PointAttribute &attribute,
|
||||
DecoderBuffer *decoder_buffer) override;
|
||||
|
||||
int32_t quantization_bits() const { return quantization_bits_; }
|
||||
float min_value(int axis) const { return min_values_[axis]; }
|
||||
|
@ -52,16 +62,30 @@ class AttributeQuantizationTransform : public AttributeTransform {
|
|||
float range() const { return range_; }
|
||||
bool is_initialized() const { return quantization_bits_ != -1; }
|
||||
|
||||
protected:
|
||||
// Create portable attribute using 1:1 mapping between points in the input and
|
||||
// output attribute.
|
||||
std::unique_ptr<PointAttribute> GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, int num_points) const;
|
||||
void GeneratePortableAttribute(const PointAttribute &attribute,
|
||||
int num_points,
|
||||
PointAttribute *target_attribute) const;
|
||||
|
||||
// Create portable attribute using custom mapping between input and output
|
||||
// points.
|
||||
std::unique_ptr<PointAttribute> GeneratePortableAttribute(
|
||||
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
|
||||
int num_points) const;
|
||||
void GeneratePortableAttribute(const PointAttribute &attribute,
|
||||
const std::vector<PointIndex> &point_ids,
|
||||
int num_points,
|
||||
PointAttribute *target_attribute) const;
|
||||
|
||||
DataType GetTransformedDataType(
|
||||
const PointAttribute &attribute) const override {
|
||||
return DT_UINT32;
|
||||
}
|
||||
int GetTransformedNumComponents(
|
||||
const PointAttribute &attribute) const override {
|
||||
return attribute.num_components();
|
||||
}
|
||||
|
||||
static bool IsQuantizationValid(int quantization_bits);
|
||||
|
||||
private:
|
||||
int32_t quantization_bits_;
|
||||
|
|
|
@ -24,21 +24,18 @@ bool AttributeTransform::TransferToAttribute(PointAttribute *attribute) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<PointAttribute> AttributeTransform::InitPortableAttribute(
|
||||
int num_entries, int num_components, int num_points,
|
||||
const PointAttribute &attribute, bool is_unsigned) const {
|
||||
const DataType dt = is_unsigned ? DT_UINT32 : DT_INT32;
|
||||
GeometryAttribute va;
|
||||
va.Init(attribute.attribute_type(), nullptr, num_components, dt, false,
|
||||
std::unique_ptr<PointAttribute> AttributeTransform::InitTransformedAttribute(
|
||||
const PointAttribute &src_attribute, int num_entries) {
|
||||
const int num_components = GetTransformedNumComponents(src_attribute);
|
||||
const DataType dt = GetTransformedDataType(src_attribute);
|
||||
GeometryAttribute ga;
|
||||
ga.Init(src_attribute.attribute_type(), nullptr, num_components, dt, false,
|
||||
num_components * DataTypeLength(dt), 0);
|
||||
std::unique_ptr<PointAttribute> portable_attribute(new PointAttribute(va));
|
||||
portable_attribute->Reset(num_entries);
|
||||
if (num_points) {
|
||||
portable_attribute->SetExplicitMapping(num_points);
|
||||
} else {
|
||||
portable_attribute->SetIdentityMapping();
|
||||
}
|
||||
return portable_attribute;
|
||||
std::unique_ptr<PointAttribute> transformed_attribute(new PointAttribute(ga));
|
||||
transformed_attribute->Reset(num_entries);
|
||||
transformed_attribute->SetIdentityMapping();
|
||||
transformed_attribute->set_unique_id(src_attribute.unique_id());
|
||||
return transformed_attribute;
|
||||
}
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "draco/attributes/attribute_transform_data.h"
|
||||
#include "draco/attributes/point_attribute.h"
|
||||
#include "draco/core/decoder_buffer.h"
|
||||
#include "draco/core/encoder_buffer.h"
|
||||
|
||||
namespace draco {
|
||||
|
||||
|
@ -35,10 +37,38 @@ class AttributeTransform {
|
|||
AttributeTransformData *out_data) const = 0;
|
||||
bool TransferToAttribute(PointAttribute *attribute) const;
|
||||
|
||||
// Applies the transform to |attribute| and stores the result in
|
||||
// |target_attribute|. |point_ids| is an optional vector that can be used to
|
||||
// remap values during the transform.
|
||||
virtual bool TransformAttribute(const PointAttribute &attribute,
|
||||
const std::vector<PointIndex> &point_ids,
|
||||
PointAttribute *target_attribute) = 0;
|
||||
|
||||
// Applies an inverse transform to |attribute| and stores the result in
|
||||
// |target_attribute|. In this case, |attribute| is an attribute that was
|
||||
// already transformed (e.g. quantized) and |target_attribute| is the
|
||||
// attribute before the transformation.
|
||||
virtual bool InverseTransformAttribute(const PointAttribute &attribute,
|
||||
PointAttribute *target_attribute) = 0;
|
||||
|
||||
// Encodes all data needed by the transformation into the |encoder_buffer|.
|
||||
virtual bool EncodeParameters(EncoderBuffer *encoder_buffer) const = 0;
|
||||
|
||||
// Decodes all data needed to transform |attribute| back to the original
|
||||
// format.
|
||||
virtual bool DecodeParameters(const PointAttribute &attribute,
|
||||
DecoderBuffer *decoder_buffer) = 0;
|
||||
|
||||
// Initializes a transformed attribute that can be used as target in the
|
||||
// TransformAttribute() function call.
|
||||
virtual std::unique_ptr<PointAttribute> InitTransformedAttribute(
|
||||
const PointAttribute &src_attribute, int num_entries);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<PointAttribute> InitPortableAttribute(
|
||||
int num_entries, int num_components, int num_points,
|
||||
const PointAttribute &attribute, bool is_unsigned) const;
|
||||
virtual DataType GetTransformedDataType(
|
||||
const PointAttribute &attribute) const = 0;
|
||||
virtual int GetTransformedNumComponents(
|
||||
const PointAttribute &attribute) const = 0;
|
||||
};
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -43,10 +43,6 @@ void GeometryAttribute::Init(GeometryAttribute::Type attribute_type,
|
|||
}
|
||||
|
||||
bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) {
|
||||
if (buffer_ == nullptr || src_att.buffer_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size());
|
||||
num_components_ = src_att.num_components_;
|
||||
data_type_ = src_att.data_type_;
|
||||
normalized_ = src_att.normalized_;
|
||||
|
@ -55,6 +51,14 @@ bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) {
|
|||
attribute_type_ = src_att.attribute_type_;
|
||||
buffer_descriptor_ = src_att.buffer_descriptor_;
|
||||
unique_id_ = src_att.unique_id_;
|
||||
if (src_att.buffer_ == nullptr) {
|
||||
buffer_ = nullptr;
|
||||
} else {
|
||||
if (buffer_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "draco/attributes/geometry_indices.h"
|
||||
#include "draco/core/data_buffer.h"
|
||||
#include "draco/core/hash_utils.h"
|
||||
#include "draco/draco_features.h"
|
||||
|
||||
namespace draco {
|
||||
|
||||
|
@ -51,6 +52,16 @@ class GeometryAttribute {
|
|||
// predefined use case. Such attributes are often used for a shader specific
|
||||
// data.
|
||||
GENERIC,
|
||||
#ifdef DRACO_TRANSCODER_SUPPORTED
|
||||
// TODO(ostava): Adding a new attribute would be bit-stream change for GLTF.
|
||||
// Older decoders wouldn't know what to do with this attribute type. This
|
||||
// should be open-sourced only when we are ready to increase our bit-stream
|
||||
// version.
|
||||
TANGENT,
|
||||
MATERIAL,
|
||||
JOINTS,
|
||||
WEIGHTS,
|
||||
#endif
|
||||
// Total number of different attribute types.
|
||||
// Always keep behind all named attributes.
|
||||
NAMED_ATTRIBUTES_COUNT,
|
||||
|
@ -111,6 +122,9 @@ class GeometryAttribute {
|
|||
const int64_t byte_pos = GetBytePos(att_index);
|
||||
return buffer_->data() + byte_pos;
|
||||
}
|
||||
inline bool IsAddressValid(const uint8_t *address) const {
|
||||
return ((buffer_->data() + buffer_->data_size()) > address);
|
||||
}
|
||||
|
||||
// Fills out_data with the raw value of the requested attribute entry.
|
||||
// out_data must be at least byte_stride_ long.
|
||||
|
@ -263,7 +277,35 @@ class GeometryAttribute {
|
|||
|
||||
// Convert all components available in both the original and output formats.
|
||||
for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
|
||||
if (!IsAddressValid(src_address)) {
|
||||
return false;
|
||||
}
|
||||
const T in_value = *reinterpret_cast<const T *>(src_address);
|
||||
|
||||
// Make sure the in_value fits within the range of values that OutT
|
||||
// is able to represent. Perform the check only for integral types.
|
||||
if (std::is_integral<T>::value && std::is_integral<OutT>::value) {
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4804)
|
||||
#endif
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wbool-compare"
|
||||
#endif
|
||||
static constexpr OutT kOutMin =
|
||||
std::is_signed<T>::value ? std::numeric_limits<OutT>::lowest() : 0;
|
||||
if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
|
||||
return false;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
out_value[i] = static_cast<OutT>(in_value);
|
||||
// When converting integer to floating point, normalize the value if
|
||||
// necessary.
|
||||
|
|
|
@ -222,4 +222,47 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateFormattedValues(
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef DRACO_TRANSCODER_SUPPORTED
|
||||
void PointAttribute::RemoveUnusedValues() {
|
||||
if (is_mapping_identity()) {
|
||||
return; // For identity mapping, all values are always used.
|
||||
}
|
||||
// For explicit mapping we need to check if any point is mapped to a value.
|
||||
// If not we can delete the value.
|
||||
IndexTypeVector<AttributeValueIndex, bool> is_value_used(size(), false);
|
||||
int num_used_values = 0;
|
||||
for (PointIndex pi(0); pi < indices_map_.size(); ++pi) {
|
||||
const AttributeValueIndex avi = indices_map_[pi];
|
||||
if (!is_value_used[avi]) {
|
||||
is_value_used[avi] = true;
|
||||
num_used_values++;
|
||||
}
|
||||
}
|
||||
if (num_used_values == size()) {
|
||||
return; // All values are used.
|
||||
}
|
||||
|
||||
// Remap the values and update the point to value mapping.
|
||||
IndexTypeVector<AttributeValueIndex, AttributeValueIndex>
|
||||
old_to_new_value_map(size(), kInvalidAttributeValueIndex);
|
||||
AttributeValueIndex new_avi(0);
|
||||
for (AttributeValueIndex avi(0); avi < size(); ++avi) {
|
||||
if (!is_value_used[avi]) {
|
||||
continue;
|
||||
}
|
||||
if (avi != new_avi) {
|
||||
SetAttributeValue(new_avi, GetAddress(avi));
|
||||
}
|
||||
old_to_new_value_map[avi] = new_avi++;
|
||||
}
|
||||
|
||||
// Remap all points to the new attribute values.
|
||||
for (PointIndex pi(0); pi < indices_map_.size(); ++pi) {
|
||||
indices_map_[pi] = old_to_new_value_map[indices_map_[pi]];
|
||||
}
|
||||
|
||||
num_unique_entries_ = num_used_values;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -133,6 +133,12 @@ class PointAttribute : public GeometryAttribute {
|
|||
return attribute_transform_data_.get();
|
||||
}
|
||||
|
||||
#ifdef DRACO_TRANSCODER_SUPPORTED
|
||||
// Removes unused values from the attribute. Value is unused when no point
|
||||
// is mapped to the value. Only applicable when the mapping is not identity.
|
||||
void RemoveUnusedValues();
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
|
||||
template <typename T>
|
||||
|
|
|
@ -43,9 +43,18 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that decoded number of attributes is valid.
|
||||
if (num_attributes == 0) {
|
||||
return false;
|
||||
}
|
||||
if (num_attributes > 5 * in_buffer->remaining_size()) {
|
||||
// The decoded number of attributes is unreasonably high, because at least
|
||||
// five bytes of attribute descriptor data per attribute are expected.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode attribute descriptor data.
|
||||
point_attribute_ids_.resize(num_attributes);
|
||||
PointCloud *pc = point_cloud_;
|
||||
for (uint32_t i = 0; i < num_attributes; ++i) {
|
||||
|
@ -69,9 +78,14 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
|
|||
if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) {
|
||||
return false;
|
||||
}
|
||||
const DataType draco_dt = static_cast<DataType>(data_type);
|
||||
|
||||
// Add the attribute to the point cloud
|
||||
// Check decoded attribute descriptor data.
|
||||
if (num_components == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the attribute to the point cloud.
|
||||
const DataType draco_dt = static_cast<DataType>(data_type);
|
||||
GeometryAttribute ga;
|
||||
ga.Init(static_cast<GeometryAttribute::Type>(att_type), nullptr,
|
||||
num_components, draco_dt, normalized > 0,
|
||||
|
@ -90,7 +104,9 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
DecodeVarint(&unique_id, in_buffer);
|
||||
if (!DecodeVarint(&unique_id, in_buffer)) {
|
||||
return false;
|
||||
}
|
||||
ga.set_unique_id(unique_id);
|
||||
}
|
||||
const int att_id = pc->AddAttribute(
|
||||
|
|
|
@ -15,14 +15,16 @@
|
|||
#include "draco/compression/attributes/attributes_encoder.h"
|
||||
|
||||
#include "draco/core/varint_encoding.h"
|
||||
#include "draco/draco_features.h"
|
||||
|
||||
namespace draco {
|
||||
|
||||
AttributesEncoder::AttributesEncoder()
|
||||
: point_cloud_encoder_(nullptr), point_cloud_(nullptr) {}
|
||||
|
||||
AttributesEncoder::AttributesEncoder(int att_id) : AttributesEncoder() {
|
||||
AddAttributeId(att_id);
|
||||
AttributesEncoder::AttributesEncoder(int point_attrib_id)
|
||||
: AttributesEncoder() {
|
||||
AddAttributeId(point_attrib_id);
|
||||
}
|
||||
|
||||
bool AttributesEncoder::Init(PointCloudEncoder *encoder, const PointCloud *pc) {
|
||||
|
@ -37,7 +39,15 @@ bool AttributesEncoder::EncodeAttributesEncoderData(EncoderBuffer *out_buffer) {
|
|||
for (uint32_t i = 0; i < num_attributes(); ++i) {
|
||||
const int32_t att_id = point_attribute_ids_[i];
|
||||
const PointAttribute *const pa = point_cloud_->attribute(att_id);
|
||||
out_buffer->Encode(static_cast<uint8_t>(pa->attribute_type()));
|
||||
GeometryAttribute::Type type = pa->attribute_type();
|
||||
#ifdef DRACO_TRANSCODER_SUPPORTED
|
||||
// Attribute types TANGENT, MATERIAL, JOINTS, and WEIGHTS are not supported
|
||||
// in the official bitstream. They will be encoded as GENERIC.
|
||||
if (type > GeometryAttribute::GENERIC) {
|
||||
type = GeometryAttribute::GENERIC;
|
||||
}
|
||||
#endif
|
||||
out_buffer->Encode(static_cast<uint8_t>(type));
|
||||
out_buffer->Encode(static_cast<uint8_t>(pa->data_type()));
|
||||
out_buffer->Encode(static_cast<uint8_t>(pa->num_components()));
|
||||
out_buffer->Encode(static_cast<uint8_t>(pa->normalized()));
|
||||
|
|
|
@ -72,7 +72,7 @@ class PointAttributeVectorOutputIterator {
|
|||
|
||||
Self &operator*() { return *this; }
|
||||
// Still needed in some cases.
|
||||
// TODO(hemmer): remove.
|
||||
// TODO(b/199760123): Remove.
|
||||
// hardcoded to 3 based on legacy usage.
|
||||
const Self &operator=(const VectorD<CoeffT, 3> &val) {
|
||||
DRACO_DCHECK_EQ(attributes_.size(), 1); // Expect only ONE attribute.
|
||||
|
@ -278,8 +278,10 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
|
|||
return false;
|
||||
}
|
||||
AttributeQuantizationTransform transform;
|
||||
transform.SetParameters(quantization_bits, min_value.data(),
|
||||
num_components, max_value_dif);
|
||||
if (!transform.SetParameters(quantization_bits, min_value.data(),
|
||||
num_components, max_value_dif)) {
|
||||
return false;
|
||||
}
|
||||
const int num_transforms =
|
||||
static_cast<int>(attribute_quantization_transforms_.size());
|
||||
if (!transform.TransferToAttribute(
|
||||
|
@ -293,7 +295,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
|
|||
// Decode transform data for signed integer attributes.
|
||||
for (int i = 0; i < min_signed_values_.size(); ++i) {
|
||||
int32_t val;
|
||||
DecodeVarint(&val, in_buffer);
|
||||
if (!DecodeVarint(&val, in_buffer)) {
|
||||
return false;
|
||||
}
|
||||
min_signed_values_[i] = val;
|
||||
}
|
||||
return true;
|
||||
|
@ -353,8 +357,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
|
|||
return false;
|
||||
}
|
||||
if (6 < compression_level) {
|
||||
LOGE("KdTreeAttributesDecoder: compression level %i not supported.\n",
|
||||
compression_level);
|
||||
DRACO_LOGE(
|
||||
"KdTreeAttributesDecoder: compression level %i not supported.\n",
|
||||
compression_level);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -371,7 +376,7 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
|
|||
GetDecoder()->point_cloud()->attribute(att_id);
|
||||
attr->Reset(num_points);
|
||||
attr->SetIdentityMapping();
|
||||
};
|
||||
}
|
||||
|
||||
PointAttributeVectorOutputIterator<uint32_t> out_it(atts);
|
||||
|
||||
|
|
|
@ -71,16 +71,21 @@ bool KdTreeAttributesEncoder::TransformAttributesToPortableFormat() {
|
|||
att->num_components(), range);
|
||||
} else {
|
||||
// Compute quantization settings from the attribute values.
|
||||
attribute_quantization_transform.ComputeParameters(*att,
|
||||
quantization_bits);
|
||||
if (!attribute_quantization_transform.ComputeParameters(
|
||||
*att, quantization_bits)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
attribute_quantization_transforms_.push_back(
|
||||
attribute_quantization_transform);
|
||||
// Store the quantized attribute in an array that will be used when we do
|
||||
// the actual encoding of the data.
|
||||
quantized_portable_attributes_.push_back(
|
||||
attribute_quantization_transform.GeneratePortableAttribute(
|
||||
*att, static_cast<int>(num_points)));
|
||||
auto portable_att =
|
||||
attribute_quantization_transform.InitTransformedAttribute(*att,
|
||||
num_points);
|
||||
attribute_quantization_transform.TransformAttribute(*att, {},
|
||||
portable_att.get());
|
||||
quantized_portable_attributes_.push_back(std::move(portable_att));
|
||||
} else if (att->data_type() == DT_INT32 || att->data_type() == DT_INT16 ||
|
||||
att->data_type() == DT_INT8) {
|
||||
// For signed types, find the minimum value for each component. These
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
|
||||
#include "draco/attributes/attribute_quantization_transform.h"
|
||||
#include "draco/compression/attributes/attributes_encoder.h"
|
||||
|
@ -48,4 +48,4 @@ class KdTreeAttributesEncoder : public AttributesEncoder {
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
#endif // DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
|
||||
|
|
|
@ -53,6 +53,7 @@ class OctahedronToolBox {
|
|||
: quantization_bits_(-1),
|
||||
max_quantized_value_(-1),
|
||||
max_value_(-1),
|
||||
dequantization_scale_(1.f),
|
||||
center_value_(-1) {}
|
||||
|
||||
bool SetQuantizationBits(int32_t q) {
|
||||
|
@ -62,6 +63,7 @@ class OctahedronToolBox {
|
|||
quantization_bits_ = q;
|
||||
max_quantized_value_ = (1 << quantization_bits_) - 1;
|
||||
max_value_ = max_quantized_value_ - 1;
|
||||
dequantization_scale_ = 2.f / max_value_;
|
||||
center_value_ = max_value_ / 2;
|
||||
return true;
|
||||
}
|
||||
|
@ -192,64 +194,11 @@ class OctahedronToolBox {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(b/149328891): Change function to not use templates as |T| is only
|
||||
// float.
|
||||
template <typename T>
|
||||
void OctaherdalCoordsToUnitVector(T in_s, T in_t, T *out_vector) const {
|
||||
DRACO_DCHECK_GE(in_s, 0);
|
||||
DRACO_DCHECK_GE(in_t, 0);
|
||||
DRACO_DCHECK_LE(in_s, 1);
|
||||
DRACO_DCHECK_LE(in_t, 1);
|
||||
T s = in_s;
|
||||
T t = in_t;
|
||||
T spt = s + t;
|
||||
T smt = s - t;
|
||||
T x_sign = 1.0;
|
||||
if (spt >= 0.5 && spt <= 1.5 && smt >= -0.5 && smt <= 0.5) {
|
||||
// Right hemisphere. Don't do anything.
|
||||
} else {
|
||||
// Left hemisphere.
|
||||
x_sign = -1.0;
|
||||
if (spt <= 0.5) {
|
||||
s = 0.5 - in_t;
|
||||
t = 0.5 - in_s;
|
||||
} else if (spt >= 1.5) {
|
||||
s = 1.5 - in_t;
|
||||
t = 1.5 - in_s;
|
||||
} else if (smt <= -0.5) {
|
||||
s = in_t - 0.5;
|
||||
t = in_s + 0.5;
|
||||
} else {
|
||||
s = in_t + 0.5;
|
||||
t = in_s - 0.5;
|
||||
}
|
||||
spt = s + t;
|
||||
smt = s - t;
|
||||
}
|
||||
const T y = 2.0 * s - 1.0;
|
||||
const T z = 2.0 * t - 1.0;
|
||||
const T x = std::min(std::min(2.0 * spt - 1.0, 3.0 - 2.0 * spt),
|
||||
std::min(2.0 * smt + 1.0, 1.0 - 2.0 * smt)) *
|
||||
x_sign;
|
||||
// Normalize the computed vector.
|
||||
const T normSquared = x * x + y * y + z * z;
|
||||
if (normSquared < 1e-6) {
|
||||
out_vector[0] = 0;
|
||||
out_vector[1] = 0;
|
||||
out_vector[2] = 0;
|
||||
} else {
|
||||
const T d = 1.0 / std::sqrt(normSquared);
|
||||
out_vector[0] = x * d;
|
||||
out_vector[1] = y * d;
|
||||
out_vector[2] = z * d;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void QuantizedOctaherdalCoordsToUnitVector(int32_t in_s, int32_t in_t,
|
||||
T *out_vector) const {
|
||||
T scale = 1.0 / static_cast<T>(max_value_);
|
||||
OctaherdalCoordsToUnitVector(in_s * scale, in_t * scale, out_vector);
|
||||
inline void QuantizedOctahedralCoordsToUnitVector(int32_t in_s, int32_t in_t,
|
||||
float *out_vector) const {
|
||||
OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f,
|
||||
in_t * dequantization_scale_ - 1.f,
|
||||
out_vector);
|
||||
}
|
||||
|
||||
// |s| and |t| are expected to be signed values.
|
||||
|
@ -333,9 +282,77 @@ class OctahedronToolBox {
|
|||
int32_t center_value() const { return center_value_; }
|
||||
|
||||
private:
|
||||
inline void OctahedralCoordsToUnitVector(float in_s_scaled, float in_t_scaled,
|
||||
float *out_vector) const {
|
||||
// Background about the encoding:
|
||||
// A normal is encoded in a normalized space <s, t> depicted below. The
|
||||
// encoding correponds to an octahedron that is unwrapped to a 2D plane.
|
||||
// During encoding, a normal is projected to the surface of the octahedron
|
||||
// and the projection is then unwrapped to the 2D plane. Decoding is the
|
||||
// reverse of this process.
|
||||
// All points in the central diamond are located on triangles on the
|
||||
// right "hemisphere" of the octahedron while all points outside of the
|
||||
// diamond are on the left hemisphere (basically, they would have to be
|
||||
// wrapped along the diagonal edges to form the octahedron). The central
|
||||
// point corresponds to the right most vertex of the octahedron and all
|
||||
// corners of the plane correspond to the left most vertex of the
|
||||
// octahedron.
|
||||
//
|
||||
// t
|
||||
// ^ *-----*-----*
|
||||
// | | /|\ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// *-----*---- *
|
||||
// | \ | / |
|
||||
// | \ | / |
|
||||
// | \ | / |
|
||||
// | \|/ |
|
||||
// *-----*-----* --> s
|
||||
|
||||
// Note that the input |in_s_scaled| and |in_t_scaled| are already scaled to
|
||||
// <-1, 1> range. This way, the central point is at coordinate (0, 0).
|
||||
float y = in_s_scaled;
|
||||
float z = in_t_scaled;
|
||||
|
||||
// Remaining coordinate can be computed by projecting the (y, z) values onto
|
||||
// the surface of the octahedron.
|
||||
const float x = 1.f - std::abs(y) - std::abs(z);
|
||||
|
||||
// |x| is essentially a signed distance from the diagonal edges of the
|
||||
// diamond shown on the figure above. It is positive for all points in the
|
||||
// diamond (right hemisphere) and negative for all points outside the
|
||||
// diamond (left hemisphere). For all points on the left hemisphere we need
|
||||
// to update their (y, z) coordinates to account for the wrapping along
|
||||
// the edges of the diamond.
|
||||
float x_offset = -x;
|
||||
x_offset = x_offset < 0 ? 0 : x_offset;
|
||||
|
||||
// This will do nothing for the points on the right hemisphere but it will
|
||||
// mirror the (y, z) location along the nearest diagonal edge of the
|
||||
// diamond.
|
||||
y += y < 0 ? x_offset : -x_offset;
|
||||
z += z < 0 ? x_offset : -x_offset;
|
||||
|
||||
// Normalize the computed vector.
|
||||
const float norm_squared = x * x + y * y + z * z;
|
||||
if (norm_squared < 1e-6) {
|
||||
out_vector[0] = 0;
|
||||
out_vector[1] = 0;
|
||||
out_vector[2] = 0;
|
||||
} else {
|
||||
const float d = 1.0f / std::sqrt(norm_squared);
|
||||
out_vector[0] = x * d;
|
||||
out_vector[1] = y * d;
|
||||
out_vector[2] = z * d;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t quantization_bits_;
|
||||
int32_t max_quantized_value_;
|
||||
int32_t max_value_;
|
||||
float dequantization_scale_;
|
||||
int32_t center_value_;
|
||||
};
|
||||
} // namespace draco
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_
|
||||
|
||||
#include "draco/mesh/corner_table.h"
|
||||
#include "draco/mesh/mesh.h"
|
||||
|
|
|
@ -69,7 +69,14 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
|
|||
|
||||
// Computing cross product.
|
||||
const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
|
||||
normal = normal + cross;
|
||||
|
||||
// Prevent signed integer overflows by doing math as unsigned.
|
||||
auto normal_data = reinterpret_cast<uint64_t *>(normal.data());
|
||||
auto cross_data = reinterpret_cast<const uint64_t *>(cross.data());
|
||||
normal_data[0] = normal_data[0] + cross_data[0];
|
||||
normal_data[1] = normal_data[1] + cross_data[1];
|
||||
normal_data[2] = normal_data[2] + cross_data[2];
|
||||
|
||||
cit.Next();
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,13 @@ inline bool ComputeParallelogramPrediction(
|
|||
const int v_next_off = vert_next * num_components;
|
||||
const int v_prev_off = vert_prev * num_components;
|
||||
for (int c = 0; c < num_components; ++c) {
|
||||
out_prediction[c] = (in_data[v_next_off + c] + in_data[v_prev_off + c]) -
|
||||
in_data[v_opp_off + c];
|
||||
const int64_t in_data_next_off = in_data[v_next_off + c];
|
||||
const int64_t in_data_prev_off = in_data[v_prev_off + c];
|
||||
const int64_t in_data_opp_off = in_data[v_opp_off + c];
|
||||
const int64_t result =
|
||||
(in_data_next_off + in_data_prev_off) - in_data_opp_off;
|
||||
|
||||
out_prediction[c] = static_cast<DataTypeT>(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -156,6 +156,13 @@ bool MeshPredictionSchemeTexCoordsPortablePredictor<
|
|||
const VectorD<int64_t, 2> x_uv =
|
||||
n_uv * pn_norm2_squared + (cn_dot_pn * pn_uv);
|
||||
|
||||
const int64_t pn_absmax_element =
|
||||
std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
|
||||
if (cn_dot_pn > std::numeric_limits<int64_t>::max() / pn_absmax_element) {
|
||||
// return false if squared length calculation would overflow.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute squared length of vector CX in position coordinate system:
|
||||
const VectorD<int64_t, 3> x_pos =
|
||||
next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
|
||||
|
|
|
@ -18,34 +18,51 @@ namespace draco {
|
|||
|
||||
PredictionSchemeMethod SelectPredictionMethod(
|
||||
int att_id, const PointCloudEncoder *encoder) {
|
||||
if (encoder->options()->GetSpeed() >= 10) {
|
||||
return SelectPredictionMethod(att_id, *encoder->options(), encoder);
|
||||
}
|
||||
|
||||
PredictionSchemeMethod SelectPredictionMethod(
|
||||
int att_id, const EncoderOptions &options,
|
||||
const PointCloudEncoder *encoder) {
|
||||
if (options.GetSpeed() >= 10) {
|
||||
// Selected fastest, though still doing some compression.
|
||||
return PREDICTION_DIFFERENCE;
|
||||
}
|
||||
if (encoder->GetGeometryType() == TRIANGULAR_MESH) {
|
||||
// Use speed setting to select the best encoding method.
|
||||
const PointAttribute *const att = encoder->point_cloud()->attribute(att_id);
|
||||
if (att->attribute_type() == GeometryAttribute::TEX_COORD) {
|
||||
if (encoder->options()->GetSpeed() < 4) {
|
||||
if (att->attribute_type() == GeometryAttribute::TEX_COORD &&
|
||||
att->num_components() == 2) {
|
||||
if (options.GetSpeed() < 4) {
|
||||
// Use texture coordinate prediction for speeds 0, 1, 2, 3.
|
||||
return MESH_PREDICTION_TEX_COORDS_PORTABLE;
|
||||
}
|
||||
}
|
||||
if (att->attribute_type() == GeometryAttribute::NORMAL) {
|
||||
#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
|
||||
if (encoder->options()->GetSpeed() < 4) {
|
||||
if (options.GetSpeed() < 4) {
|
||||
// Use geometric normal prediction for speeds 0, 1, 2, 3.
|
||||
return MESH_PREDICTION_GEOMETRIC_NORMAL;
|
||||
// For this prediction, the position attribute needs to be either
|
||||
// integer or quantized as well.
|
||||
const int pos_att_id = encoder->point_cloud()->GetNamedAttributeId(
|
||||
GeometryAttribute::POSITION);
|
||||
const PointAttribute *const pos_att =
|
||||
encoder->point_cloud()->GetNamedAttribute(
|
||||
GeometryAttribute::POSITION);
|
||||
if (pos_att && (IsDataTypeIntegral(pos_att->data_type()) ||
|
||||
options.GetAttributeInt(pos_att_id, "quantization_bits",
|
||||
-1) > 0)) {
|
||||
return MESH_PREDICTION_GEOMETRIC_NORMAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return PREDICTION_DIFFERENCE; // default
|
||||
}
|
||||
// Handle other attribute types.
|
||||
if (encoder->options()->GetSpeed() >= 8) {
|
||||
if (options.GetSpeed() >= 8) {
|
||||
return PREDICTION_DIFFERENCE;
|
||||
}
|
||||
if (encoder->options()->GetSpeed() >= 2 ||
|
||||
encoder->point_cloud()->num_points() < 40) {
|
||||
if (options.GetSpeed() >= 2 || encoder->point_cloud()->num_points() < 40) {
|
||||
// Parallelogram prediction is used for speeds 2 - 7 or when the overhead
|
||||
// of using constrained multi-parallelogram would be too high.
|
||||
return MESH_PREDICTION_PARALLELOGRAM;
|
||||
|
|
|
@ -38,6 +38,10 @@ namespace draco {
|
|||
PredictionSchemeMethod SelectPredictionMethod(int att_id,
|
||||
const PointCloudEncoder *encoder);
|
||||
|
||||
PredictionSchemeMethod SelectPredictionMethod(int att_id,
|
||||
const EncoderOptions &options,
|
||||
const PointCloudEncoder *encoder);
|
||||
|
||||
// Factory class for creating mesh prediction schemes.
|
||||
template <typename DataTypeT>
|
||||
struct MeshPredictionSchemeEncoderFactory {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
|
||||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
|
||||
|
||||
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h"
|
||||
#include "draco/core/encoder_buffer.h"
|
||||
|
@ -52,4 +52,4 @@ class PredictionSchemeTypedEncoderInterface
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
|
||||
#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
|
||||
|
|
|
@ -36,9 +36,25 @@ class PredictionSchemeWrapDecodingTransform
|
|||
inline void ComputeOriginalValue(const DataTypeT *predicted_vals,
|
||||
const CorrTypeT *corr_vals,
|
||||
DataTypeT *out_original_vals) const {
|
||||
// For now we assume both |DataTypeT| and |CorrTypeT| are equal.
|
||||
static_assert(std::is_same<DataTypeT, CorrTypeT>::value,
|
||||
"Predictions and corrections must have the same type.");
|
||||
|
||||
// The only valid implementation right now is for int32_t.
|
||||
static_assert(std::is_same<DataTypeT, int32_t>::value,
|
||||
"Only int32_t is supported for predicted values.");
|
||||
|
||||
predicted_vals = this->ClampPredictedValue(predicted_vals);
|
||||
|
||||
// Perform the wrapping using unsigned coordinates to avoid potential signed
|
||||
// integer overflows caused by malformed input.
|
||||
const uint32_t *const uint_predicted_vals =
|
||||
reinterpret_cast<const uint32_t *>(predicted_vals);
|
||||
const uint32_t *const uint_corr_vals =
|
||||
reinterpret_cast<const uint32_t *>(corr_vals);
|
||||
for (int i = 0; i < this->num_components(); ++i) {
|
||||
out_original_vals[i] = predicted_vals[i] + corr_vals[i];
|
||||
out_original_vals[i] =
|
||||
static_cast<DataTypeT>(uint_predicted_vals[i] + uint_corr_vals[i]);
|
||||
if (out_original_vals[i] > this->max_value()) {
|
||||
out_original_vals[i] -= this->max_dif();
|
||||
} else if (out_original_vals[i] < this->min_value()) {
|
||||
|
|
|
@ -73,7 +73,7 @@ class PredictionSchemeWrapTransformBase {
|
|||
return &clamped_value_[0];
|
||||
}
|
||||
|
||||
// TODO(hemmer): Consider refactoring to avoid this dummy.
|
||||
// TODO(b/199760123): Consider refactoring to avoid this dummy.
|
||||
int quantization_bits() const {
|
||||
DRACO_DCHECK(false);
|
||||
return -1;
|
||||
|
|
|
@ -26,8 +26,8 @@ SequentialAttributeEncodersController::SequentialAttributeEncodersController(
|
|||
: sequencer_(std::move(sequencer)) {}
|
||||
|
||||
SequentialAttributeEncodersController::SequentialAttributeEncodersController(
|
||||
std::unique_ptr<PointsSequencer> sequencer, int att_id)
|
||||
: AttributesEncoder(att_id), sequencer_(std::move(sequencer)) {}
|
||||
std::unique_ptr<PointsSequencer> sequencer, int point_attrib_id)
|
||||
: AttributesEncoder(point_attrib_id), sequencer_(std::move(sequencer)) {}
|
||||
|
||||
bool SequentialAttributeEncodersController::Init(PointCloudEncoder *encoder,
|
||||
const PointCloud *pc) {
|
||||
|
|
|
@ -53,6 +53,11 @@ bool SequentialIntegerAttributeDecoder::DecodeValues(
|
|||
if (!in_buffer->Decode(&prediction_transform_type)) {
|
||||
return false;
|
||||
}
|
||||
// Check that decoded prediction scheme transform type is valid.
|
||||
if (prediction_transform_type < PREDICTION_TRANSFORM_NONE ||
|
||||
prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) {
|
||||
return false;
|
||||
}
|
||||
prediction_scheme_ = CreateIntPredictionScheme(
|
||||
static_cast<PredictionSchemeMethod>(prediction_scheme_method),
|
||||
static_cast<PredictionSchemeTransformType>(prediction_transform_type));
|
||||
|
@ -143,8 +148,9 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues(
|
|||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < num_values; ++i) {
|
||||
if (!in_buffer->Decode(portable_attribute_data + i, num_bytes))
|
||||
if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,12 +229,13 @@ void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
|
|||
|
||||
void SequentialIntegerAttributeDecoder::PreparePortableAttribute(
|
||||
int num_entries, int num_components) {
|
||||
GeometryAttribute va;
|
||||
va.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
|
||||
GeometryAttribute ga;
|
||||
ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
|
||||
false, num_components * DataTypeLength(DT_INT32), 0);
|
||||
std::unique_ptr<PointAttribute> port_att(new PointAttribute(va));
|
||||
std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga));
|
||||
port_att->SetIdentityMapping();
|
||||
port_att->Reset(num_entries);
|
||||
port_att->set_unique_id(attribute()->unique_id());
|
||||
SetPortableAttribute(std::move(port_att));
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ bool SequentialIntegerAttributeEncoder::TransformAttributeToPortableFormat(
|
|||
value_to_value_map[orig_att->mapped_index(point_ids[i])] =
|
||||
AttributeValueIndex(i);
|
||||
}
|
||||
if (portable_att->is_mapping_identity()) {
|
||||
portable_att->SetExplicitMapping(encoder()->point_cloud()->num_points());
|
||||
}
|
||||
// Go over all points of the original attribute and update the mapping in
|
||||
// the portable attribute.
|
||||
for (PointIndex i(0); i < encoder()->point_cloud()->num_points(); ++i) {
|
||||
|
|
|
@ -14,18 +14,17 @@
|
|||
//
|
||||
#include "draco/compression/attributes/sequential_normal_attribute_decoder.h"
|
||||
|
||||
#include "draco/attributes/attribute_octahedron_transform.h"
|
||||
#include "draco/compression/attributes/normal_compression_utils.h"
|
||||
|
||||
namespace draco {
|
||||
|
||||
SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder()
|
||||
: quantization_bits_(-1) {}
|
||||
SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() {}
|
||||
|
||||
bool SequentialNormalAttributeDecoder::Init(PointCloudDecoder *decoder,
|
||||
int attribute_id) {
|
||||
if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id))
|
||||
if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
|
||||
return false;
|
||||
}
|
||||
// Currently, this encoder works only for 3-component normal vectors.
|
||||
if (attribute()->num_components() != 3) {
|
||||
return false;
|
||||
|
@ -41,11 +40,13 @@ bool SequentialNormalAttributeDecoder::DecodeIntegerValues(
|
|||
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
|
||||
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
|
||||
if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
|
||||
uint8_t quantization_bits;
|
||||
if (!in_buffer->Decode(&quantization_bits)) {
|
||||
// Note: in older bitstreams, we do not have a PortableAttribute() decoded
|
||||
// at this stage so we cannot pass it down to the DecodeParameters() call.
|
||||
// It still works fine for octahedral transform because it does not need to
|
||||
// use any data from the attribute.
|
||||
if (!octahedral_transform_.DecodeParameters(*attribute(), in_buffer)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
}
|
||||
#endif
|
||||
return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
|
||||
|
@ -56,39 +57,20 @@ bool SequentialNormalAttributeDecoder::DecodeDataNeededByPortableTransform(
|
|||
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
|
||||
if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
|
||||
// For newer file version, decode attribute transform data here.
|
||||
uint8_t quantization_bits;
|
||||
if (!in_buffer->Decode(&quantization_bits)) {
|
||||
if (!octahedral_transform_.DecodeParameters(*GetPortableAttribute(),
|
||||
in_buffer)) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
}
|
||||
|
||||
// Store the decoded transform data in portable attribute.
|
||||
AttributeOctahedronTransform octahedral_transform;
|
||||
octahedral_transform.SetParameters(quantization_bits_);
|
||||
return octahedral_transform.TransferToAttribute(portable_attribute());
|
||||
return octahedral_transform_.TransferToAttribute(portable_attribute());
|
||||
}
|
||||
|
||||
bool SequentialNormalAttributeDecoder::StoreValues(uint32_t num_points) {
|
||||
// Convert all quantized values back to floats.
|
||||
const int num_components = attribute()->num_components();
|
||||
const int entry_size = sizeof(float) * num_components;
|
||||
float att_val[3];
|
||||
int quant_val_id = 0;
|
||||
int out_byte_pos = 0;
|
||||
const int32_t *const portable_attribute_data = GetPortableAttributeData();
|
||||
OctahedronToolBox octahedron_tool_box;
|
||||
if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_))
|
||||
return false;
|
||||
for (uint32_t i = 0; i < num_points; ++i) {
|
||||
const int32_t s = portable_attribute_data[quant_val_id++];
|
||||
const int32_t t = portable_attribute_data[quant_val_id++];
|
||||
octahedron_tool_box.QuantizedOctaherdalCoordsToUnitVector(s, t, att_val);
|
||||
// Store the decoded floating point value into the attribute buffer.
|
||||
attribute()->buffer()->Write(out_byte_pos, att_val, entry_size);
|
||||
out_byte_pos += entry_size;
|
||||
}
|
||||
return true;
|
||||
return octahedral_transform_.InverseTransformAttribute(
|
||||
*GetPortableAttribute(), attribute());
|
||||
}
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_
|
||||
|
||||
#include "draco/attributes/attribute_octahedron_transform.h"
|
||||
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h"
|
||||
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h"
|
||||
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h"
|
||||
|
@ -42,7 +43,7 @@ class SequentialNormalAttributeDecoder
|
|||
bool StoreValues(uint32_t num_points) override;
|
||||
|
||||
private:
|
||||
int32_t quantization_bits_;
|
||||
AttributeOctahedronTransform octahedral_transform_;
|
||||
|
||||
std::unique_ptr<PredictionSchemeTypedDecoderInterface<int32_t>>
|
||||
CreateIntPredictionScheme(
|
||||
|
|
|
@ -20,8 +20,9 @@ namespace draco {
|
|||
|
||||
bool SequentialNormalAttributeEncoder::Init(PointCloudEncoder *encoder,
|
||||
int attribute_id) {
|
||||
if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id))
|
||||
if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) {
|
||||
return false;
|
||||
}
|
||||
// Currently this encoder works only for 3-component normal vectors.
|
||||
if (attribute()->num_components() != 3) {
|
||||
return false;
|
||||
|
@ -44,9 +45,13 @@ bool SequentialNormalAttributeEncoder::EncodeDataNeededByPortableTransform(
|
|||
|
||||
bool SequentialNormalAttributeEncoder::PrepareValues(
|
||||
const std::vector<PointIndex> &point_ids, int num_points) {
|
||||
SetPortableAttribute(
|
||||
attribute_octahedron_transform_.GeneratePortableAttribute(
|
||||
*(attribute()), point_ids, num_points));
|
||||
auto portable_att = attribute_octahedron_transform_.InitTransformedAttribute(
|
||||
*(attribute()), point_ids.size());
|
||||
if (!attribute_octahedron_transform_.TransformAttribute(
|
||||
*(attribute()), point_ids, portable_att.get())) {
|
||||
return false;
|
||||
}
|
||||
SetPortableAttribute(std::move(portable_att));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
//
|
||||
#include "draco/compression/attributes/sequential_quantization_attribute_decoder.h"
|
||||
|
||||
#include "draco/attributes/attribute_quantization_transform.h"
|
||||
#include "draco/core/quantization_utils.h"
|
||||
|
||||
namespace draco {
|
||||
|
||||
SequentialQuantizationAttributeDecoder::SequentialQuantizationAttributeDecoder()
|
||||
: quantization_bits_(-1), max_value_dif_(0.f) {}
|
||||
SequentialQuantizationAttributeDecoder::
|
||||
SequentialQuantizationAttributeDecoder() {}
|
||||
|
||||
bool SequentialQuantizationAttributeDecoder::Init(PointCloudDecoder *decoder,
|
||||
int attribute_id) {
|
||||
|
@ -59,62 +58,31 @@ bool SequentialQuantizationAttributeDecoder::
|
|||
}
|
||||
|
||||
// Store the decoded transform data in portable attribute;
|
||||
AttributeQuantizationTransform transform;
|
||||
transform.SetParameters(quantization_bits_, min_value_.get(),
|
||||
attribute()->num_components(), max_value_dif_);
|
||||
return transform.TransferToAttribute(portable_attribute());
|
||||
return quantization_transform_.TransferToAttribute(portable_attribute());
|
||||
}
|
||||
|
||||
bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_values) {
|
||||
return DequantizeValues(num_values);
|
||||
bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_points) {
|
||||
return DequantizeValues(num_points);
|
||||
}
|
||||
|
||||
bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
|
||||
const int num_components = attribute()->num_components();
|
||||
min_value_ = std::unique_ptr<float[]>(new float[num_components]);
|
||||
if (!decoder()->buffer()->Decode(min_value_.get(),
|
||||
sizeof(float) * num_components)) {
|
||||
return false;
|
||||
// Get attribute used as source for decoding.
|
||||
auto att = GetPortableAttribute();
|
||||
if (att == nullptr) {
|
||||
// This should happen only in the backward compatibility mode. It will still
|
||||
// work fine for this case because the only thing the quantization transform
|
||||
// cares about is the number of components that is the same for both source
|
||||
// and target attributes.
|
||||
att = attribute();
|
||||
}
|
||||
if (!decoder()->buffer()->Decode(&max_value_dif_)) {
|
||||
return false;
|
||||
}
|
||||
uint8_t quantization_bits;
|
||||
if (!decoder()->buffer()->Decode(&quantization_bits) ||
|
||||
quantization_bits > 31) {
|
||||
return false;
|
||||
}
|
||||
quantization_bits_ = quantization_bits;
|
||||
return true;
|
||||
return quantization_transform_.DecodeParameters(*att, decoder()->buffer());
|
||||
}
|
||||
|
||||
bool SequentialQuantizationAttributeDecoder::DequantizeValues(
|
||||
uint32_t num_values) {
|
||||
// Convert all quantized values back to floats.
|
||||
const int32_t max_quantized_value =
|
||||
(1u << static_cast<uint32_t>(quantization_bits_)) - 1;
|
||||
const int num_components = attribute()->num_components();
|
||||
const int entry_size = sizeof(float) * num_components;
|
||||
const std::unique_ptr<float[]> att_val(new float[num_components]);
|
||||
int quant_val_id = 0;
|
||||
int out_byte_pos = 0;
|
||||
Dequantizer dequantizer;
|
||||
if (!dequantizer.Init(max_value_dif_, max_quantized_value)) {
|
||||
return false;
|
||||
}
|
||||
const int32_t *const portable_attribute_data = GetPortableAttributeData();
|
||||
for (uint32_t i = 0; i < num_values; ++i) {
|
||||
for (int c = 0; c < num_components; ++c) {
|
||||
float value =
|
||||
dequantizer.DequantizeFloat(portable_attribute_data[quant_val_id++]);
|
||||
value = value + min_value_[c];
|
||||
att_val[c] = value;
|
||||
}
|
||||
// Store the floating point value into the attribute buffer.
|
||||
attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
|
||||
out_byte_pos += entry_size;
|
||||
}
|
||||
return true;
|
||||
return quantization_transform_.InverseTransformAttribute(
|
||||
*GetPortableAttribute(), attribute());
|
||||
}
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_
|
||||
#define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_
|
||||
|
||||
#include "draco/attributes/attribute_quantization_transform.h"
|
||||
#include "draco/compression/attributes/sequential_integer_attribute_decoder.h"
|
||||
#include "draco/draco_features.h"
|
||||
|
||||
|
@ -43,12 +44,7 @@ class SequentialQuantizationAttributeDecoder
|
|||
virtual bool DequantizeValues(uint32_t num_values);
|
||||
|
||||
private:
|
||||
// Max number of quantization bits used to encode each component of the
|
||||
// attribute.
|
||||
int32_t quantization_bits_;
|
||||
|
||||
std::unique_ptr<float[]> min_value_;
|
||||
float max_value_dif_;
|
||||
AttributeQuantizationTransform quantization_transform_;
|
||||
};
|
||||
|
||||
} // namespace draco
|
||||
|
|
|
@ -50,9 +50,11 @@ bool SequentialQuantizationAttributeEncoder::Init(PointCloudEncoder *encoder,
|
|||
&quantization_origin[0]);
|
||||
const float range = encoder->options()->GetAttributeFloat(
|
||||
attribute_id, "quantization_range", 1.f);
|
||||
attribute_quantization_transform_.SetParameters(
|
||||
quantization_bits, quantization_origin.data(),
|
||||
attribute->num_components(), range);
|
||||
if (!attribute_quantization_transform_.SetParameters(
|
||||
quantization_bits, quantization_origin.data(),
|
||||
attribute->num_components(), range)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Compute quantization settings from the attribute values.
|
||||
if (!attribute_quantization_transform_.ComputeParameters(
|
||||
|
@ -70,9 +72,14 @@ bool SequentialQuantizationAttributeEncoder::
|
|||
|
||||
bool SequentialQuantizationAttributeEncoder::PrepareValues(
|
||||
const std::vector<PointIndex> &point_ids, int num_points) {
|
||||
SetPortableAttribute(
|
||||
attribute_quantization_transform_.GeneratePortableAttribute(
|
||||
*(attribute()), point_ids, num_points));
|
||||
auto portable_attribute =
|
||||
attribute_quantization_transform_.InitTransformedAttribute(
|
||||
*attribute(), point_ids.size());
|
||||
if (!attribute_quantization_transform_.TransformAttribute(
|
||||
*(attribute()), point_ids, portable_attribute.get())) {
|
||||
return false;
|
||||
}
|
||||
SetPortableAttribute(std::move(portable_attribute));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ enum EncodedGeometryType {
|
|||
INVALID_GEOMETRY_TYPE = -1,
|
||||
POINT_CLOUD = 0,
|
||||
TRIANGULAR_MESH,
|
||||
NUM_ENCODED_GEOMETRY_TYPES
|
||||
};
|
||||
|
||||
// List of encoding methods for point clouds.
|
||||
|
@ -105,6 +106,8 @@ enum PredictionSchemeTransformType {
|
|||
// Specialized transform for normal coordinates using canonicalized inverted
|
||||
// tiles.
|
||||
PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED = 3,
|
||||
// The number of valid (non-negative) prediction scheme transform types.
|
||||
NUM_PREDICTION_SCHEME_TRANSFORM_TYPES
|
||||
};
|
||||
|
||||
// List of all mesh traversal methods supported by Draco framework.
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
#define DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
#ifndef DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
#define DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
@ -246,4 +246,4 @@ void DracoOptions<AttributeKeyT>::SetAttributeOptions(
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
#endif // DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
|
||||
|
|
|
@ -56,7 +56,10 @@ StatusOr<EncodedGeometryType> Decoder::GetEncodedGeometryType(
|
|||
DecoderBuffer *in_buffer) {
|
||||
DecoderBuffer temp_buffer(*in_buffer);
|
||||
DracoHeader header;
|
||||
DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
|
||||
DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header));
|
||||
if (header.encoder_type >= NUM_ENCODED_GEOMETRY_TYPES) {
|
||||
return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
|
||||
}
|
||||
return static_cast<EncodedGeometryType>(header.encoder_type);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
#define DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
#ifndef DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
#define DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
|
||||
#include "draco/attributes/geometry_attribute.h"
|
||||
#include "draco/compression/config/compression_shared.h"
|
||||
|
@ -98,7 +98,7 @@ class EncoderBase {
|
|||
"Invalid prediction scheme for attribute type.");
|
||||
}
|
||||
}
|
||||
// TODO(hemmer): Try to enable more prediction schemes for normals.
|
||||
// TODO(b/199760123): Try to enable more prediction schemes for normals.
|
||||
if (att_type == GeometryAttribute::NORMAL) {
|
||||
if (!(prediction_scheme == PREDICTION_DIFFERENCE ||
|
||||
prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL)) {
|
||||
|
@ -128,4 +128,4 @@ void EncoderBase<EncoderOptionsT>::SetTrackEncodedProperties(bool flag) {
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
#endif // DRACO_COMPRESSION_ENCODE_BASE_H_
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_CORE_ANS_H_
|
||||
#define DRACO_CORE_ANS_H_
|
||||
#ifndef DRACO_COMPRESSION_ENTROPY_ANS_H_
|
||||
#define DRACO_COMPRESSION_ENTROPY_ANS_H_
|
||||
// An implementation of Asymmetric Numeral Systems (rANS).
|
||||
// See http://arxiv.org/abs/1311.2540v2 for more information on rANS.
|
||||
// This file is based off libvpx's ans.h.
|
||||
|
@ -391,7 +391,6 @@ class RAnsEncoder {
|
|||
ans_.buf[ans_.buf_offset++] = ans_.state % DRACO_ANS_IO_BASE;
|
||||
ans_.state /= DRACO_ANS_IO_BASE;
|
||||
}
|
||||
// TODO(ostava): The division and multiplication should be optimized.
|
||||
ans_.state =
|
||||
(ans_.state / p) * rans_precision + ans_.state % p + sym->cum_prob;
|
||||
}
|
||||
|
@ -524,4 +523,4 @@ class RAnsDecoder {
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_CORE_ANS_H_
|
||||
#endif // DRACO_COMPRESSION_ENTROPY_ANS_H_
|
||||
|
|
|
@ -31,11 +31,10 @@ constexpr int ComputeRAnsUnclampedPrecision(int symbols_bit_length) {
|
|||
// our rANS library (which is between 12 to 20 bits).
|
||||
constexpr int ComputeRAnsPrecisionFromUniqueSymbolsBitLength(
|
||||
int symbols_bit_length) {
|
||||
return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12
|
||||
? 12
|
||||
: ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20
|
||||
? 20
|
||||
: ComputeRAnsUnclampedPrecision(symbols_bit_length);
|
||||
return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12 ? 12
|
||||
: ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20
|
||||
? 20
|
||||
: ComputeRAnsUnclampedPrecision(symbols_bit_length);
|
||||
}
|
||||
|
||||
// Compute approximate frequency table size needed for storing the provided
|
||||
|
|
|
@ -125,8 +125,8 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create(
|
|||
for (int i = 0; i < num_symbols; ++i) {
|
||||
sorted_probabilities[i] = i;
|
||||
}
|
||||
std::sort(sorted_probabilities.begin(), sorted_probabilities.end(),
|
||||
ProbabilityLess(&probability_table_));
|
||||
std::stable_sort(sorted_probabilities.begin(), sorted_probabilities.end(),
|
||||
ProbabilityLess(&probability_table_));
|
||||
if (total_rans_prob < rans_precision_) {
|
||||
// This happens rather infrequently, just add the extra needed precision
|
||||
// to the most frequent symbol.
|
||||
|
|
|
@ -72,7 +72,7 @@ bool DecodeTaggedSymbols(uint32_t num_values, int num_components,
|
|||
int value_id = 0;
|
||||
for (uint32_t i = 0; i < num_values; i += num_components) {
|
||||
// Decode the tag.
|
||||
const int bit_length = tag_decoder.DecodeSymbol();
|
||||
const uint32_t bit_length = tag_decoder.DecodeSymbol();
|
||||
// Decode the actual value.
|
||||
for (int j = 0; j < num_components; ++j) {
|
||||
uint32_t val;
|
||||
|
|
|
@ -67,7 +67,7 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc,
|
|||
kd_tree_possible = false;
|
||||
}
|
||||
if (kd_tree_possible && att->data_type() == DT_FLOAT32 &&
|
||||
options().GetAttributeInt(0, "quantization_bits", -1) <= 0) {
|
||||
options().GetAttributeInt(i, "quantization_bits", -1) <= 0) {
|
||||
kd_tree_possible = false; // Quantization not enabled.
|
||||
}
|
||||
if (!kd_tree_possible) {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
#define DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
#ifndef DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
#define DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
|
||||
#include "draco/compression/config/compression_shared.h"
|
||||
#include "draco/compression/config/encoder_options.h"
|
||||
|
@ -144,4 +144,4 @@ class ExpertEncoder : public EncoderBase<EncoderOptions> {
|
|||
|
||||
} // namespace draco
|
||||
|
||||
#endif // DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
#endif // DRACO_COMPRESSION_EXPERT_ENCODE_H_
|
||||
|
|
|
@ -162,6 +162,10 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder(
|
|||
if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
|
||||
return false;
|
||||
}
|
||||
// Check that decoded traversal method is valid.
|
||||
if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
|
||||
return false;
|
||||
}
|
||||
traversal_method =
|
||||
static_cast<MeshTraversalMethod>(traversal_method_encoded);
|
||||
}
|
||||
|
@ -450,7 +454,7 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
|
|||
#endif
|
||||
|
||||
// Decode connectivity of non-position attributes.
|
||||
if (attribute_data_.size() > 0) {
|
||||
if (!attribute_data_.empty()) {
|
||||
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
|
||||
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
|
||||
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
|
||||
|
@ -577,11 +581,16 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
|
|||
SetOppositeCorners(corner_b, corner + 2);
|
||||
|
||||
// Update vertex mapping.
|
||||
corner_table_->MapCornerToVertex(corner, vertex_x);
|
||||
corner_table_->MapCornerToVertex(
|
||||
corner + 1, corner_table_->Vertex(corner_table_->Next(corner_b)));
|
||||
const VertexIndex vert_a_prev =
|
||||
corner_table_->Vertex(corner_table_->Previous(corner_a));
|
||||
const VertexIndex vert_b_next =
|
||||
corner_table_->Vertex(corner_table_->Next(corner_b));
|
||||
if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
|
||||
// Encoding is invalid, because face vertices are degenerate.
|
||||
return -1;
|
||||
}
|
||||
corner_table_->MapCornerToVertex(corner, vertex_x);
|
||||
corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
|
||||
corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
|
||||
corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
|
||||
// Mark the vertex |x| as interior.
|
||||
|
@ -791,7 +800,7 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
|
|||
return -1; // Unexpected number of decoded vertices.
|
||||
}
|
||||
// Decode start faces and connect them to the faces from the active stack.
|
||||
while (active_corner_stack.size() > 0) {
|
||||
while (!active_corner_stack.empty()) {
|
||||
const CornerIndex corner = active_corner_stack.back();
|
||||
active_corner_stack.pop_back();
|
||||
const bool interior_face =
|
||||
|
@ -952,9 +961,13 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
|
|||
for (uint32_t i = 0; i < num_topology_splits; ++i) {
|
||||
TopologySplitEventData event_data;
|
||||
uint32_t delta;
|
||||
DecodeVarint<uint32_t>(&delta, decoder_buffer);
|
||||
if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
|
||||
return -1;
|
||||
}
|
||||
event_data.source_symbol_id = delta + last_source_symbol_id;
|
||||
DecodeVarint<uint32_t>(&delta, decoder_buffer);
|
||||
if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
|
||||
return -1;
|
||||
}
|
||||
if (delta > event_data.source_symbol_id) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1009,7 +1022,9 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
|
|||
for (uint32_t i = 0; i < num_hole_events; ++i) {
|
||||
HoleEventData event_data;
|
||||
uint32_t delta;
|
||||
DecodeVarint<uint32_t>(&delta, decoder_buffer);
|
||||
if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
|
||||
return -1;
|
||||
}
|
||||
event_data.symbol_id = delta + last_symbol_id;
|
||||
last_symbol_id = event_data.symbol_id;
|
||||
hole_event_data_.push_back(event_data);
|
||||
|
|
|
@ -31,7 +31,6 @@ bool MeshEdgebreakerEncoder::InitializeEncoder() {
|
|||
impl_ = nullptr;
|
||||
// For tiny meshes it's usually better to use the basic edgebreaker as the
|
||||
// overhead of the predictive one may turn out to be too big.
|
||||
// TODO(b/111065939): Check if this can be improved.
|
||||
const bool is_tiny_mesh = mesh()->num_faces() < 1000;
|
||||
|
||||
int selected_edgebreaker_method =
|
||||
|
|
|
@ -408,7 +408,7 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
|
|||
init_face_connectivity_corners.begin(),
|
||||
init_face_connectivity_corners.end());
|
||||
// Encode connectivity for all non-position attributes.
|
||||
if (attribute_data_.size() > 0) {
|
||||
if (!attribute_data_.empty()) {
|
||||
// Use the same order of corner that will be used by the decoder.
|
||||
visited_faces_.assign(mesh_->num_faces(), false);
|
||||
for (CornerIndex ci : processed_connectivity_corners_) {
|
||||
|
|
|
@ -177,7 +177,6 @@ class MeshEdgebreakerEncoderImpl : public MeshEdgebreakerEncoderImplInterface {
|
|||
uint32_t num_split_symbols_;
|
||||
|
||||
// Struct holding data used for encoding each non-position attribute.
|
||||
// TODO(ostava): This should be probably renamed to something better.
|
||||
struct AttributeData {
|
||||
AttributeData() : attribute_index(-1), is_connectivity_used(true) {}
|
||||
int attribute_index;
|
||||
|
|
|
@ -50,8 +50,6 @@ namespace draco {
|
|||
// \ / S \ / / E \
|
||||
// *-------* *-------*
|
||||
//
|
||||
// TODO(ostava): Get rid of the topology bit pattern. It's important only for
|
||||
// encoding but the algorithms should use EdgebreakerSymbol instead.
|
||||
enum EdgebreakerTopologyBitPattern {
|
||||
TOPOLOGY_C = 0x0, // 0
|
||||
TOPOLOGY_S = 0x1, // 1 0 0
|
||||
|
|
|
@ -106,7 +106,12 @@ class MeshEdgebreakerTraversalValenceDecoder
|
|||
context_counters_.resize(context_symbols_.size());
|
||||
for (int i = 0; i < context_symbols_.size(); ++i) {
|
||||
uint32_t num_symbols;
|
||||
DecodeVarint<uint32_t>(&num_symbols, out_buffer);
|
||||
if (!DecodeVarint<uint32_t>(&num_symbols, out_buffer)) {
|
||||
return false;
|
||||
}
|
||||
if (num_symbols > static_cast<uint32_t>(corner_table_->num_faces())) {
|
||||
return false;
|
||||
}
|
||||
if (num_symbols > 0) {
|
||||
context_symbols_[i].resize(num_symbols);
|
||||
DecodeSymbols(num_symbols, 1, out_buffer, context_symbols_[i].data());
|
||||
|
|
|
@ -53,6 +53,11 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
|
|||
if (faces_64 > 0xffffffff / 3) {
|
||||
return false;
|
||||
}
|
||||
if (faces_64 > buffer()->remaining_size() / 3) {
|
||||
// The number of faces is unreasonably high, because face indices do not
|
||||
// fit in the remaining size of the buffer.
|
||||
return false;
|
||||
}
|
||||
if (points_64 > faces_64 * 3) {
|
||||
return false;
|
||||
}
|
||||
|
@ -91,7 +96,7 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
|
|||
}
|
||||
mesh()->AddFace(face);
|
||||
}
|
||||
} else if (mesh()->num_points() < (1 << 21) &&
|
||||
} else if (num_points < (1 << 21) &&
|
||||
bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) {
|
||||
// Decode indices as uint32_t.
|
||||
for (uint32_t i = 0; i < num_faces; ++i) {
|
||||
|
|
|
@ -32,8 +32,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() {
|
|||
EncodeVarint(static_cast<uint32_t>(mesh()->num_points()), buffer());
|
||||
|
||||
// We encode all attributes in the original (possibly duplicated) format.
|
||||
// TODO(ostava): This may not be optimal if we have only one attribute or if
|
||||
// all attributes share the same index mapping.
|
||||
if (options()->GetGlobalBool("compress_connectivity", false)) {
|
||||
// 0 = Encode compressed indices.
|
||||
buffer()->Encode(static_cast<uint8_t>(0));
|
||||
|
@ -44,8 +42,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() {
|
|||
// 1 = Encode indices directly.
|
||||
buffer()->Encode(static_cast<uint8_t>(1));
|
||||
// Store vertex indices using a smallest data type that fits their range.
|
||||
// TODO(ostava): This can be potentially improved by using a tighter
|
||||
// fit that is not bound by a bit-length of any particular data type.
|
||||
if (mesh()->num_points() < 256) {
|
||||
// Serialize indices as uint8_t.
|
||||
for (FaceIndex i(0); i < num_faces; ++i) {
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace draco {
|
|||
|
||||
// Class that encodes mesh data using a simple binary representation of mesh's
|
||||
// connectivity and geometry.
|
||||
// TODO(ostava): Use a better name.
|
||||
class MeshSequentialEncoder : public MeshEncoder {
|
||||
public:
|
||||
MeshSequentialEncoder();
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace draco {
|
|||
// values based on the traversal of the encoded mesh. The class should be used
|
||||
// as the TraversalObserverT member of a Traverser class such as the
|
||||
// DepthFirstTraverser (depth_first_traverser.h).
|
||||
// TODO(hemmer): rename to AttributeIndicesCodingTraverserObserver
|
||||
// TODO(b/199760123): Rename to AttributeIndicesCodingTraverserObserver.
|
||||
template <class CornerTableT>
|
||||
class MeshAttributeIndicesEncodingObserver {
|
||||
public:
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace draco {
|
|||
// Sequencer that generates point sequence in an order given by a deterministic
|
||||
// traversal on the mesh surface. Note that all attributes encoded with this
|
||||
// sequence must share the same connectivity.
|
||||
// TODO(hemmer): Consider refactoring such that this is an observer.
|
||||
// TODO(b/199760123): Consider refactoring such that this is an observer.
|
||||
template <class TraverserT>
|
||||
class MeshTraversalSequencer : public PointsSequencer {
|
||||
public:
|
||||
|
|
|
@ -227,7 +227,7 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal(
|
|||
std::stack<Status> status_stack;
|
||||
status_stack.push(init_status);
|
||||
|
||||
// TODO(hemmer): use preallocated vector instead of stack.
|
||||
// TODO(b/199760123): Use preallocated vector instead of stack.
|
||||
while (!status_stack.empty()) {
|
||||
const DecodingStatus status = status_stack.top();
|
||||
status_stack.pop();
|
||||
|
@ -263,7 +263,8 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal(
|
|||
|
||||
// Fast decoding of remaining bits if number of points is 1 or 2.
|
||||
if (num_remaining_points <= 2) {
|
||||
// TODO(hemmer): axes_ not necessary, remove would change bitstream!
|
||||
// TODO(b/199760123): |axes_| not necessary, remove would change
|
||||
// bitstream!
|
||||
axes_[0] = axis;
|
||||
for (uint32_t i = 1; i < dimension_; i++) {
|
||||
axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
|
||||
|
|
|
@ -280,7 +280,7 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal(
|
|||
std::stack<Status> status_stack;
|
||||
status_stack.push(init_status);
|
||||
|
||||
// TODO(hemmer): use preallocated vector instead of stack.
|
||||
// TODO(b/199760123): Use preallocated vector instead of stack.
|
||||
while (!status_stack.empty()) {
|
||||
Status status = status_stack.top();
|
||||
status_stack.pop();
|
||||
|
@ -305,7 +305,8 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal(
|
|||
// Fast encoding of remaining bits if number of points is 1 or 2.
|
||||
// Doing this also for 2 gives a slight additional speed up.
|
||||
if (num_remaining_points <= 2) {
|
||||
// TODO(hemmer): axes_ not necessary, remove would change bitstream!
|
||||
// TODO(b/199760123): |axes_| not necessary, remove would change
|
||||
// bitstream!
|
||||
axes_[0] = axis;
|
||||
for (uint32_t i = 1; i < dimension_; i++) {
|
||||
axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
|
||||
|
|
|
@ -69,18 +69,29 @@ FloatPointsTreeDecoder::FloatPointsTreeDecoder()
|
|||
|
||||
bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal(
|
||||
DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) {
|
||||
if (!buffer->Decode(&qinfo_.quantization_bits)) return false;
|
||||
if (qinfo_.quantization_bits > 31) return false;
|
||||
if (!buffer->Decode(&qinfo_.range)) return false;
|
||||
if (!buffer->Decode(&num_points_)) return false;
|
||||
if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_)
|
||||
if (!buffer->Decode(&qinfo_.quantization_bits)) {
|
||||
return false;
|
||||
if (!buffer->Decode(&compression_level_)) return false;
|
||||
}
|
||||
if (qinfo_.quantization_bits > 31) {
|
||||
return false;
|
||||
}
|
||||
if (!buffer->Decode(&qinfo_.range)) {
|
||||
return false;
|
||||
}
|
||||
if (!buffer->Decode(&num_points_)) {
|
||||
return false;
|
||||
}
|
||||
if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) {
|
||||
return false;
|
||||
}
|
||||
if (!buffer->Decode(&compression_level_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only allow compression level in [0..6].
|
||||
if (6 < compression_level_) {
|
||||
LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
|
||||
compression_level_);
|
||||
DRACO_LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
|
||||
compression_level_);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace draco {
|
|||
// there are more leading zeros, which is then compressed better by the
|
||||
// arithmetic encoding.
|
||||
|
||||
// TODO(hemmer): Remove class because it duplicates quantization code.
|
||||
// TODO(b/199760123): Remove class because it duplicates quantization code.
|
||||
class FloatPointsTreeEncoder {
|
||||
public:
|
||||
explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method);
|
||||
|
@ -91,7 +91,7 @@ bool FloatPointsTreeEncoder::EncodePointCloud(InputIteratorT points_begin,
|
|||
// Collect necessary data for encoding.
|
||||
num_points_ = std::distance(points_begin, points_end);
|
||||
|
||||
// TODO(hemmer): Extend quantization tools to make this more automatic.
|
||||
// TODO(b/199760123): Extend quantization tools to make this more automatic.
|
||||
// Compute range of points for quantization
|
||||
std::vector<Point3ui> qpoints;
|
||||
qpoints.reserve(num_points_);
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeDecoder.
|
||||
// TODO(b/199760123): Make this a wrapper using
|
||||
// DynamicIntegerPointsKdTreeDecoder.
|
||||
//
|
||||
// See integer_points_kd_tree_encoder.h for documentation.
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeEncoder.
|
||||
// TODO(b/199760123): Make this a wrapper using
|
||||
// DynamicIntegerPointsKdTreeEncoder.
|
||||
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_
|
||||
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue