1
1

Merge branch 'main' into tmp-usd-022123

This commit is contained in:
2023-02-21 15:06:09 -05:00
891 changed files with 2056205 additions and 2376 deletions

View File

@@ -1,8 +0,0 @@
{
"project_id" : "Blender",
"conduit_uri" : "https://developer.blender.org/",
"phabricator.uri" : "https://developer.blender.org/",
"git.default-relative-commit" : "origin/master",
"arc.land.update.default" : "rebase",
"arc.land.onto.default" : "master"
}

View File

@@ -1,9 +1,9 @@
name: Bug Report
about: File a bug report
labels:
- "type::Report"
- "status::Needs Triage"
- "priority::Normal"
- "Type/Report"
- "Status/Needs Triage"
- "Priority/Normal"
body:
- type: markdown
attributes:

View File

@@ -1,7 +1,7 @@
name: Design
about: Create a design task (for developers only)
labels:
- "type::Design"
- "Type/Design"
body:
- type: textarea
id: body

View File

@@ -1,7 +1,7 @@
name: To Do
about: Create a to do task (for developers only)
labels:
- "type::To Do"
- "Type/To Do"
body:
- type: textarea
id: body

20
.gitignore vendored
View File

@@ -39,7 +39,7 @@ Desktop.ini
/doc/python_api/rst/bmesh.ops.rst
# in-source lib downloads
/build_files/build_environment/downloads
/build_files/build_environment/downloads/
# in-source buildbot signing configuration
/build_files/buildbot/codesign/config_server.py
@@ -48,4 +48,20 @@ Desktop.ini
waveletNoiseTile.bin
# testing environment
/Testing
/Testing/
# Translations.
/locale/user-config.py
# External repositories.
/scripts/addons/
/scripts/addons_contrib/
# Ignore old submodules directories.
# Eventually need to get rid of those, but for the first time of transition
# avoid indidents when the folders exists after bisect and developers staging
# them by accident.
/release/scripts/addons/
/release/datafiles/locale/
/release/scripts/addons_contrib/
/source/tools/

20
.gitmodules vendored
View File

@@ -1,20 +0,0 @@
[submodule "release/scripts/addons"]
path = release/scripts/addons
url = ../blender-addons.git
branch = main
ignore = all
[submodule "release/scripts/addons_contrib"]
path = release/scripts/addons_contrib
url = ../blender-addons-contrib.git
branch = main
ignore = all
[submodule "release/datafiles/locale"]
path = release/datafiles/locale
url = ../blender-translations.git
branch = main
ignore = all
[submodule "source/tools"]
path = source/tools
url = ../blender-dev-tools.git
branch = main
ignore = all

View File

@@ -954,21 +954,6 @@ endif()
# -----------------------------------------------------------------------------
# Check if Sub-modules are Cloned
if(WITH_INTERNATIONAL)
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/datafiles/locale")
list(LENGTH RESULT DIR_LEN)
if(DIR_LEN EQUAL 0)
message(
WARNING
"Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, "
"This is a 'git submodule', which are known not to work with bridges to other version "
"control systems."
)
set(TRANSLATIONS_FOUND OFF)
set_and_warn_library_found("Translations" TRANSLATIONS_FOUND WITH_INTERNATIONAL)
endif()
endif()
if(WITH_PYTHON)
# While we have this as an '#error' in 'bpy_capi_utils.h',
# upgrading Python tends to cause confusion for users who build.
@@ -984,14 +969,14 @@ if(WITH_PYTHON)
)
endif()
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/scripts/addons")
list(LENGTH RESULT DIR_LEN)
if(DIR_LEN EQUAL 0)
message(
WARNING
"Addons path '${CMAKE_SOURCE_DIR}/release/scripts/addons' is missing, "
"This is a 'git submodule', which are known not to work with bridges to other version "
"control systems: * CONTINUING WITHOUT ADDONS *"
"Addons path '${CMAKE_SOURCE_DIR}/scripts/addons' is missing. "
"This is an external repository which needs to be checked out. Use `make update` to do so. "
"* CONTINUING WITHOUT ADDONS *"
)
endif()
endif()

View File

