Merge remote-tracking branch 'origin' into sculpt-dev

This commit is contained in:
Joseph Eagar 2022-10-12 13:19:59 -07:00
commit 92bc610c36
567 changed files with 5178 additions and 3770 deletions

View File

@ -242,17 +242,17 @@ if(UNIX AND NOT (APPLE OR HAIKU))
option(WITH_GHOST_X11 "Enable building Blender against X11 for windowing" ON)
mark_as_advanced(WITH_GHOST_X11)
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing" ON)
mark_as_advanced(WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND)
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" OFF)
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" ON)
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)
option(WITH_GHOST_WAYLAND_DYNLOAD "Enable runtime dynamic WAYLAND libraries loading" OFF)
option(WITH_GHOST_WAYLAND_DYNLOAD "Enable runtime dynamic WAYLAND libraries loading" ON)
mark_as_advanced(WITH_GHOST_WAYLAND_DYNLOAD)
endif()
endif()
@ -1922,9 +1922,25 @@ if(FIRST_RUN)
info_cfg_option(WITH_INSTALL_PORTABLE)
info_cfg_option(WITH_MEM_JEMALLOC)
info_cfg_option(WITH_MEM_VALGRIND)
info_cfg_option(WITH_X11_XF86VMODE)
info_cfg_option(WITH_X11_XFIXES)
info_cfg_option(WITH_X11_XINPUT)
info_cfg_text("GHOST Options:")
info_cfg_option(WITH_GHOST_DEBUG)
info_cfg_option(WITH_GHOST_SDL)
if(UNIX AND NOT APPLE)
info_cfg_option(WITH_GHOST_X11)
info_cfg_option(WITH_GHOST_WAYLAND)
if(WITH_GHOST_X11)
info_cfg_option(WITH_GHOST_XDND)
info_cfg_option(WITH_X11_XF86VMODE)
info_cfg_option(WITH_X11_XFIXES)
info_cfg_option(WITH_X11_XINPUT)
endif()
if(WITH_GHOST_WAYLAND)
info_cfg_option(WITH_GHOST_WAYLAND_DYNLOAD)
info_cfg_option(WITH_GHOST_WAYLAND_LIBDECOR)
info_cfg_option(WITH_GHOST_WAYLAND_DBUS)
endif()
endif()
info_cfg_text("Image Formats:")
info_cfg_option(WITH_IMAGE_CINEON)

View File

@ -172,6 +172,8 @@ if(UNIX AND NOT APPLE)
include(cmake/wayland_protocols.cmake)
# Can be removed when the build-bot upgrades to v1.20.x or newer.
include(cmake/wayland.cmake)
include(cmake/wayland_libdecor.cmake)
endif()
include(cmake/harvest.cmake)
include(cmake/cve_check.cmake)

View File

@ -46,7 +46,7 @@ if(UNIX)
" ${_software_missing}\n"
"\n"
"On Debian and Ubuntu:\n"
" apt install autoconf automake libtool yasm tcl ninja-build meson python3-mako\n"
" apt install autoconf automake bison libtool yasm tcl ninja-build meson python3-mako\n"
"\n"
"On macOS (with homebrew):\n"
" brew install autoconf automake bison flex libtool meson ninja pkg-config yasm\n"

View File

@ -0,0 +1,73 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# CVE Check requirements
#
# - A working installation of intels cve-bin-tool [1] has to be available in
# your path
#
# - Not strictly required, but highly recommended is obtaining a NVD key from
# nist since it significantly speeds up downloading/updating the required
# databases one can request a key on the following website:
# https://nvd.nist.gov/developers/request-an-api-key
# Bill of Materials construction
#
# This constructs a CSV cve-bin-tool [1] can read and process. Sadly
# cve-bin-tool at this point does not take a list of CPE's and output a check
# based on that list. so we need to pick apart the CPE retrieve the vendor,
# product and version tokens and generate a CSV.
#
# [1] https://github.com/intel/cve-bin-tool
# Because not all deps are downloaded (ie python packages) but can still have a
# xxx_CPE declared loop over all variables and look for variables ending in CPE.
set(SBOMCONTENTS)
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if(_variableName MATCHES "CPE$")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
list(GET CPE_LIST 3 CPE_VENDOR)
list(GET CPE_LIST 4 CPE_NAME)
list(GET CPE_LIST 5 CPE_VERSION)
set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n")
endif()
endforeach()
configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY)
# Custom Targets
#
# This defines two new custom targets one could run in the build folder
# `cve_check` which will output the report to the console, and `cve_check_html`
# which will write out blender_dependencies.html in the build folder that one
# could share with other people or be used to get more information on the
# reported CVE's.
#
# cve-bin-tool takes data from the nist nvd database which rate limits
# unauthenticated requests to 1 requests per 6 seconds making the database
# download take "quite a bit" of time.
#
# When adding -DCVE_CHECK_NVD_KEY=your_api_key_here to your cmake invocation
# this key will be passed on to cve-bin-tool speeding up the process.
#
if(DEFINED CVE_CHECK_NVD_KEY)
set(NVD_ARGS --nvd-api-key ${CVE_CHECK_NVD_KEY})
endif()
# This will just report to the console
add_custom_target(cve_check
COMMAND cve-bin-tool
${NVD_ARGS}
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
--affected-versions
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
)
# This will write out blender_dependencies.html
add_custom_target(cve_check_html
COMMAND cve-bin-tool
${NVD_ARGS}
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
-f html
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
)

View File

@ -0,0 +1,2 @@
vendor,product,version
@SBOMCONTENTS@

View File

@ -133,6 +133,7 @@ download_source(NASM)
download_source(XR_OPENXR_SDK)
download_source(WL_PROTOCOLS)
download_source(WAYLAND)
download_source(WAYLAND_LIBDECOR)
download_source(ISPC)
download_source(GMP)
download_source(POTRACE)

View File

@ -118,6 +118,8 @@ else()
harvest(wayland-protocols/share/wayland-protocols wayland-protocols/share/wayland-protocols/ "*.xml")
harvest(wayland/bin wayland/bin "wayland-scanner")
harvest(wayland/include wayland/include "*.h")
harvest(wayland_libdecor/include wayland_libdecor/include "*.h")
else()
harvest(blosc/lib openvdb/lib "*.a")
harvest(xml2/lib opencollada/lib "*.a")

View File

@ -1,10 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# CPE's are used to identify dependencies, for more information on what they
# are please see https://nvd.nist.gov/products/cpe
#
# We use them in combination with cve-bin-tool to scan for known security issues.
#
# Not all of our dependencies are currently in the nvd database so not all
# dependencies have one assigned.
set(ZLIB_VERSION 1.2.12)
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
set(ZLIB_HASH_TYPE MD5)
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
set(OPENAL_VERSION 1.21.1)
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
@ -17,12 +26,14 @@ set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.
set(PNG_HASH 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca)
set(PNG_HASH_TYPE SHA256)
set(PNG_FILE libpng-${PNG_VERSION}.tar.xz)
set(PNG_CPE "cpe:2.3:a:libpng:libpng:${PNG_VERSION}:*:*:*:*:*:*:*")
set(JPEG_VERSION 2.1.3)
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
set(JPEG_HASH 627b980fad0573e08e4c3b80b290fc91)
set(JPEG_HASH_TYPE MD5)
set(JPEG_FILE libjpeg-turbo-${JPEG_VERSION}.tar.gz)
set(JPEG_CPE "cpe:2.3:a:d.r.commander:libjpeg-turbo:${JPEG_VERSION}:*:*:*:*:*:*:*")
set(BOOST_VERSION 1.78.0)
set(BOOST_VERSION_SHORT 1.78)
@ -32,12 +43,14 @@ set(BOOST_URI https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION
set(BOOST_HASH c2f6428ac52b0e5a3c9b2e1d8cc832b5)
set(BOOST_HASH_TYPE MD5)
set(BOOST_FILE boost_${BOOST_VERSION_NODOTS}.tar.gz)
set(BOOST_CPE "cpe:2.3:a:boost:boost:${BOOST_VERSION}:*:*:*:*:*:*:*")
set(BLOSC_VERSION 1.21.1)
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
set(BLOSC_HASH_TYPE MD5)
set(BLOSC_FILE blosc-${BLOSC_VERSION}.tar.gz)
set(BLOSC_CPE "cpe:2.3:a:c-blosc2_project:c-blosc2:${BLOSC_VERSION}:*:*:*:*:*:*:*")
set(PTHREADS_VERSION 3.0.0)
set(PTHREADS_URI http://prdownloads.sourceforge.net/pthreads4w/pthreads4w-code-v${PTHREADS_VERSION}.zip)
@ -50,6 +63,7 @@ set(OPENEXR_URI https://github.com/AcademySoftwareFoundation/openexr/archive/v${
set(OPENEXR_HASH a92f38eedd43e56c0af56d4852506886)
set(OPENEXR_HASH_TYPE MD5)
set(OPENEXR_FILE openexr-${OPENEXR_VERSION}.tar.gz)
set(OPENEXR_CPE "cpe:2.3:a:openexr:openexr:${OPENEXR_VERSION}:*:*:*:*:*:*:*")
set(IMATH_VERSION 3.1.5)
set(IMATH_URI https://github.com/AcademySoftwareFoundation/Imath/archive/v${OPENEXR_VERSION}.tar.gz)
@ -79,6 +93,7 @@ set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
set(FREETYPE_HASH_TYPE MD5)
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
set(EPOXY_VERSION 1.5.10)
set(EPOXY_URI https://github.com/anholt/libepoxy/archive/refs/tags/${EPOXY_VERSION}.tar.gz)
@ -97,6 +112,7 @@ set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.ta
set(ALEMBIC_HASH 2cd8d6e5a3ac4a014e24a4b04f4fadf9)
set(ALEMBIC_HASH_TYPE MD5)
set(ALEMBIC_FILE alembic-${ALEMBIC_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
set(OPENSUBDIV_VERSION v3_4_4)
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
@ -109,6 +125,7 @@ set(SDL_URI https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz)
set(SDL_HASH a53acc02e1cca98c4123229069b67c9e)
set(SDL_HASH_TYPE MD5)
set(SDL_FILE SDL2-${SDL_VERSION}.tar.gz)
set(SDL_CPE "cpe:2.3:a:libsdl:sdl:${SDL_VERSION}:*:*:*:*:*:*:*")
set(OPENCOLLADA_VERSION v1.6.68)
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
@ -127,6 +144,7 @@ set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LL
set(LLVM_HASH 5a4fab4d7fc84aefffb118ac2c8a4fc0)
set(LLVM_HASH_TYPE MD5)
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
set(LLVM_CPE "cpe:2.3:a:llvm:compiler:${LLVM_VERSION}:*:*:*:*:*:*:*")
if(APPLE)
# Cloth physics test is crashing due to this bug:
@ -154,6 +172,7 @@ set(FMT_URI https://github.com/fmtlib/fmt/archive/refs/tags/${FMT_VERSION}.tar.g
set(FMT_HASH 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
set(FMT_HASH_TYPE SHA256)
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
set(FMT_CPE "cpe:2.3:a:fmt:fmt:${FMT_VERSION}:*:*:*:*:*:*:*")
# 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
@ -168,6 +187,7 @@ set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_HASH 376f17f189e9d02280dfe709b2b2bbea)
set(TIFF_HASH_TYPE MD5)
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*")
set(OSL_VERSION 1.11.17.0)
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
@ -182,12 +202,15 @@ set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTH
set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
set(TBB_VERSION 2020_U3)
set(TBB_YEAR 2020)
set(TBB_VERSION ${TBB_YEAR}_U3)
set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
set(TBB_HASH 55ec8df6eae5ed6364a47f0e671e460c)
set(TBB_HASH_TYPE MD5)
set(TBB_FILE oneTBB-${TBB_VERSION}.tar.gz)
set(TBB_CPE "cpe:2.3:a:intel:threading_building_blocks:${TBB_YEAR}:*:*:*:*:*:*:*")
set(OPENVDB_VERSION 9.0.0)
set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
@ -198,6 +221,7 @@ set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz)
set(IDNA_VERSION 3.3)
set(CHARSET_NORMALIZER_VERSION 2.0.10)
set(URLLIB3_VERSION 1.26.8)
set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*")
set(CERTIFI_VERSION 2021.10.8)
set(REQUESTS_VERSION 2.27.1)
set(CYTHON_VERSION 0.29.26)
@ -214,12 +238,14 @@ set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}
set(NUMPY_HASH 252de134862a27bd66705d29622edbfe)
set(NUMPY_HASH_TYPE MD5)
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
set(NUMPY_CPE "cpe:2.3:a:numpy:numpy:${NUMPY_VERSION}:*:*:*:*:*:*:*")
set(LAME_VERSION 3.100)
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
set(LAME_HASH_TYPE MD5)
set(LAME_FILE lame-${LAME_VERSION}.tar.gz)
set(LAME_CPE "cpe:2.3:a:lame_project:lame:${LAME_VERSION}:*:*:*:*:*:*:*")
set(OGG_VERSION 1.3.5)
set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
@ -232,6 +258,7 @@ set(VORBIS_URI http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERS
set(VORBIS_HASH 0e982409a9c3fc82ee06e08205b1355e5c6aa4c36bca58146ef399621b0ce5ab)
set(VORBIS_HASH_TYPE SHA256)
set(VORBIS_FILE libvorbis-${VORBIS_VERSION}.tar.gz)
set(VORBIS_CPE "cpe:2.3:a:xiph.org:libvorbis:${VORBIS_VERSION}:*:*:*:*:*:*:*")
set(THEORA_VERSION 1.1.1)
set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
@ -244,12 +271,14 @@ set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz
set(FLAC_HASH 8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737 )
set(FLAC_HASH_TYPE SHA256)
set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
set(FLAC_CPE "cpe:2.3:a:flac_project:flac:${FLAC_VERSION}:*:*:*:*:*:*:*")
set(VPX_VERSION 1.11.0)
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_HASH 965e51c91ad9851e2337aebcc0f517440c637c506f3a03948062e3d5ea129a83)
set(VPX_HASH_TYPE SHA256)
set(VPX_FILE libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_CPE "cpe:2.3:a:webmproject:libvpx:${VPX_VERSION}:*:*:*:*:*:*:*")
set(OPUS_VERSION 1.3.1)
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
@ -275,12 +304,14 @@ set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSI
set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
set(OPENJPEG_HASH_TYPE SHA256)
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
set(FFMPEG_VERSION 5.0)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
set(FFMPEG_HASH_TYPE SHA256)
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
set(FFTW_VERSION 3.3.10)
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
@ -299,12 +330,14 @@ set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_V
set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
set(SNDFILE_HASH_TYPE MD5)
set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz)
set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*")
set(WEBP_VERSION 1.2.2)
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
set(WEBP_HASH b5e2e414a8adee4c25fe56b18dd9c549)
set(WEBP_HASH_TYPE MD5)
set(WEBP_FILE libwebp-${WEBP_VERSION}.tar.gz)
set(WEBP_CPE "cpe:2.3:a:webmproject:libwebp:${WEBP_VERSION}:*:*:*:*:*:*:*")
set(SPNAV_VERSION 0.2.3)
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
@ -323,6 +356,7 @@ set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
set(XML2_HASH_TYPE MD5)
set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*")
set(TINYXML_VERSION 2_6_2)
set(TINYXML_VERSION_DOTS 2.6.2)
@ -330,12 +364,14 @@ set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXM
set(TINYXML_HASH c1b864c96804a10526540c664ade67f0)
set(TINYXML_HASH_TYPE MD5)
set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz)
set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*")
set(YAMLCPP_VERSION 0.6.3)
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
set(YAMLCPP_HASH_TYPE MD5)
set(YAMLCPP_FILE yaml-cpp-${YAMLCPP_VERSION}.tar.gz)
set(YAMLCPP "cpe:2.3:a:yaml-cpp_project:yaml-cpp:${YAMLCPP_VERSION}:*:*:*:*:*:*:*")
set(PYSTRING_VERSION v1.1.3)
set(PYSTRING_URI https://codeload.github.com/imageworks/pystring/tar.gz/refs/tags/${PYSTRING_VERSION})
@ -344,16 +380,19 @@ set(PYSTRING_HASH_TYPE MD5)
set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz)
set(EXPAT_VERSION 2_4_4)
set(EXPAT_VERSION_DOTS 2.4.4)
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
set(EXPAT_HASH_TYPE MD5)
set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz)
set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*")
set(PUGIXML_VERSION 1.10)
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
set(PUGIXML_HASH_TYPE MD5)
set(PUGIXML_FILE pugixml-${PUGIXML_VERSION}.tar.gz)
set(PUGIXML_CPE "cpe:2.3:a:pugixml_project:pugixml:${PUGIXML_VERSION}:*:*:*:*:*:*:*")
set(FLEXBISON_VERSION 2.5.24)
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison/win_flex_bison-${FLEXBISON_VERSION}.zip)
@ -376,12 +415,14 @@ set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERS
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
set(BZIP2_HASH_TYPE SHA256)
set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz)
set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*")
set(FFI_VERSION 3.3)
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
set(FFI_HASH_TYPE SHA256)
set(FFI_FILE libffi-${FFI_VERSION}.tar.gz)
set(FFI_CPE "cpe:2.3:a:libffi_project:libffi:${FFI_VERSION}:*:*:*:*:*:*:*")
set(LZMA_VERSION 5.2.5)
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
@ -403,12 +444,14 @@ else()
set(SSL_HASH_TYPE SHA256)
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
endif()
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
set(SQLITE_VERSION 3.31.1)
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
set(SQLITE_HASH_TYPE SHA1)
set(SQLITE_FILE sqlite-src-3240000.zip)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
set(EMBREE_VERSION 3.13.4)
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
@ -439,12 +482,14 @@ set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa/mesa-${MESA_VERSION}.tar.xz)
set(MESA_HASH 022c7293074aeeced2278c872db4fa693147c70f8595b076cf3f1ef81520766d)
set(MESA_HASH_TYPE SHA256)
set(MESA_FILE mesa-${MESA_VERSION}.tar.xz)
set(MESA_CPE "cpe:2.3:a:mesa3d:mesa:${MESA_VERSION}:*:*:*:*:*:*:*")
set(NASM_VERSION 2.15.02)
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
set(NASM_HASH_TYPE SHA256)
set(NASM_FILE nasm-${NASM_VERSION}.tar.gz)
set(NASM_PCE "cpe:2.3:a:nasm:nasm:${NASM_VERSION}:*:*:*:*:*:*:*")
set(XR_OPENXR_SDK_VERSION 1.0.22)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
@ -464,6 +509,12 @@ set(WAYLAND_URI https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.21.0
set(WAYLAND_HASH f2653a2293bcd882d756c6a83d278903)
set(WAYLAND_HASH_TYPE MD5)
set(WAYLAND_LIBDECOR_VERSION 0.1.0)
set(WAYLAND_LIBDECOR_FILE libdecor-${WAYLAND_LIBDECOR_VERSION}.tar.xz)
set(WAYLAND_LIBDECOR_URI https://gitlab.gnome.org/jadahl/libdecor/uploads/81adf91d27620e20bcc5f6b9b312d768/libdecor-${WAYLAND_LIBDECOR_VERSION}.tar.xz )
set(WAYLAND_LIBDECOR_HASH 47b59eba76faa3787f0878bf8700e912)
set(WAYLAND_LIBDECOR_HASH_TYPE MD5)
set(ISPC_VERSION v1.17.0)
set(ISPC_URI https://github.com/ispc/ispc/archive/${ISPC_VERSION}.tar.gz)
set(ISPC_HASH 4f476a3109332a77fe839a9014c60ca9)
@ -475,12 +526,14 @@ set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
set(GMP_HASH_TYPE MD5)
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
set(GMP_CPE "cpe:2.3:a:gmplib:gmp:${GMP_VERSION}:*:*:*:*:*:*:*")
set(POTRACE_VERSION 1.16)
set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz)
set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69)
set(POTRACE_HASH_TYPE MD5)
set(POTRACE_FILE potrace-${POTRACE_VERSION}.tar.gz)
set(POTRACE_CPE "cpe:2.3:a:icoasoft:potrace:${POTRACE_VERSION}:*:*:*:*:*:*:*")
set(HARU_VERSION 2_3_0)
set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz)
@ -493,6 +546,7 @@ set(ZSTD_URI https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}
set(ZSTD_HASH 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94)
set(ZSTD_HASH_TYPE SHA256)
set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
set(ZSTD_CPE "cpe:2.3:a:facebook:zstandard:${ZSTD_VERSION}:*:*:*:*:*:*:*")
set(SSE2NEON_VERSION fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
set(SSE2NEON_URI https://github.com/DLTcollab/sse2neon/archive/${SSE2NEON_VERSION}.tar.gz)
@ -500,11 +554,12 @@ set(SSE2NEON_HASH 0780253525d299c31775ef95853698d03db9c7739942af8570000f4a25a5d6
set(SSE2NEON_HASH_TYPE SHA256)
set(SSE2NEON_FILE sse2neon-${SSE2NEON_VERSION}.tar.gz)
set(BROTLI_VERSION v1.0.9)
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/${BROTLI_VERSION}.tar.gz)
set(BROTLI_VERSION 1.0.9)
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz)
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
set(BROTLI_HASH_TYPE SHA256)
set(BROTLI_FILE brotli-${BROTLI_VERSION}.tar.gz)
set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz)
set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
set(OPENPGL_VERSION v0.3.1-beta)
set(OPENPGL_SHORT_VERSION 0.3.1)

