diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f9671496d3..9f627d29f84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -411,10 +411,17 @@ option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON) if(UNIX AND NOT APPLE) option(WITH_OPENMP_STATIC "Link OpenMP statically (only used by the release environment)" OFF) mark_as_advanced(WITH_OPENMP_STATIC) -elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") - # At time of testing (LLVM 18.1.6) OMP is not included in public LLVM builds for Windows ARM64 - set(WITH_OPENMP OFF) - set(WITH_OPENMP_STATIC OFF) +elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.1) + # Prior to LLVM 19.1, OpenMP was not included in public LLVM builds for Windows ARM64 + if(WITH_OPENMP) + if(WITH_STRICT_BUILD_OPTIONS) + message(SEND_ERROR "OpenMP enabled, but LLVM ${CMAKE_CXX_COMPILER_VERSION} detected, minimum of 19.1 required for OpenMP functionality") + else() + message(STATUS "Disabling OpenMP, LLVM ${CMAKE_CXX_COMPILER_VERSION} detected, minimum of 19.1 required for OpenMP functionality") + endif() + set(WITH_OPENMP OFF) + set(WITH_OPENMP_STATIC OFF) + endif() endif() if(WITH_GHOST_X11) @@ -2231,6 +2238,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") # And some additional ones that came up when using LLVM 18.1.8 on Windows ARM64 C_WARN_CLANG_CL_SWITCH_DEFAULT -Wno-switch-default C_WARN_CLANG_CL_NAN_INFINITY_DISABLED -Wno-nan-infinity-disabled + # And another from 19.1.5 + C_WARN_CLANG_CL_PRE_C11_COMPAT -Wno-pre-c11-compat ) add_check_cxx_compiler_flags( @@ -2365,6 +2374,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") # And some additional ones that came up when using LLVM 18.1.8 on Windows ARM64 CXX_WARN_CLANG_CL_SWITCH_DEFAULT -Wno-switch-default CXX_WARN_CLANG_CL_NAN_INFINITY_DISABLED -Wno-nan-infinity-disabled + # And another from 19.1.5 + CXX_WARN_CLANG_CL_PRE_C11_COMPAT -Wno-pre-c11-compat ) endif() diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd index c26a98ee1b4..330fc4b5dcc 100644 --- a/build_files/windows/configure_msbuild.cmd +++ b/build_files/windows/configure_msbuild.cmd @@ -8,7 +8,22 @@ if "%BUILD_WITH_SCCACHE%"=="1" ( ) if "%WITH_CLANG%"=="1" ( + REM We want to use an external manifest with Clang set CLANG_CMAKE_ARGS=-T"ClangCl" -DWITH_WINDOWS_EXTERNAL_MANIFEST=ON + + REM Create the build directory, so that we can create the Directory.build.props file + if NOT EXIST %BUILD_DIR%\nul ( + mkdir %BUILD_DIR% + ) + + REM This is required as per https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=msvc-170#custom_llvm_location + REM Which allows any copy of LLVM to be used, not just the one that ships with VS + echo ^ >> %BUILD_DIR%\Directory.build.props + echo ^ >> %BUILD_DIR%\Directory.build.props + echo ^%LLVM_DIR%^ >> %BUILD_DIR%\Directory.build.props + echo ^%CLANG_VERSION%^ >> %BUILD_DIR%\Directory.build.props + echo ^ >> %BUILD_DIR%\Directory.build.props + echo ^ >> %BUILD_DIR%\Directory.build.props ) if "%WITH_ASAN%"=="1" ( diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd index 98d469ab1da..a0cde8ccc0e 100644 --- a/build_files/windows/configure_ninja.cmd +++ b/build_files/windows/configure_ninja.cmd @@ -14,28 +14,10 @@ if "%BUILD_WITH_SCCACHE%"=="1" ( ) if "%WITH_CLANG%" == "1" ( -set LLVM_DIR= + REM We want to use an external manifest with Clang set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_WINDOWS_EXTERNAL_MANIFEST=On - for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C - if DEFINED LLVM_DIR ( - if NOT "%verbose%" == "" ( - echo LLVM Detected at "%LLVM_DIR%" - ) - goto DetectionComplete - ) - REM Check 32 bits - for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C - if DEFINED LLVM_DIR ( - if NOT "%verbose%" == "" ( - echo LLVM Detected at "%LLVM_DIR%" - ) - goto DetectionComplete - ) - echo LLVM not found - exit /b 1 - -:DetectionComplete + REM We can assume that we have a working copy via find_llvm.cmd set CC=%LLVM_DIR%\bin\clang-cl set CXX=%LLVM_DIR%\bin\clang-cl set CFLAGS=-m64 diff --git a/build_files/windows/detect_msvc_vswhere.cmd b/build_files/windows/detect_msvc_vswhere.cmd index 52f765c20c4..081f1ce9bdb 100644 --- a/build_files/windows/detect_msvc_vswhere.cmd +++ b/build_files/windows/detect_msvc_vswhere.cmd @@ -13,11 +13,16 @@ if not exist "%vs_where%" ( goto FAIL ) -if NOT "%verbose%" == "" ( - echo "%vs_where%" -latest %VSWHERE_ARGS% -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 - ) +if "%BUILD_ARCH%" == "arm64" ( + set VSWHERE_ARCH=ARM64 +) else ( + set VSWHERE_ARCH=x86.x64 +) -for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64`) do ( +if NOT "%verbose%" == "" ( + echo "%vs_where%" -latest %VSWHERE_ARGS% -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) -requires Microsoft.VisualStudio.Component.VC.Tools.%VSWHERE_ARCH% +) +for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.%VSWHERE_ARCH%`) do ( if /i "%%i"=="installationPath" set VS_InstallDir=%%j ) @@ -38,6 +43,34 @@ if "%VS_InstallDir%"=="" ( ) ) +rem If we are using Clang + MSBuild, check to make sure the clang tools are installed +if "%WITH_CLANG%" == "1" ( + if NOT "%BUILD_WITH_NINJA%" == "1" ( + if NOT "%verbose%" == "" ( + echo "%vs_where%" -latest %VSWHERE_ARGS% -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) -requires Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset + ) + + for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest -version ^[%BUILD_VS_VER%.0^,%BUILD_VS_VER%.99^) %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset`) do ( + if /i "%%i"=="installationName" set VSWhere_ClangFound=%%j + ) + ) +) + +REM This needs to be in a seperate block, due to no delayed expansion (which breaks other things if enabled) +if "%WITH_CLANG%" == "1" ( + if NOT "%BUILD_WITH_NINJA%" == "1" ( + if "%VSWhere_ClangFound%"=="" ( + echo. + echo Clang was specified whilst using the Visual Studio CMake generator, but the Clang Toolset was not found in Visual Studio. + echo. + echo Check the "MSBuild support for LLVM (clang-cl) toolset" component has been installed. + echo. + echo Alternatively use the Ninja generator via the "ninja" switch when calling make.bat + goto FAIL + ) + ) +) + set VCVARS=%VS_InstallDir%\VC\Auxiliary\Build\vcvarsall.bat if exist "%VCVARS%" ( if NOT "%verbose%" == "" ( diff --git a/build_files/windows/find_llvm.cmd b/build_files/windows/find_llvm.cmd new file mode 100644 index 00000000000..f00ca7bb7c7 --- /dev/null +++ b/build_files/windows/find_llvm.cmd @@ -0,0 +1,57 @@ +REM Find a copy of LLVM on the system +set LLVM_DIR= + +REM First, we try and find the copy on the PATH (unless already specified, in which case we use that) +if "%LLVM_EXE%" == "" ( + for %%X in (clang-cl.exe) do (set "LLVM_EXE=%%~$PATH:X") +) else ( + echo LLVM EXE manually specified, using that +) + +if NOT "%LLVM_EXE%" == "" ( + REM We have found LLVM on the path + for %%X in ("%LLVM_EXE%\..\..") do set "LLVM_DIR=%%~fX" + if NOT "%verbose%" == "" ( + echo LLVM detected via path + ) + goto detect_llvm_done +) + +REM If that fails, we try and get it from the registry +REM Check 64-bit path +for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C +if NOT "%LLVM_DIR%" == "" ( + if NOT "%verbose%" == "" ( + echo LLVM Detected via 64-bit registry + ) + goto detect_llvm_done +) + +REM Check 32-bit path +for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C +if NOT "%LLVM_DIR%" == "" ( + if NOT "%verbose%" == "" ( + echo LLVM Detected via 32-bit registry + ) + goto detect_llvm_done +) + +rem No copy has been found, so error out +if "%LLVM_DIR%" == "" ( + echo LLVM not found on the path, or in the registry. Please verify your installation. + goto ERR +) + +:detect_llvm_done +for /F "usebackq tokens=3" %%X in (`CALL "%LLVM_DIR%\bin\clang-cl.exe" --version ^| findstr "clang version"`) do set CLANG_VERSION=%%X + +if NOT "%verbose%" == "" ( + echo Using Clang/LLVM + echo Version : %CLANG_VERSION% + echo Location : "%LLVM_DIR%" +) + +:EOF +exit /b 0 +:ERR +exit /b 1 \ No newline at end of file diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd index cdf7eb1d661..1c00dd471ca 100644 --- a/build_files/windows/parse_arguments.cmd +++ b/build_files/windows/parse_arguments.cmd @@ -115,6 +115,8 @@ if NOT "%1" == "" ( ) else if "%1" == "doc_py" ( set DOC_PY=1 goto EOF + ) else if "%1" == "msvc" ( + set WITH_MSVC=1 ) else ( echo Command "%1" unknown, aborting! goto ERR diff --git a/build_files/windows/show_help.cmd b/build_files/windows/show_help.cmd index 6ad1adb8c1b..83c3fd61fa5 100644 --- a/build_files/windows/show_help.cmd +++ b/build_files/windows/show_help.cmd @@ -29,6 +29,8 @@ echo - 2019b ^(build with visual studio 2019 Build Tools^) echo - 2022 ^(build with visual studio 2022^) echo - 2022pre ^(build with visual studio 2022 pre-release^) echo - 2022b ^(build with visual studio 2022 Build Tools^) +echo - clang ^(enable building with clang - default on ARM64^) +echo - msvc ^(enable building with msvc - default on x64, unsupported on ARM64^) echo. echo Documentation Targets ^(Not associated with building^) @@ -37,7 +39,6 @@ echo - doc_py ^(Generate sphinx python api docs^) echo. echo Experimental options echo - with_gpu_tests ^(enable both the render and draw gpu test suites including EEVEE, Workbench, Grease Pencil, draw manager and GPU backends^) -echo - clang ^(enable building with clang^) echo - asan ^(enable asan^) echo - ninja ^(enable building with ninja instead of msbuild^) echo. diff --git a/make.bat b/make.bat index b59a94d4860..b04df6b9c0d 100644 --- a/make.bat +++ b/make.bat @@ -47,6 +47,18 @@ if "%LICENSE%" == "1" ( call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd" if errorlevel 1 goto EOF +REM Enforce the default compiler to be clang on ARM64 +if "%BUILD_ARCH%" == "arm64" ( + if not "%WITH_CLANG%" == "1" ( + if "%WITH_MSVC%" == "1" ( + echo WARNING, MSVC compilation on Windows ARM64 is unsupported, and errors may occur. + ) else ( + echo Windows ARM64 builds with clang by default, enabling. If you wish to use MSVC ^(unsupported^), please use the msvc switch. + set WITH_CLANG=1 + ) + ) +) + if "%BUILD_VS_YEAR%" == "" ( call "%BLENDER_DIR%\build_files\windows\autodetect_msvc.cmd" if errorlevel 1 ( @@ -98,6 +110,14 @@ if "%CMAKE%" == "" ( exit /b 1 ) +if "%WITH_CLANG%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\find_llvm.cmd" + if errorlevel 1 ( + echo LLVM/Clang not found ^(try with the 'verbose' switch for more information^) + goto EOF + ) +) + echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR% call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" diff --git a/scripts/startup/bl_operators/sequencer.py b/scripts/startup/bl_operators/sequencer.py index e53c538418b..734803496dc 100644 --- a/scripts/startup/bl_operators/sequencer.py +++ b/scripts/startup/bl_operators/sequencer.py @@ -287,16 +287,9 @@ class SequencerFadesAdd(Operator): Returns the matching FCurve or creates a new one if the function can't find a match. """ scene = context.scene - fade_fcurve = None - fcurves = scene.animation_data.action.fcurves + action = scene.animation_data.action searched_data_path = sequence.path_from_id(animated_property) - for fcurve in fcurves: - if fcurve.data_path == searched_data_path: - fade_fcurve = fcurve - break - if not fade_fcurve: - fade_fcurve = fcurves.new(data_path=searched_data_path) - return fade_fcurve + return action.fcurve_ensure_for_datablock(scene, searched_data_path) def fade_animation_clear(self, fade_fcurve, fades): """ diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc index 74b73cd5baa..889ab6c6f49 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.cc +++ b/source/blender/draw/engines/eevee_next/eevee_film.cc @@ -331,6 +331,21 @@ void Film::init(const int2 &extent, const rcti *output_rect) data_.overscan = overscan_pixels_get(inst_.camera.overscan(), data_.render_extent); data_.render_extent += data_.overscan * 2; + is_valid_render_extent_ = data_.render_extent.x <= GPU_max_texture_size() && + data_.render_extent.y <= GPU_max_texture_size(); + if (!is_valid_render_extent_) { + inst_.info_append_i18n( + "Required render size ({}px) is larger than reported texture size limit ({}px).", + max_ii(data_.render_extent.x, data_.render_extent.y), + GPU_max_texture_size()); + + data_.extent = int2(4, 4); + data_.render_extent = int2(4, 4); + data_.extent_inv = 1.0f / float2(data_.extent); + data_.offset = int2(0, 0); + data_.overscan = 0; + } + data_.filter_radius = clamp_f(scene.r.gauss, 0.0f, 100.0f); if (sampling.sample_count() == 1) { /* Disable filtering if sample count is 1. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_film.hh b/source/blender/draw/engines/eevee_next/eevee_film.hh index b26044b3e1b..a163b8a4a52 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.hh +++ b/source/blender/draw/engines/eevee_next/eevee_film.hh @@ -92,6 +92,7 @@ class Film { eViewLayerEEVEEPassType viewport_compositor_enabled_passes_ = eViewLayerEEVEEPassType(0); PassCategory enabled_categories_ = PassCategory(0); bool use_reprojection_ = false; + bool is_valid_render_extent_ = true; public: Film(Instance &inst, FilmData &data) : inst_(inst), data_(data){}; @@ -131,6 +132,10 @@ class Film { { return data_.render_extent; } + inline bool is_valid_render_extent() const + { + return is_valid_render_extent_; + } /** Size and offset of the film (taking into account render region). */ int2 film_extent_get() const diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 234f2a011e9..1279170d43f 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -76,6 +76,7 @@ void Instance::init(const int2 &output_res, shaders_are_ready_ = shaders.is_ready(is_image_render()); if (!shaders_are_ready_) { + skip_render_ = true; return; } @@ -126,7 +127,8 @@ void Instance::init(const int2 &output_res, /* Pre-compile specialization constants in parallel (if supported). */ shaders.precompile_specializations( render_buffers.data.shadow_id, shadows.get_data().ray_count, shadows.get_data().step_count); - shaders_are_ready_ = shaders.is_ready(is_image_render()); + shaders_are_ready_ = shaders.is_ready(is_image_render()) || !film.is_valid_render_extent(); + skip_render_ = !shaders_are_ready_ || !film.is_valid_render_extent(); } void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager) @@ -201,7 +203,7 @@ void Instance::view_update() void Instance::begin_sync() { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -245,7 +247,7 @@ void Instance::begin_sync() void Instance::object_sync(ObjectRef &ob_ref) { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -321,7 +323,7 @@ void Instance::object_sync_render(void *instance_, void Instance::end_sync() { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -504,6 +506,13 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name) { + if (skip_render_) { + if (!info_.empty()) { + RE_engine_set_error_message(engine, info_.c_str()); + info_ = ""; + } + return; + } /* TODO: Break on RE_engine_test_break(engine) */ while (!sampling.finished()) { this->render_sample(); @@ -555,11 +564,13 @@ void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, con void Instance::draw_viewport() { - if (!shaders_are_ready_) { + if (skip_render_) { DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); GPU_framebuffer_clear_color_depth(dfbl->default_fb, float4(0.0f), 1.0f); - info_append_i18n("Compiling EEVEE engine shaders"); - DRW_viewport_request_redraw(); + if (!shaders_are_ready_) { + info_append_i18n("Compiling EEVEE engine shaders"); + DRW_viewport_request_redraw(); + } return; } @@ -596,6 +607,9 @@ void Instance::draw_viewport() void Instance::draw_viewport_image_render() { + if (skip_render_) { + return; + } while (!sampling.finished_viewport()) { this->render_sample(); } @@ -608,6 +622,9 @@ void Instance::draw_viewport_image_render() void Instance::store_metadata(RenderResult *render_result) { + if (skip_render_) { + return; + } cryptomatte.store_metadata(render_result); } diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 4c870c74ba3..41dad1d9a92 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -83,8 +83,8 @@ class Instance { uint64_t depsgraph_last_update_ = 0; bool overlays_enabled_ = false; - bool shaders_are_ready_ = true; + bool skip_render_ = false; /** Info string displayed at the top of the render / viewport, or the console when baking. */ std::string info_ = "";