@@ -69,7 +69,7 @@ Static Source Code Checking
* check_cmake: Runs our own cmake file checker which detects errors in the cmake file list definitions.
* check_pep8: Checks all Python script are pep8 which are tagged to use the stricter formatting.
* check_mypy: Checks all Python scripts using mypy,
see: source/tools/check_source/check_mypy_config.py scripts which are included.
see: tools/check_source/check_mypy_config.py scripts which are included.
Documentation Checking
@@ -85,7 +85,7 @@ Spell Checkers
* check_spelling_osl: Check for spelling errors (OSL only).
* check_spelling_py: Check for spelling errors (Python only).
Note: an additional word-list is maintained at: 'source/tools/check_source/check_spelling_c_config.py'
Note: an additional word-list is maintained at: 'tools/check_source/check_spelling_c_config.py'
Note: that spell checkers can take a 'CHECK_SPELLING_CACHE' filepath argument,
so re-running does not need to re-check unchanged files.
@@ -490,22 +490,22 @@ check_smatch: .FORCE
$(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py"
check_mypy: .FORCE
@$(PYTHON) "$(BLENDER_DIR)/source/tools/check_source/check_mypy.py"
@$(PYTHON) "$(BLENDER_DIR)/tools/check_source/check_mypy.py"
check_wiki_file_structure: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_wiki/check_wiki_file_structure.py"
"$(BLENDER_DIR)/tools/check_wiki/check_wiki_file_structure.py"
check_spelling_py: .FORCE
@cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/release/scripts"
"$(BLENDER_DIR)/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/scripts"
check_spelling_c: .FORCE
@cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/tools/check_source/check_spelling.py" \
--cache-file=$(CHECK_SPELLING_CACHE) \
"$(BLENDER_DIR)/source" \
"$(BLENDER_DIR)/intern/cycles" \
@@ -515,21 +515,21 @@ check_spelling_c: .FORCE
check_spelling_osl: .FORCE
@cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/tools/check_source/check_spelling.py" \
--cache-file=$(CHECK_SPELLING_CACHE) \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders"
check_descriptions: .FORCE
@$(BLENDER_BIN) --background -noaudio --factory-startup --python \
"$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
"$(BLENDER_DIR)/tools/check_source/check_descriptions.py"
check_deprecated: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
source/tools/check_source/check_deprecated.py
tools/check_source/check_deprecated.py
check_licenses: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_licenses.py" \
"$(BLENDER_DIR)/tools/check_source/check_licenses.py" \
"--show-headers=$(SHOW_HEADERS)"
check_pep8: .FORCE
@@ -538,7 +538,7 @@ check_pep8: .FORCE
check_cmake: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
source/tools/check_source/check_cmake_consistency.py
tools/check_source/check_cmake_consistency.py
# -----------------------------------------------------------------------------
@@ -576,8 +576,8 @@ update_code: .FORCE
@$(PYTHON) ./build_files/utils/make_update.py --no-libraries
format: .FORCE
@PATH="${LIBDIR}/llvm/bin/:$(PATH)" $(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS)
@$(PYTHON) source/tools/utils_maintenance/autopep8_format_paths.py --autopep8-command="$(AUTOPEP8)" $(PATHS)
@PATH="${LIBDIR}/llvm/bin/:$(PATH)" $(PYTHON) tools/utils_maintenance/clang_format_paths.py $(PATHS)
@$(PYTHON) tools/utils_maintenance/autopep8_format_paths.py --autopep8-command="$(AUTOPEP8)" $(PATHS)
# -----------------------------------------------------------------------------

View File

@@ -10,7 +10,7 @@ ExternalProject_Add(external_epoxy
URL_HASH ${EPOXY_HASH_TYPE}=${EPOXY_HASH}
PREFIX ${BUILD_DIR}/epoxy
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/epoxy/src/external_epoxy/ < ${PATCH_DIR}/epoxy.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${MESON} setup --prefix ${LIBDIR}/epoxy --default-library ${EPOXY_LIB_TYPE} --libdir lib ${BUILD_DIR}/epoxy/src/external_epoxy-build ${BUILD_DIR}/epoxy/src/external_epoxy -Dtests=false
CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${MESON} setup --prefix ${LIBDIR}/epoxy --default-library ${EPOXY_LIB_TYPE} --libdir lib ${BUILD_DIR}/epoxy/src/external_epoxy-build ${BUILD_DIR}/epoxy/src/external_epoxy -Dtests=false ${MESON_BUILD_TYPE}
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@@ -9,7 +9,7 @@ ExternalProject_Add(external_fribidi
URL_HASH ${FRIBIDI_HASH_TYPE}=${FRIBIDI_HASH}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
PREFIX ${BUILD_DIR}/fribidi
CONFIGURE_COMMAND ${MESON} setup --prefix ${LIBDIR}/fribidi -Ddocs=false --default-library static --libdir lib ${BUILD_DIR}/fribidi/src/external_fribidi-build ${BUILD_DIR}/fribidi/src/external_fribidi
CONFIGURE_COMMAND ${MESON} setup --prefix ${LIBDIR}/fribidi ${MESON_BUILD_TYPE} -Ddocs=false --default-library static --libdir lib ${BUILD_DIR}/fribidi/src/external_fribidi-build ${BUILD_DIR}/fribidi/src/external_fribidi
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
INSTALL_DIR ${LIBDIR}/fribidi

View File

@@ -21,6 +21,7 @@ set(HARFBUZZ_EXTRA_OPTIONS
# Only used for command line utilities,
# disable as this would add an addition & unnecessary build-dependency.
-Dcairo=disabled
${MESON_BUILD_TYPE}
)
ExternalProject_Add(external_harfbuzz
@@ -59,3 +60,10 @@ if(BUILD_MODE STREQUAL Release AND WIN32)
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug AND WIN32)
ExternalProject_Add_Step(external_harfbuzz after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/harfbuzz/lib/libharfbuzz.a ${HARVEST_TARGET}/harfbuzz/lib/libharfbuzz_d.lib
DEPENDEES install
)
endif()

View File

@@ -15,7 +15,7 @@ llvm-config = '${LIBDIR}/llvm/bin/llvm-config'"
)
set(MESA_EXTRA_FLAGS
-Dbuildtype=release
${MESON_BUILD_TYPE}
-Dc_args=${MESA_CFLAGS}
-Dcpp_args=${MESA_CXXFLAGS}
-Dc_link_args=${MESA_LDFLAGS}

View File

@@ -44,13 +44,21 @@ set(OPENVDB_EXTRA_ARGS
# -DLLVM_DIR=${LIBDIR}/llvm/lib/cmake/llvm
)
set(OPENVDB_PATCH ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb.diff)
if(APPLE)
set(OPENVDB_PATCH
${OPENVDB_PATCH} &&
${PATCH_CMD} -p 0 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb_metal.diff
)
endif()
ExternalProject_Add(openvdb
URL file://${PACKAGE_DIR}/${OPENVDB_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${OPENVDB_HASH_TYPE}=${OPENVDB_HASH}
CMAKE_GENERATOR ${PLATFORM_ALT_GENERATOR}
PREFIX ${BUILD_DIR}/openvdb
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb.diff
PATCH_COMMAND ${OPENVDB_PATCH}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openvdb ${DEFAULT_CMAKE_FLAGS} ${OPENVDB_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openvdb
)

View File

@@ -16,8 +16,10 @@ message("BuildMode = ${BUILD_MODE}")
if(BUILD_MODE STREQUAL "Debug")
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Debug)
set(MESON_BUILD_TYPE -Dbuildtype=debug)
else()
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Release)
set(MESON_BUILD_TYPE -Dbuildtype=release)
endif()
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")

View File

@@ -13,7 +13,7 @@ ExternalProject_Add(external_wayland
# NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`,
# without this, math symbols such as `floor` aren't found.
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 -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
${MESON} --prefix ${LIBDIR}/wayland ${MESON_BUILD_TYPE} -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@@ -7,7 +7,7 @@ ExternalProject_Add(external_wayland_protocols
PREFIX ${BUILD_DIR}/wayland-protocols
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own WAYLAND.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/wayland/lib64/pkgconfig:$PKG_CONFIG_PATH
${MESON} --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false
${MESON} --prefix ${LIBDIR}/wayland-protocols ${MESON_BUILD_TYPE} . ../external_wayland_protocols -Dtests=false
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@@ -17,11 +17,13 @@ ExternalProject_Add(external_xvidcore
INSTALL_DIR ${LIBDIR}/xvidcore
)
if(WIN32)
ExternalProject_Add_Step(external_xvidcore after_install
COMMAND ${CMAKE_COMMAND} -E rename ${LIBDIR}/xvidcore/lib/xvidcore.a ${LIBDIR}/xvidcore/lib/libxvidcore.a || true
COMMAND ${CMAKE_COMMAND} -E remove ${LIBDIR}/xvidcore/lib/xvidcore.dll.a
DEPENDEES install
)
endif()
if(MSVC)
set_target_properties(external_xvidcore PROPERTIES FOLDER Mingw)

View File

@@ -6,11 +6,11 @@
# - That dependency uses all available cores.
#
# Without this, simply calling `make -j$(nproc)` from the `${CMAKE_BUILD_DIR}/deps/`
# directory will build all projects at once.
# directory will build many projects at once.
#
# This is undesirable for the following reasons:
#
# - The output from many projects is mixed together,
# - The output from projects is mixed together,
# making it difficult to track down the cause of a build failure.
#
# - Larger dependencies such as LLVM can bottleneck the build process,
@@ -20,7 +20,7 @@
# It's possible canceling happens as a patch is being applied or files are being copied.
# (steps that aren't part of the compilation process where it's typically safe to cancel).
if [[ -z "${MY_MAKE_CALL_LEVEL}" ]]; then
if [[ -z "$MY_MAKE_CALL_LEVEL" ]]; then
export MY_MAKE_CALL_LEVEL=0
export MY_MAKEFLAGS=$MAKEFLAGS
@@ -36,11 +36,11 @@ if [[ -z "${MY_MAKE_CALL_LEVEL}" ]]; then
;;
--jobs=*)
shift # past argument=value
export MY_JOBS_ARG=$i
MY_JOBS_ARG=$i
;;
*)
if (( $add_next == 1 )); then
export MY_JOBS_ARG="$MY_JOBS_ARG $i"
if (( add_next == 1 )); then
MY_JOBS_ARG="$MY_JOBS_ARG $i"
add_next=0
fi
;;
@@ -48,17 +48,18 @@ if [[ -z "${MY_MAKE_CALL_LEVEL}" ]]; then
done
unset i add_next
if [[ -z "${MY_JOBS_ARG}" ]]; then
export MY_JOBS_ARG="-j$(nproc)"
if [[ -z "$MY_JOBS_ARG" ]]; then
MY_JOBS_ARG="-j$(nproc)"
fi
export MY_JOBS_ARG
# Support user defined `MAKEFLAGS`.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
else
export MY_MAKE_CALL_LEVEL=$(( $MY_MAKE_CALL_LEVEL + 1 ))
if (( $MY_MAKE_CALL_LEVEL == 1 )); then
export MY_MAKE_CALL_LEVEL=$(( MY_MAKE_CALL_LEVEL + 1 ))
if (( MY_MAKE_CALL_LEVEL == 1 )); then
# Important to set jobs to 1, otherwise user defined jobs argument is used.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
elif (( $MY_MAKE_CALL_LEVEL == 2 )); then
elif (( MY_MAKE_CALL_LEVEL == 2 )); then
# This is the level used by each sub-project.
export MAKEFLAGS="$MY_MAKEFLAGS $MY_JOBS_ARG"
fi

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@ if(NOT APPLE)
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_HIP_BINARIES OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_ONEAPI ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_ONEAPI_BINARIES ON CACHE BOOL "" FORCE)
endif()

View File

@@ -901,11 +901,11 @@ endif()
if(WINDOWS_PYTHON_DEBUG)
# Include the system scripts in the blender_python_system_scripts project.
file(GLOB_RECURSE inFiles "${CMAKE_SOURCE_DIR}/release/scripts/*.*" )
file(GLOB_RECURSE inFiles "${CMAKE_SOURCE_DIR}/scripts/*.*" )
add_custom_target(blender_python_system_scripts SOURCES ${inFiles})
foreach(_source IN ITEMS ${inFiles})
get_filename_component(_source_path "${_source}" PATH)
string(REPLACE "${CMAKE_SOURCE_DIR}/release/scripts/" "" _source_path "${_source_path}")
string(REPLACE "${CMAKE_SOURCE_DIR}/scripts/" "" _source_path "${_source_path}")
string(REPLACE "/" "\\" _group_path "${_source_path}")
source_group("${_group_path}" FILES "${_source}")
endforeach()
@@ -940,7 +940,7 @@ if(WINDOWS_PYTHON_DEBUG)
file(WRITE ${USER_PROPS_FILE} "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup>
<LocalDebuggerCommandArguments>-con --env-system-scripts \"${CMAKE_SOURCE_DIR}/release/scripts\" </LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>-con --env-system-scripts \"${CMAKE_SOURCE_DIR}/scripts\" </LocalDebuggerCommandArguments>
</PropertyGroup>
</Project>")
endif()

View File

@@ -142,7 +142,7 @@ def cmake_advanced_info() -> Union[Tuple[List[str], List[Tuple[str, str]]], Tupl
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
if make_exe is None:
print("Make command not found in: %r not found" % project_path)
print("Make command not found: CMAKE_MAKE_PROGRAM")
return None, None
make_exe_basename = os.path.basename(make_exe)

View File

@@ -1,53 +1,3 @@
#
# Used by Buildbot build pipeline make_update.py script only for now
# We intended to update the make_update.py in the branches to use this file eventually
#
update-code:
git:
submodules:
- branch: main
commit_id: HEAD
path: release/scripts/addons
- branch: main
commit_id: HEAD
path: release/scripts/addons_contrib
- branch: main
commit_id: HEAD
path: release/datafiles/locale
- branch: main
commit_id: HEAD
path: source/tools
svn:
libraries:
darwin-arm64:
branch: trunk
commit_id: HEAD
path: lib/darwin_arm64
darwin-x86_64:
branch: trunk
commit_id: HEAD
path: lib/darwin
linux-x86_64:
branch: trunk
commit_id: HEAD
path: lib/linux_x86_64_glibc_228
windows-amd64:
branch: trunk
commit_id: HEAD
path: lib/win64_vc15
tests:
branch: trunk
commit_id: HEAD
path: lib/tests
benchmarks:
branch: trunk
commit_id: HEAD
path: lib/benchmarks
assets:
branch: trunk
commit_id: HEAD
path: lib/assets
#
# Buildbot only configs
#

View File

@@ -135,7 +135,7 @@ def submodules_to_manifest(
submodule = line.split()[1]
# Don't use native slashes as GIT for MS-Windows outputs forward slashes.
if skip_addon_contrib and submodule == "release/scripts/addons_contrib":
if skip_addon_contrib and submodule == "scripts/addons_contrib":
continue
for path in git_ls_files(blender_srcdir / submodule):

View File

@@ -16,14 +16,28 @@ import shutil
import sys
import make_utils
from pathlib import Path
from make_utils import call, check_output
from urllib.parse import urljoin
from typing import (
List,
Iterable,
Optional,
)
class Submodule:
path: str
branch: str
branch_fallback: str
def __init__(self, path: str, branch: str, branch_fallback: str) -> None:
self.path = path
self.branch = branch
self.branch_fallback = branch_fallback
def print_stage(text: str) -> None:
print("")
print(text)
@@ -42,6 +56,7 @@ def parse_arguments() -> argparse.Namespace:
parser.add_argument("--svn-branch", default=None)
parser.add_argument("--git-command", default="git")
parser.add_argument("--use-linux-libraries", action="store_true")
parser.add_argument("--architecture", type=str, choices=("x86_64", "amd64", "arm64",))
return parser.parse_args()
@@ -51,6 +66,19 @@ def get_blender_git_root() -> str:
# Setup for precompiled libraries and tests from svn.
def get_effective_architecture(args: argparse.Namespace) -> str:
architecture = args.architecture
if architecture:
assert isinstance(architecture, str)
return architecture
# Check platform.version to detect arm64 with x86_64 python binary.
if "ARM64" in platform.version():
return "arm64"
return platform.machine().lower()
def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None:
svn_non_interactive = [args.svn_command, '--non-interactive']
@@ -58,11 +86,11 @@ def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None
svn_url = make_utils.svn_libraries_base_url(release_version, args.svn_branch)
# Checkout precompiled libraries
architecture = get_effective_architecture(args)
if sys.platform == 'darwin':
# Check platform.version to detect arm64 with x86_64 python binary.
if platform.machine() == 'arm64' or ('ARM64' in platform.version()):
if architecture == 'arm64':
lib_platform = "darwin_arm64"
elif platform.machine() == 'x86_64':
elif architecture == 'x86_64':
lib_platform = "darwin"
else:
lib_platform = None
@@ -184,58 +212,221 @@ def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True)
return ""
def use_upstream_workflow(args: argparse.Namespace) -> bool:
return make_utils.git_remote_exist(args.git_command, "upstream")
def work_tree_update_upstream_workflow(args: argparse.Namespace, use_fetch=True) -> str:
"""
Update the Blender repository using the Github style of fork organization
Returns true if the current local branch has been updated to the upstream state.
Otherwise false is returned.
"""
branch_name = make_utils.git_branch(args.git_command)
if use_fetch:
call((args.git_command, "fetch", "upstream"))
upstream_branch = f"upstream/{branch_name}"
if not make_utils.git_branch_exists(args.git_command, upstream_branch):
return "no_branch"
retcode = call((args.git_command, "merge", "--ff-only", upstream_branch), exit_on_error=False)
if retcode != 0:
return "Unable to fast forward\n"
return ""
def work_tree_update(args: argparse.Namespace, use_fetch=True) -> str:
"""
Update the Git working tree using the best strategy
This function detects whether it is a github style of fork remote organization is used, or
is it a repository which origin is an upstream.
"""
if use_upstream_workflow(args):
message = work_tree_update_upstream_workflow(args, use_fetch)
if message != "no_branch":
return message
# If there is upstream configured but the local branch is not in the upstream, try to
# update the branch from the fork.
update_command = [args.git_command, "pull", "--rebase"]
call(update_command)
return ""
# Update blender repository.
def blender_update(args: argparse.Namespace) -> None:
def blender_update(args: argparse.Namespace) -> str:
print_stage("Updating Blender Git Repository")
call([args.git_command, "pull", "--rebase"])
return work_tree_update(args)
# Update submodules.
def submodules_update(
args: argparse.Namespace,
release_version: Optional[str],
branch: Optional[str],
) -> str:
print_stage("Updating Submodules")
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n")
sys.exit(1)
def resolve_external_url(blender_url: str, repo_name: str) -> str:
return urljoin(blender_url + "/", "../" + repo_name)
# Update submodules to appropriate given branch,
# falling back to main if none is given and/or found in a sub-repository.
def external_script_copy_old_submodule_over(args: argparse.Namespace, directory_name: str) -> None:
blender_git_root = Path(get_blender_git_root())
scripts_dir = blender_git_root / "scripts"
external_dir = scripts_dir / directory_name
old_submodule_relative_dir = Path("release") / "scripts" / directory_name
print(f"Moving {old_submodule_relative_dir} to scripts/{directory_name} ...")
old_submodule_dir = blender_git_root / old_submodule_relative_dir
shutil.move(old_submodule_dir, external_dir)
# Remove old ".git" which is a file with path to a submodule bare repo inside of main
# repo .git/modules directory.
(external_dir / ".git").unlink()
bare_repo_relative_dir = Path(".git") / "modules" / "release" / "scripts" / directory_name
print(f"Copying {bare_repo_relative_dir} to scripts/{directory_name}/.git ...")
bare_repo_dir = blender_git_root / bare_repo_relative_dir
shutil.copytree(bare_repo_dir, external_dir / ".git")
git_config = external_dir / ".git" / "config"
call((args.git_command, "config", "--file", git_config, "--unset", "core.worktree"))
def external_script_initialize_if_needed(args: argparse.Namespace,
repo_name: str,
directory_name: str) -> None:
"""Initialize checkout of an external repository scripts directory"""
blender_git_root = Path(get_blender_git_root())
blender_dot_git = blender_git_root / ".git"
scripts_dir = blender_git_root / "scripts"
external_dir = scripts_dir / directory_name
if external_dir.exists():
return
print(f"Initializing scripts/{directory_name} ...")
old_submodule_dot_git = blender_git_root / "release" / "scripts" / directory_name / ".git"
if old_submodule_dot_git.exists() and blender_dot_git.is_dir():
external_script_copy_old_submodule_over(args, directory_name)
return
origin_name = "upstream" if use_upstream_workflow(args) else "origin"
blender_url = make_utils.git_get_remote_url(args.git_command, origin_name)
external_url = resolve_external_url(blender_url, repo_name)
call((args.git_command, "clone", "--origin", origin_name, external_url, external_dir))
def external_script_add_origin_if_needed(args: argparse.Namespace,
repo_name: str,
directory_name: str) -> str:
"""
Add remote called 'origin' if there is a fork of the external repository available
This is only done when using Github style upstream workflow in the main repository.
"""
if not use_upstream_workflow(args):
return ""
cwd = os.getcwd()
blender_git_root = Path(get_blender_git_root())
scripts_dir = blender_git_root / "scripts"
external_dir = scripts_dir / directory_name
origin_blender_url = make_utils.git_get_remote_url(args.git_command, "origin")
origin_external_url = resolve_external_url(origin_blender_url, repo_name)
try:
os.chdir(external_dir)
if (make_utils.git_remote_exist(args.git_command, "origin") or
not make_utils.git_remote_exist(args.git_command, "upstream")):
return
if not make_utils.git_is_remote_repository(args.git_command, origin_external_url):
return
print(f"Adding origin remote to {directory_name} pointing to fork ...")
# Non-obvious tricks to introduce the new remote called "origin" to the existing
# submodule configuration.
#
# This is all within the content of creating a fork of a submodule after `make update`
# has been run and possibly local branches tracking upstream were added.
#
# The idea here goes as following:
#
# - Rename remote "upstream" to "origin", which takes care of changing the names of
# remotes the local branches are tracking.
#
# - Change the URL to the "origin", which so was was still pointing to upstream.
#
# - Re-introduce the "upstream" remote, with the same URL as it had prior to rename.
upstream_url = make_utils.git_get_remote_url(args.git_command, "upstream")
call((args.git_command, "remote", "rename", "upstream", "origin"))
make_utils.git_set_config(args.git_command, f"remote.origin.url", origin_external_url)
call((args.git_command, "remote", "add", "upstream", upstream_url))
finally:
os.chdir(cwd)
return ""
def external_scripts_update(args: argparse.Namespace,
repo_name: str,
directory_name: str,
branch: Optional[str]) -> str:
"""Update a single external checkout with the given name in the scripts folder"""
external_script_initialize_if_needed(args, repo_name, directory_name)
external_script_add_origin_if_needed(args, repo_name, directory_name)
print(f"Updating scripts/{directory_name} ...")
cwd = os.getcwd()
blender_git_root = Path(get_blender_git_root())
scripts_dir = blender_git_root / "scripts"
external_dir = scripts_dir / directory_name
# Update externals to appropriate given branch, falling back to main if none is given and/or
# found in a sub-repository.
branch_fallback = "main"
if not branch:
branch = branch_fallback
submodules = [
("release/scripts/addons", branch, branch_fallback),
("release/scripts/addons_contrib", branch, branch_fallback),
("release/datafiles/locale", branch, branch_fallback),
("source/tools", branch, branch_fallback),
]
# Initialize submodules only if needed.
for submodule_path, submodule_branch, submodule_branch_fallback in submodules:
if not os.path.exists(os.path.join(submodule_path, ".git")):
call([args.git_command, "submodule", "update", "--init", "--recursive"])
break
# Checkout appropriate branch and pull changes.
skip_msg = ""
for submodule_path, submodule_branch, submodule_branch_fallback in submodules:
cwd = os.getcwd()
try:
os.chdir(submodule_path)
os.chdir(external_dir)
msg = git_update_skip(args, check_remote_exists=False)
if msg:
skip_msg += submodule_path + " skipped: " + msg + "\n"
skip_msg += directory_name + " skipped: " + msg + "\n"
else:
# Find a matching branch that exists.
call([args.git_command, "fetch", "origin"])
for remote in ("origin", "upstream"):
if make_utils.git_remote_exist(args.git_command, remote):
call([args.git_command, "fetch", remote])
submodule_branch = branch
if make_utils.git_branch_exists(args.git_command, submodule_branch):
pass
elif make_utils.git_branch_exists(args.git_command, submodule_branch_fallback):
submodule_branch = submodule_branch_fallback
elif make_utils.git_branch_exists(args.git_command, branch_fallback):
submodule_branch = branch_fallback
else:
# Skip.
submodule_branch = ""
@@ -244,37 +435,59 @@ def submodules_update(
if submodule_branch:
if make_utils.git_branch(args.git_command) != submodule_branch:
call([args.git_command, "checkout", submodule_branch])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
# Don't use extra fetch since all remotes of interest have been already fetched
# some lines above.
skip_msg += work_tree_update(args, use_fetch=False)
finally:
os.chdir(cwd)
return skip_msg
def scripts_submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str:
"""Update working trees of addons and addons_contrib within the scripts/ directory"""
msg = ""
msg += external_scripts_update(args, "blender-addons", "addons", branch)
msg += external_scripts_update(args, "blender-addons-contrib", "addons_contrib", branch)
return msg
def submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str:
"""Update submodules or other externally tracked source trees"""
msg = ""
msg += scripts_submodules_update(args, branch)
return msg
if __name__ == "__main__":
args = parse_arguments()
blender_skip_msg = ""
submodules_skip_msg = ""
# Test if we are building a specific release version.
branch = make_utils.git_branch(args.git_command)
if branch == 'HEAD':
sys.stderr.write('Blender git repository is in detached HEAD state, must be in a branch\n')
sys.exit(1)
tag = make_utils.git_tag(args.git_command)
release_version = make_utils.git_branch_release_version(branch, tag)
blender_version = make_utils. parse_blender_version()
if blender_version.cycle != 'alpha':
major = blender_version.version // 100
minor = blender_version.version % 100
branch = f"blender-v{major}.{minor}-release"
release_version: Optional[str] = f"{major}.{minor}"
else:
branch = 'main'
release_version = None
if not args.no_libraries:
svn_update(args, release_version)
if not args.no_blender:
blender_skip_msg = git_update_skip(args)
if not blender_skip_msg:
blender_skip_msg = blender_update(args)
if blender_skip_msg:
blender_skip_msg = "Blender repository skipped: " + blender_skip_msg + "\n"
else:
blender_update(args)
if not args.no_submodules:
submodules_skip_msg = submodules_update(args, release_version, branch)
submodules_skip_msg = submodules_update(args, branch)
# Report any skipped repositories at the end, so it's not as easy to miss.
skip_msg = blender_skip_msg + submodules_skip_msg

View File

@@ -9,7 +9,9 @@ import re
import shutil
import subprocess
import sys
import os
from pathlib import Path
from urllib.parse import urljoin
from typing import (
Sequence,
@@ -19,7 +21,7 @@ from typing import (
def call(cmd: Sequence[str], exit_on_error: bool = True, silent: bool = False) -> int:
if not silent:
print(" ".join(cmd))
print(" ".join([str(x) for x in cmd]))
# Flush to ensure correct order output on Windows.
sys.stdout.flush()
@@ -55,10 +57,48 @@ def check_output(cmd: Sequence[str], exit_on_error: bool = True) -> str:
def git_branch_exists(git_command: str, branch: str) -> bool:
return (
call([git_command, "rev-parse", "--verify", branch], exit_on_error=False, silent=True) == 0 or
call([git_command, "rev-parse", "--verify", "remotes/upstream/" + branch], exit_on_error=False, silent=True) == 0 or
call([git_command, "rev-parse", "--verify", "remotes/origin/" + branch], exit_on_error=False, silent=True) == 0
)
def git_get_remote_url(git_command: str, remote_name: str) -> bool:
return check_output((git_command, "ls-remote", "--get-url", remote_name))
def git_remote_exist(git_command: str, remote_name: str) -> bool:
"""Check whether there is a remote with the given name"""
# `git ls-remote --get-url upstream` will print an URL if there is such remote configured, and
# otherwise will print "upstream".
remote_url = check_output((git_command, "ls-remote", "--get-url", remote_name))
return remote_url != remote_name
def git_get_resolved_submodule_url(git_command: str, blender_url: str, submodule_path: str) -> str:
git_root = check_output([git_command, "rev-parse", "--show-toplevel"])
dot_gitmodules = os.path.join(git_root, ".gitmodules")
submodule_key_prefix = f"submodule.{submodule_path}"
submodule_key_url = f"{submodule_key_prefix}.url"
gitmodule_url = git_get_config(
git_command, submodule_key_url, file=dot_gitmodules)
# A bit of a trickery to construct final URL.
# Only works for the relative submodule URLs.
#
# Note that unless the LHS URL ends up with a slash urljoin treats the last component as a
# file.
assert gitmodule_url.startswith('..')
return urljoin(blender_url + "/", gitmodule_url)
def git_is_remote_repository(git_command: str, repo: str) -> bool:
"""Returns true if the given repository is a valid/clonable git repo"""
exit_code = call((git_command, "ls-remote", repo, "HEAD"), exit_on_error=False, silent=True)
return exit_code == 0
def git_branch(git_command: str) -> str:
# Get current branch name.
try:
@@ -70,6 +110,20 @@ def git_branch(git_command: str) -> str:
return branch.strip().decode('utf8')
def git_get_config(git_command: str, key: str, file: Optional[str] = None) -> str:
if file:
return check_output([git_command, "config", "--file", file, "--get", key])
return check_output([git_command, "config", "--get", key])
def git_set_config(git_command: str, key: str, value: str, file: Optional[str] = None) -> str:
if file:
return check_output([git_command, "config", "--file", file, key, value])
return check_output([git_command, "config", key, value])
def git_tag(git_command: str) -> Optional[str]:
# Get current tag name.
try:

View File

@@ -4,9 +4,9 @@ if "%GIT%" == "" (
)
cd "%BLENDER_DIR%"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Branch_hash=%%i
cd "%BLENDER_DIR%/release/datafiles/locale"
cd "%BLENDER_DIR%/locale"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Locale_hash=%%i
cd "%BLENDER_DIR%/release/scripts/addons"
cd "%BLENDER_DIR%/scripts/addons"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Addons_Hash=%%i
cd "%BLENDER_DIR%"
:EOF

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = V3.5
PROJECT_NUMBER = V3.6
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -31,7 +31,7 @@ For an overview of BMesh data types and how they reference each other see:
Example Script
--------------
.. literalinclude:: __/__/__/release/scripts/templates_py/bmesh_simple.py
.. literalinclude:: __/__/__/scripts/templates_py/bmesh_simple.py
Standalone Module

View File

@@ -288,7 +288,7 @@ In Python, this is done by defining a class, which is a subclass of an existing
Example Operator
----------------
.. literalinclude:: __/__/__/release/scripts/templates_py/operator_simple.py
.. literalinclude:: __/__/__/scripts/templates_py/operator_simple.py
Once this script runs, ``SimpleOperator`` is registered with Blender
and can be called from Operator Search or added to the toolbar.
@@ -320,7 +320,7 @@ Example Panel
Panels are registered as a class, like an operator.
Notice the extra ``bl_`` variables used to set the context they display in.
.. literalinclude:: __/__/__/release/scripts/templates_py/ui_panel_simple.py
.. literalinclude:: __/__/__/scripts/templates_py/ui_panel_simple.py
To run the script:

View File

@@ -367,13 +367,13 @@ except ImportError:
# Note that ".." is replaced by "__" in the RST files,
# to avoid having to match Blender's source tree.
EXTRA_SOURCE_FILES = (
"../../../release/scripts/templates_py/bmesh_simple.py",
"../../../release/scripts/templates_py/gizmo_operator.py",
"../../../release/scripts/templates_py/gizmo_operator_target.py",
"../../../release/scripts/templates_py/gizmo_simple.py",
"../../../release/scripts/templates_py/operator_simple.py",
"../../../release/scripts/templates_py/ui_panel_simple.py",
"../../../release/scripts/templates_py/ui_previews_custom_icon.py",
"../../../scripts/templates_py/bmesh_simple.py",
"../../../scripts/templates_py/gizmo_operator.py",
"../../../scripts/templates_py/gizmo_operator_target.py",
"../../../scripts/templates_py/gizmo_simple.py",
"../../../scripts/templates_py/operator_simple.py",
"../../../scripts/templates_py/ui_panel_simple.py",
"../../../scripts/templates_py/ui_previews_custom_icon.py",
"../examples/bmesh.ops.1.py",
"../examples/bpy.app.translations.py",
)
@@ -1816,7 +1816,7 @@ def pyrna2sphinx(basepath):
# operators
def write_ops():
API_BASEURL = "https://projects.blender.org/blender/blender/src/branch/main/release/scripts"
API_BASEURL = "https://projects.blender.org/blender/blender/src/branch/main/scripts"
API_BASEURL_ADDON = "https://projects.blender.org/blender/blender-addons"
API_BASEURL_ADDON_CONTRIB = "https://projects.blender.org/blender/blender-addons-contrib"

View File

@@ -1676,6 +1676,9 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="and NVIDIA driver version %s or newer" % driver_version,
icon='BLANK1', translate=False)
elif device_type == 'HIP':
if True:
col.label(text="HIP temporarily disabled due to compiler bugs", icon='BLANK1')
else:
import sys
if sys.platform[:3] == "win":
driver_version = "21.Q4"

View File

@@ -94,7 +94,7 @@ void python_thread_state_restore(void **python_thread_state)
*python_thread_state = NULL;
}
static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
static const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce)
{
const char *result = PyUnicode_AsUTF8(py_str);
if (result) {
@@ -131,8 +131,8 @@ static PyObject *init_func(PyObject * /*self*/, PyObject *args)
}
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
path_init(PyC_UnicodeAsByte(path, &path_coerce),
PyC_UnicodeAsByte(user_path, &user_path_coerce));
path_init(PyC_UnicodeAsBytes(path, &path_coerce),
PyC_UnicodeAsBytes(user_path, &user_path_coerce));
Py_XDECREF(path_coerce);
Py_XDECREF(user_path_coerce);

View File

@@ -349,8 +349,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
bool use_light_tree = get_boolean(cscene, "use_light_tree");
integrator->set_use_light_tree(use_light_tree);
integrator->set_light_sampling_threshold(
(use_light_tree) ? 0.0f : get_float(cscene, "light_sampling_threshold"));
integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold"));
if (integrator->use_light_tree_is_modified()) {
scene->light_manager->tag_update(scene, LightManager::UPDATE_ALL);

View File

@@ -42,12 +42,15 @@ endif()
###########################################################################
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
find_package(HIP)
set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
set(WITH_CYCLES_HIP_BINARIES OFF)
message(STATUS "HIP temporarily disabled due to compiler bugs")
if(HIP_FOUND)
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
endif()
# find_package(HIP)
# set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
# if(HIP_FOUND)
# message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
# endif()
endif()
if(NOT WITH_HIP_DYNLOAD)

View File

@@ -55,9 +55,8 @@ void device_metal_info(vector<DeviceInfo> &devices)
info.denoisers = DENOISER_NONE;
info.id = id;
if (MetalInfo::get_device_vendor(device) == METAL_GPU_AMD) {
info.has_light_tree = false;
}
info.has_nanovdb = MetalInfo::get_device_vendor(device) == METAL_GPU_APPLE;
info.has_light_tree = MetalInfo::get_device_vendor(device) != METAL_GPU_AMD;
devices.push_back(info);
device_index++;

View File

@@ -67,9 +67,12 @@ class MetalDevice : public Device {
std::recursive_mutex metal_mem_map_mutex;
/* Bindless Textures */
bool is_texture(const TextureInfo &tex);
device_vector<TextureInfo> texture_info;
bool need_texture_info;
id<MTLArgumentEncoder> mtlTextureArgEncoder = nil;
id<MTLArgumentEncoder> mtlBufferArgEncoder = nil;
id<MTLBuffer> buffer_bindings_1d = nil;
id<MTLBuffer> texture_bindings_2d = nil;
id<MTLBuffer> texture_bindings_3d = nil;
std::vector<id<MTLTexture>> texture_slot_map;

View File

@@ -91,11 +91,6 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
}
}
texture_bindings_2d = [mtlDevice newBufferWithLength:4096 options:default_storage_mode];
texture_bindings_3d = [mtlDevice newBufferWithLength:4096 options:default_storage_mode];
stats.mem_alloc(texture_bindings_2d.allocatedSize + texture_bindings_3d.allocatedSize);
switch (device_vendor) {
default:
break;
@@ -156,6 +151,16 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
arg_desc_texture.dataType = MTLDataTypeTexture;
arg_desc_texture.access = MTLArgumentAccessReadOnly;
mtlTextureArgEncoder = [mtlDevice newArgumentEncoderWithArguments:@[ arg_desc_texture ]];
MTLArgumentDescriptor *arg_desc_buffer = [[MTLArgumentDescriptor alloc] init];
arg_desc_buffer.dataType = MTLDataTypePointer;
arg_desc_buffer.access = MTLArgumentAccessReadOnly;
mtlBufferArgEncoder = [mtlDevice newArgumentEncoderWithArguments:@[ arg_desc_buffer ]];
buffer_bindings_1d = [mtlDevice newBufferWithLength:8192 options:default_storage_mode];
texture_bindings_2d = [mtlDevice newBufferWithLength:8192 options:default_storage_mode];
texture_bindings_3d = [mtlDevice newBufferWithLength:8192 options:default_storage_mode];
stats.mem_alloc(buffer_bindings_1d.allocatedSize + texture_bindings_2d.allocatedSize +
texture_bindings_3d.allocatedSize);
/* command queue for non-tracing work on the GPU */
mtlGeneralCommandQueue = [mtlDevice newCommandQueue];
@@ -180,6 +185,8 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
arg_desc_tex.dataType = MTLDataTypePointer;
arg_desc_tex.access = MTLArgumentAccessReadOnly;
arg_desc_tex.index = index++;
[ancillary_desc addObject:[arg_desc_tex copy]]; /* metal_buf_1d */
arg_desc_tex.index = index++;
[ancillary_desc addObject:[arg_desc_tex copy]]; /* metal_tex_2d */
arg_desc_tex.index = index++;
@@ -225,11 +232,15 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
mtlAncillaryArgEncoder = [mtlDevice newArgumentEncoderWithArguments:ancillary_desc];
// preparing the blas arg encoder
if (@available(macos 11.0, *)) {
if (use_metalrt) {
MTLArgumentDescriptor *arg_desc_blas = [[MTLArgumentDescriptor alloc] init];
arg_desc_blas.dataType = MTLDataTypeInstanceAccelerationStructure;
arg_desc_blas.access = MTLArgumentAccessReadOnly;
mtlBlasArgEncoder = [mtlDevice newArgumentEncoderWithArguments:@[ arg_desc_blas ]];
[arg_desc_blas release];
}
}
for (int i = 0; i < ancillary_desc.count; i++) {
[ancillary_desc[i] release];
@@ -249,22 +260,26 @@ MetalDevice::~MetalDevice()
* existing_devices_mutex). */
thread_scoped_lock lock(existing_devices_mutex);
for (auto &tex : texture_slot_map) {
if (tex) {
[tex release];
tex = nil;
int num_resources = texture_info.size();
for (int res = 0; res < num_resources; res++) {
if (is_texture(texture_info[res])) {
[texture_slot_map[res] release];
texture_slot_map[res] = nil;
}
}
flush_delayed_free_list();
if (texture_bindings_2d) {
stats.mem_free(texture_bindings_2d.allocatedSize + texture_bindings_3d.allocatedSize);
stats.mem_free(buffer_bindings_1d.allocatedSize + texture_bindings_2d.allocatedSize +
texture_bindings_3d.allocatedSize);
[buffer_bindings_1d release];
[texture_bindings_2d release];
[texture_bindings_3d release];
}
[mtlTextureArgEncoder release];
[mtlBufferKernelParamsEncoder release];
[mtlBufferArgEncoder release];
[mtlASArgEncoder release];
[mtlAncillaryArgEncoder release];
[mtlGeneralCommandQueue release];
@@ -328,6 +343,9 @@ void MetalDevice::make_source(MetalPipelineType pso_type, const uint kernel_feat
break;
case METAL_GPU_APPLE:
global_defines += "#define __KERNEL_METAL_APPLE__\n";
# ifdef WITH_NANOVDB
global_defines += "#define WITH_NANOVDB\n";
# endif
break;
}
@@ -542,6 +560,11 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
}
}
bool MetalDevice::is_texture(const TextureInfo &tex)
{
return (tex.depth > 0 || tex.height > 0);
}
void MetalDevice::load_texture_info()
{
if (need_texture_info) {
@@ -553,21 +576,20 @@ void MetalDevice::load_texture_info()
for (int tex = 0; tex < num_textures; tex++) {
uint64_t offset = tex * sizeof(void *);
if (is_texture(texture_info[tex]) && texture_slot_map[tex]) {
id<MTLTexture> metal_texture = texture_slot_map[tex];
if (!metal_texture) {
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_2d offset:offset];
[mtlTextureArgEncoder setTexture:nil atIndex:0];
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_3d offset:offset];
[mtlTextureArgEncoder setTexture:nil atIndex:0];
}
else {
MTLTextureType type = metal_texture.textureType;
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_2d offset:offset];
[mtlTextureArgEncoder setTexture:type == MTLTextureType2D ? metal_texture : nil atIndex:0];
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_3d offset:offset];
[mtlTextureArgEncoder setTexture:type == MTLTextureType3D ? metal_texture : nil atIndex:0];
}
else {
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_2d offset:offset];
[mtlTextureArgEncoder setTexture:nil atIndex:0];
[mtlTextureArgEncoder setArgumentBuffer:texture_bindings_3d offset:offset];
[mtlTextureArgEncoder setTexture:nil atIndex:0];
}
}
if (default_storage_mode == MTLResourceStorageModeManaged) {
[texture_bindings_2d didModifyRange:NSMakeRange(0, num_textures * sizeof(void *))];
@@ -740,7 +762,6 @@ void MetalDevice::generic_free(device_memory &mem)
mem.shared_pointer = 0;
/* Free device memory. */
delayed_free_list.push_back(mmem.mtlBuffer);
mmem.mtlBuffer = nil;
}
@@ -975,7 +996,7 @@ void MetalDevice::global_free(device_memory &mem)
void MetalDevice::tex_alloc_as_buffer(device_texture &mem)
{
generic_alloc(mem);
MetalDevice::MetalMem *mmem = generic_alloc(mem);
generic_copy_to(mem);
/* Resize once */
@@ -984,19 +1005,24 @@ void MetalDevice::tex_alloc_as_buffer(device_texture &mem)
/* Allocate some slots in advance, to reduce amount
* of re-allocations. */
texture_info.resize(round_up(slot + 1, 128));
texture_slot_map.resize(round_up(slot + 1, 128));
}
mem.info.data = (uint64_t)mem.device_pointer;
/* Set Mapping and tag that we need to (re-)upload to device */
texture_info[slot] = mem.info;
uint64_t offset = slot * sizeof(void *);
[mtlBufferArgEncoder setArgumentBuffer:buffer_bindings_1d offset:offset];
[mtlBufferArgEncoder setBuffer:mmem->mtlBuffer offset:0 atIndex:0];
texture_info[slot].data = *(uint64_t *)((uint64_t)buffer_bindings_1d.contents + offset);
texture_slot_map[slot] = nil;
need_texture_info = true;
}
void MetalDevice::tex_alloc(device_texture &mem)
{
/* Check that dimensions fit within maximum allowable size.
* If 1D texture is allocated, use 1D buffer.
* See: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
if (mem.data_height > 0) {
if (mem.data_width > 16384 || mem.data_height > 16384) {
set_error(string_printf(
"Texture exceeds maximum allowed size of 16384 x 16384 (requested: %zu x %zu)",
@@ -1004,7 +1030,7 @@ void MetalDevice::tex_alloc(device_texture &mem)
mem.data_height));
return;
}
}
MTLStorageMode storage_mode = MTLStorageModeManaged;
if (@available(macos 10.15, *)) {
if ([mtlDevice hasUnifiedMemory] &&
@@ -1144,8 +1170,9 @@ void MetalDevice::tex_alloc(device_texture &mem)
bytesPerRow:src_pitch];
}
else {
assert(0);
/* 1D texture, using linear memory. */
tex_alloc_as_buffer(mem);
return;
}
mem.device_pointer = (device_ptr)mtlTexture;
@@ -1169,17 +1196,22 @@ void MetalDevice::tex_alloc(device_texture &mem)
ssize_t min_buffer_length = sizeof(void *) * texture_info.size();
if (!texture_bindings_2d || (texture_bindings_2d.length < min_buffer_length)) {
if (texture_bindings_2d) {
delayed_free_list.push_back(buffer_bindings_1d);
delayed_free_list.push_back(texture_bindings_2d);
delayed_free_list.push_back(texture_bindings_3d);
stats.mem_free(texture_bindings_2d.allocatedSize + texture_bindings_3d.allocatedSize);
stats.mem_free(buffer_bindings_1d.allocatedSize + texture_bindings_2d.allocatedSize +
texture_bindings_3d.allocatedSize);
}
buffer_bindings_1d = [mtlDevice newBufferWithLength:min_buffer_length
options:default_storage_mode];
texture_bindings_2d = [mtlDevice newBufferWithLength:min_buffer_length
options:default_storage_mode];
texture_bindings_3d = [mtlDevice newBufferWithLength:min_buffer_length
options:default_storage_mode];
stats.mem_alloc(texture_bindings_2d.allocatedSize + texture_bindings_3d.allocatedSize);
stats.mem_alloc(buffer_bindings_1d.allocatedSize + texture_bindings_2d.allocatedSize +
texture_bindings_3d.allocatedSize);
}
}
@@ -1206,11 +1238,17 @@ void MetalDevice::tex_alloc(device_texture &mem)
void MetalDevice::tex_free(device_texture &mem)
{
if (mem.data_depth == 0 && mem.data_height == 0) {
generic_free(mem);
return;
}
if (metal_mem_map.count(&mem)) {
std::lock_guard<std::recursive_mutex> lock(metal_mem_map_mutex);
MetalMem &mmem = *metal_mem_map.at(&mem);
assert(texture_slot_map[mem.slot] == mmem.mtlTexture);
if (texture_slot_map[mem.slot] == mmem.mtlTexture)
texture_slot_map[mem.slot] = nil;
if (mmem.mtlTexture) {

View File

@@ -477,17 +477,21 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->texture_bindings_3d
offset:0
atIndex:1];
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->buffer_bindings_1d
offset:0
atIndex:2];
if (@available(macos 12.0, *)) {
if (metal_device_->use_metalrt) {
if (metal_device_->bvhMetalRT) {
id<MTLAccelerationStructure> accel_struct = metal_device_->bvhMetalRT->accel_struct;
[metal_device_->mtlAncillaryArgEncoder setAccelerationStructure:accel_struct atIndex:2];
[metal_device_->mtlAncillaryArgEncoder setAccelerationStructure:accel_struct atIndex:3];
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->blas_buffer
offset:0
atIndex:7];
atIndex:8];
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->blas_lookup_buffer
offset:0
atIndex:8];
atIndex:9];
}
for (int table = 0; table < METALRT_TABLE_NUM; table++) {
@@ -497,13 +501,13 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
atIndex:1];
[metal_device_->mtlAncillaryArgEncoder
setIntersectionFunctionTable:metal_kernel_pso->intersection_func_table[table]
atIndex:3 + table];
atIndex:4 + table];
[mtlComputeCommandEncoder useResource:metal_kernel_pso->intersection_func_table[table]
usage:MTLResourceUsageRead];
}
else {
[metal_device_->mtlAncillaryArgEncoder setIntersectionFunctionTable:nil
atIndex:3 + table];
atIndex:4 + table];
}
}
}
@@ -874,6 +878,7 @@ void MetalDeviceQueue::prepare_resources(DeviceKernel kernel)
/* ancillaries */
[mtlComputeEncoder_ useResource:metal_device_->texture_bindings_2d usage:MTLResourceUsageRead];
[mtlComputeEncoder_ useResource:metal_device_->texture_bindings_3d usage:MTLResourceUsageRead];
[mtlComputeEncoder_ useResource:metal_device_->buffer_bindings_1d usage:MTLResourceUsageRead];
}
id<MTLComputeCommandEncoder> MetalDeviceQueue::get_compute_encoder(DeviceKernel kernel)