View File

@ -6,9 +6,11 @@ ExternalProject_Add(external_wayland
URL_HASH ${WAYLAND_HASH_TYPE}=${WAYLAND_HASH}
PREFIX ${BUILD_DIR}/wayland
PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:$PKG_CONFIG_PATH
meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dlibraries=false . ../external_wayland
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT & LIBXML2.
# Note that passing link args "ffi/lib" should not be needed, but
# `pkgconfig` would incorrectly look in "ffi/lib/../lib64" otherwise.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH
meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dc_link_args=-L${LIBDIR}/ffi/lib . ../external_wayland
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)
@ -17,4 +19,5 @@ add_dependencies(
external_wayland
external_expat
external_xml2
external_ffi
)

View File

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# NOTE: currently only the header file is extracted, no compilation is needed
# as the library is dynamically loaded when found on the system.
ExternalProject_Add(external_wayland_libdecor
URL file://${PACKAGE_DIR}/${WAYLAND_LIBDECOR_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${WAYLAND_LIBDECOR_HASH_TYPE}=${WAYLAND_LIBDECOR_HASH}
PREFIX ${BUILD_DIR}/wayland_libdecor
BUILD_COMMAND echo .
CONFIGURE_COMMAND echo .
INSTALL_COMMAND cp ../external_wayland_libdecor/src/libdecor.h ${LIBDIR}/wayland_libdecor/include/libdecor-0/libdecor.h
INSTALL_DIR ${LIBDIR}/wayland_libdecor/include/libdecor-0
)

View File

@ -0,0 +1,65 @@
#!/bin/sh
set -e
if [ `id -u` -ne 0 ]; then
echo "This script must be run as root"
exit 1
fi
# yum-config-manager does not come in the default minimal install,
# so make sure it is installed and available.
yum -y update
yum -y install yum-utils
# Install all the packages needed for a new toolchain.
#
# NOTE: Keep this separate from the packages install, since otherwise
# older toolchain will be installed.
yum -y update
yum -y install epel-release
yum -y install centos-release-scl
yum -y install devtoolset-9
# Install packages needed for Blender's dependencies.
yum -y install -y \
git subversion bzip2 tar cmake3 patch make autoconf automake libtool \
meson ninja-build \
libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel \
libX11-devel libXt-devel \
mesa-libEGL-devel mesa-libGL-devel mesa-libGLU-devel \
zlib-devel \
rubygem-asciidoctor \
wget tcl yasm python36 python-setuptools bison flex \
ncurses-devel \
wayland-devel libwayland-client libwayland-server \
# Dependencies for Mesa
yum -y install expat-devel
python3 -m pip install mako
# Dependencies for pip (needed for buildbot-worker).
yum -y install python36-pip python36-devel
# Dependencies for asound.
yum -y install -y \
alsa-lib-devel pulseaudio-libs-devel
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake 10 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake \
--family cmake
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
--family cmake
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
--family cmake

View File

@ -62,6 +62,13 @@ FIND_LIBRARY(SYCL_LIBRARY
lib64 lib
)
if(WIN32)
string(REPLACE ".lib" "d.lib" SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY})
set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY_DEBUG} CACHE FILEPATH "Path to SYCL debug library")
else()
set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY} CACHE FILEPATH "Path to SYCL debug library")
endif()
FIND_PATH(SYCL_INCLUDE_DIR
NAMES
CL/sycl.hpp
@ -85,4 +92,5 @@ ENDIF()
MARK_AS_ADVANCED(
_SYCL_INCLUDE_PARENT_DIR
SYCL_LIBRARY_DEBUG
)

View File

@ -335,10 +335,18 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO})
endif()
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to DPC++ and SYCL installation")
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
set(SYCL_ROOT_DIR ${CYCLES_SYCL})
endif()
file(GLOB _sycl_runtime_libraries
${SYCL_ROOT_DIR}/lib/libsycl.so
${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9]
${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9]
${SYCL_ROOT_DIR}/lib/libpi_level_zero.so
)
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
unset(_sycl_runtime_libraries)
endif()
if(WITH_OPENVDB)
@ -691,14 +699,23 @@ endif()
if(WITH_GHOST_WAYLAND)
find_package(PkgConfig)
pkg_check_modules(wayland-client wayland-client>=1.12)
pkg_check_modules(wayland-egl wayland-egl)
pkg_check_modules(wayland-scanner wayland-scanner)
pkg_check_modules(xkbcommon xkbcommon)
pkg_check_modules(wayland-cursor wayland-cursor)
pkg_check_modules(wayland-protocols wayland-protocols>=1.15)
if(${wayland-protocols_FOUND})
# When dynamically linked WAYLAND is used and `${LIBDIR}/wayland` is present,
# there is no need to search for the libraries as they are not needed for building.
# Only the headers are needed which can reference the known paths.
if(EXISTS "${LIBDIR}/wayland" AND WITH_GHOST_WAYLAND_DYNLOAD)
set(_use_system_wayland OFF)
else()
set(_use_system_wayland ON)
endif()
if(_use_system_wayland)
pkg_check_modules(wayland-client wayland-client>=1.12)
pkg_check_modules(wayland-egl wayland-egl)
pkg_check_modules(wayland-scanner wayland-scanner)
pkg_check_modules(wayland-cursor wayland-cursor)
pkg_check_modules(wayland-protocols wayland-protocols>=1.15)
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
else()
# CentOS 7 packages have too old a version, a newer version exist in the
@ -712,6 +729,15 @@ if(WITH_GHOST_WAYLAND)
if(EXISTS ${WAYLAND_PROTOCOLS_DIR})
set(wayland-protocols_FOUND ON)
endif()
set(wayland-client_INCLUDE_DIRS "${LIBDIR}/wayland/include")
set(wayland-egl_INCLUDE_DIRS "${LIBDIR}/wayland/include")
set(wayland-cursor_INCLUDE_DIRS "${LIBDIR}/wayland/include")
set(wayland-client_FOUND ON)
set(wayland-egl_FOUND ON)
set(wayland-scanner_FOUND ON)
set(wayland-cursor_FOUND ON)
endif()
if (NOT ${wayland-client_FOUND})
@ -745,7 +771,11 @@ if(WITH_GHOST_WAYLAND)
endif()
if(WITH_GHOST_WAYLAND_LIBDECOR)
pkg_check_modules(libdecor REQUIRED libdecor-0>=0.1)
if(_use_system_wayland)
pkg_check_modules(libdecor REQUIRED libdecor-0>=0.1)
else()
set(libdecor_INCLUDE_DIRS "${LIBDIR}/wayland_libdecor/include/libdecor-0")
endif()
endif()
list(APPEND PLATFORM_LINKLIBS
@ -815,6 +845,8 @@ if(WITH_GHOST_WAYLAND)
# End wayland-scanner version check.
endif()
unset(_use_system_wayland)
endif()
if(WITH_GHOST_X11)

View File

@ -952,5 +952,23 @@ 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)
if(WITH_CYCLES_DEVICE_ONEAPI)
set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero)
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
set(SYCL_ROOT_DIR ${CYCLES_SYCL})
endif()
file(GLOB _sycl_runtime_libraries_glob
${SYCL_ROOT_DIR}/bin/sycl.dll
${SYCL_ROOT_DIR}/bin/sycl[0-9].dll
)
foreach(sycl_runtime_library IN LISTS _sycl_runtime_libraries_glob)
string(REPLACE ".dll" "$<$<CONFIG:Debug>:d>.dll" sycl_runtime_library ${sycl_runtime_library})
list(APPEND _sycl_runtime_libraries ${sycl_runtime_library})
endforeach()
unset(_sycl_runtime_libraries_glob)
list(APPEND _sycl_runtime_libraries ${SYCL_ROOT_DIR}/bin/pi_level_zero.dll)
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
unset(_sycl_runtime_libraries)
endif()

View File

@ -525,8 +525,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_deterministic_guiding: BoolProperty(
name="Deterministic",
description="Makes path guiding deterministic which means renderings will be"
"reproducible with the same pixel values every time. This feature slows down"
description="Makes path guiding deterministic which means renderings will be "
"reproducible with the same pixel values every time. This feature slows down "
"training",
default=True,
)
@ -562,7 +562,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="The maximum number of samples used for training path guiding. "
"Higher samples lead to more accurate guiding, however may also unnecessarily slow "
"down rendering once guiding is accurate enough. "
"A value 0 will continue training until the last sample",
"A value of 0 will continue training until the last sample",
min=0,
soft_min=1,
default=128,

View File

@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
* Utility class to map between Blender datablocks and Cycles data structures,
* and keep track of recalc tags from the dependency graph. */
template<typename K, typename T> class id_map {
template<typename K, typename T, typename Flags = uint> class id_map {
public:
id_map(Scene *scene_) : scene(scene_)
{
@ -63,6 +63,11 @@ template<typename K, typename T> class id_map {
b_recalc.insert(id_ptr);
}
bool check_recalc(const BL::ID &id)
{
return id.ptr.data && b_recalc.find(id.ptr.data) != b_recalc.end();
}
bool has_recalc()
{
return !(b_recalc.empty());
@ -154,6 +159,7 @@ template<typename K, typename T> class id_map {
TMapPair &pair = *jt;
if (do_delete && used_set.find(pair.second) == used_set.end()) {
flags.erase(pair.second);
scene->delete_node(pair.second);
}
else {
@ -171,9 +177,33 @@ template<typename K, typename T> class id_map {
return b_map;
}
bool test_flag(T *data, Flags val)
{
typename map<T *, uint>::iterator it = flags.find(data);
return it != flags.end() && (it->second & (1 << val)) != 0;
}
void set_flag(T *data, Flags val)
{
flags[data] |= (1 << val);
}
void clear_flag(T *data, Flags val)
{
typename map<T *, uint>::iterator it = flags.find(data);
if (it != flags.end()) {
it->second &= ~(1 << val);
if (it->second == 0) {
flags.erase(it);
}
}
}
protected:
map<K, T *> b_map;
set<T *> used_set;
map<T *, uint> flags;
set<void *> b_recalc;
Scene *scene;
};

View File

@ -96,6 +96,13 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
}
bool BlenderSync::object_is_camera(BL::Object &b_ob)
{
BL::ID b_ob_data = b_ob.data();
return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
}
void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
{
/* Initialize motion blur for object, detecting if it's enabled and creating motion
@ -400,7 +407,8 @@ bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance
std::string real_name;
BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name);
if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) {
if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
type == BL::ShaderNodeAttribute::attribute_type_INSTANCER) {
bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
float4 value = lookup_instance_property(b_instance, real_name, use_instancer);

View File

@ -22,6 +22,8 @@
#include "util/string.h"
#include "util/task.h"
#include "BKE_duplilist.h"
CCL_NAMESPACE_BEGIN
typedef map<void *, ShaderInput *> PtrInputMap;
@ -103,6 +105,7 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
static const string_view object_attr_prefix("\x01object:");
static const string_view instancer_attr_prefix("\x01instancer:");
static const string_view view_layer_attr_prefix("\x01layer:");
static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
{
@ -111,6 +114,8 @@ static ustring blender_attribute_name_add_type(const string &name, BlenderAttrib
return ustring::concat(object_attr_prefix, name);
case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
return ustring::concat(instancer_attr_prefix, name);
case BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER:
return ustring::concat(view_layer_attr_prefix, name);
default:
return ustring(name);
}
@ -130,6 +135,11 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
}
if (sname.substr(0, view_layer_attr_prefix.size()) == view_layer_attr_prefix) {
*r_real_name = sname.substr(view_layer_attr_prefix.size());
return BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER;
}
return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
}
@ -205,7 +215,9 @@ static void set_default_value(ShaderInput *input,
}
case SocketType::INT: {
if (b_sock.type() == BL::NodeSocket::type_BOOLEAN) {
node->set(socket, get_boolean(b_sock.ptr, "default_value"));
/* Make sure to call the int overload of set() since this is an integer socket as far as
* Cycles is concerned. */
node->set(socket, get_boolean(b_sock.ptr, "default_value") ? 1 : 0);
}
else {
node->set(socket, get_int(b_sock.ptr, "default_value"));
@ -1420,6 +1432,89 @@ static void add_nodes(Scene *scene,
empty_proxy_map);
}
/* Look up and constant fold all references to View Layer attributes. */
void BlenderSync::resolve_view_layer_attributes(Shader *shader,
ShaderGraph *graph,
BL::Depsgraph &b_depsgraph)
{
bool updated = false;
foreach (ShaderNode *node, graph->nodes) {
if (node->is_a(AttributeNode::node_type)) {
AttributeNode *attr_node = static_cast<AttributeNode *>(node);
std::string real_name;
BlenderAttributeType type = blender_attribute_name_split_type(attr_node->get_attribute(),
&real_name);
if (type == BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER) {
/* Look up the value. */
BL::ViewLayer b_layer = b_depsgraph.view_layer_eval();
BL::Scene b_scene = b_depsgraph.scene_eval();
float4 value;
BKE_view_layer_find_rgba_attribute((::Scene *)b_scene.ptr.data,
(::ViewLayer *)b_layer.ptr.data,
real_name.c_str(),
&value.x);
/* Replace all outgoing links, using appropriate output types. */
float val_avg = (value.x + value.y + value.z) / 3.0f;
foreach (ShaderOutput *output, node->outputs) {
float val_float;
float3 val_float3;
if (output->type() == SocketType::FLOAT) {
val_float = (output->name() == "Alpha") ? value.w : val_avg;
val_float3 = make_float3(val_float);
}
else {
val_float = val_avg;
val_float3 = float4_to_float3(value);
}
foreach (ShaderInput *sock, output->links) {
if (sock->type() == SocketType::FLOAT) {
sock->set(val_float);
}
else if (SocketType::is_float3(sock->type())) {
sock->set(val_float3);
}
sock->constant_folded_in = true;
}
graph->disconnect(output);
}
/* Clear the attribute name to avoid further attempts to look up. */
attr_node->set_attribute(ustring());
updated = true;
}
}
}
if (updated) {
shader_map.set_flag(shader, SHADER_WITH_LAYER_ATTRS);
}
else {
shader_map.clear_flag(shader, SHADER_WITH_LAYER_ATTRS);
}
}
bool BlenderSync::scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph)
{
if (shader && shader_map.test_flag(shader, SHADER_WITH_LAYER_ATTRS)) {
BL::Scene scene = b_depsgraph.scene_eval();
return shader_map.check_recalc(scene) || shader_map.check_recalc(scene.world()) ||
shader_map.check_recalc(scene.camera());
}
return false;
}
/* Sync Materials */
void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
@ -1438,7 +1533,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
if (shader_map.add_or_update(&shader, b_mat) || update_all) {
if (shader_map.add_or_update(&shader, b_mat) || update_all ||
scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@ -1459,6 +1555,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
}
resolve_view_layer_attributes(shader, graph, b_depsgraph);
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
@ -1515,9 +1613,11 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
Shader *shader = scene->default_background;
if (world_recalc || update_all || b_world.ptr.data != world_map ||
viewport_parameters.shader_modified(new_viewport_parameters)) {
Shader *shader = scene->default_background;
viewport_parameters.shader_modified(new_viewport_parameters) ||
scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@ -1615,6 +1715,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_visibility(visibility);
}
resolve_view_layer_attributes(shader, graph, b_depsgraph);
shader->set_graph(graph);
shader->tag_update(scene);
}
@ -1681,7 +1783,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
if (shader_map.add_or_update(&shader, b_light) || update_all) {
if (shader_map.add_or_update(&shader, b_light) || update_all ||
scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@ -1702,6 +1805,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(emission->output("Emission"), out->input("Surface"));
}
resolve_view_layer_attributes(shader, graph, b_depsgraph);
shader->set_graph(graph);
shader->tag_update(scene);
}

View File

@ -206,6 +206,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
}
}
}
else if (object_is_camera(b_ob)) {
shader_map.set_recalc(b_ob);
}
}
/* Mesh */
else if (b_id.is_a(&RNA_Mesh)) {
@ -218,6 +221,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
if (world_map == b_world.ptr.data) {
world_recalc = true;
}
shader_map.set_recalc(b_world);
}
/* World */
else if (b_id.is_a(&RNA_Scene)) {
shader_map.set_recalc(b_id);
}
/* Volume */
else if (b_id.is_a(&RNA_Volume)) {

View File

@ -120,6 +120,11 @@ class BlenderSync {
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
bool scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph);
void resolve_view_layer_attributes(Shader *shader,
ShaderGraph *graph,
BL::Depsgraph &b_depsgraph);
/* Object */
Object *sync_object(BL::Depsgraph &b_depsgraph,
BL::ViewLayer &b_view_layer,
@ -207,13 +212,16 @@ class BlenderSync {
bool object_is_geometry(BObjectInfo &b_ob_info);
bool object_can_have_geometry(BL::Object &b_ob);
bool object_is_light(BL::Object &b_ob);
bool object_is_camera(BL::Object &b_ob);
/* variables */
BL::RenderEngine b_engine;
BL::BlendData b_data;
BL::Scene b_scene;
id_map<void *, Shader> shader_map;
enum ShaderFlags { SHADER_WITH_LAYER_ATTRS };
id_map<void *, Shader, ShaderFlags> shader_map;
id_map<ObjectKey, Object> object_map;
id_map<void *, Procedural> procedural_map;
id_map<GeometryKey, Geometry> geometry_map;

View File

@ -274,7 +274,7 @@ endif()
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING)
if(EXISTS ${_cycles_lib_dir})
if(NOT openpgl_DIR AND EXISTS ${_cycles_lib_dir})
set(openpgl_DIR ${_cycles_lib_dir}/openpgl/lib/cmake/openpgl)
endif()

View File

@ -142,7 +142,6 @@ set(SRC
${SRC_DUMMY}
${SRC_MULTI}
${SRC_OPTIX}
${SRC_ONEAPI}
${SRC_HEADERS}
)
@ -188,7 +187,25 @@ if(WITH_CYCLES_DEVICE_METAL)
)
endif()
if (WITH_CYCLES_DEVICE_ONEAPI)
if(WIN32)
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi.lib)
else()
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so)
endif()
list(APPEND LIB
${cycles_kernel_oneapi_lib}
"$<$<CONFIG:Debug>:${SYCL_LIBRARY_DEBUG}>"
"$<$<CONFIG:Release>:${SYCL_LIBRARY}>"
"$<$<CONFIG:RelWithDebInfo>:${SYCL_LIBRARY}>"
"$<$<CONFIG:MinSizeRel>:${SYCL_LIBRARY}>"
)
add_definitions(-DWITH_ONEAPI)
list(APPEND SRC
${SRC_ONEAPI}
)
list(APPEND INC_SYS
${SYCL_INCLUDE_DIR}
)
endif()
if(WITH_OPENIMAGEDENOISE)

View File

