diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-01-26 12:21:47 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-01-26 12:21:47 +0300 |
commit | 3ffd662586e017668f6c0a1c2f1c754f4db0bf4e (patch) | |
tree | 35cb9af1c2656d39be3a3b5db16edcf2bf37df02 | |
parent | be4f593758c5913705b43fa092ee0294b4e1bb0a (diff) | |
parent | 0cb5eae9d0617abedf745753c23061ddfcfd1416 (diff) |
Merge branch 'master' into tmp-workbench-shader-create-infostmp-workbench-shader-create-infos
35 files changed, 448 insertions, 172 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 25cdd122a7f..0a73a2fae1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,11 +273,13 @@ endif() if(UNIX AND NOT APPLE) option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF) - option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON) + option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF) + option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF) else() # not an option for other OS's set(WITH_SYSTEM_GLEW OFF) set(WITH_SYSTEM_GLES OFF) + set(WITH_SYSTEM_FREETYPE OFF) endif() diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake index 5170a3a123e..f2944a41af8 100644 --- a/build_files/build_environment/cmake/boost.cmake +++ b/build_files/build_environment/cmake/boost.cmake @@ -25,8 +25,13 @@ else() endif() if(WIN32) - set(BOOST_TOOLSET toolset=msvc-14.1) - set(BOOST_COMPILER_STRING -vc141) + if(MSVC_VERSION GREATER_EQUAL 1920) # 2019 + set(BOOST_TOOLSET toolset=msvc-14.2) + set(BOOST_COMPILER_STRING -vc142) + else() # 2017 + set(BOOST_TOOLSET toolset=msvc-14.1) + set(BOOST_COMPILER_STRING -vc141) + endif() set(BOOST_CONFIGURE_COMMAND bootstrap.bat) set(BOOST_BUILD_COMMAND b2) diff --git a/build_files/build_environment/windows/build_deps.cmd b/build_files/build_environment/windows/build_deps.cmd index 5174af8e20d..c0e13ac3a55 100644 --- a/build_files/build_environment/windows/build_deps.cmd +++ b/build_files/build_environment/windows/build_deps.cmd @@ -1,19 +1,5 @@ @echo off if NOT "%1" == "" ( - if "%1" == "2013" ( - echo "Building for VS2013" - set VSVER=12.0 - set VSVER_SHORT=12 - set BuildDir=VS12 - goto par2 - ) - if "%1" == "2015" ( - echo "Building for VS2015" - set VSVER=14.0 - set VSVER_SHORT=14 - set BuildDir=VS14 - goto par2 - ) if "%1" == "2017" ( echo "Building for VS2017" set VSVER=15.0 @@ -21,44 +7,33 @@ if NOT "%1" == "" ( set BuildDir=VS15 goto par2 ) + if "%1" == "2019" ( + echo "Building for VS2019" + set VSVER=15.0 + set VSVER_SHORT=15 + set BuildDir=VS15 + goto par2 + ) ) :usage -Echo Usage build_deps 2013/2015/2017 x64/x86 +Echo Usage build_deps 2017/2019 x64 goto exit :par2 if NOT "%2" == "" ( - if "%2" == "x86" ( - echo "Building for x86" - set HARVESTROOT=Windows_vc - set ARCH=86 - if "%1" == "2013" ( - set CMAKE_BUILDER=Visual Studio 12 2013 - ) - if "%1" == "2015" ( - set CMAKE_BUILDER=Visual Studio 14 2015 - ) - if "%1" == "2017" ( - set CMAKE_BUILDER=Visual Studio 15 2017 - ) - - goto start - ) if "%2" == "x64" ( echo "Building for x64" set HARVESTROOT=Win64_vc set ARCH=64 - if "%1" == "2013" ( - set CMAKE_BUILDER=Visual Studio 12 2013 Win64 - ) - if "%1" == "2015" ( - set CMAKE_BUILDER=Visual Studio 14 2015 Win64 + if "%1" == "2019" ( + set CMAKE_BUILDER=Visual Studio 16 2019 + set CMAKE_BUILD_ARCH=-A x64 ) if "%1" == "2017" ( set CMAKE_BUILDER=Visual Studio 15 2017 Win64 + set CMAKE_BUILD_ARCH= ) - goto start ) ) @@ -120,7 +95,7 @@ set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads mkdir %STAGING%\%BuildDir%%ARCH%R cd %Staging%\%BuildDir%%ARCH%R echo %DATE% %TIME% : Start > %StatusFile% -cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ +cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ echo %DATE% %TIME% : Release Configuration done >> %StatusFile% if "%dobuild%" == "1" ( msbuild /m "ll.vcxproj" /p:Configuration=Release /fl /flp:logfile=BlenderDeps_llvm.log;Verbosity=normal @@ -133,7 +108,7 @@ if "%NODEBUG%" == "1" goto exit cd %BUILD_DIR% mkdir %STAGING%\%BuildDir%%ARCH%D cd %Staging%\%BuildDir%%ARCH%D -cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS% +cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS% echo %DATE% %TIME% : Debug Configuration done >> %StatusFile% if "%dobuild%" == "1" ( msbuild /m "ll.vcxproj" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps_llvm.log;;Verbosity=normal diff --git a/build_files/cmake/Modules/FindBrotli.cmake b/build_files/cmake/Modules/FindBrotli.cmake index 7460a87b14a..d1e40b1966a 100644 --- a/build_files/cmake/Modules/FindBrotli.cmake +++ b/build_files/cmake/Modules/FindBrotli.cmake @@ -75,6 +75,8 @@ ENDIF() MARK_AS_ADVANCED( BROTLI_INCLUDE_DIR + BROTLI_LIBRARY_COMMON + BROTLI_LIBRARY_DEC BROTLI_LIBRARY_DIR ) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 5778699ee49..261a794b5c8 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -48,6 +48,9 @@ if(NOT DEFINED LIBDIR) unset(LIBDIR_CENTOS7_ABI) endif() +# Support restoring this value once pre-compiled libraries have been handled. +set(WITH_STATIC_LIBS_INIT ${WITH_STATIC_LIBS}) + if(EXISTS ${LIBDIR}) message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") @@ -101,10 +104,15 @@ find_package_wrapper(PNG REQUIRED) find_package_wrapper(ZLIB REQUIRED) find_package_wrapper(Zstd REQUIRED) -# FreeType compiled with Brotli compression for woff2. -find_package_wrapper(Freetype REQUIRED) -if(EXISTS ${LIBDIR}) - find_package_wrapper(Brotli REQUIRED) +if(NOT WITH_SYSTEM_FREETYPE) + # FreeType compiled with Brotli compression for woff2. + find_package_wrapper(Freetype REQUIRED) + if(EXISTS ${LIBDIR}) + find_package_wrapper(Brotli REQUIRED) + list(APPEND FREETYPE_LIBRARIES + ${BROTLI_LIBRARIES} + ) + endif() endif() if(WITH_PYTHON) @@ -541,6 +549,21 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE # # Keep last, so indirectly linked libraries don't override our own pre-compiled libs. +if(EXISTS ${LIBDIR}) + # Clear the prefix path as it causes the `LIBDIR` to override system locations. + unset(CMAKE_PREFIX_PATH) + + # Since the pre-compiled `LIBDIR` directories have been handled, don't prefer static libraries. + set(WITH_STATIC_LIBS ${WITH_STATIC_LIBS_INIT}) +endif() + +if(WITH_SYSTEM_FREETYPE) + find_package_wrapper(Freetype) + if(NOT FREETYPE_FOUND) + message(FATAL_ERROR "Failed finding system FreeType version!") + endif() +endif() + if(WITH_LZO AND WITH_SYSTEM_LZO) find_package_wrapper(LZO) if(NOT LZO_FOUND) diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 40d2e0ba814..34675be8e80 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -32,6 +32,7 @@ #include "util/color.h" #include "util/foreach.h" #include "util/log.h" +#include "util/string.h" #include "util/transform.h" #include "kernel/tables.h" @@ -462,8 +463,12 @@ void ImageTextureNode::compile(OSLCompiler &compiler) const ustring known_colorspace = metadata.colorspace; if (handle.svm_slot() == -1) { + /* OIIO currently does not support <UVTILE> substitutions natively. Replace with a format they + * understand. */ + std::string osl_filename = filename.string(); + string_replace(osl_filename, "<UVTILE>", "<U>_<V>"); compiler.parameter_texture( - "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace); + "filename", ustring(osl_filename), compress_as_srgb ? u_colorspace_raw : known_colorspace); } else { compiler.parameter_texture("filename", handle.svm_slot()); @@ -472,7 +477,8 @@ void ImageTextureNode::compile(OSLCompiler &compiler) const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) || alpha_type == IMAGE_ALPHA_CHANNEL_PACKED || alpha_type == IMAGE_ALPHA_IGNORE); - const bool is_tiled = (filename.find("<UDIM>") != string::npos); + const bool is_tiled = (filename.find("<UDIM>") != string::npos || + filename.find("<UVTILE>") != string::npos); compiler.parameter(this, "projection"); compiler.parameter(this, "projection_blend"); @@ -4388,9 +4394,6 @@ NODE_DEFINE(HairInfoNode) SOCKET_OUT_FLOAT(size, "Length"); SOCKET_OUT_FLOAT(thickness, "Thickness"); SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal"); -#if 0 /* Output for minimum hair width transparency - deactivated. */ - SOCKET_OUT_FLOAT(fade, "Fade"); -#endif SOCKET_OUT_FLOAT(index, "Random"); return type; @@ -4448,12 +4451,7 @@ void HairInfoNode::compile(SVMCompiler &compiler) if (!out->links.empty()) { compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out)); } -#if 0 - out = output("Fade"); - if(!out->links.empty()) { - compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out)); - } -#endif + out = output("Random"); if (!out->links.empty()) { int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM); diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h index 18b60b70a4b..605a19aaef0 100644 --- a/intern/cycles/util/math.h +++ b/intern/cycles/util/math.h @@ -401,7 +401,7 @@ ccl_device_inline float fractf(float x) return x - floorf(x); } -/* Adapted from godot-engine math_funcs.h. */ +/* Adapted from `godot-engine` math_funcs.h. */ ccl_device_inline float wrapf(float value, float max, float min) { float range = max - min; diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index c564085c774..acd0da8785e 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -292,7 +292,7 @@ target_link_libraries(multitest_c guardedalloc_lib wcwidth_lib ${OPENGL_gl_LIBRARY} - ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES} + ${FREETYPE_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_DL_LIBS} ${PLATFORM_LINKLIBS} diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index dd22bc2e7e0..b1453b243c0 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -54,7 +54,7 @@ set(LIB bf_gpu bf_intern_guardedalloc - ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES} + ${FREETYPE_LIBRARIES} ) if(WIN32) diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h index 61c5b2ae29e..42d85c70bc1 100644 --- a/source/blender/blenkernel/BKE_crazyspace.h +++ b/source/blender/blenkernel/BKE_crazyspace.h @@ -72,7 +72,7 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, float (**deformcos)[3]); /* -------------------------------------------------------------------- */ -/** \name Crazyspace API +/** \name Crazy-Space API * \{ */ void BKE_crazyspace_api_eval(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 6460dedb736..accdfe1ca25 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -157,7 +157,8 @@ int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct La void BKE_layer_collection_resync_forbid(void); void BKE_layer_collection_resync_allow(void); -/** Helper to fix older pre-2.80 blendfiles. +/** + * Helper to fix older pre-2.80 blend-files. * * Ensures the given `view_layer` as a valid first-level layer collection, i.e. a single one * matching the scene's master collection. This is a requirement for `BKE_layer_collection_sync`. diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 41ca8084849..358ae934088 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -522,7 +522,7 @@ set(LIB bf_simulation # For `vfontdata_freetype.c`. - ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES} + ${FREETYPE_LIBRARIES} ) if(WITH_BINRELOC) diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 26b0b72cd63..49a518607f1 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -462,7 +462,7 @@ void BKE_lib_id_make_local_generic_action_define( BLI_assert(force_copy == false || force_copy != force_local); if (force_local || force_copy) { - /* Already set by caller code, nothig to do here. */ + /* Already set by caller code, nothing to do here. */ *r_force_local = force_local; *r_force_copy = force_copy; return; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index ed0174bd592..e177b1ce29e 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -4572,7 +4572,7 @@ Mesh *BKE_object_get_editmesh_eval_final(const Object *object) const Mesh *mesh = static_cast<const Mesh *>(object->data); if (mesh->edit_mesh == nullptr) { - /* Heppens when requesting material of evaluated 3d font obejct: the evaluated object get + /* Happens when requesting material of evaluated 3d font object: the evaluated object get * converted to mesh, and it does not have edit mesh. */ return nullptr; } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index ef522e57d02..03b6d8c7381 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1560,7 +1560,8 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) clip->proxy.build_size_flag, clip->proxy.quality, true, - NULL); + NULL, + false); } WM_jobs_customdata_set(wm_job, pj, proxy_freejob); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 9f31e55439d..72c39839739 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -59,6 +59,7 @@ #include "SEQ_add.h" #include "SEQ_effects.h" +#include "SEQ_iterator.h" #include "SEQ_proxy.h" #include "SEQ_relations.h" #include "SEQ_render.h" @@ -601,29 +602,28 @@ static IMB_Proxy_Size seq_get_proxy_size_flags(bContext *C) return proxy_sizes; } -static void seq_build_proxy(bContext *C, Sequence *seq) +static void seq_build_proxy(bContext *C, SeqCollection *movie_strips) { if (U.sequencer_proxy_setup != USER_SEQ_PROXY_SETUP_AUTOMATIC) { return; } - /* Enable and set proxy size. */ - SEQ_proxy_set(seq, true); - seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C); - seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; - - /* Build proxy. */ - GSet *file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list"); wmJob *wm_job = ED_seq_proxy_wm_job_get(C); ProxyJob *pj = ED_seq_proxy_job_get(C, wm_job); - SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); - BLI_gset_free(file_list, MEM_freeN); + + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, movie_strips) { + /* Enable and set proxy size. */ + SEQ_proxy_set(seq, true); + seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C); + seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; + SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, NULL, &pj->queue, true); + } if (!WM_jobs_is_running(wm_job)) { G.is_break = false; WM_jobs_start(CTX_wm_manager(C), wm_job); } - ED_area_tag_redraw(CTX_wm_area(C)); } @@ -642,7 +642,8 @@ static void sequencer_add_movie_clamp_sound_strip_length(Scene *scene, static void sequencer_add_movie_multiple_strips(bContext *C, wmOperator *op, - SeqLoadData *load_data) + SeqLoadData *load_data, + SeqCollection *r_movie_strips) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -705,13 +706,16 @@ static void sequencer_add_movie_multiple_strips(bContext *C, sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound); seq_load_apply_generic_options(C, op, seq_sound); seq_load_apply_generic_options(C, op, seq_movie); - seq_build_proxy(C, seq_movie); + SEQ_collection_append_strip(seq_movie, r_movie_strips); } } RNA_END; } -static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data) +static bool sequencer_add_movie_single_strip(bContext *C, + wmOperator *op, + SeqLoadData *load_data, + SeqCollection *r_movie_strips) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -757,7 +761,7 @@ static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoa sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound); seq_load_apply_generic_options(C, op, seq_sound); seq_load_apply_generic_options(C, op, seq_movie); - seq_build_proxy(C, seq_movie); + SEQ_collection_append_strip(seq_movie, r_movie_strips); return true; } @@ -774,21 +778,25 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) ED_sequencer_deselect_all(scene); } + SeqCollection *movie_strips = SEQ_collection_create(__func__); const int tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); if (tot_files > 1) { - sequencer_add_movie_multiple_strips(C, op, &load_data); + sequencer_add_movie_multiple_strips(C, op, &load_data, movie_strips); } else { - if (!sequencer_add_movie_single_strip(C, op, &load_data)) { - sequencer_add_cancel(C, op); - return OPERATOR_CANCELLED; - } + sequencer_add_movie_single_strip(C, op, &load_data, movie_strips); + } + + if (SEQ_collection_len(movie_strips) == 0) { + SEQ_collection_free(movie_strips); + return OPERATOR_CANCELLED; } /* Free custom data. */ sequencer_add_cancel(C, op); + seq_build_proxy(C, movie_strips); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index 0a8eb7cb88f..fb561025da2 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -85,7 +85,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports) } bool success = SEQ_proxy_rebuild_context( - pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); + pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue, false); if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) { BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping", seq->name); @@ -137,7 +137,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) short stop = 0, do_update; float progress; - SEQ_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue); + SEQ_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue, false); for (link = queue.first; link; link = link->next) { struct SeqIndexBuildContext *context = link->data; diff --git a/source/blender/geometry/GEO_mesh_merge_by_distance.hh b/source/blender/geometry/GEO_mesh_merge_by_distance.hh index 00ba45f9dd2..1d64680a02b 100644 --- a/source/blender/geometry/GEO_mesh_merge_by_distance.hh +++ b/source/blender/geometry/GEO_mesh_merge_by_distance.hh @@ -33,8 +33,8 @@ namespace blender::geometry { * Merge selected vertices into other selected vertices within the \a merge_distance. The merged * indices favor speed over accuracy, since the results will depend on the order of the vertices. * - * \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to - * avoid copying the input. Otherwise returns the new mesh with merged geoemetry. + * \returns #std::nullopt if the mesh should not be changed (no vertices are merged), in order to + * avoid copying the input. Otherwise returns the new mesh with merged geometry. */ std::optional<Mesh *> mesh_merge_by_distance_all(const Mesh &mesh, IndexMask selection, @@ -44,8 +44,8 @@ std::optional<Mesh *> mesh_merge_by_distance_all(const Mesh &mesh, * Merge selected vertices along edges to other selected vertices. Only vertices connected by edges * are considered for merging. * - * \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to - * avoid copying the input. Otherwise returns the new mesh with merged geoemetry. + * \returns #std::nullopt if the mesh should not be changed (no vertices are merged), in order to + * avoid copying the input. Otherwise returns the new mesh with merged geometry. */ std::optional<Mesh *> mesh_merge_by_distance_connected(const Mesh &mesh, Span<bool> selection, diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index e49848a030b..1a07ebf31f6 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -563,14 +563,10 @@ static void weld_edge_groups_setup(const int medge_len, Array<WeldGroupEdge> &r_edge_groups) { /* Get weld edge groups. */ - - struct WeldGroupEdge *wegrp_iter; - int wgroups_len = wedge.size() - edge_kill_len; r_edge_groups.reinitialize(wgroups_len); r_edge_groups.fill({{0}}); MutableSpan<WeldGroupEdge> wegroups = r_edge_groups; - wegrp_iter = &r_edge_groups[0]; wgroups_len = 0; for (const int i : IndexRange(medge_len)) { @@ -584,11 +580,10 @@ static void weld_edge_groups_setup(const int medge_len, } else { we->edge_dest = we->edge_orig; - wegrp_iter->v1 = we->vert_a; - wegrp_iter->v2 = we->vert_b; + wegroups[wgroups_len].v1 = we->vert_a; + wegroups[wgroups_len].v2 = we->vert_b; r_edge_groups_map[i] = wgroups_len; wgroups_len++; - wegrp_iter++; } } else { @@ -598,6 +593,11 @@ static void weld_edge_groups_setup(const int medge_len, BLI_assert(wgroups_len == wedge.size() - edge_kill_len); + if (wgroups_len == 0) { + /* All edges in the context are collapsed. */ + return; + } + for (const WeldEdge &we : wedge) { if (we.flag == ELEM_COLLAPSED) { continue; diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index aadb52fb49c..958aab65b57 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -61,6 +61,15 @@ typedef struct GPUSelectState { char algorithm; /* allow GPU_select_begin/end without drawing */ bool use_cache; + /** + * Signifies that #GPU_select_cache_begin has been called, + * future calls to #GPU_select_begin should initialize the cache. + * + * \note #GPU_select_cache_begin could perform initialization but doesn't as it's inconvenient + * for callers making the cache begin/end calls outside lower level selection logic + * where the `mode` to pass to #GPU_select_begin yet isn't known. + */ + bool use_cache_needs_init; } GPUSelectState; static GPUSelectState g_select_state = {0}; @@ -90,9 +99,26 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, g_select_state.algorithm = ALGO_GL_QUERY; } + /* This function is called when cache has already been initialized, + * so only manipulate cache values when cache is pending. */ + if (g_select_state.use_cache_needs_init) { + g_select_state.use_cache_needs_init = false; + + switch (g_select_state.algorithm) { + case ALGO_GL_QUERY: { + g_select_state.use_cache = false; + break; + } + default: { + g_select_state.use_cache = true; + gpu_select_pick_cache_begin(); + break; + } + } + } + switch (g_select_state.algorithm) { case ALGO_GL_QUERY: { - g_select_state.use_cache = false; gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits); break; } @@ -154,12 +180,13 @@ uint GPU_select_end(void) void GPU_select_cache_begin(void) { - /* validate on GPU_select_begin, clear if not supported */ - BLI_assert(g_select_state.use_cache == false); - g_select_state.use_cache = true; - if (g_select_state.algorithm == ALGO_GL_PICK) { - gpu_select_pick_cache_begin(); - } + BLI_assert(g_select_state.select_is_active == false); + /* Ensure #GPU_select_cache_end is always called. */ + BLI_assert(g_select_state.use_cache_needs_init == false); + + /* Signal that cache should be used, instead of calling the algorithms cache-begin function. + * This is more convenient as the exact method of selection may not be known by the caller. */ + g_select_state.use_cache_needs_init = true; } void GPU_select_cache_load_id(void) @@ -173,9 +200,12 @@ void GPU_select_cache_load_id(void) void GPU_select_cache_end(void) { if (g_select_state.algorithm == ALGO_GL_PICK) { + BLI_assert(g_select_state.use_cache == true); gpu_select_pick_cache_end(); } g_select_state.use_cache = false; + /* Paranoid assignment, should already be false. */ + g_select_state.use_cache_needs_init = false; } bool GPU_select_is_cached(void) diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 737e4c6e874..ddd3dfc6879 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -673,7 +673,7 @@ uint gpu_select_pick_end(void) #endif /* first 3 are dummy values */ g_pick_state.buffer[hits][0] = 1; - g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */ + g_pick_state.buffer[hits][1] = depth_data[i].depth; g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */ g_pick_state.buffer[hits][3] = depth_data[i].id; hits++; diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc index e245d9b5269..f7622751726 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.cc +++ b/source/blender/gpu/intern/gpu_shader_create_info.cc @@ -112,7 +112,7 @@ void ShaderCreateInfo::finalize() void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info) { { - /* Check same bindpoints usage in OGL. */ + /* Check same bind-points usage in OGL. */ Set<int> images, samplers, ubos, ssbos; auto register_resource = [&](const Resource &res) -> bool { diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index 391752a31a8..6236e92a226 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -63,7 +63,10 @@ enum class Type { }; enum class BuiltinBits { - /** Allow getting barycentic coordinates inside the fragment shader. NOTE: emulated on OpenGL. */ + /** + * Allow getting barycentric coordinates inside the fragment shader. + * \note Emulated on OpenGL. + */ BARYCENTRIC_COORD = (1 << 0), FRAG_COORD = (1 << 2), FRONT_FACING = (1 << 4), diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index c32123bc15e..92d180f1140 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -423,7 +423,7 @@ static void detect_workarounds() /* Buggy interface query functions cause crashes when handling SSBOs (T93680) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY) && - (strstr(renderer, "HD Graphics 4400")|| strstr(renderer, "HD Graphics 4600"))) { + (strstr(renderer, "HD Graphics 4400") || strstr(renderer, "HD Graphics 4600"))) { GCaps.shader_storage_buffer_objects_support = false; } } // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 0d4f1d15f39..1e6e2475665 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -601,11 +601,6 @@ static char *glsl_patch_default_get() STR_CONCAT(patch, slen, "#extension GL_ARB_shading_language_420pack: enable\n"); } - if (!GLContext::shader_draw_parameters_support) { - /* Fallback: Emulate base instance using a uniform. */ - STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance;\n"); - } - /* Fallbacks. */ if (!GLContext::shader_draw_parameters_support) { STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance;\n"); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 65d7631445d..a557d7dc6d1 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -378,8 +378,9 @@ struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, IMB_Proxy_Size proxy_sizes_in_use, int quality, - bool overwrite, - struct GSet *file_list); + const bool overwrite, + struct GSet *file_list, + bool build_only_on_bad_performance); /** * Will rebuild all used indices and proxies at once. @@ -431,6 +432,7 @@ bool IMB_anim_can_produce_frames(const struct anim *anim); int ismovie(const char *filepath); int IMB_anim_get_image_width(struct anim *anim); int IMB_anim_get_image_height(struct anim *anim); +bool IMB_get_gop_decode_time(struct anim *anim); /** * diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 7aeee2740c0..a85ba65d014 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -37,6 +37,8 @@ # include "BLI_winstuff.h" #endif +#include "PIL_time.h" + #include "IMB_anim.h" #include "IMB_indexer.h" #include "imbuf.h" @@ -814,12 +816,16 @@ typedef struct FFmpegIndexBuilderContext { double pts_time_base; int frameno, frameno_gapless; int start_pts_set; + + bool build_only_on_bad_performance; + bool building_cancelled; } FFmpegIndexBuilderContext; static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, IMB_Proxy_Size proxy_sizes_in_use, - int quality) + int quality, + bool build_only_on_bad_performance) { FFmpegIndexBuilderContext *context = MEM_callocN(sizeof(FFmpegIndexBuilderContext), "FFmpeg index builder context"); @@ -831,6 +837,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, context->proxy_sizes_in_use = proxy_sizes_in_use; context->num_proxy_sizes = IMB_PROXY_MAX_SLOT; context->num_indexers = IMB_TC_MAX_SLOT; + context->build_only_on_bad_performance = build_only_on_bad_performance; memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx)); memset(context->indexer, 0, sizeof(context->indexer)); @@ -936,15 +943,17 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int { int i; + const bool do_rollback = stop || context->building_cancelled; + for (i = 0; i < context->num_indexers; i++) { if (context->tcs_in_use & tc_types[i]) { - IMB_index_builder_finish(context->indexer[i], stop); + IMB_index_builder_finish(context->indexer[i], do_rollback); } } for (i = 0; i < context->num_proxy_sizes; i++) { if (context->proxy_sizes_in_use & proxy_sizes[i]) { - free_proxy_output_ffmpeg(context->proxy_ctx[i], stop); + free_proxy_output_ffmpeg(context->proxy_ctx[i], do_rollback); } } @@ -1095,6 +1104,111 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, return 1; } +/* Get number of frames, that can be decoded in specified time period. */ +static int indexer_performance_get_decode_rate(FFmpegIndexBuilderContext *context, + const double time_period) +{ + AVFrame *in_frame = av_frame_alloc(); + AVPacket *packet = av_packet_alloc(); + + const double start = PIL_check_seconds_timer(); + int frames_decoded = 0; + + while (av_read_frame(context->iFormatCtx, packet) >= 0) { + if (packet->stream_index != context->videoStream) { + continue; + } + + int ret = avcodec_send_packet(context->iCodecCtx, packet); + while (ret >= 0) { + ret = avcodec_receive_frame(context->iCodecCtx, in_frame); + + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + + if (ret < 0) { + fprintf(stderr, "Error decoding proxy frame: %s\n", av_err2str(ret)); + break; + } + frames_decoded++; + } + + const double end = PIL_check_seconds_timer(); + + if (end > start + time_period) { + break; + } + } + + avcodec_flush_buffers(context->iCodecCtx); + av_seek_frame(context->iFormatCtx, -1, 0, AVSEEK_FLAG_BACKWARD); + return frames_decoded; +} + +/* Read up to 10k movie packets and return max GOP size detected. + * Number of packets is arbitrary. It should be as large as possible, but processed within + * reasonable time period, so detected GOP size is as close to real as possible. */ +static int indexer_performance_get_max_gop_size(FFmpegIndexBuilderContext *context) +{ + AVPacket *packet = av_packet_alloc(); + + const int packets_max = 10000; + int packet_index = 0; + int max_gop = 0; + int cur_gop = 0; + + while (av_read_frame(context->iFormatCtx, packet) >= 0) { + if (packet->stream_index != context->videoStream) { + continue; + } + packet_index++; + cur_gop++; + + if (packet->flags & AV_PKT_FLAG_KEY) { + max_gop = max_ii(max_gop, cur_gop); + cur_gop = 0; + } + + if (packet_index > packets_max) { + break; + } + } + + av_seek_frame(context->iFormatCtx, -1, 0, AVSEEK_FLAG_BACKWARD); + return max_gop; +} + +/* Assess scrubbing performance of provided file. This function is not meant to be very exact. + * It compares number number of frames decoded in reasonable time with largest detected GOP size. + * Because seeking happens in single GOP, it means, that maximum seek time can be detected this + * way. + * Since proxies use GOP size of 10 frames, skip building if detected GOP size is less or + * equal. + */ +static bool indexer_need_to_build_proxy(FFmpegIndexBuilderContext *context) +{ + if (!context->build_only_on_bad_performance) { + return true; + } + + /* Make sure, that file is not cold read. */ + indexer_performance_get_decode_rate(context, 0.1); + /* Get decode rate per 100ms. This is arbitrary, but seems to be good baseline cadence of + * seeking. */ + const int decode_rate = indexer_performance_get_decode_rate(context, 0.1); + const int max_gop_size = indexer_performance_get_max_gop_size(context); + + if (max_gop_size <= 10 || max_gop_size < decode_rate) { + printf("Skipping proxy building for %s: Decoding performance is already good.\n", + context->iFormatCtx->url); + context->building_cancelled = true; + return false; + } + + return true; +} + #endif /* ---------------------------------------------------------------------- @@ -1274,7 +1388,8 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Proxy_Size proxy_sizes_in_use, int quality, const bool overwrite, - GSet *file_list) + GSet *file_list, + bool build_only_on_bad_performance) { IndexBuildContext *context = NULL; IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use; @@ -1328,9 +1443,13 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, switch (anim->curtype) { #ifdef WITH_FFMPEG case ANIM_FFMPEG: - context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); + context = index_ffmpeg_create_context( + anim, tcs_in_use, proxy_sizes_to_build, quality, build_only_on_bad_performance); break; +#else + UNUSED_VARS(build_only_on_bad_performance); #endif + #ifdef WITH_AVI default: context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); @@ -1358,7 +1477,9 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context, switch (context->anim_type) { #ifdef WITH_FFMPEG case ANIM_FFMPEG: - index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); + if (indexer_need_to_build_proxy((FFmpegIndexBuilderContext *)context)) { + index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); + } break; #endif #ifdef WITH_AVI diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h index 68e50c5b29d..2f41389f2c6 100644 --- a/source/blender/makesdna/DNA_brush_enums.h +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -522,7 +522,7 @@ typedef enum eBrushUVSculptTool { SCULPT_TOOL_SLIDE_RELAX, \ SCULPT_TOOL_MASK) == 0) -/* ImagePaintSettings.tool */ +/** #ImagePaintSettings.tool */ typedef enum eBrushImagePaintTool { PAINT_TOOL_DRAW = 0, PAINT_TOOL_SOFTEN = 1, @@ -534,7 +534,7 @@ typedef enum eBrushImagePaintTool { /* The enums here should be kept in sync with the weight paint tool. * This is because #smooth_brush_toggle_on and #smooth_brush_toggle_off - * assumes that the Blur blursh has the same enum value. */ + * assumes that the blur brush has the same enum value. */ typedef enum eBrushVertexPaintTool { VPAINT_TOOL_DRAW = 0, VPAINT_TOOL_BLUR = 1, diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b154576df76..099e41d7ff0 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1848,7 +1848,6 @@ enum { /* math node clamp */ #define SHD_MATH_CLAMP 1 -/** Math node operations. */ typedef enum NodeMathOperation { NODE_MATH_ADD = 0, NODE_MATH_SUBTRACT = 1, @@ -1892,7 +1891,6 @@ typedef enum NodeMathOperation { NODE_MATH_SMOOTH_MAX = 39, } NodeMathOperation; -/** Vector Math node operations. */ typedef enum NodeVectorMathOperation { NODE_VECTOR_MATH_ADD = 0, NODE_VECTOR_MATH_SUBTRACT = 1, @@ -1926,7 +1924,6 @@ typedef enum NodeVectorMathOperation { NODE_VECTOR_MATH_MULTIPLY_ADD = 26, } NodeVectorMathOperation; -/** Boolean math node operations. */ typedef enum NodeBooleanMathOperation { NODE_BOOLEAN_MATH_AND = 0, NODE_BOOLEAN_MATH_OR = 1, @@ -1941,7 +1938,6 @@ typedef enum NodeBooleanMathOperation { NODE_BOOLEAN_MATH_NIMPLY = 8, } NodeBooleanMathOperation; -/** Float compare node operations. */ typedef enum NodeCompareMode { NODE_COMPARE_MODE_ELEMENT = 0, NODE_COMPARE_MODE_LENGTH = 1, @@ -1959,10 +1955,8 @@ typedef enum NodeCompareOperation { NODE_COMPARE_NOT_EQUAL = 5, NODE_COMPARE_COLOR_BRIGHTER = 6, NODE_COMPARE_COLOR_DARKER = 7, - } NodeCompareOperation; -/** Float to Int node operations. */ typedef enum FloatToIntRoundingMode { FN_NODE_FLOAT_TO_INT_ROUND = 0, FN_NODE_FLOAT_TO_INT_FLOOR = 1, diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ec9b67deeac..e2411f5f4ae 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2340,7 +2340,8 @@ static void seq_build_proxy(bContext *C, PointerRNA *ptr) seq->strip->proxy->build_size_flags |= SEQ_rendersize_to_proxysize(sseq->render_size); /* Build proxy. */ - SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); + SEQ_proxy_rebuild_context( + pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue, true); } BLI_gset_free(file_list, MEM_freeN); diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.cc b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc index e22a825c066..12c29c40b1d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hair_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc @@ -28,7 +28,6 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output<decl::Float>(N_("Length")); b.add_output<decl::Float>(N_("Thickness")); b.add_output<decl::Vector>(N_("Tangent Normal")); - // b.add_output<decl::Float>(N_("Fade")); b.add_output<decl::Float>(N_("Random")); } diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h index 7bfe932ff1c..164b279245c 100644 --- a/source/blender/sequencer/SEQ_proxy.h +++ b/source/blender/sequencer/SEQ_proxy.h @@ -42,7 +42,8 @@ bool SEQ_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list, - struct ListBase *queue); + struct ListBase *queue, + bool build_only_on_bad_performance); void SEQ_proxy_rebuild(struct SeqIndexBuildContext *context, short *stop, short *do_update, diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index cc0ea0634a3..5982f89a287 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -415,7 +415,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list, - ListBase *queue) + ListBase *queue, + bool build_only_on_bad_performance) { SeqIndexBuildContext *context; Sequence *nseq; @@ -476,7 +477,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain, context->size_flags, context->quality, context->overwrite, - file_list); + file_list, + build_only_on_bad_performance); } if (!context->index_context) { MEM_freeN(context); diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c index 86a37aca4a9..0788003fb12 100644 --- a/source/blender/sequencer/intern/sound.c +++ b/source/blender/sequencer/intern/sound.c @@ -31,6 +31,7 @@ #include "DNA_sound_types.h" #include "BLI_listbase.h" +#include "BLI_utildefines.h" #include "BKE_main.h" #include "BKE_scene.h" @@ -56,11 +57,15 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, } } else if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound) { - const float length = BKE_sound_get_length(bmain, seq->sound); + SoundInfo info; + if (!BKE_sound_info_get(bmain, seq->sound, &info)) { + continue; + } + int old = seq->len; float fac; - seq->len = (int)ceil((double)length * FPS); + seq->len = MAX2(1, round((info.length - seq->sound->offset_time) * FPS)); fac = (float)seq->len / (float)old; old = seq->startofs; seq->startofs *= fac; diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index d3e682f1490..e61de28d0a4 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -38,9 +38,11 @@ #include "ED_select_utils.h" #include "ED_view3d.h" +#include "GPU_framebuffer.h" #include "GPU_matrix.h" #include "GPU_select.h" #include "GPU_state.h" +#include "GPU_viewport.h" #include "MEM_guardedalloc.h" @@ -505,8 +507,7 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap, static void gizmo_draw_select_3d_loop(const bContext *C, wmGizmo **visible_gizmos, - const int visible_gizmos_len, - bool *r_use_select_bias) + const int visible_gizmos_len) { /* TODO(campbell): this depends on depth buffer being written to, @@ -542,10 +543,6 @@ static void gizmo_draw_select_3d_loop(const bContext *C, is_depth_skip_prev = is_depth_skip; } - if (gz->select_bias != 0.0) { - *r_use_select_bias = true; - } - /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */ gz->type->draw_select(C, gz, select_id << 8); @@ -563,7 +560,10 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, const int visible_gizmos_len, const bContext *C, const int co[2], - const int hotspot) + const int hotspot, + const bool use_depth_test, + const bool has_3d_select_bias, + int *r_hits) { const wmWindowManager *wm = CTX_wm_manager(C); ScrArea *area = CTX_wm_area(C); @@ -577,30 +577,69 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, BLI_rcti_init_pt_radius(&rect, co, hotspot); - ED_view3d_draw_setup_view( - wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect); - - bool use_select_bias = false; + /* The selection mode is assigned for the following reasons: + * + * - #GPU_SELECT_ALL: Use it to check if there is anything at the cursor location + * (only ever runs once). + * - #GPU_SELECT_PICK_NEAREST: Use if there are more than 1 item at the cursor location, + * select the best one. + * - #GPU_SELECT_PICK_ALL: Use for the same purpose as #GPU_SELECT_PICK_NEAREST + * when the selection depths need to re-ordered based on a bias. + * */ + const int gpu_select_mode = (use_depth_test ? + (has_3d_select_bias ? + /* Using select bias means the depths need to be + * re-calculated based on the bias to pick the best. */ + GPU_SELECT_PICK_ALL : + /* No bias, just pick the closest. */ + GPU_SELECT_PICK_NEAREST) : + /* Fast-path (occlusion queries). */ + GPU_SELECT_ALL); + + if (GPU_select_is_cached()) { + GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0); + GPU_select_cache_load_id(); + hits = GPU_select_end(); + } + else { + /* TODO: waiting for the GPU in the middle of the event loop for every + * mouse move is bad for performance, we need to find a solution to not + * use the GPU or draw something once. (see T61474) */ + + ED_view3d_draw_setup_view( + wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect); + + /* There is no need to bind to the depth buffer outside this function + * because all future passes the will use the cached depths. */ + GPUFrameBuffer *depth_read_fb = NULL; + if (use_depth_test) { + GPUViewport *viewport = WM_draw_region_get_viewport(CTX_wm_region(C)); + GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport); + GPU_framebuffer_ensure_config(&depth_read_fb, + { + GPU_ATTACHMENT_TEXTURE(depth_tx), + GPU_ATTACHMENT_NONE, + }); + GPU_framebuffer_bind(depth_read_fb); + } - /* TODO: waiting for the GPU in the middle of the event loop for every - * mouse move is bad for performance, we need to find a solution to not - * use the GPU or draw something once. (see T61474) */ - GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); - /* do the drawing */ - gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias); + GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0); + gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len); + hits = GPU_select_end(); - hits = GPU_select_end(); + if (use_depth_test) { + GPU_framebuffer_restore(); + GPU_framebuffer_free(depth_read_fb); + } - if (hits > 0) { - GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias); - GPU_select_end(); + ED_view3d_draw_setup_view( + wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL); } - ED_view3d_draw_setup_view( - wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL); + /* When selection bias is needed, this function will run again with `use_depth_test` enabled. */ + int hit_found = -1; - if (use_select_bias && (hits > 1)) { + if (has_3d_select_bias && use_depth_test && (hits > 1)) { float co_direction[3]; float co_screen[3] = {co[0], co[1], 0.0f}; ED_view3d_win_to_vector(region, (float[2]){UNPACK2(co)}, co_direction); @@ -612,7 +651,6 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin); uint *buf_iter = buffer; - int hit_found = -1; float dot_best = FLT_MAX; for (int i = 0; i < hits; i++, buf_iter += 4) { @@ -632,11 +670,16 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, hit_found = buf_iter[3]; } } - return hit_found; + } + else { + const uint *hit_near = GPU_select_buffer_near(buffer, hits); + if (hit_near) { + hit_found = hit_near[3]; + } } - const uint *hit_near = GPU_select_buffer_near(buffer, hits); - return hit_near ? hit_near[3] : -1; + *r_hits = hits; + return hit_found; } /** @@ -659,6 +702,7 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C, /* Search for 3D gizmo's that use the 2D callback for checking intersections. */ bool has_3d = false; + bool has_3d_select_bias = false; { for (int select_id = 0; select_id < visible_gizmos_len; select_id++) { wmGizmo *gz = visible_gizmos[select_id]; @@ -674,6 +718,9 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C, } else if (gz->type->draw_select != NULL) { has_3d = true; + if (gz->select_bias != 0.0f) { + has_3d_select_bias = true; + } } } } @@ -681,17 +728,78 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C, /* Search for 3D intersections if they're before 2D that have been found (if any). * This way we always use the first hit. */ if (has_3d) { + + /* NOTE(@campbellbarton): The selection logic here uses a fast-path that exits early + * where possible. This is important as this runs on cursor-motion in the 3D view-port. + * + * - First, don't use the depth buffer at all, use occlusion queries to detect any gizmos. + * If there are no gizmos or only one - early exit, otherwise. + * + * - Bind the depth buffer and and use selection picking logic. + * This is much slower than occlusion queries (since it's reading depths while drawing). + * When there is a single gizmo under the cursor (quite common), early exit, otherwise. + * + * - Perform another pass at a reduced size (see: `hotspot_radii`), + * since the result depths are cached this pass is practically free. + * + * Other notes: + * + * - If any of these passes fail, use the nearest result from the previous pass. + * + * - Drawing is only ever done twice. + */ + + /* Order largest to smallest so the first pass can be used as cache for + * later passes (when `use_depth_test == true`). */ const int hotspot_radii[] = { - 3 * U.pixelsize, - /* This runs on mouse move, careful doing too many tests! */ 10 * U.pixelsize, + /* This runs on mouse move, careful doing too many tests! */ + 3 * U.pixelsize, }; + + /* Narrowing may assign zero to `hit`, allow falling back to the previous test. */ + int hit_prev = -1; + + bool use_depth_test = false; + bool use_depth_cache = false; + for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) { - hit = gizmo_find_intersected_3d_intern( - visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]); - if (hit != -1) { + + if (use_depth_test && (use_depth_cache == false)) { + GPU_select_cache_begin(); + use_depth_cache = true; + } + + int hit_count; + hit = gizmo_find_intersected_3d_intern(visible_gizmos, + visible_gizmos_len_trim, + C, + co, + hotspot_radii[i], + use_depth_test, + has_3d_select_bias, + &hit_count); + /* Only continue searching when there are multiple options to narrow down. */ + if (hit_count < 2) { break; } + + /* Fast path for simple case, one item or nothing. */ + if (use_depth_test == false) { + /* Restart, using depth buffer (slower). */ + use_depth_test = true; + i = -1; + } + hit_prev = hit; + } + /* Narrowing the search area may yield no hits, + * in this case fall back to the previous search. */ + if (hit == -1) { + hit = hit_prev; + } + + if (use_depth_cache) { + GPU_select_cache_end(); } if (hit != -1) { |