View File

@@ -5,13 +5,14 @@
CCL_NAMESPACE_BEGIN
#if !defined __KERNEL_METAL__
# ifdef WITH_NANOVDB
# define NDEBUG /* Disable "assert" in device code */
# define NANOVDB_USE_INTRINSICS
# include "nanovdb/NanoVDB.h"
# include "nanovdb/util/SampleFromVoxels.h"
# endif
#endif
/* w0, w1, w2, and w3 are the four cubic B-spline basis functions. */
ccl_device float cubic_w0(float a)
{
@@ -126,7 +127,7 @@ kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, fl
#ifdef WITH_NANOVDB
template<typename T, typename S>
ccl_device typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_tricubic_nanovdb(
S &s, float x, float y, float z)
ccl_private S &s, float x, float y, float z)
{
float px = floorf(x);
float py = floorf(y);
@@ -157,13 +158,19 @@ ccl_device typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_tric
g1y * (g0x * s(Vec3f(x0, y1, z1)) + g1x * s(Vec3f(x1, y1, z1))));
}
# if defined(__KERNEL_METAL__)
template<typename T>
__attribute__((noinline)) typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_nanovdb(
ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
# else
template<typename T>
ccl_device_noinline typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_nanovdb(
ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
# endif
{
using namespace nanovdb;
NanoGrid<T> *const grid = (NanoGrid<T> *)info.data;
ccl_global NanoGrid<T> *const grid = (ccl_global NanoGrid<T> *)info.data;
typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType;
AccessorType acc = grid->getAccessor();

View File

@@ -290,6 +290,10 @@ typedef metal::raytracing::intersector<triangle_data> metalrt_blas_intersector_t
/* texture bindings and sampler setup */
struct Buffer1DParamsMetal {
device float *buf;
};
struct Texture2DParamsMetal {
texture2d<float, access::sample> tex;
};
@@ -306,6 +310,7 @@ struct MetalRTBlasWrapper {
struct MetalAncillaries {
device Texture2DParamsMetal *textures_2d;
device Texture3DParamsMetal *textures_3d;
device Buffer1DParamsMetal *buffers;
#ifdef __METALRT__
metalrt_as_type accel_struct;

View File

@@ -3,6 +3,13 @@
// clang-format off
#ifdef WITH_NANOVDB
# define NDEBUG /* Disable "assert" in device code */
# define NANOVDB_USE_INTRINSICS
# include "nanovdb/NanoVDB.h"
# include "nanovdb/util/SampleFromVoxels.h"
#endif
/* Open the Metal kernel context class
* Necessary to access resource bindings */
class MetalKernelContext {

View File

@@ -122,7 +122,7 @@ KERNEL_STRUCT_MEMBER(guiding, bool, use_surface_guiding, KERNEL_FEATURE_PATH_GUI
KERNEL_STRUCT_MEMBER(guiding, float, sample_surface_guiding_rand, KERNEL_FEATURE_PATH_GUIDING)
/* The probability to use surface guiding (i.e., diffuse sampling prob * guiding prob)*/
KERNEL_STRUCT_MEMBER(guiding, float, surface_guiding_sampling_prob, KERNEL_FEATURE_PATH_GUIDING)
/* Probability of sampling a BSSRDF closure instead of a BSDF closure*/
/* Probability of sampling a BSSRDF closure instead of a BSDF closure. */
KERNEL_STRUCT_MEMBER(guiding, float, bssrdf_sampling_prob, KERNEL_FEATURE_PATH_GUIDING)
/* If volume guiding is enabled */
KERNEL_STRUCT_MEMBER(guiding, bool, use_volume_guiding, KERNEL_FEATURE_PATH_GUIDING)

View File

@@ -113,13 +113,16 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
{
int prim;
MeshLight mesh_light;
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
emitter_index);
prim = kemitter->prim;
mesh_light = kemitter->mesh_light;
}
else {
else
#endif
{
ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
light_distribution, emitter_index);
prim = kdistribution->prim;

View File

@@ -255,8 +255,10 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->scrambling_distance = scrambling_distance;
kintegrator->sobol_index_mask = reverse_integer_bits(next_power_of_two(aa_samples - 1) - 1);
kintegrator->use_light_tree = scene->integrator->use_light_tree;
if (light_sampling_threshold > 0.0f) {
/* NOTE: The kintegrator->use_light_tree is assigned to the efficient value in the light manager,
* and the synchronization code is expected to tag the light manager for update when the
* `use_light_tree` is changed. */
if (light_sampling_threshold > 0.0f && !kintegrator->use_light_tree) {
kintegrator->light_inv_rr_threshold = scene->film->get_exposure() / light_sampling_threshold;
}
else {

View File

@@ -1177,7 +1177,7 @@ void LightManager::device_update(Device *device,
void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_background)
{
/* to-do: check if the light tree member variables need to be wrapped in a conditional too*/
/* TODO: check if the light tree member variables need to be wrapped in a conditional too. */
dscene->light_tree_nodes.free();
dscene->light_tree_emitters.free();
dscene->light_to_tree.free();

View File

@@ -1195,24 +1195,89 @@ int GHOST_XrGetControllerModelData(GHOST_XrContextHandle xr_context,
#ifdef WITH_VULKAN_BACKEND
/**
* Return VULKAN handles for the given context.
* Get Vulkan handles for the given context.
*
* These handles are the same for a given context.
* Should should only be called when using a Vulkan context.
* Other contexts will not return any handles and leave the
* handles where the parameters are referring to unmodified.
*
* \param context: GHOST context handle of a vulkan context to
* get the Vulkan handles from.
* \param r_instance: After calling this function the VkInstance
* referenced by this parameter will contain the VKInstance handle
* of the context associated with the `context` parameter.
* \param r_physical_device: After calling this function the VkPhysicalDevice
* referenced by this parameter will contain the VKPhysicalDevice handle
* of the context associated with the `context` parameter.
* \param r_device: After calling this function the VkDevice
* referenced by this parameter will contain the VKDevice handle
* of the context associated with the `context` parameter.
* \param r_graphic_queue_family: After calling this function the uint32_t
* referenced by this parameter will contain the graphic queue family id
* of the context associated with the `context` parameter.
* \param r_queue: After calling this function the VkQueue
* referenced by this parameter will contain the VKQueue handle
* of the context associated with the `context` parameter.
*/
void GHOST_GetVulkanHandles(GHOST_ContextHandle context,
void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family);
uint32_t *r_graphic_queue_family,
void *r_queue);
/**
* Return VULKAN back-buffer resources handles for the given window.
* Return Vulkan command buffer.
*
* Command buffers are different for each image in the swap chain.
* At the start of each frame the correct command buffer should be
* retrieved with this function.
*
* Should should only be called when using a Vulkan context.
* Other contexts will not return any handles and leave the
* handles where the parameters are referring to unmodified.
*
* \param context: GHOST context handle to a vulkan context to get the
* command queue from.
* \param r_command_buffer: After calling this function the VkCommandBuffer
* referenced by this parameter will contain the VKCommandBuffer handle
* of the current back buffer (when swap chains are enabled) or
* it will contain a general VkCommandQueue.
*/
void GHOST_GetVulkanCommandBuffer(GHOST_ContextHandle context, void *r_command_buffer);
/**
* Gets the Vulkan backbuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap event as the backbuffer will change.
*
* Should should only be called when using a Vulkan context with an active swap chain.
* Other contexts will not return any handles and leave the
* handles where the parameters are referring to unmodified.
*
* \param windowhandle: GHOST window handle to a window to get the resource from.
* \param r_image: After calling this function the VkImage
* referenced by this parameter will contain the VKImage handle
* of the current back buffer.
* \param r_framebuffer: After calling this function the VkFramebuffer
* referenced by this parameter will contain the VKFramebuffer handle
* of the current back buffer.
* \param r_render_pass: After calling this function the VkRenderPass
* referenced by this parameter will contain the VKRenderPass handle
* of the current back buffer.
* \param r_extent: After calling this function the VkExtent2D
* referenced by this parameter will contain the size of the
* frame buffer and image in pixels.
* \param r_fb_id: After calling this function the uint32_t
* referenced by this parameter will contain the id of the
* framebuffer of the current back buffer.
*/
void GHOST_GetVulkanBackbuffer(GHOST_WindowHandle windowhandle,
void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id);
void *r_image,
void *r_framebuffer,
void *r_render_pass,
void *r_extent,
uint32_t *r_fb_id);
#endif

View File

@@ -40,19 +40,84 @@ class GHOST_IContext {
virtual unsigned int getDefaultFramebuffer() = 0;
virtual GHOST_TSuccess getVulkanHandles(void *, void *, void *, uint32_t *) = 0;
/**
* Get Vulkan handles for the given context.
*
* These handles are the same for a given context.
* Should should only be called when using a Vulkan context.
* Other contexts will not return any handles and leave the
* handles where the parameters are referring to unmodified.
*
* \param r_instance: After calling this function the VkInstance
* referenced by this parameter will contain the VKInstance handle
* of the context associated with the `context` parameter.
* \param r_physical_device: After calling this function the VkPhysicalDevice
* referenced by this parameter will contain the VKPhysicalDevice handle
* of the context associated with the `context` parameter.
* \param r_device: After calling this function the VkDevice
* referenced by this parameter will contain the VKDevice handle
* of the context associated with the `context` parameter.
* \param r_graphic_queue_family: After calling this function the uint32_t
* referenced by this parameter will contain the graphic queue family id
* of the context associated with the `context` parameter.
* \param r_queue: After calling this function the VkQueue
* referenced by this parameter will contain the VKQueue handle
* of the context associated with the `context` parameter.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanHandles(void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family,
void *r_queue) = 0;
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
* Return Vulkan command buffer.
*
* Command buffers are different for each image in the swap chain.
* At the start of each frame the correct command buffer should be
* retrieved with this function.
*
* \param r_command_buffer: After calling this function the VkCommandBuffer
* referenced by this parameter will contain the VKCommandBuffer handle
* of the current back buffer (when swap chains are enabled) or
* it will contain a general VkCommandQueue.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id) = 0;
virtual GHOST_TSuccess getVulkanCommandBuffer(void *r_command_buffer) = 0;
/**
* Gets the Vulkan backbuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap event as the backbuffer will change.
*
* \param r_image: After calling this function the VkImage
* referenced by this parameter will contain the VKImage handle
* of the current back buffer.
* \param r_framebuffer: After calling this function the VkFramebuffer
* referenced by this parameter will contain the VKFramebuffer handle
* of the current back buffer.
* \param r_render_pass: After calling this function the VkRenderPass
* referenced by this parameter will contain the VKRenderPass handle
* of the current back buffer.
* \param r_extent: After calling this function the VkExtent2D
* referenced by this parameter will contain the size of the
* frame buffer and image in pixels.
* \param r_fb_id: After calling this function the uint32_t
* referenced by this parameter will contain the id of the
* framebuffer of the current back buffer.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void *r_image,
void *r_framebuffer,
void *r_render_pass,
void *r_extent,
uint32_t *r_fb_id) = 0;
virtual GHOST_TSuccess swapBuffers() = 0;

View File

@@ -217,7 +217,6 @@ class GHOST_IWindow {
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id) = 0;

View File

@@ -1203,22 +1203,29 @@ void GHOST_GetVulkanHandles(GHOST_ContextHandle contexthandle,
void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family)
uint32_t *r_graphic_queue_family,
void *r_queue)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
context->getVulkanHandles(r_instance, r_physical_device, r_device, r_graphic_queue_family);
context->getVulkanHandles(
r_instance, r_physical_device, r_device, r_graphic_queue_family, r_queue);
}
void GHOST_GetVulkanCommandBuffer(GHOST_ContextHandle contexthandle, void *r_command_buffer)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
context->getVulkanCommandBuffer(r_command_buffer);
}
void GHOST_GetVulkanBackbuffer(GHOST_WindowHandle windowhandle,
void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
window->getVulkanBackbuffer(image, framebuffer, command_buffer, render_pass, extent, fb_id);
window->getVulkanBackbuffer(image, framebuffer, render_pass, extent, fb_id);
}
#endif /* WITH_VULKAN */

View File

@@ -136,27 +136,88 @@ class GHOST_Context : public GHOST_IContext {
}
/**
* Gets the Vulkan context related resource handles.
* \return A boolean success indicator.
* Get Vulkan handles for the given context.
*
* These handles are the same for a given context.
* Should should only be called when using a Vulkan context.
* Other contexts will not return any handles and leave the
* handles where the parameters are referring to unmodified.
*
* \param r_instance: After calling this function the VkInstance
* referenced by this parameter will contain the VKInstance handle
* of the context associated with the `context` parameter.
* \param r_physical_device: After calling this function the VkPhysicalDevice
* referenced by this parameter will contain the VKPhysicalDevice handle
* of the context associated with the `context` parameter.
* \param r_device: After calling this function the VkDevice
* referenced by this parameter will contain the VKDevice handle
* of the context associated with the `context` parameter.
* \param r_graphic_queue_family: After calling this function the uint32_t
* referenced by this parameter will contain the graphic queue family id
* of the context associated with the `context` parameter.
* \param r_queue: After calling this function the VkQueue
* referenced by this parameter will contain the VKQueue handle
* of the context associated with the `context` parameter.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanHandles(void * /*r_instance*/,
void * /*r_physical_device*/,
void * /*r_device*/,
uint32_t * /*r_graphic_queue_family*/) override
uint32_t * /*r_graphic_queue_family*/,
void * /*r_queue*/) override
{
return GHOST_kFailure;
};
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
* Return Vulkan command buffer.
*
* Command buffers are different for each image in the swap chain.
* At the start of each frame the correct command buffer should be
* retrieved with this function.
*
* \param r_command_buffer: After calling this function the VkCommandBuffer
* referenced by this parameter will contain the VKCommandBuffer handle
* of the current back buffer (when swap chains are enabled) or
* it will contain a general VkCommandQueue.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void * /*image*/,
void * /*framebuffer*/,
void * /*command_buffer*/,
void * /*render_pass*/,
void * /*extent*/,
virtual GHOST_TSuccess getVulkanCommandBuffer(void * /*r_command_buffer*/) override
{
return GHOST_kFailure;
};
/**
* Gets the Vulkan backbuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap event as the backbuffer will change.
*
* \param r_image: After calling this function the VkImage
* referenced by this parameter will contain the VKImage handle
* of the current back buffer.
* \param r_framebuffer: After calling this function the VkFramebuffer
* referenced by this parameter will contain the VKFramebuffer handle
* of the current back buffer.
* \param r_render_pass: After calling this function the VkRenderPass
* referenced by this parameter will contain the VKRenderPass handle
* of the current back buffer.
* \param r_extent: After calling this function the VkExtent2D
* referenced by this parameter will contain the size of the
* frame buffer and image in pixels.
* \param r_fb_id: After calling this function the uint32_t
* referenced by this parameter will contain the id of the
* framebuffer of the current back buffer.
* \returns GHOST_kFailure when context isn't a Vulkan context.
* GHOST_kSuccess when the context is a Vulkan context and the
* handles have been set.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void * /*r_image*/,
void * /*r_framebuffer*/,
void * /*r_render_pass*/,
void * /*r_extent*/,
uint32_t * /*fb_id*/) override
{
return GHOST_kFailure;

View File

@@ -288,19 +288,14 @@ GHOST_TSuccess GHOST_ContextVK::swapBuffers()
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextVK::getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id)
GHOST_TSuccess GHOST_ContextVK::getVulkanBackbuffer(
void *image, void *framebuffer, void *render_pass, void *extent, uint32_t *fb_id)
{
if (m_swapchain == VK_NULL_HANDLE) {
return GHOST_kFailure;
}
*((VkImage *)image) = m_swapchain_images[m_currentImage];
*((VkFramebuffer *)framebuffer) = m_swapchain_framebuffers[m_currentImage];
*((VkCommandBuffer *)command_buffer) = m_command_buffers[m_currentImage];
*((VkRenderPass *)render_pass) = m_render_pass;
*((VkExtent2D *)extent) = m_render_extent;
*fb_id = m_swapchain_id * 10 + m_currentFrame;
@@ -311,12 +306,30 @@ GHOST_TSuccess GHOST_ContextVK::getVulkanBackbuffer(void *image,
GHOST_TSuccess GHOST_ContextVK::getVulkanHandles(void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family)
uint32_t *r_graphic_queue_family,
void *r_queue)
{
*((VkInstance *)r_instance) = m_instance;
*((VkPhysicalDevice *)r_physical_device) = m_physical_device;
*((VkDevice *)r_device) = m_device;
*r_graphic_queue_family = m_queue_family_graphic;
*((VkQueue *)r_queue) = m_graphic_queue;
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextVK::getVulkanCommandBuffer(void *r_command_buffer)
{
if (m_command_buffers.empty()) {
return GHOST_kFailure;
}
if (m_swapchain == VK_NULL_HANDLE) {
*((VkCommandBuffer *)r_command_buffer) = m_command_buffers[0];
}
else {
*((VkCommandBuffer *)r_command_buffer) = m_command_buffers[m_currentImage];
}
return GHOST_kSuccess;
}
@@ -520,6 +533,9 @@ static GHOST_TSuccess getGraphicQueueFamily(VkPhysicalDevice device, uint32_t *r
*r_queue_index = 0;
for (const auto &queue_family : queue_families) {
/* Every vulkan implementation by spec must have one queue family that support both graphics
* and compute pipelines. We select this one; compute only queue family hints at async compute
* implementations.*/
if ((queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) &&
(queue_family.queueFlags & VK_QUEUE_COMPUTE_BIT)) {
return GHOST_kSuccess;
@@ -619,16 +635,36 @@ static GHOST_TSuccess selectPresentMode(VkPhysicalDevice device,
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ContextVK::createCommandBuffers()
GHOST_TSuccess GHOST_ContextVK::createCommandPools()
{
m_command_buffers.resize(m_swapchain_image_views.size());
VkCommandPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = m_queue_family_graphic;
VK_CHECK(vkCreateCommandPool(m_device, &poolInfo, NULL, &m_command_pool));
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextVK::createGraphicsCommandBuffer()
{
assert(m_command_pool != VK_NULL_HANDLE);
assert(m_command_buffers.size() == 0);
m_command_buffers.resize(1);
VkCommandBufferAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
alloc_info.commandPool = m_command_pool;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandBufferCount = static_cast<uint32_t>(m_command_buffers.size());
VK_CHECK(vkAllocateCommandBuffers(m_device, &alloc_info, m_command_buffers.data()));
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextVK::createGraphicsCommandBuffers()
{
assert(m_command_pool != VK_NULL_HANDLE);
m_command_buffers.resize(m_swapchain_image_views.size());
VkCommandBufferAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@@ -637,7 +673,6 @@ GHOST_TSuccess GHOST_ContextVK::createCommandBuffers()
alloc_info.commandBufferCount = static_cast<uint32_t>(m_command_buffers.size());
VK_CHECK(vkAllocateCommandBuffers(m_device, &alloc_info, m_command_buffers.data()));
return GHOST_kSuccess;
}
@@ -776,7 +811,7 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
VK_CHECK(vkCreateFence(m_device, &fence_info, NULL, &m_in_flight_fences[i]));
}
createCommandBuffers();
createGraphicsCommandBuffers();
return GHOST_kSuccess;
}
@@ -841,6 +876,13 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
extensions_device.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
extensions_device.push_back("VK_KHR_dedicated_allocation");
extensions_device.push_back("VK_KHR_get_memory_requirements2");
/* Enable MoltenVK required instance extensions.*/
#ifdef VK_MVK_MOLTENVK_EXTENSION_NAME
requireExtension(
extensions_available, extensions_enabled, "VK_KHR_get_physical_device_properties2");
#endif
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -903,6 +945,15 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
return GHOST_kFailure;
}
#ifdef VK_MVK_MOLTENVK_EXTENSION_NAME
/* According to the Vulkan specs, when `VK_KHR_portability_subset` is available it should be
* enabled. See
* https://vulkan.lunarg.com/doc/view/1.2.198.1/mac/1.2-extensions/vkspec.html#VUID-VkDeviceCreateInfo-pProperties-04451*/
if (device_extensions_support(m_physical_device, {VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME})) {
extensions_device.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
}
#endif
vector<VkDeviceQueueCreateInfo> queue_create_infos;
{
@@ -962,11 +1013,14 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
vkGetDeviceQueue(m_device, m_queue_family_graphic, 0, &m_graphic_queue);
createCommandPools();
if (use_window_surface) {
vkGetDeviceQueue(m_device, m_queue_family_present, 0, &m_present_queue);
createSwapchain();
}
else {
createGraphicsCommandBuffer();
}
return GHOST_kSuccess;
}

View File

@@ -113,18 +113,17 @@ class GHOST_ContextVK : public GHOST_Context {
GHOST_TSuccess getVulkanHandles(void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_family);
uint32_t *r_graphic_queue_family,
void *r_queue);
GHOST_TSuccess getVulkanCommandBuffer(void *r_command_buffer);
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id);
GHOST_TSuccess getVulkanBackbuffer(
void *image, void *framebuffer, void *render_pass, void *extent, uint32_t *fb_id);
/**
* Sets the swap interval for swapBuffers.
@@ -200,6 +199,8 @@ class GHOST_ContextVK : public GHOST_Context {
GHOST_TSuccess pickPhysicalDevice(std::vector<const char *> required_exts);
GHOST_TSuccess createSwapchain();
GHOST_TSuccess destroySwapchain();
GHOST_TSuccess createCommandBuffers();
GHOST_TSuccess createCommandPools();
GHOST_TSuccess createGraphicsCommandBuffers();
GHOST_TSuccess createGraphicsCommandBuffer();
GHOST_TSuccess recordCommandBuffers();
};

View File

@@ -109,13 +109,12 @@ uint GHOST_Window::getDefaultFramebuffer()
GHOST_TSuccess GHOST_Window::getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id)
{
return m_context->getVulkanBackbuffer(
image, framebuffer, command_buffer, render_pass, extent, fb_id);
image, framebuffer, render_pass, extent, fb_id);
}
GHOST_TSuccess GHOST_Window::activateDrawingContext()

View File

@@ -274,12 +274,8 @@ class GHOST_Window : public GHOST_IWindow {
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id) override;
virtual GHOST_TSuccess getVulkanBackbuffer(
void *image, void *framebuffer, void *render_pass, void *extent, uint32_t *fb_id) override;
/**
* Returns the window user data.

View File

@@ -306,14 +306,23 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win);
#ifdef USE_EVENT_BACKGROUND_THREAD
enum eGWL_PendingWindowActions {
PENDING_FRAME_CONFIGURE = 0,
PENDING_EGL_RESIZE,
/**
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
*/
PENDING_WINDOW_FRAME_CONFIGURE = 0,
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
PENDING_EGL_WINDOW_RESIZE,
# ifdef GHOST_OPENGL_ALPHA
/** Draw an opaque region behind the window. */
PENDING_OPAQUE_SET,
# endif
PENDING_SCALE_UPDATE,
/**
* The DPI for a monitor has changed or the monitors (outputs)
* this window is visible on may have changed. Recalculate the windows scale.
*/
PENDING_OUTPUT_SCALE_UPDATE,
};
# define PENDING_NUM (PENDING_SCALE_UPDATE + 1)
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
{
@@ -323,10 +332,10 @@ static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWin
static void gwl_window_pending_actions_handle(GWL_Window *win)
{
if (win->pending_actions[PENDING_FRAME_CONFIGURE].exchange(false)) {
if (win->pending_actions[PENDING_WINDOW_FRAME_CONFIGURE].exchange(false)) {
gwl_window_frame_update_from_pending(win);
}
if (win->pending_actions[PENDING_EGL_RESIZE].exchange(false)) {
if (win->pending_actions[PENDING_EGL_WINDOW_RESIZE].exchange(false)) {
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
}
# ifdef GHOST_OPENGL_ALPHA
@@ -334,7 +343,7 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
win->ghost_window->setOpaque();
}
# endif
if (win->pending_actions[PENDING_SCALE_UPDATE].exchange(false)) {
if (win->pending_actions[PENDING_OUTPUT_SCALE_UPDATE].exchange(false)) {
win->ghost_window->outputs_changed_update_scale();
}
}
@@ -342,9 +351,10 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
#endif /* USE_EVENT_BACKGROUND_THREAD */
/**
* Update the window's #GWL_WindowFrame
* Update the window's #GWL_WindowFrame.
* The caller must handle locking & run from the main thread.
*/
static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
GHOST_ASSERT(win->ghost_system->main_thread_id == std::this_thread::get_id(),
@@ -381,7 +391,7 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win)
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
#endif
gwl_window_frame_update_from_pending_lockfree(win);
gwl_window_frame_update_from_pending_no_lock(win);
}
/** \} */
@@ -576,12 +586,12 @@ static void frame_handle_configure(struct libdecor_frame *frame,
GHOST_SystemWayland *system = win->ghost_system;
const bool is_main_thread = system->main_thread_id == std::this_thread::get_id();
if (!is_main_thread) {
gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE);
gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE);
}
else
# endif
{
gwl_window_frame_update_from_pending_lockfree(win);
gwl_window_frame_update_from_pending_no_lock(win);
}
}
}
@@ -671,7 +681,7 @@ static void xdg_surface_handle_configure(void *data,
if (!is_main_thread) {
/* NOTE(@ideasman42): this only gets one redraw,
* I could not find a case where this causes problems. */
gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE);
gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE);
}
else
#endif
@@ -1373,7 +1383,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
{
#ifdef USE_EVENT_BACKGROUND_THREAD
if (system_->main_thread_id != std::this_thread::get_id()) {
gwl_window_pending_actions_tag(window_, PENDING_SCALE_UPDATE);
gwl_window_pending_actions_tag(window_, PENDING_OUTPUT_SCALE_UPDATE);
return false;
}
#endif

View File

@@ -93,7 +93,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
RECT win_rect = {left, top, long(left + width), long(top + height)};
adjustWindowRectForClosestMonitor(&win_rect, style, extended_style);
adjustWindowRectForDesktop(&win_rect, style, extended_style);
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */
@@ -298,24 +298,55 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_directManipulationHelper = NULL;
}
void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
DWORD dwStyle,
DWORD dwExStyle)
void GHOST_WindowWin32::adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle)
{
/* Get Details of the closest monitor. */
HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
/* Windows can span multiple monitors, but must be usable. The desktop can have a larger
* surface than all monitors combined, for example when two monitors are aligned diagonally.
* Therefore we ensure that all the window's corners are within some monitor's Work area. */
POINT pt;
HMONITOR hmonitor;
MONITORINFOEX monitor;
monitor.cbSize = sizeof(MONITORINFOEX);
monitor.dwFlags = 0;
GetMonitorInfo(hmonitor, &monitor);
/* Constrain requested size and position to fit within this monitor. */
LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left);
LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top);
win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width);
win_rect->right = win_rect->left + width;
win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height);
win_rect->bottom = win_rect->top + height;
/* We'll need this value before it is altered for checking later. */
LONG requested_top = win_rect->top;
/* Note that with MonitorFromPoint using MONITOR_DEFAULTTONEAREST, it will return
* the exact monitor if there is one at the location or the nearest monitor if not. */
/* Top-left. */
pt.x = win_rect->left;
pt.y = win_rect->top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(win_rect->top, monitor.rcWork.top);
win_rect->left = max(win_rect->left, monitor.rcWork.left);
/* Top-right. */
pt.x = win_rect->right;
pt.y = win_rect->top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(win_rect->top, monitor.rcWork.top);
win_rect->right = min(win_rect->right, monitor.rcWork.right);
/* Bottom-left. */
pt.x = win_rect->left;
pt.y = win_rect->bottom;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom);
win_rect->left = max(win_rect->left, monitor.rcWork.left);
/* Bottom-right. */
pt.x = win_rect->right;
pt.y = win_rect->bottom;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom);
win_rect->right = min(win_rect->right, monitor.rcWork.right);
/* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */
GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr;
@@ -327,6 +358,9 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
/* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be
* correctly outside of monitor bounds. NOTE: You cannot specify #WS_OVERLAPPED when calling. */
if (fpAdjustWindowRectExForDpi) {
/* Use the DPI of the monitor that is at the middle of the rect. */
hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
UINT dpiX, dpiY;
GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
fpAdjustWindowRectExForDpi(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle, dpiX);
@@ -335,7 +369,12 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle);
}
/* But never allow a top position that can hide part of the title bar. */
/* Don't hide the title bar. Check the working area of the monitor at the top-left corner, using
* the original top since the justWindowRects might have altered it to different monitor. */
pt.x = win_rect->left;
pt.y = requested_top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(monitor.rcWork.top, win_rect->top);
}