@ -19,62 +19,12 @@
CCL_NAMESPACE_BEGIN
#ifdef WITH_ONEAPI
static OneAPIDLLInterface oneapi_dll;
#endif
#ifdef _WIN32
# define LOAD_ONEAPI_SHARED_LIBRARY(path) (void *)(LoadLibrary(path))
# define LOAD_ONEAPI_SHARED_LIBRARY_ERROR() GetLastError()
# define FREE_SHARED_LIBRARY(handle) FreeLibrary((HMODULE)handle)
# define GET_SHARED_LIBRARY_SYMBOL(handle, name) GetProcAddress((HMODULE)handle, name)
#elif __linux__
# define LOAD_ONEAPI_SHARED_LIBRARY(path) dlopen(path, RTLD_NOW)
# define LOAD_ONEAPI_SHARED_LIBRARY_ERROR() dlerror()
# define FREE_SHARED_LIBRARY(handle) dlclose(handle)
# define GET_SHARED_LIBRARY_SYMBOL(handle, name) dlsym(handle, name)
#endif
bool device_oneapi_init()
{
#if !defined(WITH_ONEAPI)
return false;
#else
string lib_path = path_get("lib");
# ifdef _WIN32
lib_path = path_join(lib_path, "cycles_kernel_oneapi.dll");
# else
lib_path = path_join(lib_path, "cycles_kernel_oneapi.so");
# endif
void *lib_handle = LOAD_ONEAPI_SHARED_LIBRARY(lib_path.c_str());
/* This shouldn't happen, but it still makes sense to have a branch for this. */
if (lib_handle == NULL) {
LOG(ERROR) << "oneAPI kernel shared library cannot be loaded: "
<< LOAD_ONEAPI_SHARED_LIBRARY_ERROR();
return false;
}
# define DLL_INTERFACE_CALL(function, return_type, ...) \
(oneapi_dll.function) = reinterpret_cast<decltype(oneapi_dll.function)>( \
GET_SHARED_LIBRARY_SYMBOL(lib_handle, #function)); \
if (oneapi_dll.function == NULL) { \
LOG(ERROR) << "oneAPI shared library function \"" << #function \
<< "\" has not been loaded from kernel shared - disable oneAPI " \
"library disable oneAPI implementation due to this"; \
FREE_SHARED_LIBRARY(lib_handle); \
return false; \
}
# include "kernel/device/oneapi/dll_interface_template.h"
# undef DLL_INTERFACE_CALL
VLOG_INFO << "oneAPI kernel shared library has been loaded successfully";
/* We need to have this oneapi kernel shared library during all life-span of the Blender.
* So it is not unloaded because of this.
* FREE_SHARED_LIBRARY(lib_handle); */
/* NOTE(@nsirgien): we need to enable JIT cache from here and
* right now this cache policy is controlled by env. variables. */
/* NOTE(hallade) we also disable use of copy engine as it
@ -109,17 +59,10 @@ bool device_oneapi_init()
#endif
}
#if defined(_WIN32) || defined(__linux__)
# undef LOAD_SYCL_SHARED_LIBRARY
# undef LOAD_ONEAPI_SHARED_LIBRARY
# undef FREE_SHARED_LIBRARY
# undef GET_SHARED_LIBRARY_SYMBOL
#endif
Device *device_oneapi_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
{
#ifdef WITH_ONEAPI
return new OneapiDevice(info, oneapi_dll, stats, profiler);
return new OneapiDevice(info, stats, profiler);
#else
(void)info;
(void)stats;
@ -165,7 +108,7 @@ static void device_iterator_cb(const char *id, const char *name, int num, void *
void device_oneapi_info(vector<DeviceInfo> &devices)
{
#ifdef WITH_ONEAPI
(oneapi_dll.oneapi_iterate_devices)(device_iterator_cb, &devices);
OneapiDevice::iterate_devices(device_iterator_cb, &devices);
#else /* WITH_ONEAPI */
(void)devices;
#endif /* WITH_ONEAPI */
@ -175,10 +118,10 @@ string device_oneapi_capabilities()
{
string capabilities;
#ifdef WITH_ONEAPI
char *c_capabilities = (oneapi_dll.oneapi_device_capabilities)();
char *c_capabilities = OneapiDevice::device_capabilities();
if (c_capabilities) {
capabilities = c_capabilities;
(oneapi_dll.oneapi_free)(c_capabilities);
free(c_capabilities);
}
#endif
return capabilities;

View File

@ -8,7 +8,7 @@
# include "util/debug.h"
# include "util/log.h"
# include "kernel/device/oneapi/kernel.h"
# include "kernel/device/oneapi/globals.h"
CCL_NAMESPACE_BEGIN
@ -19,26 +19,19 @@ static void queue_error_cb(const char *message, void *user_ptr)
}
}
OneapiDevice::OneapiDevice(const DeviceInfo &info,
OneAPIDLLInterface &oneapi_dll_object,
Stats &stats,
Profiler &profiler)
OneapiDevice::OneapiDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler)
: Device(info, stats, profiler),
device_queue_(nullptr),
texture_info_(this, "texture_info", MEM_GLOBAL),
kg_memory_(nullptr),
kg_memory_device_(nullptr),
kg_memory_size_(0),
oneapi_dll_(oneapi_dll_object)
kg_memory_size_(0)
{
need_texture_info_ = false;
oneapi_dll_.oneapi_set_error_cb(queue_error_cb, &oneapi_error_string_);
oneapi_set_error_cb(queue_error_cb, &oneapi_error_string_);
/* OneAPI calls should be initialized on this moment. */
assert(oneapi_dll_.oneapi_create_queue != nullptr);
bool is_finished_ok = oneapi_dll_.oneapi_create_queue(device_queue_, info.num);
bool is_finished_ok = create_queue(device_queue_, info.num);
if (is_finished_ok == false) {
set_error("oneAPI queue initialization error: got runtime exception \"" +
oneapi_error_string_ + "\"");
@ -50,7 +43,7 @@ OneapiDevice::OneapiDevice(const DeviceInfo &info,
}
size_t globals_segment_size;
is_finished_ok = oneapi_dll_.oneapi_kernel_globals_size(device_queue_, globals_segment_size);
is_finished_ok = kernel_globals_size(device_queue_, globals_segment_size);
if (is_finished_ok == false) {
set_error("oneAPI constant memory initialization got runtime exception \"" +
oneapi_error_string_ + "\"");
@ -59,27 +52,27 @@ OneapiDevice::OneapiDevice(const DeviceInfo &info,
VLOG_DEBUG << "Successfully created global/constant memory segment (kernel globals object)";
}
kg_memory_ = oneapi_dll_.oneapi_usm_aligned_alloc_host(device_queue_, globals_segment_size, 16);
oneapi_dll_.oneapi_usm_memset(device_queue_, kg_memory_, 0, globals_segment_size);
kg_memory_ = usm_aligned_alloc_host(device_queue_, globals_segment_size, 16);
usm_memset(device_queue_, kg_memory_, 0, globals_segment_size);
kg_memory_device_ = oneapi_dll_.oneapi_usm_alloc_device(device_queue_, globals_segment_size);
kg_memory_device_ = usm_alloc_device(device_queue_, globals_segment_size);
kg_memory_size_ = globals_segment_size;
max_memory_on_device_ = oneapi_dll_.oneapi_get_memcapacity(device_queue_);
max_memory_on_device_ = get_memcapacity();
}
OneapiDevice::~OneapiDevice()
{
texture_info_.free();
oneapi_dll_.oneapi_usm_free(device_queue_, kg_memory_);
oneapi_dll_.oneapi_usm_free(device_queue_, kg_memory_device_);
usm_free(device_queue_, kg_memory_);
usm_free(device_queue_, kg_memory_device_);
for (ConstMemMap::iterator mt = const_mem_map_.begin(); mt != const_mem_map_.end(); mt++)
delete mt->second;
if (device_queue_)
oneapi_dll_.oneapi_free_queue(device_queue_);
free_queue(device_queue_);
}
bool OneapiDevice::check_peer_access(Device * /*peer_device*/)
@ -95,18 +88,26 @@ BVHLayoutMask OneapiDevice::get_bvh_layout_mask() const
bool OneapiDevice::load_kernels(const uint requested_features)
{
assert(device_queue_);
/* NOTE(@nsirgien): oneAPI can support compilation of kernel code with certain feature set
* with specialization constants, but it hasn't been implemented yet. */
(void)requested_features;
bool is_finished_ok = oneapi_dll_.oneapi_run_test_kernel(device_queue_);
bool is_finished_ok = oneapi_run_test_kernel(device_queue_);
if (is_finished_ok == false) {
set_error("oneAPI kernel load: got runtime exception \"" + oneapi_error_string_ + "\"");
set_error("oneAPI test kernel execution: got a runtime exception \"" + oneapi_error_string_ +
"\"");
return false;
}
else {
VLOG_INFO << "Runtime compilation done for \"" << info.description << "\"";
VLOG_INFO << "Test kernel has been executed successfully for \"" << info.description << "\"";
assert(device_queue_);
}
is_finished_ok = oneapi_load_kernels(device_queue_, (const unsigned int)requested_features);
if (is_finished_ok == false) {
set_error("oneAPI kernels loading: got a runtime exception \"" + oneapi_error_string_ + "\"");
}
else {
VLOG_INFO << "Kernels loading (compilation) has been done for \"" << info.description << "\"";
}
return is_finished_ok;
}
@ -138,7 +139,7 @@ void OneapiDevice::generic_alloc(device_memory &mem)
* type has been used for oneAPI device in order to better fit in Cycles architecture. */
void *device_pointer = nullptr;
if (mem.memory_size() + stats.mem_used < max_memory_on_device_)
device_pointer = oneapi_dll_.oneapi_usm_alloc_device(device_queue_, memory_size);
device_pointer = usm_alloc_device(device_queue_, memory_size);
if (device_pointer == nullptr) {
set_error("oneAPI kernel - device memory allocation error for " +
string_human_readable_size(mem.memory_size()) +
@ -163,8 +164,7 @@ void OneapiDevice::generic_copy_to(device_memory &mem)
/* Copy operation from host shouldn't be requested if there is no memory allocated on host. */
assert(mem.host_pointer);
assert(device_queue_);
oneapi_dll_.oneapi_usm_memcpy(
device_queue_, (void *)mem.device_pointer, (void *)mem.host_pointer, memory_size);
usm_memcpy(device_queue_, (void *)mem.device_pointer, (void *)mem.host_pointer, memory_size);
}
/* TODO: Make sycl::queue part of OneapiQueue and avoid using pointers to sycl::queue. */
@ -178,11 +178,6 @@ string OneapiDevice::oneapi_error_message()
return string(oneapi_error_string_);
}
OneAPIDLLInterface OneapiDevice::oneapi_dll_object()
{
return oneapi_dll_;
}
void *OneapiDevice::kernel_globals_device_pointer()
{
return kg_memory_device_;
@ -198,7 +193,7 @@ void OneapiDevice::generic_free(device_memory &mem)
mem.device_size = 0;
assert(device_queue_);
oneapi_dll_.oneapi_usm_free(device_queue_, (void *)mem.device_pointer);
usm_free(device_queue_, (void *)mem.device_pointer);
mem.device_pointer = 0;
}
@ -266,8 +261,7 @@ void OneapiDevice::mem_copy_from(device_memory &mem, size_t y, size_t w, size_t
if (mem.device_pointer) {
char *shifted_host = reinterpret_cast<char *>(mem.host_pointer) + offset;
char *shifted_device = reinterpret_cast<char *>(mem.device_pointer) + offset;
bool is_finished_ok = oneapi_dll_.oneapi_usm_memcpy(
device_queue_, shifted_host, shifted_device, size);
bool is_finished_ok = usm_memcpy(device_queue_, shifted_host, shifted_device, size);
if (is_finished_ok == false) {
set_error("oneAPI memory operation error: got runtime exception \"" +
oneapi_error_string_ + "\"");
@ -292,7 +286,7 @@ void OneapiDevice::mem_zero(device_memory &mem)
}
assert(device_queue_);
bool is_finished_ok = oneapi_dll_.oneapi_usm_memset(
bool is_finished_ok = usm_memset(
device_queue_, (void *)mem.device_pointer, 0, mem.memory_size());
if (is_finished_ok == false) {
set_error("oneAPI memory operation error: got runtime exception \"" + oneapi_error_string_ +
@ -349,10 +343,9 @@ void OneapiDevice::const_copy_to(const char *name, void *host, size_t size)
memcpy(data->data(), host, size);
data->copy_to_device();
oneapi_dll_.oneapi_set_global_memory(
device_queue_, kg_memory_, name, (void *)data->device_pointer);
set_global_memory(device_queue_, kg_memory_, name, (void *)data->device_pointer);
oneapi_dll_.oneapi_usm_memcpy(device_queue_, kg_memory_device_, kg_memory_, kg_memory_size_);
usm_memcpy(device_queue_, kg_memory_device_, kg_memory_, kg_memory_size_);
}
void OneapiDevice::global_alloc(device_memory &mem)
@ -367,10 +360,9 @@ void OneapiDevice::global_alloc(device_memory &mem)
generic_alloc(mem);
generic_copy_to(mem);
oneapi_dll_.oneapi_set_global_memory(
device_queue_, kg_memory_, mem.name, (void *)mem.device_pointer);
set_global_memory(device_queue_, kg_memory_, mem.name, (void *)mem.device_pointer);
oneapi_dll_.oneapi_usm_memcpy(device_queue_, kg_memory_device_, kg_memory_, kg_memory_size_);
usm_memcpy(device_queue_, kg_memory_device_, kg_memory_, kg_memory_size_);
}
void OneapiDevice::global_free(device_memory &mem)
@ -410,18 +402,6 @@ unique_ptr<DeviceQueue> OneapiDevice::gpu_queue_create()
return make_unique<OneapiDeviceQueue>(this);
}
int OneapiDevice::get_num_multiprocessors()
{
assert(device_queue_);
return oneapi_dll_.oneapi_get_num_multiprocessors(device_queue_);
}
int OneapiDevice::get_max_num_threads_per_multiprocessor()
{
assert(device_queue_);
return oneapi_dll_.oneapi_get_max_num_threads_per_multiprocessor(device_queue_);
}
bool OneapiDevice::should_use_graphics_interop()
{
/* NOTE(@nsirgien): oneAPI doesn't yet support direct writing into graphics API objects, so
@ -432,13 +412,460 @@ bool OneapiDevice::should_use_graphics_interop()
void *OneapiDevice::usm_aligned_alloc_host(size_t memory_size, size_t alignment)
{
assert(device_queue_);
return oneapi_dll_.oneapi_usm_aligned_alloc_host(device_queue_, memory_size, alignment);
return usm_aligned_alloc_host(device_queue_, memory_size, alignment);
}
void OneapiDevice::usm_free(void *usm_ptr)
{
assert(device_queue_);
return oneapi_dll_.oneapi_usm_free(device_queue_, usm_ptr);
return usm_free(device_queue_, usm_ptr);
}
void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_host = false)
{
# ifdef _DEBUG
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
sycl::info::device_type device_type =
queue->get_device().get_info<sycl::info::device::device_type>();
sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context());
(void)usm_type;
assert(usm_type == sycl::usm::alloc::device ||
((device_type == sycl::info::device_type::host ||
device_type == sycl::info::device_type::cpu || allow_host) &&
usm_type == sycl::usm::alloc::host));
# endif
}
bool OneapiDevice::create_queue(SyclQueue *&external_queue, int device_index)
{
bool finished_correct = true;
try {
std::vector<sycl::device> devices = OneapiDevice::available_devices();
if (device_index < 0 || device_index >= devices.size()) {
return false;
}
sycl::queue *created_queue = new sycl::queue(devices[device_index],
sycl::property::queue::in_order());
external_queue = reinterpret_cast<SyclQueue *>(created_queue);
}
catch (sycl::exception const &e) {
finished_correct = false;
oneapi_error_string_ = e.what();
}
return finished_correct;
}
void OneapiDevice::free_queue(SyclQueue *queue_)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
delete queue;
}
void *OneapiDevice::usm_aligned_alloc_host(SyclQueue *queue_, size_t memory_size, size_t alignment)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
return sycl::aligned_alloc_host(alignment, memory_size, *queue);
}
void *OneapiDevice::usm_alloc_device(SyclQueue *queue_, size_t memory_size)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
return sycl::malloc_device(memory_size, *queue);
}
void OneapiDevice::usm_free(SyclQueue *queue_, void *usm_ptr)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
OneapiDevice::check_usm(queue_, usm_ptr, true);
sycl::free(usm_ptr, *queue);
}
bool OneapiDevice::usm_memcpy(SyclQueue *queue_, void *dest, void *src, size_t num_bytes)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
OneapiDevice::check_usm(queue_, dest, true);
OneapiDevice::check_usm(queue_, src, true);
sycl::event mem_event = queue->memcpy(dest, src, num_bytes);
# ifdef WITH_CYCLES_DEBUG
try {
/* NOTE(@nsirgien) Waiting on memory operation may give more precise error
* messages. Due to impact on occupancy, it makes sense to enable it only during Cycles debug.
*/
mem_event.wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
oneapi_error_string_ = e.what();
return false;
}
# else
sycl::usm::alloc dest_type = get_pointer_type(dest, queue->get_context());
sycl::usm::alloc src_type = get_pointer_type(src, queue->get_context());
bool from_device_to_host = dest_type == sycl::usm::alloc::host &&
src_type == sycl::usm::alloc::device;
bool host_or_device_memop_with_offset = dest_type == sycl::usm::alloc::unknown ||
src_type == sycl::usm::alloc::unknown;
/* NOTE(@sirgienko) Host-side blocking wait on this operation is mandatory, otherwise the host
* may not wait until the end of the transfer before using the memory.
*/
if (from_device_to_host || host_or_device_memop_with_offset)
mem_event.wait();
return true;
# endif
}
bool OneapiDevice::usm_memset(SyclQueue *queue_,
void *usm_ptr,
unsigned char value,
size_t num_bytes)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
OneapiDevice::check_usm(queue_, usm_ptr, true);
sycl::event mem_event = queue->memset(usm_ptr, value, num_bytes);
# ifdef WITH_CYCLES_DEBUG
try {
/* NOTE(@nsirgien) Waiting on memory operation may give more precise error
* messages. Due to impact on occupancy, it makes sense to enable it only during Cycles debug.
*/
mem_event.wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
oneapi_error_string_ = e.what();
return false;
}
# else
(void)mem_event;
return true;
# endif
}
bool OneapiDevice::queue_synchronize(SyclQueue *queue_)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
try {
queue->wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
oneapi_error_string_ = e.what();
return false;
}
}
bool OneapiDevice::kernel_globals_size(SyclQueue *queue_, size_t &kernel_global_size)
{
kernel_global_size = sizeof(KernelGlobalsGPU);
return true;
}
void OneapiDevice::set_global_memory(SyclQueue *queue_,
void *kernel_globals,
const char *memory_name,
void *memory_device_pointer)
{
assert(queue_);
assert(kernel_globals);
assert(memory_name);
assert(memory_device_pointer);
KernelGlobalsGPU *globals = (KernelGlobalsGPU *)kernel_globals;
OneapiDevice::check_usm(queue_, memory_device_pointer);
OneapiDevice::check_usm(queue_, kernel_globals, true);
std::string matched_name(memory_name);
/* This macro will change global ptr of KernelGlobals via name matching. */
# define KERNEL_DATA_ARRAY(type, name) \
else if (#name == matched_name) \
{ \
globals->__##name = (type *)memory_device_pointer; \
return; \
}
if (false) {
}
else if ("integrator_state" == matched_name) {
globals->integrator_state = (IntegratorStateGPU *)memory_device_pointer;
return;
}
KERNEL_DATA_ARRAY(KernelData, data)
# include "kernel/data_arrays.h"
else
{
std::cerr << "Can't found global/constant memory with name \"" << matched_name << "\"!"
<< std::endl;
assert(false);
}
# undef KERNEL_DATA_ARRAY
}
bool OneapiDevice::enqueue_kernel(KernelContext *kernel_context,
int kernel,
size_t global_size,
void **args)
{
return oneapi_enqueue_kernel(kernel_context, kernel, global_size, args);
}
/* Compute-runtime (ie. NEO) version is what gets returned by sycl/L0 on Windows
* since Windows driver 101.3268. */
/* The same min compute-runtime version is currently required across Windows and Linux.
* For Windows driver 101.3430, compute-runtime version is 23904. */
static const int lowest_supported_driver_version_win = 1013430;
static const int lowest_supported_driver_version_neo = 23904;
int OneapiDevice::parse_driver_build_version(const sycl::device &device)
{
const std::string &driver_version = device.get_info<sycl::info::device::driver_version>();
int driver_build_version = 0;
size_t second_dot_position = driver_version.find('.', driver_version.find('.') + 1);
if (second_dot_position == std::string::npos) {
std::cerr << "Unable to parse unknown Intel GPU driver version \"" << driver_version
<< "\" does not match xx.xx.xxxxx (Linux), x.x.xxxx (L0),"
<< " xx.xx.xxx.xxxx (Windows) for device \""
<< device.get_info<sycl::info::device::name>() << "\"." << std::endl;
}
else {
try {
size_t third_dot_position = driver_version.find('.', second_dot_position + 1);
if (third_dot_position != std::string::npos) {
const std::string &third_number_substr = driver_version.substr(
second_dot_position + 1, third_dot_position - second_dot_position - 1);
const std::string &forth_number_substr = driver_version.substr(third_dot_position + 1);
if (third_number_substr.length() == 3 && forth_number_substr.length() == 4)
driver_build_version = std::stoi(third_number_substr) * 10000 +
std::stoi(forth_number_substr);
}
else {
const std::string &third_number_substr = driver_version.substr(second_dot_position + 1);
driver_build_version = std::stoi(third_number_substr);
}
}
catch (std::invalid_argument &) {
std::cerr << "Unable to parse unknown Intel GPU driver version \"" << driver_version
<< "\" does not match xx.xx.xxxxx (Linux), x.x.xxxx (L0),"
<< " xx.xx.xxx.xxxx (Windows) for device \""
<< device.get_info<sycl::info::device::name>() << "\"." << std::endl;
}
}
return driver_build_version;
}
std::vector<sycl::device> OneapiDevice::available_devices()
{
bool allow_all_devices = false;
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr)
allow_all_devices = true;
/* Host device is useful only for debugging at the moment
* so we hide this device with default build settings. */
# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
bool allow_host = true;
# else
bool allow_host = false;
# endif
const std::vector<sycl::platform> &oneapi_platforms = sycl::platform::get_platforms();
std::vector<sycl::device> available_devices;
for (const sycl::platform &platform : oneapi_platforms) {
/* ignore OpenCL platforms to avoid using the same devices through both Level-Zero and OpenCL.
*/
if (platform.get_backend() == sycl::backend::opencl) {
continue;
}
const std::vector<sycl::device> &oneapi_devices =
(allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) :
platform.get_devices(sycl::info::device_type::gpu);
for (const sycl::device &device : oneapi_devices) {
if (allow_all_devices) {
/* still filter out host device if build doesn't support it. */
if (allow_host || !device.is_host()) {
available_devices.push_back(device);
}
}
else {
bool filter_out = false;
/* For now we support all Intel(R) Arc(TM) devices and likely any future GPU,
* assuming they have either more than 96 Execution Units or not 7 threads per EU.
* Official support can be broaden to older and smaller GPUs once ready. */
if (device.is_gpu() && platform.get_backend() == sycl::backend::ext_oneapi_level_zero) {
/* Filtered-out defaults in-case these values aren't available through too old L0
* runtime. */
int number_of_eus = 96;
int threads_per_eu = 7;
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
number_of_eus = device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
}
if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
threads_per_eu =
device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
}
/* This filters out all Level-Zero supported GPUs from older generation than Arc. */
if (number_of_eus <= 96 && threads_per_eu == 7) {
filter_out = true;
}
/* if not already filtered out, check driver version. */
if (!filter_out) {
int driver_build_version = parse_driver_build_version(device);
if ((driver_build_version > 100000 &&
driver_build_version < lowest_supported_driver_version_win) ||
driver_build_version < lowest_supported_driver_version_neo) {
filter_out = true;
}
}
}
else if (!allow_host && device.is_host()) {
filter_out = true;
}
else if (!allow_all_devices) {
filter_out = true;
}
if (!filter_out) {
available_devices.push_back(device);
}
}
}
}
return available_devices;
}
char *OneapiDevice::device_capabilities()
{
std::stringstream capabilities;
const std::vector<sycl::device> &oneapi_devices = available_devices();
for (const sycl::device &device : oneapi_devices) {
const std::string &name = device.get_info<sycl::info::device::name>();
capabilities << std::string("\t") << name << "\n";
# define WRITE_ATTR(attribute_name, attribute_variable) \
capabilities << "\t\tsycl::info::device::" #attribute_name "\t\t\t" << attribute_variable \
<< "\n";
# define GET_NUM_ATTR(attribute) \
{ \
size_t attribute = (size_t)device.get_info<sycl::info::device ::attribute>(); \
capabilities << "\t\tsycl::info::device::" #attribute "\t\t\t" << attribute << "\n"; \
}
GET_NUM_ATTR(vendor_id)
GET_NUM_ATTR(max_compute_units)
GET_NUM_ATTR(max_work_item_dimensions)
sycl::id<3> max_work_item_sizes =
device.get_info<sycl::info::device::max_work_item_sizes<3>>();
WRITE_ATTR("max_work_item_sizes_dim0", ((size_t)max_work_item_sizes.get(0)))
WRITE_ATTR("max_work_item_sizes_dim1", ((size_t)max_work_item_sizes.get(1)))
WRITE_ATTR("max_work_item_sizes_dim2", ((size_t)max_work_item_sizes.get(2)))
GET_NUM_ATTR(max_work_group_size)
GET_NUM_ATTR(max_num_sub_groups)
GET_NUM_ATTR(sub_group_independent_forward_progress)
GET_NUM_ATTR(preferred_vector_width_char)
GET_NUM_ATTR(preferred_vector_width_short)
GET_NUM_ATTR(preferred_vector_width_int)
GET_NUM_ATTR(preferred_vector_width_long)
GET_NUM_ATTR(preferred_vector_width_float)
GET_NUM_ATTR(preferred_vector_width_double)
GET_NUM_ATTR(preferred_vector_width_half)
GET_NUM_ATTR(native_vector_width_char)
GET_NUM_ATTR(native_vector_width_short)
GET_NUM_ATTR(native_vector_width_int)
GET_NUM_ATTR(native_vector_width_long)
GET_NUM_ATTR(native_vector_width_float)
GET_NUM_ATTR(native_vector_width_double)
GET_NUM_ATTR(native_vector_width_half)
size_t max_clock_frequency =
(size_t)(device.is_host() ? (size_t)0 :
device.get_info<sycl::info::device::max_clock_frequency>());
WRITE_ATTR("max_clock_frequency", max_clock_frequency)
GET_NUM_ATTR(address_bits)
GET_NUM_ATTR(max_mem_alloc_size)
/* NOTE(@nsirgien): Implementation doesn't use image support as bindless images aren't
* supported so we always return false, even if device supports HW texture usage acceleration.
*/
bool image_support = false;
WRITE_ATTR("image_support", (size_t)image_support)
GET_NUM_ATTR(max_parameter_size)
GET_NUM_ATTR(mem_base_addr_align)
GET_NUM_ATTR(global_mem_size)
GET_NUM_ATTR(local_mem_size)
GET_NUM_ATTR(error_correction_support)
GET_NUM_ATTR(profiling_timer_resolution)
GET_NUM_ATTR(is_available)
# undef GET_NUM_ATTR
# undef WRITE_ATTR
capabilities << "\n";
}
return ::strdup(capabilities.str().c_str());
}
void OneapiDevice::iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_ptr)
{
int num = 0;
std::vector<sycl::device> devices = OneapiDevice::available_devices();
for (sycl::device &device : devices) {
const std::string &platform_name =
device.get_platform().get_info<sycl::info::platform::name>();
std::string name = device.get_info<sycl::info::device::name>();
std::string id = "ONEAPI_" + platform_name + "_" + name;
if (device.has(sycl::aspect::ext_intel_pci_address)) {
id.append("_" + device.get_info<sycl::info::device::ext_intel_pci_address>());
}
(cb)(id.c_str(), name.c_str(), num, user_ptr);
num++;
}
}
size_t OneapiDevice::get_memcapacity()
{
return reinterpret_cast<sycl::queue *>(device_queue_)
->get_device()
.get_info<sycl::info::device::global_mem_size>();
}
int OneapiDevice::get_num_multiprocessors()
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
return device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
}
else
return 0;
}
int OneapiDevice::get_max_num_threads_per_multiprocessor()
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
return device.get_info<sycl::info::device::ext_intel_gpu_eu_simd_width>() *
device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
}
else
return 0;
}
CCL_NAMESPACE_END

View File

@ -3,9 +3,12 @@
#ifdef WITH_ONEAPI
# include <CL/sycl.hpp>
# include "device/device.h"
# include "device/oneapi/device.h"
# include "device/oneapi/queue.h"
# include "kernel/device/oneapi/kernel.h"
# include "util/map.h"
@ -13,6 +16,11 @@ CCL_NAMESPACE_BEGIN
class DeviceQueue;
typedef void (*OneAPIDeviceIteratorCallback)(const char *id,
const char *name,
int num,
void *user_ptr);
class OneapiDevice : public Device {
private:
SyclQueue *device_queue_;
@ -25,16 +33,12 @@ class OneapiDevice : public Device {
void *kg_memory_device_;
size_t kg_memory_size_ = (size_t)0;
size_t max_memory_on_device_ = (size_t)0;
OneAPIDLLInterface oneapi_dll_;
std::string oneapi_error_string_;
public:
virtual BVHLayoutMask get_bvh_layout_mask() const override;
OneapiDevice(const DeviceInfo &info,
OneAPIDLLInterface &oneapi_dll_object,
Stats &stats,
Profiler &profiler);
OneapiDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler);
virtual ~OneapiDevice();
@ -50,12 +54,8 @@ class OneapiDevice : public Device {
void generic_free(device_memory &mem);
SyclQueue *sycl_queue();
string oneapi_error_message();
OneAPIDLLInterface oneapi_dll_object();
void *kernel_globals_device_pointer();
void mem_alloc(device_memory &mem) override;
@ -90,13 +90,37 @@ class OneapiDevice : public Device {
virtual unique_ptr<DeviceQueue> gpu_queue_create() override;
int get_num_multiprocessors();
int get_max_num_threads_per_multiprocessor();
/* NOTE(@nsirgien): Create this methods to avoid some compilation problems on Windows with host
* side compilation (MSVC). */
void *usm_aligned_alloc_host(size_t memory_size, size_t alignment);
void usm_free(void *usm_ptr);
static std::vector<sycl::device> available_devices();
static char *device_capabilities();
static int parse_driver_build_version(const sycl::device &device);
static void iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_ptr);
size_t get_memcapacity();
int get_num_multiprocessors();
int get_max_num_threads_per_multiprocessor();
bool queue_synchronize(SyclQueue *queue);
bool kernel_globals_size(SyclQueue *queue, size_t &kernel_global_size);
void set_global_memory(SyclQueue *queue,
void *kernel_globals,
const char *memory_name,
void *memory_device_pointer);
bool enqueue_kernel(KernelContext *kernel_context, int kernel, size_t global_size, void **args);
SyclQueue *sycl_queue();
protected:
void check_usm(SyclQueue *queue, const void *usm_ptr, bool allow_host);
bool create_queue(SyclQueue *&external_queue, int device_index);
void free_queue(SyclQueue *queue);
void *usm_aligned_alloc_host(SyclQueue *queue, size_t memory_size, size_t alignment);
void *usm_alloc_device(SyclQueue *queue, size_t memory_size);
void usm_free(SyclQueue *queue, void *usm_ptr);
bool usm_memcpy(SyclQueue *queue, void *dest, void *src, size_t num_bytes);
bool usm_memset(SyclQueue *queue, void *usm_ptr, unsigned char value, size_t num_bytes);
};
CCL_NAMESPACE_END

View File

@ -1,17 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
/* Include kernel header to get access to SYCL-specific types, like SyclQueue and
* OneAPIDeviceIteratorCallback. */
#include "kernel/device/oneapi/kernel.h"
#ifdef WITH_ONEAPI
struct OneAPIDLLInterface {
# define DLL_INTERFACE_CALL(function, return_type, ...) \
return_type (*function)(__VA_ARGS__) = nullptr;
# include "kernel/device/oneapi/dll_interface_template.h"
# undef DLL_INTERFACE_CALL
};
#endif

View File

@ -22,10 +22,7 @@ struct KernelExecutionInfo {
/* OneapiDeviceQueue */
OneapiDeviceQueue::OneapiDeviceQueue(OneapiDevice *device)
: DeviceQueue(device),
oneapi_device_(device),
oneapi_dll_(device->oneapi_dll_object()),
kernel_context_(nullptr)
: DeviceQueue(device), oneapi_device_(device), kernel_context_(nullptr)
{
}
@ -81,14 +78,14 @@ bool OneapiDeviceQueue::enqueue(DeviceKernel kernel,
assert(signed_kernel_work_size >= 0);
size_t kernel_work_size = (size_t)signed_kernel_work_size;
size_t kernel_local_size = oneapi_dll_.oneapi_kernel_preferred_local_size(
size_t kernel_local_size = oneapi_kernel_preferred_local_size(
kernel_context_->queue, (::DeviceKernel)kernel, kernel_work_size);
size_t uniformed_kernel_work_size = round_up(kernel_work_size, kernel_local_size);
assert(kernel_context_);
/* Call the oneAPI kernel DLL to launch the requested kernel. */
bool is_finished_ok = oneapi_dll_.oneapi_enqueue_kernel(
bool is_finished_ok = oneapi_device_->enqueue_kernel(
kernel_context_, kernel, uniformed_kernel_work_size, args);
if (is_finished_ok == false) {
@ -108,7 +105,7 @@ bool OneapiDeviceQueue::synchronize()
return false;
}
bool is_finished_ok = oneapi_dll_.oneapi_queue_synchronize(oneapi_device_->sycl_queue());
bool is_finished_ok = oneapi_device_->queue_synchronize(oneapi_device_->sycl_queue());
if (is_finished_ok == false)
oneapi_device_->set_error("oneAPI unknown kernel execution error: got runtime exception \"" +
oneapi_device_->oneapi_error_message() + "\"");

View File

@ -10,7 +10,7 @@
# include "device/queue.h"
# include "device/oneapi/device.h"
# include "device/oneapi/dll_interface.h"
# include "kernel/device/oneapi/kernel.h"
CCL_NAMESPACE_BEGIN
@ -41,9 +41,7 @@ class OneapiDeviceQueue : public DeviceQueue {
protected:
OneapiDevice *oneapi_device_;
OneAPIDLLInterface oneapi_dll_;
KernelContext *kernel_context_;
bool with_kernel_statistics_;
};
CCL_NAMESPACE_END

View File

@ -43,8 +43,11 @@ PathTrace::PathTrace(Device *device,
/* Create path tracing work in advance, so that it can be reused by incremental sampling as much
* as possible. */
device_->foreach_device([&](Device *path_trace_device) {
path_trace_works_.emplace_back(PathTraceWork::create(
path_trace_device, film, device_scene, &render_cancel_.is_requested));
unique_ptr<PathTraceWork> work = PathTraceWork::create(
path_trace_device, film, device_scene, &render_cancel_.is_requested);
if (work) {
path_trace_works_.emplace_back(std::move(work));
}
});
work_balance_infos_.resize(path_trace_works_.size());

View File

@ -23,6 +23,10 @@ unique_ptr<PathTraceWork> PathTraceWork::create(Device *device,
if (device->info.type == DEVICE_CPU) {
return make_unique<PathTraceWorkCPU>(device, film, device_scene, cancel_requested_flag);
}
if (device->info.type == DEVICE_DUMMY) {
/* Dummy devices can't perform any work. */
return nullptr;
}
return make_unique<PathTraceWorkGPU>(device, film, device_scene, cancel_requested_flag);
}

View File

@ -285,7 +285,7 @@ void PathTraceWorkCPU::cryptomatte_postproces()
}
#ifdef WITH_PATH_GUIDING
/* Note: It seems that this is called before every rendering iteration/progression and not once per
/* NOTE: It seems that this is called before every rendering iteration/progression and not once per
* rendering. May be we find a way to call it only once per rendering. */
void PathTraceWorkCPU::guiding_init_kernel_globals(void *guiding_field,
void *sample_data_storage,

View File

@ -17,6 +17,9 @@ void work_balance_do_initial(vector<WorkBalanceInfo> &work_balance_infos)
work_balance_infos[0].weight = 1.0;
return;
}
else if (num_infos == 0) {
return;
}
/* There is no statistics available, so start with an equal distribution. */
const double weight = 1.0 / num_infos;

View File

@ -718,7 +718,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
if(WIN32)
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll)
else()
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.so)
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so)
endif()
set(cycles_oneapi_kernel_sources
@ -760,7 +760,6 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
${SYCL_CPP_FLAGS}
)
if (WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_ENABLED)
endif()
@ -817,6 +816,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
if(WIN32)
list(APPEND sycl_compiler_flags
-fuse-ld=link
-fms-extensions
-fms-compatibility
-D_WINDLL
@ -827,36 +827,43 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
-D_CRT_SECURE_NO_DEPRECATE
-DONEAPI_EXPORT)
if(sycl_compiler_compiler_name MATCHES "dpcpp")
# The oneAPI distribution calls the compiler "dpcpp" and comes with a script that sets environment variables.
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND "${sycl_compiler_root}/../../env/vars.bat"
COMMAND ${SYCL_COMPILER} $<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g> ${sycl_compiler_flags}
DEPENDS ${cycles_oneapi_kernel_sources})
string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR})
if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows
get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY)
string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir})
get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE)
else()
# The open source SYCL compiler just goes by clang++ and does not have such a script.
# Set the variables manually.
string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR})
if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows
get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY)
string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir})
get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE)
else()
set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
endif()
list(APPEND sycl_compiler_flags
-L "${MSVC_TOOLS_DIR}/lib/x64"
-L "${WINDOWS_KIT_DIR}/um/x64"
-L "${WINDOWS_KIT_DIR}/ucrt/x64")
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib
"PATH=${OCLOC_INSTALL_DIR};${sycl_compiler_root}"
${SYCL_COMPILER} $<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g> ${sycl_compiler_flags}
DEPENDS ${cycles_oneapi_kernel_sources})
set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
endif()
list(APPEND sycl_compiler_flags
-L "${MSVC_TOOLS_DIR}/lib/x64"
-L "${WINDOWS_KIT_DIR}/um/x64"
-L "${WINDOWS_KIT_DIR}/ucrt/x64")
set(sycl_compiler_flags_Release ${sycl_compiler_flags})
set(sycl_compiler_flags_Debug ${sycl_compiler_flags})
set(sycl_compiler_flags_RelWithDebInfo ${sycl_compiler_flags})
set(sycl_compiler_flags_MinSizeRel ${sycl_compiler_flags})
list(APPEND sycl_compiler_flags_RelWithDebInfo -g)
get_filename_component(sycl_library_debug_name ${SYCL_LIBRARY_DEBUG} NAME_WE)
list(APPEND sycl_compiler_flags_Debug
-g
-D_DEBUG
-nostdlib -Xclang --dependent-lib=msvcrtd
-Xclang --dependent-lib=${sycl_library_debug_name})
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib
"PATH=${OCLOC_INSTALL_DIR}\;${sycl_compiler_root}"
${SYCL_COMPILER}
"$<$<CONFIG:Release>:${sycl_compiler_flags_Release}>"
"$<$<CONFIG:RelWithDebInfo>:${sycl_compiler_flags_RelWithDebInfo}>"
"$<$<CONFIG:Debug>:${sycl_compiler_flags_Debug}>"
"$<$<CONFIG:MinSizeRel>:${sycl_compiler_flags_Release}>"
COMMAND_EXPAND_LISTS
DEPENDS ${cycles_oneapi_kernel_sources})
else()
list(APPEND sycl_compiler_flags -fPIC)
@ -868,55 +875,36 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
# libpi_level_zero.so can be placed next to it and get found.
list(APPEND sycl_compiler_flags -Wl,-rpath,'$$ORIGIN')
# The oneAPI distribution calls the compiler "dpcpp" and comes with a script that sets environment variables.
if(sycl_compiler_compiler_name MATCHES "dpcpp")
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND bash -c \"source ${sycl_compiler_root}/../../env/vars.sh&&${SYCL_COMPILER} $<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g> ${sycl_compiler_flags}\"
DEPENDS ${cycles_oneapi_kernel_sources})
else()
# The open source SYCL compiler just goes by clang++ and does not have such a script.
# Set the variables manually.
if(NOT IGC_INSTALL_DIR)
get_filename_component(IGC_INSTALL_DIR "${sycl_compiler_root}/../lib/igc" ABSOLUTE)
endif()
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LD_LIBRARY_PATH=${sycl_compiler_root}/../lib:${OCLOC_INSTALL_DIR}/lib:${IGC_INSTALL_DIR}/lib"
"PATH=${OCLOC_INSTALL_DIR}/bin:${sycl_compiler_root}:$ENV{PATH}" # env PATH is for compiler to find ld
${SYCL_COMPILER} $<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g> ${sycl_compiler_flags}
DEPENDS ${cycles_oneapi_kernel_sources})
if(NOT IGC_INSTALL_DIR)
get_filename_component(IGC_INSTALL_DIR "${sycl_compiler_root}/../lib/igc" ABSOLUTE)
endif()
add_custom_command(
OUTPUT ${cycles_kernel_oneapi_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LD_LIBRARY_PATH=${sycl_compiler_root}/../lib:${OCLOC_INSTALL_DIR}/lib:${IGC_INSTALL_DIR}/lib"
"PATH=${OCLOC_INSTALL_DIR}/bin:${sycl_compiler_root}:$ENV{PATH}" # env PATH is for compiler to find ld
${SYCL_COMPILER} $<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g> ${sycl_compiler_flags}
DEPENDS ${cycles_oneapi_kernel_sources})
endif()
if(NOT WITH_BLENDER)
# For the Cycles standalone put libraries next to the Cycles application.
set(cycles_oneapi_target_path ${CYCLES_INSTALL_PATH})
else()
# For Blender put the libraries next to the Blender executable.
#
# Note that the installation path in the delayed_install is relative to the versioned folder,
# which means we need to go one level up.
set(cycles_oneapi_target_path "../")
endif()
# install dynamic libraries required at runtime
if(WIN32)
set(SYCL_RUNTIME_DEPENDENCIES
sycl.dll
pi_level_zero.dll
)
if(NOT WITH_BLENDER)
# For the Cycles standalone put libraries next to the Cycles application.
delayed_install("${sycl_compiler_root}" "${SYCL_RUNTIME_DEPENDENCIES}" ${CYCLES_INSTALL_PATH})
else()
# For Blender put the libraries next to the Blender executable.
#
# Note that the installation path in the delayed_install is relative to the versioned folder,
# which means we need to go one level up.
delayed_install("${sycl_compiler_root}" "${SYCL_RUNTIME_DEPENDENCIES}" "../")
endif()
delayed_install("" "${cycles_kernel_oneapi_lib}" ${cycles_oneapi_target_path})
elseif(UNIX AND NOT APPLE)
file(GLOB SYCL_RUNTIME_DEPENDENCIES
${sycl_compiler_root}/../lib/libsycl.so
${sycl_compiler_root}/../lib/libsycl.so.[0-9]
${sycl_compiler_root}/../lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9]
)
list(APPEND SYCL_RUNTIME_DEPENDENCIES ${sycl_compiler_root}/../lib/libpi_level_zero.so)
delayed_install("" "${SYCL_RUNTIME_DEPENDENCIES}" ${CYCLES_INSTALL_PATH}/lib)
delayed_install("" "${cycles_kernel_oneapi_lib}" ${cycles_oneapi_target_path}/lib)
endif()
delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cycles_kernel_oneapi_lib}" ${CYCLES_INSTALL_PATH}/lib)
add_custom_target(cycles_kernel_oneapi ALL DEPENDS ${cycles_kernel_oneapi_lib})
endif()