View File

@@ -87,12 +87,12 @@ class GHOST_WindowWin32 : public GHOST_Window {
~GHOST_WindowWin32();
/**
* Adjusts a requested window rect to fit and position correctly in monitor.
* Adjusts a requested window rect to fit and position within the desktop.
* \param win_rect: pointer to rectangle that will be modified.
* \param dwStyle: The Window Style of the window whose required size is to be calculated.
* \param dwExStyle: The Extended Window Style of the window.
*/
void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle);
void adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle);
/**
* Returns indication as to whether the window is valid.

65
locale/languages Normal file
View File

@@ -0,0 +1,65 @@
# File used by Blender to know which languages (translations) are available,
# and to generate translation menu.
#
# File format:
# ID:MENULABEL:ISOCODE
# ID must be unique, except for 0 value (marks categories for menu).
# Line starting with a # are comments!
#
# Automatically generated by bl_i18n_utils/update_languages_menu.py script.
# Highest ID currently in use: 48
#
0:Complete:
0:Automatic (Automatic):DEFAULT
1:English (English):en_US
9:Spanish (Español):es
8:French (Français):fr_FR
2:Japanese (日本語):ja_JP
47:Slovak (Slovenčina):sk_SK
41:Vietnamese (tiếng Việt):vi_VN
13:Simplified Chinese (简体中文):zh_CN
#
0:In Progress:
10:Catalan (Català):ca_AD
11:Czech (Český):cs_CZ
5:German (Deutsch):de_DE
4:Italian (Italiano):it_IT
48:Georgian (ქართული):ka
24:Korean (한국어):ko_KR
32:Brazilian Portuguese (Português do Brasil):pt_BR
12:Portuguese (Português):pt_PT
15:Russian (Русский):ru_RU
18:Ukrainian (Українська):uk_UA
14:Traditional Chinese (繁體中文):zh_TW
#
0:Starting:
45:Abkhaz (Аԥсуа бызшәа):ab
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #37:Amharic (አማርኛ):am_ET
21:Arabic (ﺔﻴﺑﺮﻌﻟﺍ):ar_EG
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #22:Bulgarian (Български):bg_BG
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #23:Greek (Ελληνικά):el_GR
35:Esperanto (Esperanto):eo
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #36:Spanish from Spain (Español de España):es_ES
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #34:Estonian (Eestlane):et_EE
42:Basque (Euskara):eu_EU
26:Persian (ﯽﺳﺭﺎﻓ):fa_IR
6:Finnish (Suomi):fi_FI
43:Hausa (Hausa):ha
33:Hebrew (תירִבְעִ):he_IL
40:Hindi (मानक हिन्दी):hi_IN
16:Croatian (Hrvatski):hr_HR
31:Hungarian (Magyar):hu_HU
27:Indonesian (Bahasa indonesia):id_ID
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #44:Kazakh (қазақша):kk_KZ
29:Kyrgyz (Кыргыз тили):ky_KG
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #25:Nepali (नेपाली):ne_NP
3:Dutch (Nederlandse taal):nl_NL
19:Polish (Polski):pl_PL
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #20:Romanian (Român):ro_RO
17:Serbian (Српски):sr_RS
28:Serbian Latin (Srpski latinica):sr_RS@latin
7:Swedish (Svenska):sv_SE
46:Thai (ภาษาไทย):th_TH
30:Turkish (Türkçe):tr_TR
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #38:Uzbek (Oʻzbek):uz_UZ
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #39:Uzbek Cyrillic (Ўзбек):uz_UZ@cyrillic

720
locale/po/ab.po Normal file
View File

@@ -0,0 +1,720 @@
msgid ""
msgstr ""
"Project-Id-Version: Blender 3.5.0 Beta (b'5fd4d47206ff')\n"
"Report-Msgid-Bugs-To: \n"
"\"POT-Creation-Date: 2019-02-25 20:41:30\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Daniel Tlisha <daniel.abzakh@gmail.com>\n"
"Language-Team: Abkhaz language team <daniel.abzakh@gmail.com>\n"
"Language: ab\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit"
msgid "Select"
msgstr "Алхра"
msgid "Add"
msgstr "Ацҵара"
msgid "Subtract"
msgstr "Ацхра"
msgid "Empty"
msgstr "Аҭацәы"
msgid "Edge"
msgstr "Акьыԥшь"
msgid "Face"
msgstr "Ахаҿы"
msgid "Object"
msgstr "Амаҭәар"
msgid "Texts"
msgstr "Аҳәоуқәа"
msgid "Main Images"
msgstr "Ихадоу Асахьақәа"
msgid "Main Lights"
msgstr "Ихадоу Алашарақәа"
msgid "Main Meshes"
msgstr "Ихадоу Аҿарԥагақәа"
msgid "Mode"
msgstr "А́иҿкаашьа"
msgid "Marker"
msgstr "Ашьҭа"
msgid "Image"
msgstr "Асахьанҵа"
msgid "Rotation"
msgstr "Агьежьра"
msgid "Scale"
msgstr "Ашәага"
msgid "Curve"
msgstr "Архәара"
msgid "Difference"
msgstr "Аиԥшымра"
msgid "Armature"
msgstr "Абаҩ"
msgid "Camera"
msgstr "Акамера"
msgid "Location"
msgstr "Аҭыԥ"
msgid "Cursor"
msgstr "Ахырхага"
msgid "Plane"
msgstr "Аҟьаҟьа"
msgid "View"
msgstr "Аԥшра"
msgid "Render"
msgstr "Архиара"
msgid "Shading"
msgstr "Аршәшьра"
msgctxt "ID"
msgid "Armature"
msgstr "Абаҩ"
msgctxt "ID"
msgid "Camera"
msgstr "Акамера"
msgctxt "ID"
msgid "Image"
msgstr "Асахьанҵа"
msgctxt "ID"
msgid "Lattice"
msgstr "Аҭыџьеихац"
msgctxt "ID"
msgid "Library"
msgstr "Ашәҟәыԥхьарҭа"
msgctxt "ID"
msgid "Light"
msgstr "Алашара"
msgctxt "ID"
msgid "Metaball"
msgstr "Метампыл"
msgctxt "ID"
msgid "Speaker"
msgstr "Абжьы Ахыҵхырҭа"
msgid "Vertex"
msgstr "Ақәыцә"
msgid "Group"
msgstr "Агәыԥ"
msgid "Cone"
msgstr "Аконус"
msgid "Sphere"
msgstr "Асфера"
msgid "End"
msgstr "Алгара"
msgid "Start"
msgstr "Алагара"
msgid "Window"
msgstr "Аԥенџьыр"
msgid "Edit Mode"
msgstr "Аиҭакра Аиҿкаашьа"
msgid "Lattice"
msgstr "Аҭыџьеихац"
msgid "Library"
msgstr "Ашәҟәыԥхьарҭа"
msgid "Local"
msgstr "Ҷыдала"
msgid "Global"
msgstr "Зеиԥшла"
msgctxt "Light"
msgid "Light"
msgstr "Алашара"
msgctxt "Light"
msgid "Sun"
msgstr "Амра"
msgid "Cube"
msgstr "Акуб"
msgid "Roughness"
msgstr "Аџьаџьара"
msgid "Specular"
msgstr "Ацырцырра"
msgid "Circle"
msgstr "Аицыгьежь"
msgid "Object Mode"
msgstr "Амаҭәар Аиҿкаашьа"
msgid "Sculpt Mode"
msgstr "Ашәаҳара Аиҿкаашьа"
msgid "Vertex Paint"
msgstr "Ақәыцә Ашәра"
msgid "Weight Paint"
msgstr "Акапан Ашәра"
msgid "Texture Paint"
msgstr "Атекстура Ашәра"
msgctxt "ID"
msgid "Empty"
msgstr "Аҭацәы"
msgid "3D Cursor"
msgstr "3Д Ахырхага"
msgid "Edit"
msgstr "Аиҭакра"
msgid "Text"
msgstr "Аҳәоу"
msgid "Mesh"
msgstr "Аҿарҧага"
msgid "File"
msgstr "Ашәҟәы"
msgid "Help"
msgstr "Аилыркаа"
msgid "Metaball"
msgstr "Метампыл"
msgid "Light"
msgstr "Алашара"
msgid "Intersect"
msgstr "Аихҵәара"
msgid "Ball"
msgstr "Ампыл"
msgid "New"
msgstr "Аҿыц"
msgid "Keying"
msgstr " Аиҭаганҵа"
msgctxt "Operator"
msgid "Add Circle"
msgstr "Ацҵара Аицыгьежь"
msgctxt "Operator"
msgid "Add Cube"
msgstr "Ацҵара Акуб"
msgctxt "Operator"
msgid "Add Ico Sphere"
msgstr "Ацҵара Ico Асфера"
msgctxt "Operator"
msgid "Add Monkey"
msgstr "Ацҵара Амаамын"
msgctxt "Operator"
msgid "Add Plane"
msgstr "Ацҵара Аҟьаҟьа"
msgctxt "Operator"
msgid "Add UV Sphere"
msgstr "Ацҵара UV Асфера"
msgctxt "Operator"
msgid "Add Armature"
msgstr "Ацҵара Абаҩ"
msgctxt "Operator"
msgid "Add Camera"
msgstr "Ацҵара Акамера"
msgid "Monkey"
msgstr "Амаамын"
msgctxt "Operator"
msgid "Add Light"
msgstr "Ацҵара Алашара"
msgctxt "Operator"
msgid "Add Metaball"
msgstr "Ацҵара Метампыл"
msgctxt "Operator"
msgid "Add Speaker"
msgstr "Ацҵара Абжьы Ахыҵхырҭа"
msgctxt "Operator"
msgid "Add Text"
msgstr "Ацҵара Аҳәоу"
msgctxt "Scene"
msgid "New"
msgstr "Аҿыц"
msgid "Overlays"
msgstr "Ақәҵакәа"
msgctxt "Operator"
msgid "Scale"
msgstr "Ашәага"
msgid "Playback"
msgstr "Арҳәара"
msgctxt "Operator"
msgid "Circle"
msgstr "Аицыгьежь"
msgctxt "Sequence"
msgid "Image"
msgstr "Асахьанҵа"
msgctxt "Sequence"
msgid "Text"
msgstr "Аҳәоу"
msgctxt "MovieClip"
msgid "View"
msgstr "Аԥшра"
msgid "Speaker"
msgstr "Абжьы Ахыҵхырҭа"
msgctxt "WindowManager"
msgid "Armature"
msgstr "Абаҩ"
msgctxt "WindowManager"
msgid "Metaball"
msgstr "Метампы"
msgctxt "WindowManager"
msgid "Lattice"
msgstr "Аҭыџьеихац"
msgctxt "WindowManager"
msgid "Image"
msgstr "Асахьанҵа"
msgctxt "WindowManager"
msgid "Text"
msgstr "Аҳәоу"
msgctxt "Operator"
msgid "Location"
msgstr "Аҭыԥ"
msgctxt "Image"
msgid "New"
msgstr "Аҿыц"
msgctxt "Operator"
msgid "Text"
msgstr "Аҳәоу"
msgctxt "Operator"
msgid "Rotation"
msgstr "Агьежьра"
msgctxt "Text"
msgid "New"
msgstr "Аҿыц"
msgid "location"
msgstr "Аҭыԥ"
msgctxt "Operator"
msgid "Plane"
msgstr "Аҟьаҟьа"
msgctxt "Operator"
msgid "Cube"
msgstr "Акуб"
msgctxt "Operator"
msgid "UV Sphere"
msgstr "UV Асфера"
msgctxt "Operator"
msgid "Ico Sphere"
msgstr "Ico Асфера "
msgctxt "Operator"
msgid "Cylinder"
msgstr "Ацилиндр"
msgctxt "Operator"
msgid "Cone"
msgstr "Аконус"
msgctxt "Operator"
msgid "Monkey"
msgstr "Амаамын"
msgctxt "Operator"
msgid "Camera"
msgstr "Акамера"
msgctxt "Operator"
msgid "Speaker"
msgstr "Абжьы Ахыҵхырҭа"
msgctxt "Operator"
msgid "Armature"
msgstr "Абаҩ"
msgctxt "Operator"
msgid "Lattice"
msgstr "Аҭыџьеихац"
msgctxt "Object"
msgid "New"
msgstr "Аҿыц"
msgctxt "Mesh"
msgid "New"
msgstr "Аҿыц"
msgctxt "Curve"
msgid "New"
msgstr "Аҿыц"
msgctxt "Metaball"
msgid "New"
msgstr "Аҿыц"
msgctxt "Material"
msgid "New"
msgstr "Аҿыц"
msgctxt "Texture"
msgid "New"
msgstr "Аҿыц"
msgctxt "Lattice"
msgid "New"
msgstr "Аҿыц"
msgctxt "Light"
msgid "New"
msgstr "Аҿыц"
msgctxt "Camera"
msgid "New"
msgstr "Аҿыц"
msgctxt "World"
msgid "New"
msgstr "Аҿыц"
msgctxt "Screen"
msgid "New"
msgstr "Аҿыц"
msgctxt "Speaker"
msgid "New"
msgstr "Аҿыц"
msgctxt "Sound"
msgid "New"
msgstr "Аҿыц"
msgctxt "Armature"
msgid "New"
msgstr "Аҿыц"
msgctxt "Action"
msgid "New"
msgstr "Аҿыц"
msgctxt "NodeTree"
msgid "New"
msgstr "Аҿыц"
msgctxt "Brush"
msgid "New"
msgstr "Аҿыц"
msgctxt "ParticleSettings"
msgid "New"
msgstr "Аҿыц"
msgctxt "GPencil"
msgid "New"
msgstr "Аҿыц"
msgctxt "FreestyleLineStyle"
msgid "New"
msgstr "Аҿыц"
msgctxt "WorkSpace"
msgid "New"
msgstr "Аҿыц"
msgctxt "LightProbe"
msgid "New"
msgstr "Аҿыц"
msgctxt "Action"
msgid "Group"
msgstr "Агәыԥ"
msgid "Front Orthographic"
msgstr "Аԥхьа Аҩышьаԥҟара"
msgid "Front Perspective"
msgstr "Аԥхьа Ԥхьаԥшра"
msgid "Back Orthographic"
msgstr "Ашьҭахь Аҩышьаԥҟара"
msgid "Back Perspective"
msgstr "Ашьҭахь Ԥхьаԥшра"
msgid "Top Orthographic"
msgstr "Ақә Аҩышьаԥҟара"
msgid "Top Perspective"
msgstr "Ақә Ԥхьаԥшра"
msgid "Bottom Orthographic"
msgstr "Ҵаҟа Аҩышьаԥҟара"
msgid "Bottom Perspective"
msgstr "Ҵаҟа Ԥхьаԥшра"
msgid "Right Orthographic"
msgstr "Арӷьа Аҩышьаԥҟара"
msgid "Right Perspective"
msgstr "Арӷьа Ԥхьаԥшра"
msgid "Left Orthographic"
msgstr "Арма Аҩышьаԥҟара"
msgid "Left Perspective"
msgstr "Арма Ԥхьаԥшра"
msgid "Camera Perspective"
msgstr "Акамера Ԥхьаԥшра"
msgid "Camera Orthographic"
msgstr "Акамера Аҩышьаԥҟара"
msgid "User Orthographic"
msgstr "Ахархәаҩ Аҩышьаԥҟара"
msgid "User Perspective"
msgstr "Ахархәаҩ Ԥхьаԥшра"
msgid "global"
msgstr "Зеиԥшла"
msgid "local"
msgstr "Ҷыдала"
msgid "view"
msgstr "Аԥшра"
msgid "cursor"
msgstr "Ахырхага"
msgctxt "Armature"
msgid "Group"
msgstr "Агәыԥ"

41082
locale/po/ar.po Normal file

File diff suppressed because it is too large Load Diff

72547
locale/po/ca.po Normal file

File diff suppressed because it is too large Load Diff

48103
locale/po/cs.po Normal file

File diff suppressed because it is too large Load Diff

66345
locale/po/de.po Normal file

File diff suppressed because it is too large Load Diff

75
locale/po/eo.po Normal file
View File

@@ -0,0 +1,75 @@
msgid "Select"
msgstr "Elektas"
msgid "Add"
msgstr "Aldonia"
msgid "View"
msgstr "Rigardi"
msgid "Render"
msgstr "Por Kapitulacigi"
msgid "Window"
msgstr "Fenestro"
msgid "Edit Mode"
msgstr "Prilaborado Modo"
msgid "Links"
msgstr "Ligiloj"
msgid "Object Mode"
msgstr "Objekto Modo"
msgid "Sculpt Mode"
msgstr "Skulptaĵo Modo"
msgid "File"
msgstr "Dosiero"
msgid "Help"
msgstr "Helpo"
msgid "New"
msgstr "Nova"
msgctxt "Operator"
msgid "Select"
msgstr "Elektas"
msgid "View Z Axis"
msgstr "Montri Z Axis"
msgid "View X Axis"
msgstr "Montri X Axis"
msgctxt "Operator"
msgid "Render"
msgstr "Por Kapitulacigi"
msgctxt "Operator"
msgid "Recover Last Session"
msgstr "Restaŭri lasta kunsido"
msgid "Recent"
msgstr "Freŝaj"

126298
locale/po/es.po Normal file

File diff suppressed because it is too large Load Diff

99778
locale/po/es_ES.po Normal file

File diff suppressed because it is too large Load Diff

2578
locale/po/eu.po Normal file

File diff suppressed because it is too large Load Diff

4305
locale/po/fa.po Normal file

File diff suppressed because it is too large Load Diff

12368
locale/po/fi.po Normal file

File diff suppressed because it is too large Load Diff

128050
locale/po/fr.po Normal file

File diff suppressed because it is too large Load Diff

123
locale/po/ha.po Normal file
View File

@@ -0,0 +1,123 @@
msgid ""
msgstr ""
"Project-Id-Version: Blender 3.5.0 Beta (b'5fd4d47206ff')\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-20 13:46:36\n"
"PO-Revision-Date: 2017-12-25 14:01+0100\n"
"Last-Translator: UMAR HARUNA ABDULLAHI <umarbrowser20@gmail.com>\n"
"Language-Team: BlenderNigeria <pyc0der@outlook.com>\n"
"Language: ha\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11"
msgid "Name"
msgstr "Suna"
msgid "Action F-Curves"
msgstr "Aikin F-Curves"
msgid "Collection of action F-Curves"
msgstr "Karban bayanan aikin F-Curves"
msgid "Action Group"
msgstr "Aikin Kunguya"
msgid "Groups of F-Curves"
msgstr "Kungiyar F-Curves"
msgid "Channels"
msgstr "Channels"
msgid "F-Curves in this group"
msgstr "F-Curves acikin wannan kungiya"
msgid "Color Set"
msgstr "Sashin Launi"
msgid "Custom color set to use"
msgstr "Hadaddiyar sashin launin daza a saka"
msgid "Default Colors"
msgstr "Launi na ainihi"
msgid "01 - Theme Color Set"
msgstr "01 - Theme Color Set"
msgid "02 - Theme Color Set"
msgstr "02 - Theme Color Set"
msgid "03 - Theme Color Set"
msgstr "03 - Theme Color Set"
msgid "04 - Theme Color Set"
msgstr "04 - Theme Color Set"
msgid "Custom Color Set"
msgstr "Hadaddiyar sashin launuka"
msgid "Colors"
msgstr "launuka"
msgid "Copy of the colors associated with the group's color set"
msgstr "Ari launukan dasuka danganta da launukannan"
msgid "Color set is user-defined instead of a fixed theme color set"
msgstr "Launukan nawanda yasane ba na gyararren theme ba"
msgid "Lock"
msgstr "rufe"
msgid "Action group is locked"
msgstr "Aikin kungiya ya rufe"
msgid "Select"
msgstr "Zabi"
msgid "Action group is selected"
msgstr "An zabi aikin kungiya"
msgid "Expanded"
msgstr "budadde"
msgid "Action Groups"
msgstr "Aikin kungiyoyi"
msgid "Collection of action groups"
msgstr "Karban aikin kungiyoyi"
msgid "Action Pose Markers"
msgstr "Aikin Pose Markers"
msgid "Collection of timeline markers"
msgstr "Sashin lokacin markers"

531
locale/po/he.po Normal file
View File

@@ -0,0 +1,531 @@
msgid ""
msgstr ""
"Project-Id-Version: Blender 3.5.0 Beta (b'5fd4d47206ff')\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-20 13:46:36\n"
"PO-Revision-Date: 2012-10-07 13:56+0300\n"
"Last-Translator: Barak Itkin <lightningismyname@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: he\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Virtaal 0.7.0"
msgid "Name"
msgstr "םש"
msgid "Color"
msgstr "עבצ"
msgid "Value"
msgstr "ךרע"
msgid "Off"
msgstr "יובכ"
msgid "Add"
msgstr "ףסוה"
msgid "Width"
msgstr "בחור"
msgid "Vector"
msgstr "רוטקו"
msgid "Indirect"
msgstr "ףיקע"
msgid "Speed"
msgstr "תוריהמ"
msgid "Strength"
msgstr "המצוע"
msgid "Random"
msgstr "יארקא"
msgid "Remove"
msgstr "רסה"
msgid "Vertex Color"
msgstr "דוקדוק עבצ"
msgid "Smooth"
msgstr "קלח"
msgid "Saturation"
msgstr "היוור"
msgid "Path"
msgstr "ביתנ"
msgid "Rotation"
msgstr "בוביס"
msgid "Left"
msgstr "לאמש"
msgid "Right"
msgstr "ןימי"
msgid "Center"
msgstr "זכרמ"
msgid "Gamma"
msgstr "אמג"
msgid "Constant"
msgstr "עובק"
msgid "Position"
msgstr "םוקמ"
msgid "Output"
msgstr "טלפ"
msgid "Default"
msgstr "לדחמ תרירב"
msgid "Location"
msgstr "םוקימ"
msgid "White Level"
msgstr "ןבל תמר"
msgid "Surface"
msgstr "חטשמ"
msgid "View"
msgstr "הגוצת"
msgid "Scene"
msgstr "הנצס"
msgid "Shrink"
msgstr "ץווכ"
msgid "Modifiers"
msgstr "םינשמ"
msgid "Frequency"
msgstr "תורידת"
msgid "Size"
msgstr "לדוג"
msgid "Environment"
msgstr "הביבס"
msgid "End"
msgstr "ףוס"
msgid "Start"
msgstr "הלחתה"
msgid "Density"
msgstr "תופיפצ"
msgid "Generated"
msgstr "רצוימ"
msgid "Window"
msgstr "ןולח"
msgid "Header"
msgstr "תרתוכ"
msgid "Tools"
msgstr "םילכ"
msgid "Edit Mode"
msgstr "הכירע בצמ"
msgid "Mirror"
msgstr "הארמ"
msgid "Space"
msgstr "חוור"
msgid "Red"
msgstr "םודא"
msgid "Green"
msgstr "קורי"
msgid "Blue"
msgstr "לוחכ"
msgid "Mask"
msgstr "הכסמ"
msgid "Up"
msgstr "הלעמ"
msgid "Mean"
msgstr "עצוממ"
msgid "Movie"
msgstr "טרס"
msgid "Roughness"
msgstr "תוסג"
msgid "Specular"
msgstr "רלקפסא"
msgid "Both"
msgstr "םהינש"
msgid "Sculpt Mode"
msgstr "לוסיפ בצמ"
msgid "Vertex Paint"
msgstr "םידוקדוק תעיבצ"
msgid "Weight Paint"
msgstr "לקשמ תעיבצ"
msgid "Quadratic"
msgstr "יעוביר"
msgid "Mist"
msgstr "לפרע"
msgid "Color Management"
msgstr "עבצ לוהינ"
msgid "Apply"
msgstr "לחה"
msgid "Python"
msgstr "Python"
msgid "System"
msgstr "תכרעמ"
msgid "Convert"
msgstr "רמה"
msgid "World"
msgstr "םלוע"
msgid "Lift"
msgstr "יוליע"
msgid "Y Axis"
msgstr "Y ריצ"
msgid "Background"
msgstr "עקר"
msgid "Reflection"
msgstr "תופקתשה"
msgid "Emission"
msgstr "הטילפ"
msgid "Down"
msgstr "הטמ"
msgid "Lamp"
msgstr "הרונמ"
msgid "Reset"
msgstr "לוחתא"
msgid "Manual"
msgstr "ינדי"
msgid "Credits"
msgstr "תודות"
msgid "Detail"
msgstr "טוריפ"
msgid "Dimension"
msgstr "דמימ"
msgid "Location:"
msgstr ":םוקימ"
msgid "Nothing selected"
msgstr "רבד רחבנ אל"
msgctxt "Operator"
msgid "Change Shortcut"
msgstr "ךרד־רוציק הנש"
msgctxt "Operator"
msgid "Reset All to Default Values"
msgstr "לדחמה תרירב יכרעל לכה לחתא"
msgctxt "Operator"
msgid "Remove Shortcut"
msgstr "ךרד־רוציק רסה"
msgid "Value:"
msgstr ":ךרע"
msgid "(Gamma Corrected)"
msgstr "(אמג ןקותמ)"
msgid "Shortcut: %s"
msgstr "%s :ךרד־רוציק"
msgid "Python: %s"
msgstr "Python: %s"
msgid "Radians: %f"
msgstr "%f :םינאידר"
msgid "Expression: %s"
msgstr "%s :יוטיב"
msgid "Library: %s"
msgstr "%s :היירפס"
msgid "Disabled: %s"
msgstr "%s :תבשומ"
msgid "Python: %s.%s"
msgstr "Python: %s.%s"
msgid "No Properties"
msgstr "םינייפאמ אלל"
msgid "Delete points"
msgstr "תודוקנ קחמ"
msgid "Stop this job"
msgstr "וז הדובע רוצע"
msgid "%d items"
msgstr "%d םיטירפ"
msgid "Fields"
msgstr "תודש"
msgid "File Path:"
msgstr ":ץבוק ביתנ"
msgid "File path"
msgstr "ץבוק ביתנ"
msgid "Cancel"
msgstr "לוטיב"
msgid "File name"
msgstr "ץבוק םש"
msgid "Add Modifier"
msgstr "הנשמ ףסוה"
msgid "Select Layer"
msgstr "הבכש רחב"
msgid " + Z"
msgstr " + Z"
msgid "Label Size"
msgstr "תיוות לדוג"
msgid "Squash"
msgstr "ךעמ"
msgid "Disconnect"
msgstr "קתנ"
msgid "Dependency Loop"
msgstr "תויולת תאלול"
msgid "Vertex:"
msgstr ":דוקדוק"
msgid "Median:"
msgstr ":ןויצח"
msgid "Radius X:"
msgstr ":X סוידר"
msgid "Radius Y:"
msgstr ":Y סוידר"
msgid "Weight:"
msgstr ":לקשמ"
msgid "Radius:"
msgstr ":סוידר"
msgid "Mean Radius:"
msgstr ":עצוממ סוידר"
msgid "Modify"
msgstr "הנש"
msgid "Color Space:"
msgstr ":עבצ בחרמ"
msgid "Key Color"
msgstr "חתפמ עבצ"
msgid "Image 1"
msgstr "1 הנומת"
msgid "Image 2"
msgstr "2 הנומת"
msgid "Std Dev"
msgstr "ןקת תייטס"
msgid "Path:"
msgstr ":ביתנ"
msgid "Add Input"
msgstr "טלק ףסוה"
msgid "Incoming"
msgstr "סנכנ"
msgid "Color2"
msgstr "2עבצ"
msgid "Row Height"
msgstr "הרוש הבוג"
msgid "Bricks 1"
msgstr "1 םינבל"
msgid "Bricks 2"
msgstr "2 םינבל"

7300
locale/po/hi.po Normal file

File diff suppressed because it is too large Load Diff

9
locale/po/hr.po Normal file
View File

@@ -0,0 +1,9 @@
msgctxt "Operator"
msgid "Duplicate Objects"
msgstr "bbbbbbbbbbbbb"
msgid "Duplicate Objects"
msgstr "aaaaaaaaa"

21219
locale/po/hu.po Normal file

File diff suppressed because it is too large Load Diff

27271
locale/po/id.po Normal file

File diff suppressed because it is too large Load Diff

60880
locale/po/it.po Normal file

File diff suppressed because it is too large Load Diff

128626
locale/po/ja.po Normal file

File diff suppressed because it is too large Load Diff

43107
locale/po/ka.po Normal file

File diff suppressed because it is too large Load Diff

89826
locale/po/ko.po Normal file

File diff suppressed because it is too large Load Diff

4170
locale/po/ky.po Normal file

File diff suppressed because it is too large Load Diff

9751
locale/po/nl.po Normal file

File diff suppressed because it is too large Load Diff

11564
locale/po/pl.po Normal file

File diff suppressed because it is too large Load Diff

68171
locale/po/pt.po Normal file

File diff suppressed because it is too large Load Diff

76649
locale/po/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

92634
locale/po/ru.po Normal file

File diff suppressed because it is too large Load Diff

128065
locale/po/sk.po Normal file

File diff suppressed because it is too large Load Diff

28383
locale/po/sr.po Normal file

File diff suppressed because it is too large Load Diff

28363
locale/po/sr@latin.po Normal file

File diff suppressed because it is too large Load Diff

2810
locale/po/sv.po Normal file

File diff suppressed because it is too large Load Diff

5922
locale/po/th.po Normal file

File diff suppressed because it is too large Load Diff

6297
locale/po/tr.po Normal file

File diff suppressed because it is too large Load Diff

104399
locale/po/uk.po Normal file

File diff suppressed because it is too large Load Diff

122861
locale/po/vi.po Normal file

File diff suppressed because it is too large Load Diff

127996
locale/po/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

61951
locale/po/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -33,15 +33,15 @@ aggressive = 2
# Exclude:
# - `./extern/` because it's maintained separately.
# - `./release/scripts/addons*` & `./source/tools/` because they are external repositories
# - `./scripts/addons*` & `./tools/` because they are external repositories
# which can contain their own configuration and be handled separately.
# - `./release/scripts/modules/rna_manual_reference.py` because it's a generated data-file.
# - `./scripts/modules/rna_manual_reference.py` because it's a generated data-file.
exclude = """
./extern/*,
./release/scripts/addons/*,
./release/scripts/addons_contrib/*,
./release/scripts/modules/rna_manual_reference.py,
./source/tools/*,
./scripts/addons/*,
./scripts/addons_contrib/*,
./scripts/modules/rna_manual_reference.py,
./tools/*,
"""
# Omit settings such as `jobs`, `in_place` & `recursive` as they can cause editor utilities that auto-format on save

View File

@@ -7726,22 +7726,6 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccc" />
</g>
<g
id="g3791"
inkscape:label="CA-24">
<path
sodipodi:nodetypes="csssscccccc"
inkscape:connector-curvature="0"
id="path28911-6"
d="m 489,604 v 8 c 0,0.54532 0.45468,1 1,1 h 12 c 0.54532,0 1,-0.45468 1,-1 v -8 h -1 v 8 h -12 v -8 z"
style="opacity:0.6;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke" />
<path
sodipodi:nodetypes="ssccccsssccccc"
inkscape:connector-curvature="0"
style="vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke"
d="m 490,599 c -0.54532,0 -1,0.45468 -1,1 v 3 h 1 12 1 v -3 c 0,-0.54532 -0.45468,-1 -1,-1 z m 0,1 h 2 v 2 h -2 z"
id="path28913-4" />
</g>
<g
style="display:inline;enable-background:new"
id="g28909-7"
@@ -7762,6 +7746,22 @@
transform="matrix(1,0,0,-1,520,1334)"
id="path28907-4" />
</g>
<g
id="g3791"
inkscape:label="CA-24">
<path
sodipodi:nodetypes="csssscccccc"
inkscape:connector-curvature="0"
id="path28911-6"
d="m 489,604 v 8 c 0,0.54532 0.45468,1 1,1 h 12 c 0.54532,0 1,-0.45468 1,-1 v -8 h -1 v 8 h -12 v -8 z"
style="opacity:0.6;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke" />
<path
sodipodi:nodetypes="ssccccsssccccc"
inkscape:connector-curvature="0"
style="vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke"
d="m 490,599 c -0.54532,0 -1,0.45468 -1,1 v 3 h 1 12 1 v -3 c 0,-0.54532 -0.45468,-1 -1,-1 z m 0,1 h 2 v 2 h -2 z"
id="path28913-4" />
</g>
<g
id="g9239"
inkscape:label="CA-23"
@@ -13113,6 +13113,40 @@
d="m 221.03217,109.33958 c 0.67621,0.01 0.67621,-1.00961 0,-1 h -2.79493 c 1.0479,-1.11729 1.7641,-1.66802 2.82812,-2.73204 0.62065,-0.56444 -0.28321,-1.46832 -0.84765,-0.84766 -1.06063,1.10128 -1.59202,1.7772 -2.68554,2.87072 v -2.79102 c 0.01,-0.67616 -1.00956,-0.67616 -1,0 v 4 c 3e-5,0.27613 0.22387,0.49998 0.5,0.5 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<g
id="g24638"
inkscape:label="O-18"
style="display:inline;enable-background:new">
<path
style="color:#000000;opacity:1;fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;-inkscape-stroke:none"
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"
inkscape:label="O-17"
style="display:inline;enable-background:new">
<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
style="display:inline;enable-background:new"
id="g28812"
@@ -18997,36 +19031,6 @@
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

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