View File

@ -1,54 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 Intel Corporation */
/* device_capabilities() returns a C string that must be free'd with oneapi_free(). */
DLL_INTERFACE_CALL(oneapi_device_capabilities, char *)
DLL_INTERFACE_CALL(oneapi_free, void, void *)
DLL_INTERFACE_CALL(oneapi_get_memcapacity, size_t, SyclQueue *queue)
DLL_INTERFACE_CALL(oneapi_get_num_multiprocessors, int, SyclQueue *queue)
DLL_INTERFACE_CALL(oneapi_get_max_num_threads_per_multiprocessor, int, SyclQueue *queue)
DLL_INTERFACE_CALL(oneapi_iterate_devices, void, OneAPIDeviceIteratorCallback cb, void *user_ptr)
DLL_INTERFACE_CALL(oneapi_set_error_cb, void, OneAPIErrorCallback, void *user_ptr)
DLL_INTERFACE_CALL(oneapi_create_queue, bool, SyclQueue *&external_queue, int device_index)
DLL_INTERFACE_CALL(oneapi_free_queue, void, SyclQueue *queue)
DLL_INTERFACE_CALL(
oneapi_usm_aligned_alloc_host, void *, SyclQueue *queue, size_t memory_size, size_t alignment)
DLL_INTERFACE_CALL(oneapi_usm_alloc_device, void *, SyclQueue *queue, size_t memory_size)
DLL_INTERFACE_CALL(oneapi_usm_free, void, SyclQueue *queue, void *usm_ptr)
DLL_INTERFACE_CALL(
oneapi_usm_memcpy, bool, SyclQueue *queue, void *dest, void *src, size_t num_bytes)
DLL_INTERFACE_CALL(oneapi_queue_synchronize, bool, SyclQueue *queue)
DLL_INTERFACE_CALL(oneapi_usm_memset,
bool,
SyclQueue *queue,
void *usm_ptr,
unsigned char value,
size_t num_bytes)
DLL_INTERFACE_CALL(oneapi_run_test_kernel, bool, SyclQueue *queue)
/* Operation with Kernel globals structure - map of global/constant allocation - filled before
* render/kernel execution As we don't know in cycles `sizeof` this - Cycles will manage just as
* pointer. */
DLL_INTERFACE_CALL(oneapi_kernel_globals_size, bool, SyclQueue *queue, size_t &kernel_global_size)
DLL_INTERFACE_CALL(oneapi_set_global_memory,
void,
SyclQueue *queue,
void *kernel_globals,
const char *memory_name,
void *memory_device_pointer)
DLL_INTERFACE_CALL(oneapi_kernel_preferred_local_size,
size_t,
SyclQueue *queue,
const DeviceKernel kernel,
const size_t kernel_global_size)
DLL_INTERFACE_CALL(oneapi_enqueue_kernel,
bool,
KernelContext *context,
int kernel,
size_t global_size,
void **args)

View File

@ -3,7 +3,6 @@
#ifdef WITH_ONEAPI
/* clang-format off */
# include "kernel.h"
# include <iostream>
# include <map>
@ -16,163 +15,16 @@
# include "kernel/device/oneapi/kernel_templates.h"
# include "kernel/device/gpu/kernel.h"
/* clang-format on */
static OneAPIErrorCallback s_error_cb = nullptr;
static void *s_error_user_ptr = nullptr;
static std::vector<sycl::device> oneapi_available_devices();
void oneapi_set_error_cb(OneAPIErrorCallback cb, void *user_ptr)
{
s_error_cb = cb;
s_error_user_ptr = user_ptr;
}
void oneapi_check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_host = false)
{
# ifdef _DEBUG
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
sycl::info::device_type device_type =
queue->get_device().get_info<sycl::info::device::device_type>();
sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context());
(void)usm_type;
assert(usm_type == sycl::usm::alloc::device ||
((device_type == sycl::info::device_type::host ||
device_type == sycl::info::device_type::is_cpu || allow_host) &&
usm_type == sycl::usm::alloc::host));
# endif
}
bool oneapi_create_queue(SyclQueue *&external_queue, int device_index)
{
bool finished_correct = true;
try {
std::vector<sycl::device> devices = oneapi_available_devices();
if (device_index < 0 || device_index >= devices.size()) {
return false;
}
sycl::queue *created_queue = new sycl::queue(devices[device_index],
sycl::property::queue::in_order());
external_queue = reinterpret_cast<SyclQueue *>(created_queue);
}
catch (sycl::exception const &e) {
finished_correct = false;
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
}
return finished_correct;
}
void oneapi_free_queue(SyclQueue *queue_)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
delete queue;
}
void *oneapi_usm_aligned_alloc_host(SyclQueue *queue_, size_t memory_size, size_t alignment)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
return sycl::aligned_alloc_host(alignment, memory_size, *queue);
}
void *oneapi_usm_alloc_device(SyclQueue *queue_, size_t memory_size)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
return sycl::malloc_device(memory_size, *queue);
}
void oneapi_usm_free(SyclQueue *queue_, void *usm_ptr)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
oneapi_check_usm(queue_, usm_ptr, true);
sycl::free(usm_ptr, *queue);
}
bool oneapi_usm_memcpy(SyclQueue *queue_, void *dest, void *src, size_t num_bytes)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
oneapi_check_usm(queue_, dest, true);
oneapi_check_usm(queue_, src, true);
sycl::event mem_event = queue->memcpy(dest, src, num_bytes);
# ifdef WITH_CYCLES_DEBUG
try {
/* NOTE(@nsirgien) Waiting on memory operation may give more precise error
* messages. Due to impact on occupancy, it makes sense to enable it only during Cycles debug.
*/
mem_event.wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
return false;
}
# else
sycl::usm::alloc dest_type = get_pointer_type(dest, queue->get_context());
sycl::usm::alloc src_type = get_pointer_type(src, queue->get_context());
bool from_device_to_host = dest_type == sycl::usm::alloc::host &&
src_type == sycl::usm::alloc::device;
bool host_or_device_memop_with_offset = dest_type == sycl::usm::alloc::unknown ||
src_type == sycl::usm::alloc::unknown;
/* NOTE(@sirgienko) Host-side blocking wait on this operation is mandatory, otherwise the host
* may not wait until the end of the transfer before using the memory.
*/
if (from_device_to_host || host_or_device_memop_with_offset)
mem_event.wait();
return true;
# endif
}
bool oneapi_usm_memset(SyclQueue *queue_, void *usm_ptr, unsigned char value, size_t num_bytes)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
oneapi_check_usm(queue_, usm_ptr, true);
sycl::event mem_event = queue->memset(usm_ptr, value, num_bytes);
# ifdef WITH_CYCLES_DEBUG
try {
/* NOTE(@nsirgien) Waiting on memory operation may give more precise error
* messages. Due to impact on occupancy, it makes sense to enable it only during Cycles debug.
*/
mem_event.wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
return false;
}
# else
(void)mem_event;
return true;
# endif
}
bool oneapi_queue_synchronize(SyclQueue *queue_)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
try {
queue->wait_and_throw();
return true;
}
catch (sycl::exception const &e) {
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
return false;
}
}
/* NOTE(@nsirgien): Execution of this simple kernel will check basic functionality and
* also trigger runtime compilation of all existing oneAPI kernels */
bool oneapi_run_test_kernel(SyclQueue *queue_)
@ -216,60 +68,13 @@ bool oneapi_run_test_kernel(SyclQueue *queue_)
return true;
}
bool oneapi_kernel_globals_size(SyclQueue *queue_, size_t &kernel_global_size)
{
kernel_global_size = sizeof(KernelGlobalsGPU);
return true;
}
void oneapi_set_global_memory(SyclQueue *queue_,
void *kernel_globals,
const char *memory_name,
void *memory_device_pointer)
{
assert(queue_);
assert(kernel_globals);
assert(memory_name);
assert(memory_device_pointer);
KernelGlobalsGPU *globals = (KernelGlobalsGPU *)kernel_globals;
oneapi_check_usm(queue_, memory_device_pointer);
oneapi_check_usm(queue_, kernel_globals, true);
std::string matched_name(memory_name);
/* This macro will change global ptr of KernelGlobals via name matching. */
# define KERNEL_DATA_ARRAY(type, name) \
else if (#name == matched_name) \
{ \
globals->__##name = (type *)memory_device_pointer; \
return; \
}
if (false) {
}
else if ("integrator_state" == matched_name) {
globals->integrator_state = (IntegratorStateGPU *)memory_device_pointer;
return;
}
KERNEL_DATA_ARRAY(KernelData, data)
# include "kernel/data_arrays.h"
else
{
std::cerr << "Can't found global/constant memory with name \"" << matched_name << "\"!"
<< std::endl;
assert(false);
}
# undef KERNEL_DATA_ARRAY
}
/* TODO: Move device information to OneapiDevice initialized on creation and use it. */
/* TODO: Move below function to oneapi/queue.cpp. */
size_t oneapi_kernel_preferred_local_size(SyclQueue *queue_,
size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
const DeviceKernel kernel,
const size_t kernel_global_size)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
assert(queue);
(void)kernel_global_size;
const static size_t preferred_work_group_size_intersect_shading = 32;
const static size_t preferred_work_group_size_technical = 1024;
@ -311,11 +116,59 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue_,
preferred_work_group_size = 512;
}
const size_t limit_work_group_size =
queue->get_device().get_info<sycl::info::device::max_work_group_size>();
const size_t limit_work_group_size = reinterpret_cast<sycl::queue *>(queue)
->get_device()
.get_info<sycl::info::device::max_work_group_size>();
return std::min(limit_work_group_size, preferred_work_group_size);
}
bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
try {
sycl::kernel_bundle<sycl::bundle_state::input> all_kernels_bundle =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(),
{queue->get_device()});
for (const sycl::kernel_id &kernel_id : all_kernels_bundle.get_kernel_ids()) {
const std::string &kernel_name = kernel_id.get_name();
/* NOTE(@nsirgien): Names in this conditions below should match names from
* oneapi_call macro in oneapi_enqueue_kernel below */
if (((requested_features & KERNEL_FEATURE_VOLUME) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_volume") != std::string::npos) {
continue;
}
if (((requested_features & KERNEL_FEATURE_MNEE) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_surface_mnee") != std::string::npos) {
continue;
}
if (((requested_features & KERNEL_FEATURE_NODE_RAYTRACE) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_surface_raytrace") !=
std::string::npos) {
continue;
}
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order());
}
}
catch (sycl::exception const &e) {
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
return false;
}
return true;
}
bool oneapi_enqueue_kernel(KernelContext *kernel_context,
int kernel,
size_t global_size,
@ -664,266 +517,4 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
# endif
return success;
}
/* Compute-runtime (ie. NEO) version is what gets returned by sycl/L0 on Windows
* since Windows driver 101.3268. */
/* The same min compute-runtime version is currently required across Windows and Linux.
* For Windows driver 101.3430, compute-runtime version is 23904. */
static const int lowest_supported_driver_version_win = 1013430;
static const int lowest_supported_driver_version_neo = 23904;
static int parse_driver_build_version(const sycl::device &device)
{
const std::string &driver_version = device.get_info<sycl::info::device::driver_version>();
int driver_build_version = 0;
size_t second_dot_position = driver_version.find('.', driver_version.find('.') + 1);
if (second_dot_position == std::string::npos) {
std::cerr << "Unable to parse unknown Intel GPU driver version \"" << driver_version
<< "\" does not match xx.xx.xxxxx (Linux), x.x.xxxx (L0),"
<< " xx.xx.xxx.xxxx (Windows) for device \""
<< device.get_info<sycl::info::device::name>() << "\"." << std::endl;
}
else {
try {
size_t third_dot_position = driver_version.find('.', second_dot_position + 1);
if (third_dot_position != std::string::npos) {
const std::string &third_number_substr = driver_version.substr(
second_dot_position + 1, third_dot_position - second_dot_position - 1);
const std::string &forth_number_substr = driver_version.substr(third_dot_position + 1);
if (third_number_substr.length() == 3 && forth_number_substr.length() == 4)
driver_build_version = std::stoi(third_number_substr) * 10000 +
std::stoi(forth_number_substr);
}
else {
const std::string &third_number_substr = driver_version.substr(second_dot_position + 1);
driver_build_version = std::stoi(third_number_substr);
}
}
catch (std::invalid_argument &e) {
std::cerr << "Unable to parse unknown Intel GPU driver version \"" << driver_version
<< "\" does not match xx.xx.xxxxx (Linux), x.x.xxxx (L0),"
<< " xx.xx.xxx.xxxx (Windows) for device \""
<< device.get_info<sycl::info::device::name>() << "\"." << std::endl;
}
}
return driver_build_version;
}
static std::vector<sycl::device> oneapi_available_devices()
{
bool allow_all_devices = false;
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr)
allow_all_devices = true;
/* Host device is useful only for debugging at the moment
* so we hide this device with default build settings. */
# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
bool allow_host = true;
# else
bool allow_host = false;
# endif
const std::vector<sycl::platform> &oneapi_platforms = sycl::platform::get_platforms();
std::vector<sycl::device> available_devices;
for (const sycl::platform &platform : oneapi_platforms) {
/* ignore OpenCL platforms to avoid using the same devices through both Level-Zero and OpenCL.
*/
if (platform.get_backend() == sycl::backend::opencl) {
continue;
}
const std::vector<sycl::device> &oneapi_devices =
(allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) :
platform.get_devices(sycl::info::device_type::gpu);
for (const sycl::device &device : oneapi_devices) {
if (allow_all_devices) {
/* still filter out host device if build doesn't support it. */
if (allow_host || !device.is_host()) {
available_devices.push_back(device);
}
}
else {
bool filter_out = false;
/* For now we support all Intel(R) Arc(TM) devices and likely any future GPU,
* assuming they have either more than 96 Execution Units or not 7 threads per EU.
* Official support can be broaden to older and smaller GPUs once ready. */
if (device.is_gpu() && platform.get_backend() == sycl::backend::ext_oneapi_level_zero) {
/* Filtered-out defaults in-case these values aren't available through too old L0
* runtime. */
int number_of_eus = 96;
int threads_per_eu = 7;
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
number_of_eus = device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
}
if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
threads_per_eu =
device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
}
/* This filters out all Level-Zero supported GPUs from older generation than Arc. */
if (number_of_eus <= 96 && threads_per_eu == 7) {
filter_out = true;
}
/* if not already filtered out, check driver version. */
if (!filter_out) {
int driver_build_version = parse_driver_build_version(device);
if ((driver_build_version > 100000 &&
driver_build_version < lowest_supported_driver_version_win) ||
driver_build_version < lowest_supported_driver_version_neo) {
filter_out = true;
}
}
}
else if (!allow_host && device.is_host()) {
filter_out = true;
}
else if (!allow_all_devices) {
filter_out = true;
}
if (!filter_out) {
available_devices.push_back(device);
}
}
}
}
return available_devices;
}
char *oneapi_device_capabilities()
{
std::stringstream capabilities;
const std::vector<sycl::device> &oneapi_devices = oneapi_available_devices();
for (const sycl::device &device : oneapi_devices) {
const std::string &name = device.get_info<sycl::info::device::name>();
capabilities << std::string("\t") << name << "\n";
# define WRITE_ATTR(attribute_name, attribute_variable) \
capabilities << "\t\tsycl::info::device::" #attribute_name "\t\t\t" << attribute_variable \
<< "\n";
# define GET_NUM_ATTR(attribute) \
{ \
size_t attribute = (size_t)device.get_info<sycl::info::device ::attribute>(); \
capabilities << "\t\tsycl::info::device::" #attribute "\t\t\t" << attribute << "\n"; \
}
GET_NUM_ATTR(vendor_id)
GET_NUM_ATTR(max_compute_units)
GET_NUM_ATTR(max_work_item_dimensions)
sycl::id<3> max_work_item_sizes =
device.get_info<sycl::info::device::max_work_item_sizes<3>>();
WRITE_ATTR("max_work_item_sizes_dim0", ((size_t)max_work_item_sizes.get(0)))
WRITE_ATTR("max_work_item_sizes_dim1", ((size_t)max_work_item_sizes.get(1)))
WRITE_ATTR("max_work_item_sizes_dim2", ((size_t)max_work_item_sizes.get(2)))
GET_NUM_ATTR(max_work_group_size)
GET_NUM_ATTR(max_num_sub_groups)
GET_NUM_ATTR(sub_group_independent_forward_progress)
GET_NUM_ATTR(preferred_vector_width_char)
GET_NUM_ATTR(preferred_vector_width_short)
GET_NUM_ATTR(preferred_vector_width_int)
GET_NUM_ATTR(preferred_vector_width_long)
GET_NUM_ATTR(preferred_vector_width_float)
GET_NUM_ATTR(preferred_vector_width_double)
GET_NUM_ATTR(preferred_vector_width_half)
GET_NUM_ATTR(native_vector_width_char)
GET_NUM_ATTR(native_vector_width_short)
GET_NUM_ATTR(native_vector_width_int)
GET_NUM_ATTR(native_vector_width_long)
GET_NUM_ATTR(native_vector_width_float)
GET_NUM_ATTR(native_vector_width_double)
GET_NUM_ATTR(native_vector_width_half)
size_t max_clock_frequency =
(size_t)(device.is_host() ? (size_t)0 :
device.get_info<sycl::info::device::max_clock_frequency>());
WRITE_ATTR("max_clock_frequency", max_clock_frequency)
GET_NUM_ATTR(address_bits)
GET_NUM_ATTR(max_mem_alloc_size)
/* NOTE(@nsirgien): Implementation doesn't use image support as bindless images aren't
* supported so we always return false, even if device supports HW texture usage acceleration.
*/
bool image_support = false;
WRITE_ATTR("image_support", (size_t)image_support)
GET_NUM_ATTR(max_parameter_size)
GET_NUM_ATTR(mem_base_addr_align)
GET_NUM_ATTR(global_mem_size)
GET_NUM_ATTR(local_mem_size)
GET_NUM_ATTR(error_correction_support)
GET_NUM_ATTR(profiling_timer_resolution)
GET_NUM_ATTR(is_available)
# undef GET_NUM_ATTR
# undef WRITE_ATTR
capabilities << "\n";
}
return ::strdup(capabilities.str().c_str());
}
void oneapi_free(void *p)
{
if (p) {
::free(p);
}
}
void oneapi_iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_ptr)
{
int num = 0;
std::vector<sycl::device> devices = oneapi_available_devices();
for (sycl::device &device : devices) {
const std::string &platform_name =
device.get_platform().get_info<sycl::info::platform::name>();
std::string name = device.get_info<sycl::info::device::name>();
std::string id = "ONEAPI_" + platform_name + "_" + name;
if (device.has(sycl::aspect::ext_intel_pci_address)) {
id.append("_" + device.get_info<sycl::info::device::ext_intel_pci_address>());
}
(cb)(id.c_str(), name.c_str(), num, user_ptr);
num++;
}
}
size_t oneapi_get_memcapacity(SyclQueue *queue)
{
return reinterpret_cast<sycl::queue *>(queue)
->get_device()
.get_info<sycl::info::device::global_mem_size>();
}
int oneapi_get_num_multiprocessors(SyclQueue *queue)
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(queue)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
return device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
}
else
return 0;
}
int oneapi_get_max_num_threads_per_multiprocessor(SyclQueue *queue)
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(queue)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
return device.get_info<sycl::info::device::ext_intel_gpu_eu_simd_width>() *
device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
}
else
return 0;
}
#endif /* WITH_ONEAPI */

View File

@ -25,11 +25,6 @@ enum DeviceKernel : int;
class SyclQueue;
typedef void (*OneAPIDeviceIteratorCallback)(const char *id,
const char *name,
int num,
void *user_ptr);
typedef void (*OneAPIErrorCallback)(const char *error, void *user_ptr);
struct KernelContext {
@ -45,13 +40,17 @@ struct KernelContext {
extern "C" {
# endif
# define DLL_INTERFACE_CALL(function, return_type, ...) \
CYCLES_KERNEL_ONEAPI_EXPORT return_type function(__VA_ARGS__);
# include "kernel/device/oneapi/dll_interface_template.h"
# undef DLL_INTERFACE_CALL
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_run_test_kernel(SyclQueue *queue_);
CYCLES_KERNEL_ONEAPI_EXPORT void oneapi_set_error_cb(OneAPIErrorCallback cb, void *user_ptr);
CYCLES_KERNEL_ONEAPI_EXPORT size_t oneapi_kernel_preferred_local_size(
SyclQueue *queue, const DeviceKernel kernel, const size_t kernel_global_size);
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_enqueue_kernel(KernelContext *context,
int kernel,
size_t global_size,
void **args);
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_load_kernels(SyclQueue *queue,
const unsigned int requested_features);
# ifdef __cplusplus
}
# endif
#endif /* WITH_ONEAPI */

View File

@ -501,6 +501,11 @@ ccl_device_forceinline bool guiding_phase_init(KernelGlobals kg,
ccl_private float &rand)
{
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
/* we do not need to guide almost delta phase functions */
if (fabsf(g) >= 0.99f) {
return false;
}
if (kg->opgl_volume_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
kg->opgl_volume_sampling_distribution->ApplySingleLobeHenyeyGreensteinProduct(guiding_vec3f(D),

View File

@ -239,7 +239,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
}
/* We don't want to bake the back face, so make sure the ray direction never
* goes behind the geometry (flat) normal. This is a failsafe, and should rarely happen. */
* goes behind the geometry (flat) normal. This is a fail-safe, and should rarely happen. */
const float true_normal_epsilon = 0.00001f;
if (dot(D, Ng) <= true_normal_epsilon) {

View File

@ -59,6 +59,13 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg,
#ifdef __PATH_GUIDING__
INTEGRATOR_STATE_WRITE(state, path, unguided_throughput) = 1.0f;
INTEGRATOR_STATE_WRITE(state, guiding, path_segment) = nullptr;
INTEGRATOR_STATE_WRITE(state, guiding, use_surface_guiding) = false;
INTEGRATOR_STATE_WRITE(state, guiding, sample_surface_guiding_rand) = 0.5f;
INTEGRATOR_STATE_WRITE(state, guiding, surface_guiding_sampling_prob) = 0.0f;
INTEGRATOR_STATE_WRITE(state, guiding, bssrdf_sampling_prob) = 0.0f;
INTEGRATOR_STATE_WRITE(state, guiding, use_volume_guiding) = false;
INTEGRATOR_STATE_WRITE(state, guiding, sample_volume_guiding_rand) = 0.5f;
INTEGRATOR_STATE_WRITE(state, guiding, volume_guiding_sampling_prob) = 0.0f;
#endif
#ifdef __MNEE__

View File

@ -100,7 +100,7 @@ ccl_device_inline bool sample_is_class_A(int pattern, int sample)
if (!(pattern == SAMPLING_PATTERN_PMJ || pattern == SAMPLING_PATTERN_SOBOL_BURLEY)) {
/* Fallback: assign samples randomly.
* This is guaranteed to work "okay" for any sampler, but isn't good.
* (Note: the seed constant is just a random number to guard against
* (NOTE: the seed constant is just a random number to guard against
* possible interactions with other uses of the hash. There's nothing
* special about it.)
*/

View File

@ -43,6 +43,10 @@ Session::Session(const SessionParams &params_, const SceneParams &scene_params)
device = Device::create(params.device, stats, profiler);
if (device->have_error()) {
progress.set_error(device->error_message());
}
scene = new Scene(scene_params, device);
/* Configure path tracer. */

View File

@ -36,6 +36,10 @@ extern GHOST_SystemHandle GHOST_CreateSystemBackground(void);
*/
extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, GHOST_Debug debug);
#if !(defined(WIN32) || defined(__APPLE__))
extern const char *GHOST_SystemBackend(void);
#endif
/**
* Disposes the one and only system.
* \param systemhandle: The handle to the system.

View File

@ -134,6 +134,15 @@ class GHOST_ISystem {
* \return A pointer to the system.
*/
static GHOST_ISystem *getSystem();
/**
* Return an identifier for the one and only system.
* \warning while it may be tempting this should never be used to check for supported features,
* in that case, the GHOST API should be extended to query capabilities.
* This is needed for X11/WAYLAND on Unix, without this - there is no convenient way for users to
* check if WAYLAND or XWAYLAND are in use since they are dynamically selected at startup.
* When dynamically switching between X11/WAYLAND is removed, this function can go too.
*/
static const char *getSystemBackend();
static GHOST_TBacktraceFn getBacktraceFn();
static void setBacktraceFn(GHOST_TBacktraceFn backtrace_fn);
@ -515,6 +524,7 @@ class GHOST_ISystem {
/** The one and only system */
static GHOST_ISystem *m_system;
static const char *m_system_backend_id;
/** Function to call that sets the back-trace. */
static GHOST_TBacktraceFn m_backtrace_fn;

View File

@ -52,6 +52,13 @@ GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
return system->disposeSystem();
}
#if !(defined(WIN32) || defined(__APPLE__))
const char *GHOST_SystemBackend()
{
return GHOST_ISystem::getSystemBackend();
}
#endif
void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
const char *title,
const char *message,

View File

@ -30,6 +30,7 @@
#endif
GHOST_ISystem *GHOST_ISystem::m_system = nullptr;
const char *GHOST_ISystem::m_system_backend_id = nullptr;
GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr;
@ -122,7 +123,10 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
m_system = new GHOST_SystemCocoa();
#endif
if ((m_system == nullptr) && verbose) {
if (m_system) {
m_system_backend_id = backends_attempted[backends_attempted_num - 1];
}
else if (verbose) {
fprintf(stderr, "GHOST: failed to initialize display for back-end(s): [");
for (int i = 0; i < backends_attempted_num; i++) {
if (i != 0) {
@ -186,6 +190,11 @@ GHOST_ISystem *GHOST_ISystem::getSystem()
return m_system;
}
const char *GHOST_ISystem::getSystemBackend()
{
return m_system_backend_id;
}
GHOST_TBacktraceFn GHOST_ISystem::getBacktraceFn()
{
return GHOST_ISystem::m_backtrace_fn;

View File

@ -68,6 +68,12 @@ static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
static void output_handle_done(void *data, struct wl_output *wl_output);
/* -------------------------------------------------------------------- */
/** \name Local Defines
*
* Control local functionality, compositors specific workarounds.
* \{ */
/**
* GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: T98793.
* Even though this has been fixed, at time of writing it's not yet in a release.
@ -86,6 +92,22 @@ static void output_handle_done(void *data, struct wl_output *wl_output);
static bool use_gnome_confine_hack = false;
#endif
/**
* GNOME (mutter 42.5) doesn't follow the WAYLAND spec regarding keyboard handling,
* unlike (other compositors: KDE-plasma, River & Sway which work without problems).
*
* This means GNOME can't know which modifiers are held when activating windows,
* so we guess the left modifiers are held.
*
* This define could be removed without changing any functionality,
* it just means GNOME users will see verbose warning messages that alert them about
* a known problem that needs to be fixed up-stream.
* See: https://gitlab.gnome.org/GNOME/mutter/-/issues/2457
*/
#define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
/** \} */
/* -------------------------------------------------------------------- */
/** \name Inline Event Codes
*
@ -385,6 +407,13 @@ struct GWL_Seat {
/** Keys held matching `xkb_state`. */
struct WGL_KeyboardDepressedState key_depressed;
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
struct {
bool any_mod_held = false;
bool any_keys_held_on_enter = false;
} key_depressed_suppress_warning;
#endif
/**
* Cache result of `xkb_keymap_mod_get_index`
* so every time a modifier is accessed a string lookup isn't required.
@ -2303,6 +2332,7 @@ static void keyboard_handle_enter(void *data,
uint32_t *key;
WL_ARRAY_FOR_EACH (key, keys) {
const xkb_keycode_t key_code = *key + EVDEV_OFFSET;
CLOG_INFO(LOG, 2, "enter (key_held=%d)", int(key_code));
const xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->xkb_state, key_code);
const GHOST_TKey gkey = xkb_map_gkey_or_scan_code(sym, *key);
if (gkey != GHOST_kKeyUnknown) {
@ -2311,6 +2341,10 @@ static void keyboard_handle_enter(void *data,
}
keyboard_depressed_state_push_events_from_change(seat, key_depressed_prev);
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
seat->key_depressed_suppress_warning.any_keys_held_on_enter = keys->size != 0;
#endif
}
/**
@ -2336,6 +2370,11 @@ static void keyboard_handle_leave(void *data,
if (seat->key_repeat.timer) {
keyboard_handle_key_repeat_cancel(seat);
}
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
seat->key_depressed_suppress_warning.any_mod_held = false;
seat->key_depressed_suppress_warning.any_keys_held_on_enter = false;
#endif
}
/**
@ -2407,10 +2446,10 @@ static void keyboard_handle_key(void *data,
const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(
seat->xkb_state_empty, seat->xkb_state_empty_with_numlock, key_code);
if (sym == XKB_KEY_NoSymbol) {
CLOG_INFO(LOG, 2, "key (no symbol, skipped)");
CLOG_INFO(LOG, 2, "key (code=%d, state=%u, no symbol, skipped)", int(key_code), state);
return;
}
CLOG_INFO(LOG, 2, "key");
CLOG_INFO(LOG, 2, "key (code=%d, state=%u)", int(key_code), state);
GHOST_TEventType etype = GHOST_kEventUnknown;
switch (state) {
@ -2554,6 +2593,10 @@ static void keyboard_handle_modifiers(void *data,
if (seat->key_repeat.timer) {
keyboard_handle_key_repeat_reset(seat, true);
}
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
seat->key_depressed_suppress_warning.any_mod_held = mods_depressed != 0;
#endif
}
static void keyboard_repeat_handle_info(void *data,
@ -3163,6 +3206,15 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED);
bool show_warning = true;
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
if ((seat->key_depressed_suppress_warning.any_mod_held == true) &&
(seat->key_depressed_suppress_warning.any_keys_held_on_enter == false)) {
/* The compositor gave us invalid information, don't show a warning. */
show_warning = false;
}
#endif
/* Use local #WGL_KeyboardDepressedState to check which key is pressed.
* Use XKB as the source of truth, if there is any discrepancy. */
for (int i = 0; i < MOD_INDEX_NUM; i++) {
@ -3178,18 +3230,22 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
* Warn so if this happens it can be investigated. */
if (val) {
if (UNLIKELY(!(val_l || val_r))) {
CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
"modifier (%s) state is inconsistent (held keys do not match XKB)",
mod_info.display_name);
if (show_warning) {
CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
"modifier (%s) state is inconsistent (GHOST held keys do not match XKB)",
mod_info.display_name);
}
/* Picking the left is arbitrary. */
val_l = true;
}
}
else {
if (UNLIKELY(val_l || val_r)) {
CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
"modifier (%s) state is inconsistent (released keys do not match XKB)",
mod_info.display_name);
if (show_warning) {
CLOG_WARN(&LOG_WL_KEYBOARD_DEPRESSED_STATE,
"modifier (%s) state is inconsistent (GHOST released keys do not match XKB)",
mod_info.display_name);
}
val_l = false;
val_r = false;
}
@ -4268,19 +4324,41 @@ bool ghost_wl_dynload_libraries()
* which will be used as a fallback. */
# ifdef WITH_GHOST_X11
bool verbose = false;
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* When running in Wayland, let the user know if libdecor is the only reason WAYLAND
* could not be used. Otherwise it's not obvious why X11 is used as a fallback. */
bool verbose_libdecor = getenv("WAYLAND_DISPLAY") != nullptr;
# endif
# else
bool verbose = true;
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
bool verbose_libdecor = true;
# endif
# endif /* !WITH_GHOST_X11 */
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
int8_t libdecor_init = -1;
# endif
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
wayland_dynload_egl_init(verbose) && /* `libwayland-egl`. */
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
wayland_dynload_libdecor_init(verbose) && /* `libdecor-0`. */
(libdecor_init = wayland_dynload_libdecor_init(verbose_libdecor)) && /* `libdecor-0`. */
# endif
true) {
return true;
}
# if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_GHOST_X11)
if (libdecor_init == 0) {
/* LIBDECOR was the only reason X11 was used, let the user know they need it installed. */
fprintf(stderr,
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
"falling back to X11\n");
}
# endif
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
wayland_dynload_libdecor_exit();
# endif

View File

@ -723,12 +723,11 @@ template<typename Mesh> class Mikktspace {
void build4RuleGroups()
{
/* Note: This could be parallelized by grouping all [t, i] pairs into
/* NOTE: This could be parallelized by grouping all [t, i] pairs into
* shards by hash(triangles[t].vertices[i]). This way, each shard can be processed
* independently and in parallel.
* However, the groupWithAny logic needs special handling (e.g. lock a mutex when
* encountering a groupWithAny triangle, then sort it out, then unlock and proceed).
*/
* However, the `groupWithAny` logic needs special handling (e.g. lock a mutex when
* encountering a `groupWithAny` triangle, then sort it out, then unlock and proceed). */
for (uint t = 0; t < nrTriangles; t++) {
Triangle &triangle = triangles[t];
for (uint i = 0; i < 3; i++) {

View File

@ -18997,6 +18997,36 @@
id="path4817-4"
inkscape:connector-curvature="0" />
</g>
<g
id="g24638">
<path
style="color:#000000;fill:none;stroke-linecap:round;-inkscape-stroke:none;opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round"
d="m 374.12695,305.31445 c -1.10721,0 -1.93616,0.24199 -2.97851,0.63086 -1.04236,0.38888 -2.18224,0.95849 -3.30078,1.77735 -2.2371,1.63771 -4.46485,4.54533 -4.46485,8.40625 a 3.0581999,3.0581999 0 0 0 3.0586,3.05859 3.0581999,3.0581999 0 0 0 3.05859,-3.05859 c 0,-1.63187 0.77567,-2.603 1.96094,-3.47071 0.59263,-0.43385 1.26841,-0.77311 1.82422,-0.98047 0.5558,-0.20735 1.10962,-0.24804 0.84179,-0.24804 a 3.0581999,3.0581999 0 0 0 3.05664,-3.0586 3.0581999,3.0581999 0 0 0 -3.05664,-3.05664 z"
id="path6454-6" />
<path
style="display:inline;opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1;enable-background:new"
d="m 366.4419,316.12916 c 0,-5.49278 6.00534,-7.75723 7.68412,-7.75723"
id="path15424"
sodipodi:nodetypes="cc" />
</g>
<g
id="g24643">
<path
style="opacity:0.5;fill:#ffffff;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
d="m 343.45275,317.52104 4.51631,-3.99333"
id="path4694"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
d="m 342.44508,318.83525 c 14.125,0.14581 -0.42233,-12.9179 13.5429,-12.85486"
id="path6454"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.5;fill:#ffffff;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
d="m 350.84964,311.18794 4.21454,-3.72502"
id="path19640"
sodipodi:nodetypes="cc" />
</g>
</g>
<g
inkscape:groupmode="layer"

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@ -978,17 +978,30 @@ def dump_messages(do_messages, do_checks, settings):
# Get strings from addons' bl_info.
import addon_utils
for module in addon_utils.modules():
if module.bl_info['support'] != 'OFFICIAL':
# Only process official add-ons, i.e. those marked as 'OFFICIAL' and
# existing in the system add-ons directory (not user-installed ones).
if (module.bl_info['support'] != 'OFFICIAL'
or not bpy.path.is_subdir(module.__file__, bpy.utils.system_resource('SCRIPTS'))):
continue
dump_addon_bl_info(msgs, reports, module, settings)
# Get strings from addons' categories.
system_categories = set()
for module in addon_utils.modules():
if bpy.path.is_subdir(module.__file__, bpy.utils.system_resource('SCRIPTS')):
system_categories.add(module.bl_info['category'])
for uid, label, tip in bpy.types.WindowManager.addon_filter.keywords['items'](
bpy.context.window_manager,
bpy.context,
):
process_msg(msgs, settings.DEFAULT_CONTEXT, label, "Add-ons' categories", reports, None, settings)
if tip:
if label in system_categories:
# Only process add-on if it a system one (i.e shipped with Blender). Also,
# we do want to translate official categories, even if they have no official add-ons,
# hence the different test than below.
process_msg(msgs, settings.DEFAULT_CONTEXT, label, "Add-ons' categories", reports, None, settings)
elif tip:
# Only special categories get a tip (All and User).
process_msg(msgs, settings.DEFAULT_CONTEXT, label, "Add-ons' categories", reports, None, settings)
process_msg(msgs, settings.DEFAULT_CONTEXT, tip, "Add-ons' categories", reports, None, settings)
# Get strings specific to translations' menu.

View File

@ -367,9 +367,9 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"all and invert unselected",
"and AMD driver version 22.10 or newer",
"and AMD Radeon Pro 21.Q4 driver or newer",
"and Linux driver version xx.xx.23570 or newer",
"and Linux driver version xx.xx.23904 or newer",
"and NVIDIA driver version 470 or newer",
"and Windows driver version 101.3268 or newer",
"and Windows driver version 101.3430 or newer",
"available with",
"brown fox",
"can't save image while rendering",

View File

@ -389,6 +389,8 @@ class SpellChecker:
"albedo",
"anamorphic",
"anisotropic", "anisotropy",
"arcminute", "arcminutes",
"arcsecond", "arcseconds",
"bimanual", # OpenXR?
"bitangent",
"boid", "boids",
@ -449,7 +451,7 @@ class SpellChecker:
"superellipse",
"thumbstick",
"tooltip", "tooltips",
"trackpad",
"touchpad", "trackpad",
"tuple",
"unicode",
"viewport", "viewports",
@ -650,6 +652,7 @@ class SpellChecker:
"mikktspace",
"minkowski",
"minnaert",
"mises", # von Mises-Fisher
"moskowitz", # Pierson-Moskowitz
"musgrave",
"nayar",
@ -665,6 +668,7 @@ class SpellChecker:
"runge",
"sobol",
"verlet",
"von", # von Mises-Fisher
"wilkie",
"worley",
@ -724,6 +728,7 @@ class SpellChecker:
"lmb", "mmb", "rmb",
"lscm",
"kb",
"mis",
"mocap",
"msgid", "msgids",
"mux",
@ -751,6 +756,7 @@ class SpellChecker:
"uuid",
"vbo", "vbos",
"vfx",
"vmm",
"vr",
"wxyz",
"xr",

View File

@ -142,8 +142,17 @@ def object_data_add(context, obdata, operator=None, name=None):
bpy.ops.object.mode_set(mode='EDIT')
else:
layer.objects.active = obj_new
if obdata and context.preferences.edit.use_enter_edit_mode:
bpy.ops.object.mode_set(mode='EDIT')
if context.preferences.edit.use_enter_edit_mode:
if obdata and obdata.library is None:
obtype = obj_new.type
mode = None
if obtype in {'ARMATURE', 'CURVE', 'CURVES', 'FONT', 'LATTICE', 'MESH', 'META', 'SURFACE'}:
mode = 'EDIT'
elif obtype == 'GPENCIL':
mode = 'EDIT_GPENCIL'
if mode is not None:
bpy.ops.object.mode_set(mode=mode)
return obj_new

View File

@ -53,6 +53,13 @@ def write_sysinfo(filepath):
output.write("build linkflags: %s\n" % prepr(bpy.app.build_linkflags))
output.write("build system: %s\n" % prepr(bpy.app.build_system))
# Windowing Environment (include when dynamically selectable).
from _bpy import _ghost_backend
ghost_backend = _ghost_backend()
if ghost_backend not in {'NONE', 'DEFAULT'}:
output.write("windowing environment: %s\n" % prepr(ghost_backend))
del _ghost_backend, ghost_backend
# Python info.
output.write(title("Python"))
output.write("version: %s\n" % (sys.version.replace("\n", " ")))

View File

@ -3177,6 +3177,15 @@ class WM_MT_splash_about(Menu):
bpy.app.build_commit_time.decode('utf-8', 'replace')), translate=False)
col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode('ascii'), translate=False)
col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode('utf-8', 'replace'), translate=False)
# This isn't useful information on MS-Windows or Apple systems as dynamically switching
# between windowing systems is only supported between X11/WAYLAND.
from _bpy import _ghost_backend
ghost_backend = _ghost_backend()
if ghost_backend not in {'NONE', 'DEFAULT'}:
col.label(text=iface_("Windowing Environment: %s") % _ghost_backend(), translate=False)
del _ghost_backend, ghost_backend
col.separator(factor=2.0)
col.label(text="Blender is free software")
col.label(text="Licensed under the GNU General Public License")

View File

@ -239,6 +239,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
bl_translation_context = i18n_contexts.id_particlesettings
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
@classmethod

View File

@ -2,7 +2,10 @@
import bpy
from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
from bpy.app.translations import (
pgettext_iface as iface_,
contexts as i18n_contexts,
)
from bl_ui.utils import PresetPanel
from bl_ui.properties_grease_pencil_common import (
AnnotationDrawingToolsPanel,
@ -1751,6 +1754,7 @@ class CLIP_MT_marker_pie(Menu):
class CLIP_MT_tracking_pie(Menu):
# Tracking Operators
bl_label = "Tracking"
bl_translation_context = i18n_contexts.id_movieclip
@classmethod
def poll(cls, context):

View File

@ -683,7 +683,7 @@ class SEQUENCER_MT_add(Menu):
elif bpy_data_movieclips_len > 0:
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip", icon='TRACKER')
else:
layout.menu("SEQUENCER_MT_add_empty", text="Clip", icon='TRACKER')
layout.menu("SEQUENCER_MT_add_empty", text="Clip", text_ctxt=i18n_contexts.id_movieclip, icon='TRACKER')
del bpy_data_movieclips_len
bpy_data_masks_len = len(bpy.data.masks)

View File

@ -272,7 +272,7 @@ class TOPBAR_MT_file(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW')
layout.menu("TOPBAR_MT_file_new", text="New", text_ctxt=i18n_contexts.id_windowmanager, icon='FILE_NEW')
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.menu("TOPBAR_MT_file_open_recent")
layout.operator("wm.revert_mainfile")
@ -411,9 +411,16 @@ class TOPBAR_MT_file_defaults(Menu):
app_template, has_ext=False))
layout.operator("wm.save_homefile")
props = layout.operator("wm.read_factory_settings")
if app_template:
display_name = bpy.path.display_name(iface_(app_template))
props = layout.operator("wm.read_factory_settings", text="Load Factory Blender Settings")
props.app_template = app_template
props = layout.operator("wm.read_factory_settings", text="Load Factory %s Settings" % display_name)
props.app_template = app_template
props.use_factory_startup_app_template_only = True
del display_name
else:
layout.operator("wm.read_factory_settings")
# Include technical operators here which would otherwise have no way for users to access.
@ -727,7 +734,7 @@ class TOPBAR_MT_file_context_menu(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
layout.menu("TOPBAR_MT_file_new", text="New", text_context=i18n_contexts.id_windowmanager, icon='FILE_NEW')
layout.menu("TOPBAR_MT_file_new", text="New", text_ctxt=i18n_contexts.id_windowmanager, icon='FILE_NEW')
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.separator()

View File

@ -105,7 +105,16 @@ class USERPREF_MT_save_load(Menu):
sub_revert.operator("wm.read_userpref", text="Revert to Saved Preferences")
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.read_factory_userpref", text="Load Factory Preferences")
app_template = prefs.app_template
if app_template:
display_name = bpy.path.display_name(iface_(app_template))
layout.operator("wm.read_factory_userpref", text="Load Factory Blender Preferences")
props = layout.operator("wm.read_factory_userpref", text="Load Factory %s Preferences" % display_name)
props.use_factory_startup_app_template_only = True
del display_name
else:
layout.operator("wm.read_factory_userpref", text="Load Factory Preferences")
class USERPREF_PT_save_preferences(Panel):

View File

@ -98,7 +98,7 @@ static int blf_search(const char *name)
{
for (int i = 0; i < BLF_MAX_FONT; i++) {
const FontBLF *font = global_font[i];
if (font && (STREQ(font->name, name))) {
if (font && STREQ(font->name, name)) {
return i;
}
}
@ -226,7 +226,7 @@ void BLF_unload(const char *name)
for (int i = 0; i < BLF_MAX_FONT; i++) {
FontBLF *font = global_font[i];
if (font && (STREQ(font->name, name))) {
if (font && STREQ(font->name, name)) {
BLI_assert(font->reference_count > 0);
font->reference_count--;

View File

@ -498,6 +498,115 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
/** \name Text Drawing: Buffer
* \{ */
/**
* Draw glyph `g` into `buf_info` pixels.
*/
static void blf_glyph_draw_buffer(FontBufInfoBLF *buf_info,
GlyphBLF *g,
const ft_pix pen_x,
const ft_pix pen_y_basis)
{
const int chx = ft_pix_to_int(pen_x + ft_pix_from_int(g->pos[0]));
const int chy = ft_pix_to_int(pen_y_basis + ft_pix_from_int(g->dims[1]));
ft_pix pen_y = (g->pitch < 0) ? (pen_y_basis + ft_pix_from_int(g->dims[1] - g->pos[1])) :
(pen_y_basis - ft_pix_from_int(g->dims[1] - g->pos[1]));
if ((chx + g->dims[0]) < 0 || /* Out of bounds: left. */
chx >= buf_info->dims[0] || /* Out of bounds: right. */
(ft_pix_to_int(pen_y) + g->dims[1]) < 0 || /* Out of bounds: bottom. */
ft_pix_to_int(pen_y) >= buf_info->dims[1] /* Out of bounds: top. */
) {
return;
}
/* Don't draw beyond the buffer bounds. */
int width_clip = g->dims[0];
int height_clip = g->dims[1];
int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1;
if (width_clip + chx > buf_info->dims[0]) {
width_clip -= chx + width_clip - buf_info->dims[0];
}
if (height_clip + ft_pix_to_int(pen_y) > buf_info->dims[1]) {
height_clip -= ft_pix_to_int(pen_y) + height_clip - buf_info->dims[1];
}
/* Clip drawing below the image. */
if (pen_y < 0) {
yb_start += (g->pitch < 0) ? -ft_pix_to_int(pen_y) : ft_pix_to_int(pen_y);
height_clip += ft_pix_to_int(pen_y);
pen_y = 0;
}
/* Avoid conversions in the pixel writing loop. */
const int pen_y_px = ft_pix_to_int(pen_y);
const float *b_col_float = buf_info->col_float;
const uchar *b_col_char = buf_info->col_char;
if (buf_info->fbuf) {
int yb = yb_start;
for (int y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
for (int x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
const char a_byte = *(g->bitmap + x + (yb * g->pitch));
if (a_byte) {
const float a = (a_byte / 255.0f) * b_col_float[3];
const size_t buf_ofs = (((size_t)(chx + x) +
((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
(size_t)buf_info->ch);
float *fbuf = buf_info->fbuf + buf_ofs;
float font_pixel[4];
font_pixel[0] = b_col_float[0] * a;
font_pixel[1] = b_col_float[1] * a;
font_pixel[2] = b_col_float[2] * a;
font_pixel[3] = a;
blend_color_mix_float(fbuf, fbuf, font_pixel);
}
}
if (g->pitch < 0) {
yb++;
}
else {
yb--;
}
}
}
if (buf_info->cbuf) {
int yb = yb_start;
for (int y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
for (int x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
const char a_byte = *(g->bitmap + x + (yb * g->pitch));
if (a_byte) {
const float a = (a_byte / 255.0f) * b_col_float[3];
const size_t buf_ofs = (((size_t)(chx + x) +
((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
(size_t)buf_info->ch);
uchar *cbuf = buf_info->cbuf + buf_ofs;
uchar font_pixel[4];
font_pixel[0] = b_col_char[0];
font_pixel[1] = b_col_char[1];
font_pixel[2] = b_col_char[2];
font_pixel[3] = unit_float_to_uchar_clamp(a);
blend_color_mix_byte(cbuf, cbuf, font_pixel);
}
}
if (g->pitch < 0) {
yb++;
}
else {
yb--;
}
}
}
}
/* Sanity checks are done by BLF_draw_buffer() */
static void blf_font_draw_buffer_ex(FontBLF *font,
GlyphCacheBLF *gc,
@ -513,10 +622,6 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* buffer specific vars */
FontBufInfoBLF *buf_info = &font->buf_info;
const float *b_col_float = buf_info->col_float;
const uchar *b_col_char = buf_info->col_char;
int chx, chy;
int y, x;
/* another buffer specific call for color conversion */
@ -528,101 +633,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
}
pen_x += blf_kerning(font, g_prev, g);
chx = ft_pix_to_int(pen_x + ft_pix_from_int(g->pos[0]));
chy = ft_pix_to_int(pen_y_basis + ft_pix_from_int(g->dims[1]));
if (g->pitch < 0) {
pen_y = pen_y_basis + ft_pix_from_int(g->dims[1] - g->pos[1]);
}
else {
pen_y = pen_y_basis - ft_pix_from_int(g->dims[1] - g->pos[1]);
}
if ((chx + g->dims[0]) >= 0 && chx < buf_info->dims[0] &&
(ft_pix_to_int(pen_y) + g->dims[1]) >= 0 && ft_pix_to_int(pen_y) < buf_info->dims[1]) {
/* don't draw beyond the buffer bounds */
int width_clip = g->dims[0];
int height_clip = g->dims[1];
int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1;
if (width_clip + chx > buf_info->dims[0]) {
width_clip -= chx + width_clip - buf_info->dims[0];
}
if (height_clip + ft_pix_to_int(pen_y) > buf_info->dims[1]) {
height_clip -= ft_pix_to_int(pen_y) + height_clip - buf_info->dims[1];
}
/* drawing below the image? */
if (pen_y < 0) {
yb_start += (g->pitch < 0) ? -ft_pix_to_int(pen_y) : ft_pix_to_int(pen_y);
height_clip += ft_pix_to_int(pen_y);
pen_y = 0;
}
/* Avoid conversions in the pixel writing loop. */
const int pen_y_px = ft_pix_to_int(pen_y);
if (buf_info->fbuf) {
int yb = yb_start;
for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
const char a_byte = *(g->bitmap + x + (yb * g->pitch));
if (a_byte) {
const float a = (a_byte / 255.0f) * b_col_float[3];
const size_t buf_ofs = (((size_t)(chx + x) +
((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
(size_t)buf_info->ch);
float *fbuf = buf_info->fbuf + buf_ofs;
float font_pixel[4];
font_pixel[0] = b_col_float[0] * a;
font_pixel[1] = b_col_float[1] * a;
font_pixel[2] = b_col_float[2] * a;
font_pixel[3] = a;
blend_color_mix_float(fbuf, fbuf, font_pixel);
}
}
if (g->pitch < 0) {
yb++;
}
else {
yb--;
}
}
}
if (buf_info->cbuf) {
int yb = yb_start;
for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
const char a_byte = *(g->bitmap + x + (yb * g->pitch));
if (a_byte) {
const float a = (a_byte / 255.0f) * b_col_float[3];
const size_t buf_ofs = (((size_t)(chx + x) +
((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
(size_t)buf_info->ch);
uchar *cbuf = buf_info->cbuf + buf_ofs;
uchar font_pixel[4];
font_pixel[0] = b_col_char[0];
font_pixel[1] = b_col_char[1];
font_pixel[2] = b_col_char[2];
font_pixel[3] = unit_float_to_uchar_clamp(a);
blend_color_mix_byte(cbuf, cbuf, font_pixel);
}
}
if (g->pitch < 0) {
yb++;
}
else {
yb--;
}
}
}
}
blf_glyph_draw_buffer(buf_info, g, pen_x, pen_y_basis);
pen_x = ft_pix_round_advance(pen_x, g->advance_x);
g_prev = g;

View File

@ -54,7 +54,7 @@
*/
static FT_Fixed to_16dot16(double val)
{
return (FT_Fixed)(lround(val * 65536.0));
return (FT_Fixed)lround(val * 65536.0);
}
/** \} */

View File

@ -30,7 +30,7 @@ void BKE_blender_globals_main_replace(struct Main *bmain);
* Replace current global Main by the given one, returning the old one.
*
* \warning Advanced, risky workaround addressing the issue that current RNA is not able to process
* correectly non-G_MAIN data, use with (a lot of) care.
* correctly non-G_MAIN data, use with (a lot of) care.
*/
struct Main *BKE_blender_globals_main_swap(struct Main *new_gmain);

View File

@ -16,6 +16,7 @@ struct ListBase;
struct Object;
struct ParticleSystem;
struct Scene;
struct ViewLayer;
struct ViewerPath;
struct GeometrySet;
@ -83,6 +84,13 @@ bool BKE_object_dupli_find_rgba_attribute(struct Object *ob,
const char *name,
float r_value[4]);
/** Look up the RGBA value of a view layer/scene/world shader attribute.
* \return true if the attribute was found; if not, r_value is also set to zero. */
bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
struct ViewLayer *layer,
const char *name,
float r_value[4]);
#ifdef __cplusplus
}
#endif

View File

@ -350,14 +350,14 @@ int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge,
#ifdef __cplusplus
namespace blender::mesh_topology {
Array<int> build_corner_to_poly_map(Span<MPoly> polys, int loops_num);
Array<int> build_loop_to_poly_map(Span<MPoly> polys, int loops_num);
Array<Vector<int>> build_vert_to_edge_map(Span<MEdge> edges, int verts_num);
Array<Vector<int>> build_vert_to_corner_map(Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<MLoop> loops, int verts_num);
inline int previous_poly_corner(const MPoly &poly, int corner_i)
inline int previous_poly_loop(const MPoly &poly, int loop_i)
{
return corner_i - 1 + (corner_i == poly.loopstart) * poly.totloop;
return loop_i - 1 + (loop_i == poly.loopstart) * poly.totloop;
}
} // namespace blender::mesh_topology

View File

@ -127,6 +127,7 @@ typedef enum ModifierApplyFlag {
* See `OBJECT_OT_modifier_apply` operator. */
MOD_APPLY_TO_BASE_MESH = 1 << 4,
} ModifierApplyFlag;
ENUM_OPERATORS(ModifierApplyFlag, MOD_APPLY_TO_BASE_MESH);
typedef struct ModifierUpdateDepsgraphContext {
struct Scene *scene;

View File

@ -8,7 +8,7 @@
*/
#include "BKE_subsurf.h"
#include "BLI_compiler_compat.h"
#include "BLI_utildefines.h"
#ifdef __cplusplus
extern "C" {
@ -54,12 +54,13 @@ void multires_modifier_update_hidden(struct DerivedMesh *dm);
*/
void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, struct Object *ob);
typedef enum {
typedef enum MultiresFlags {
MULTIRES_USE_LOCAL_MMD = 1,
MULTIRES_USE_RENDER_PARAMS = 2,
MULTIRES_ALLOC_PAINT_MASK = 4,
MULTIRES_IGNORE_SIMPLIFY = 8,
} MultiresFlags;
ENUM_OPERATORS(MultiresFlags, MULTIRES_IGNORE_SIMPLIFY);
struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,
struct MultiresModifierData *mmd,

View File

@ -246,6 +246,24 @@ float BKE_nlastrip_compute_frame_from_previous_strip(struct NlaStrip *strip);
*/
float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip);
/**
* Returns the next strip in this strip's NLA track, or a null pointer.
*
* \param strip The strip to find the next trip from.
* \param check_transitions Whether or not to skip transitions.
* \return The next strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions);
/**
* Returns the previous strip in this strip's NLA track, or a null pointer.
*
* \param strip The strip to find the previous trip from.
* \param check_transitions Whether or not to skip transitions.
* \return The previous strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions);
/* ............ */
/**

View File

@ -11,6 +11,7 @@
/* Thread sync primitives used directly. */
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#ifdef __cplusplus
extern "C" {
@ -32,7 +33,7 @@ struct SubsurfModifierData;
/**************************** External *****************************/
typedef enum {
typedef enum SubsurfFlags {
SUBSURF_USE_RENDER_PARAMS = 1,
SUBSURF_IS_FINAL_CALC = 2,
SUBSURF_FOR_EDIT_MODE = 4,
@ -41,6 +42,7 @@ typedef enum {
SUBSURF_USE_GPU_BACKEND = 32,
SUBSURF_IGNORE_SIMPLIFY = 64,
} SubsurfFlags;
ENUM_OPERATORS(SubsurfFlags, SUBSURF_IGNORE_SIMPLIFY);
struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm,
struct SubsurfModifierData *smd,

View File

@ -226,7 +226,7 @@ set(SRC
intern/mesh_wrapper.cc
intern/modifier.cc
intern/movieclip.c
intern/multires.c
intern/multires.cc
intern/multires_reshape.c
intern/multires_reshape_apply_base.c
intern/multires_reshape_ccg.c
@ -270,14 +270,14 @@ set(SRC
intern/scene.cc
intern/screen.c
intern/shader_fx.c
intern/shrinkwrap.c
intern/shrinkwrap.cc
intern/simulation.cc
intern/softbody.c
intern/sound.c
intern/speaker.c
intern/studiolight.c
intern/subdiv.c
intern/subdiv_ccg.c
intern/subdiv_ccg.cc
intern/subdiv_ccg_mask.c
intern/subdiv_ccg_material.c
intern/subdiv_converter.c
@ -288,7 +288,7 @@ set(SRC
intern/subdiv_eval.c
intern/subdiv_foreach.c
intern/subdiv_mesh.cc
intern/subdiv_modifier.c
intern/subdiv_modifier.cc
intern/subdiv_stats.c
intern/subdiv_topology.c
intern/subsurf_ccg.c

View File

@ -3198,7 +3198,7 @@ static void animsys_create_action_track_strip(const AnimData *adt,
* (which making new strips doesn't do due to the troublesome nature of that). */
calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1);
r_action_strip->start = r_action_strip->actstart;
r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ?
r_action_strip->end = IS_EQF(r_action_strip->actstart, r_action_strip->actend) ?
(r_action_strip->actstart + 1.0f) :
(r_action_strip->actend);

View File

@ -301,12 +301,22 @@ static void armature_vert_task_with_dvert(const ArmatureUserdata *data,
}
/* check if there's any point in calculating for this vert */
if (armature_weight == 0.0f) {
return;
}
if (vert_coords_prev) {
if (prevco_weight == 1.0f) {
return;
}
/* get the coord we work on */
co = vert_coords_prev ? vert_coords_prev[i] : vert_coords[i];
/* get the coord we work on */
co = vert_coords_prev[i];
}
else {
if (armature_weight == 0.0f) {
return;
}
/* get the coord we work on */
co = vert_coords[i];
}
/* Apply the object's matrix */
mul_m4_v3(data->premat, co);

View File

@ -25,7 +25,7 @@
bUserMenu *BKE_blender_user_menu_find(ListBase *lb, char space_type, const char *context)
{
LISTBASE_FOREACH (bUserMenu *, um, lb) {
if ((space_type == um->space_type) && (STREQ(context, um->context))) {
if ((space_type == um->space_type) && STREQ(context, um->context)) {
return um;
}
}

View File

@ -713,10 +713,8 @@ static bool camera_frame_fit_calc_from_data(CameraParams *params,
plane_from_point_normal_v3(plane_tx[i], co, data->plane_tx[i]);
}
if ((!isect_plane_plane_v3(
plane_tx[Y_MIN], plane_tx[Y_MAX], plane_isect_1, plane_isect_1_no)) ||
(!isect_plane_plane_v3(
plane_tx[Z_MIN], plane_tx[Z_MAX], plane_isect_2, plane_isect_2_no))) {
if (!isect_plane_plane_v3(plane_tx[Y_MIN], plane_tx[Y_MAX], plane_isect_1, plane_isect_1_no) ||
!isect_plane_plane_v3(plane_tx[Z_MIN], plane_tx[Z_MAX], plane_isect_2, plane_isect_2_no)) {
return false;
}

View File

@ -198,7 +198,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
DM_TYPE_CDDM,
mesh->totvert,
mesh->totedge,
0 /* mesh->totface */,
0 /* `mesh->totface` */,
mesh->totloop,
mesh->totpoly);
@ -213,7 +213,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
&dm->faceData,
cddata_masks.fmask | CD_MASK_ORIGINDEX,
alloctype,
0 /* mesh->totface */);
0 /* `mesh->totface` */);
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);

View File

@ -1130,7 +1130,7 @@ static void cloth_update_springs(ClothModifierData *clmd)
* because implicit solver would need reset! */
/* Activate / Deactivate existing springs */
if ((!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED)) &&
if (!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED) &&
(cloth->verts[spring->ij].goal > ALMOST_ZERO)) {
spring->flags &= ~CLOTH_SPRING_FLAG_DEACTIVATE;
}

View File

@ -949,7 +949,7 @@ bool BKE_collection_has_object(Collection *collection, const Object *ob)
return false;
}
return (BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob)));
return BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
}
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
@ -959,7 +959,7 @@ bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
}
const ListBase objects = BKE_collection_object_cache_get(collection);
return (BLI_findptr(&objects, ob, offsetof(Base, object)));
return BLI_findptr(&objects, ob, offsetof(Base, object));
}
bool BKE_collection_has_object_recursive_instanced(Collection *collection, Object *ob)
@ -969,7 +969,7 @@ bool BKE_collection_has_object_recursive_instanced(Collection *collection, Objec
}
const ListBase objects = BKE_collection_object_cache_instanced_get(collection);
return (BLI_findptr(&objects, ob, offsetof(Base, object)));
return BLI_findptr(&objects, ob, offsetof(Base, object));
}
static Collection *collection_next_find(Main *bmain, Scene *scene, Collection *collection)

View File

@ -1738,7 +1738,7 @@ void BKE_scopes_update(Scopes *scopes,
}
/* hmmmm */
if (!(ELEM(ibuf->channels, 3, 4))) {
if (!ELEM(ibuf->channels, 3, 4)) {
return;
}

View File

@ -634,7 +634,7 @@ ListBase CTX_data_dir_get(const bContext *C)
bool CTX_data_equals(const char *member, const char *str)
{
return (STREQ(member, str));
return STREQ(member, str);
}
bool CTX_data_dir(const char *member)

View File

@ -464,7 +464,7 @@ static std::string to_manifest(const CryptomatteLayer *layer)
else {
manifest << ",";
}
manifest << quoted(item.key) << ":\"" << (item.value.hex_encoded()) << "\"";
manifest << quoted(item.key) << ":\"" << item.value.hex_encoded() << "\"";
}
manifest << "}";
return manifest.str();

View File

@ -1935,7 +1935,7 @@ static void calc_bevel_sin_cos(
t02 = M_PI_2;
}
else {
t02 = (saacos(t02)) / 2.0f;
t02 = saacos(t02) / 2.0f;
}
t02 = sinf(t02);
@ -4085,12 +4085,12 @@ void BKE_nurb_bezt_handle_test(BezTriple *bezt,
}
if (bezt->h1 == HD_VECT) {
if ((!(flag & SEL_F1)) != (!(flag & SEL_F2))) {
if (!(flag & SEL_F1) != !(flag & SEL_F2)) {
bezt->h1 = HD_FREE;
}
}
if (bezt->h2 == HD_VECT) {
if ((!(flag & SEL_F3)) != (!(flag & SEL_F2))) {
if (!(flag & SEL_F3) != !(flag & SEL_F2)) {
bezt->h2 = HD_FREE;
}
}
@ -5101,7 +5101,7 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
ListBase temp_nurb_lb = {nullptr, nullptr};
const bool is_font = (BLI_listbase_is_empty(nurb_lb)) && (cu->len != 0);
const bool is_font = BLI_listbase_is_empty(nurb_lb) && (cu->len != 0);
/* For font curves we generate temp list of splines.
*
* This is likely to be fine, this function is not supposed to be called

View File

@ -160,7 +160,7 @@ static bool calc_curve_deform(
/* Zero the axis which is not used,
* the big block of text above now applies to these 3 lines.
* The `upflag` argument may be a dummy, set so no rotation is done. */
quat_apply_track(quat, axis, (ELEM(axis, 0, 2)) ? 1 : 0);
quat_apply_track(quat, axis, ELEM(axis, 0, 2) ? 1 : 0);
vec_apply_track(cent, axis);
cent[index] = 0.0f;

View File

@ -121,7 +121,7 @@ BLI_INLINE void value_dissolve(float *r_value,
const float scale,
const bool is_log)
{
*r_value = (is_log) ? (*r_value) * (powf(MIN_WETNESS, 1.0f / (1.2f * time / scale))) :
*r_value = (is_log) ? (*r_value) * powf(MIN_WETNESS, 1.0f / (1.2f * time / scale)) :
(*r_value) - 1.0f / time * scale;
}

View File

@ -193,7 +193,7 @@ static void cage_mapped_verts_callback(void *userData,
{
CageUserData *data = static_cast<CageUserData *>(userData);
if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
if ((index >= 0 && index < data->totvert) && !BLI_BITMAP_TEST(data->visit_bitmap, index)) {
BLI_BITMAP_ENABLE(data->visit_bitmap, index);
copy_v3_v3(data->cos_cage[index], co);
}

View File

@ -79,7 +79,7 @@ PartDeflect *BKE_partdeflect_new(int type)
pd->pdef_sbift = 0.2f;
pd->pdef_sboft = 0.02f;
pd->pdef_cfrict = 5.0f;
pd->seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128;
pd->seed = ((uint)ceil(PIL_check_seconds_timer()) + 1) % 128;
pd->f_strength = 1.0f;
pd->f_damp = 1.0f;

View File

@ -333,7 +333,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
invert_qt_normalized(q1);
mul_qt_qtqt(quat, q1, q2);
angle = 2.0f * (saacos(quat[0]));
angle = 2.0f * saacos(quat[0]);
angle = fabsf(angle);
return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle);

View File

@ -2204,9 +2204,9 @@ static void adaptive_domain_adjust(
/* add to total shift */
add_v3_v3(fds->shift_f, frame_shift_f);
/* convert to integer */
total_shift[0] = (int)(floorf(fds->shift_f[0]));
total_shift[1] = (int)(floorf(fds->shift_f[1]));
total_shift[2] = (int)(floorf(fds->shift_f[2]));
total_shift[0] = (int)floorf(fds->shift_f[0]);
total_shift[1] = (int)floorf(fds->shift_f[1]);
total_shift[2] = (int)floorf(fds->shift_f[2]);
int temp_shift[3];
copy_v3_v3_int(temp_shift, fds->shift);
sub_v3_v3v3_int(new_shift, total_shift, fds->shift);

View File

@ -13,6 +13,7 @@
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "FN_multi_function_builder.hh"
@ -213,11 +214,15 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
}
/* Deselect loose vertices without corners that are still selected from the 'true' default. */
for (const int vert_index : IndexRange(mesh.totvert)) {
if (loose_verts[vert_index]) {
r_values[vert_index] = false;
/* The record fact says that the value is true.
*Writing to the array from different threads is okay because each thread sets the same value. */
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
for (const int vert_index : range) {
if (loose_verts[vert_index]) {
r_values[vert_index] = false;
}
}
}
});
}
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
@ -413,16 +418,16 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
const Span<MLoop> loops = mesh.loops();
r_values.fill(false);
for (const int poly_index : polys.index_range()) {
const MPoly &poly = polys[poly_index];
if (old_values[poly_index]) {
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
const int vert_index = loop.v;
r_values[vert_index] = true;
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
for (const int poly_index : range) {
if (old_values[poly_index]) {
const MPoly &poly = polys[poly_index];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
r_values[loop.v] = true;
}
}
}
}
});
}
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
@ -502,16 +507,16 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
const Span<MLoop> loops = mesh.loops();
r_values.fill(false);
for (const int poly_index : polys.index_range()) {
const MPoly &poly = polys[poly_index];
if (old_values[poly_index]) {
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
const int edge_index = loop.e;
r_values[edge_index] = true;
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
for (const int poly_index : range) {
if (old_values[poly_index]) {
const MPoly &poly = polys[poly_index];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
r_values[loop.e] = true;
}
}
}
}
});
}
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
@ -619,7 +624,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
/* For every corner, mix the values from the adjacent edges on the face. */
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
const int loop_index_prev = mesh_topology::previous_poly_loop(poly, loop_index);
const MLoop &loop = loops[loop_index];
const MLoop &loop_prev = loops[loop_index_prev];
mixer.mix_in(loop_index, old_values[loop.e]);
@ -642,17 +647,19 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
r_values.fill(false);
for (const int poly_index : polys.index_range()) {
const MPoly &poly = polys[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
const MLoop &loop = loops[loop_index];
const MLoop &loop_prev = loops[loop_index_prev];
if (old_values[loop.e] && old_values[loop_prev.e]) {
r_values[loop_index] = true;
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
for (const int poly_index : range) {
const MPoly &poly = polys[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = mesh_topology::previous_poly_loop(poly, loop_index);
const MLoop &loop = loops[loop_index];
const MLoop &loop_prev = loops[loop_index_prev];
if (old_values[loop.e] && old_values[loop_prev.e]) {
r_values[loop_index] = true;
}
}
}
}
});
}
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
@ -697,14 +704,18 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
BLI_assert(r_values.size() == mesh.totvert);
const Span<MEdge> edges = mesh.edges();
/* Multiple threads can write to the same index here, but they are only
* writing true, and writing to single bytes is expected to be threadsafe. */
r_values.fill(false);
for (const int edge_index : edges.index_range()) {
const MEdge &edge = edges[edge_index];
if (old_values[edge_index]) {
r_values[edge.v1] = true;
r_values[edge.v2] = true;
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int edge_index : range) {
if (old_values[edge_index]) {
const MEdge &edge = edges[edge_index];
r_values[edge.v1] = true;
r_values[edge.v2] = true;
}
}
}
});
}
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)

View File

@ -83,8 +83,8 @@ static void greasepencil_copy_data(Main *UNUSED(bmain),
/* Apply local layer transform to all frames. Calc the active frame is not enough
* because onion skin can use more frames. This is more slow but required here. */
if (gpl_dst->actframe != NULL) {
bool transformed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) ||
(!is_one_v3(gpl_dst->scale)));
bool transformed = (!is_zero_v3(gpl_dst->location) || !is_zero_v3(gpl_dst->rotation) ||
!is_one_v3(gpl_dst->scale));
if (transformed) {
loc_eul_size_to_mat4(
gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale);
@ -2013,7 +2013,7 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
/* Read secondary material to compare with primary material. */
ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1);
if ((ma_secondary == NULL) ||
(BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary)))) {
BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
continue;
}
gp_style_primary = ma_primary->gp_style;
@ -2063,17 +2063,17 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
rgb_to_hsv_compat_v(col, f_hsv_b);
/* Check stroke and fill color. */
if ((!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold)) ||
(!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold)) ||
(!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
(!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold)) ||
(!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold)) ||
(!compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold)) ||
(!compare_ff(gp_style_primary->stroke_rgba[3],
gp_style_secondary->stroke_rgba[3],
val_threshold)) ||
(!compare_ff(
gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold))) {
if (!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold) ||
!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold) ||
!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold) ||
!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold) ||
!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold) ||
!compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold) ||
!compare_ff(gp_style_primary->stroke_rgba[3],
gp_style_secondary->stroke_rgba[3],
val_threshold) ||
!compare_ff(
gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold)) {
continue;
}
@ -2337,7 +2337,7 @@ bool BKE_gpencil_from_image(
static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
{
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->viewlayername[0] != '\0') && (!STREQ(view_layer->name, gpl->viewlayername))) {
if ((gpl->viewlayername[0] != '\0') && !STREQ(view_layer->name, gpl->viewlayername)) {
continue;
}
@ -2412,7 +2412,7 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && (!GPENCIL_PLAY_ON(gpd)));
const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && !GPENCIL_PLAY_ON(gpd));
const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
@ -2444,7 +2444,7 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
* generate renders, putting only selected GP layers for each View Layer.
* This is used only in final render and never in Viewport. */
if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') &&
(!STREQ(view_layer->name, gpl->viewlayername))) {
!STREQ(view_layer->name, gpl->viewlayername)) {
/* Do not skip masks when rendering the view-layer so that it can still be used to clip
* other layers. Instead set their opacity to zero. */
if (gpencil_is_layer_mask(view_layer, gpd, gpl)) {
@ -2786,8 +2786,8 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
}
/* Calc local layer transform. Early out if we have non-animated zero transforms. */
bool transformed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) ||
(!is_one_v3(gpl->scale)));
bool transformed = (!is_zero_v3(gpl->location) || !is_zero_v3(gpl->rotation) ||
!is_one_v3(gpl->scale));
float tmp_mat[4][4];
loc_eul_size_to_mat4(tmp_mat, gpl->location, gpl->rotation, gpl->scale);
transformed |= !equals_m4m4(gpl->layer_mat, tmp_mat);
@ -2834,7 +2834,7 @@ int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_
for (int i = 0; i < ob->totcol; i++) {
Material *ma = BKE_object_material_get(ob, i + 1);
if ((ma != NULL) && (ma->gp_style != NULL) &&
(STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len))) {
STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len)) {
return i;
}
}

View File

@ -722,8 +722,8 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
}
/* Only do layer transformations for non-zero or animated transforms. */
bool transformed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) ||
(!is_one_v3(gpl->scale)));
bool transformed = (!is_zero_v3(gpl->location) || !is_zero_v3(gpl->rotation) ||
!is_one_v3(gpl->scale));
float tmp_mat[4][4];
loc_eul_size_to_mat4(tmp_mat, gpl->location, gpl->rotation, gpl->scale);
transformed |= !equals_m4m4(gpl->layer_mat, tmp_mat);
@ -752,7 +752,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_orig);
const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) &&
(ob_orig->greasepencil_modifiers.first != NULL) &&
(!GPENCIL_SIMPLIFY_MODIF(scene)));
!GPENCIL_SIMPLIFY_MODIF(scene));
if ((!do_modifiers) && (!do_parent) && (!do_transform)) {
BLI_assert(ob->data != NULL);
return;
@ -782,7 +782,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
const bool is_multiedit = (bool)(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && !is_render);
const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) &&
(ob->greasepencil_modifiers.first != NULL) &&
(!GPENCIL_SIMPLIFY_MODIF(scene)));
!GPENCIL_SIMPLIFY_MODIF(scene));
if (!do_modifiers) {
return;
}

View File

@ -520,7 +520,7 @@ static bool do_add_image_extension(char *string,
}
#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc
if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr))) {
if (!BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr)) {
extension = extension_test;
}
}

View File

@ -824,7 +824,7 @@ bool BKE_image_render_write_exr(ReportList *reports,
/* We only store RGBA passes as half float, for
* others precision loss can be problematic. */
const bool pass_RGBA = (STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A"));
const bool pass_RGBA = STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A");
const bool pass_half_float = half_float && pass_RGBA;
/* Color-space conversion only happens on RGBA passes. */

View File

@ -1542,7 +1542,7 @@ static void icu_to_fcurves(ID *id,
}
/* correct values, by checking if the flag of interest is set */
if (((int)(dst->vec[1][1])) & (abp->bit)) {
if ((int)(dst->vec[1][1]) & (abp->bit)) {
dst->vec[0][1] = dst->vec[1][1] = dst->vec[2][1] = 1.0f;
}
else {

View File

@ -988,7 +988,7 @@ void BKE_main_view_layers_synced_ensure(const Main *bmain)
BKE_scene_view_layers_synced_ensure(scene);
}
/* NOTE: This is not (yet?) covered by the dirty tag and deffered resync system */
/* NOTE: This is not (yet?) covered by the dirty tag and differed re-sync system */
BKE_layer_collection_local_sync_all(bmain);
}

View File

@ -1389,7 +1389,7 @@ bool BKE_lib_override_library_create(Main *bmain,
id_hierarchy_root_reference = id_root_reference;
}
/* While in theory it _should_ be enough to ensure sync of given viewlayer (if any), or at least
/* While in theory it _should_ be enough to ensure sync of given view-layer (if any), or at least
* of given scene, think for now it's better to get a fully synced Main at this point, this code
* may do some very wide remapping/data access in some cases. */
BKE_main_view_layers_synced_ensure(bmain);

View File

@ -1282,8 +1282,8 @@ BLI_INLINE uint layer_bucket_index_from_xy(MaskRasterLayer *layer, const float x
{
BLI_assert(BLI_rctf_isect_pt_v(&layer->bounds, xy));
return ((uint)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0])) +
(((uint)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1])) * layer->buckets_x);
return (uint)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0]) +
((uint)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1]) * layer->buckets_x);
}
static float layer_bucket_depth_from_xy(MaskRasterLayer *layer, const float xy[2])

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