diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake index f629c964908..f8a1d781486 100644 --- a/build_files/build_environment/cmake/osl.cmake +++ b/build_files/build_environment/cmake/osl.cmake @@ -77,9 +77,13 @@ ExternalProject_Add(external_osl URL_HASH ${OSL_HASH_TYPE}=${OSL_HASH} PREFIX ${BUILD_DIR}/osl - PATCH_COMMAND ${PATCH_CMD} -p 1 -d - ${BUILD_DIR}/osl/src/external_osl < - ${PATCH_DIR}/osl.diff + PATCH_COMMAND + ${PATCH_CMD} -p 1 -d + ${BUILD_DIR}/osl/src/external_osl < + ${PATCH_DIR}/osl.diff && + ${PATCH_CMD} -p 1 -d + ${BUILD_DIR}/osl/src/external_osl < + ${PATCH_DIR}/osl_supports_isa_thread.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/osl diff --git a/build_files/build_environment/patches/osl_supports_isa_thread.diff b/build_files/build_environment/patches/osl_supports_isa_thread.diff new file mode 100644 index 00000000000..6d1886aef4c --- /dev/null +++ b/build_files/build_environment/patches/osl_supports_isa_thread.diff @@ -0,0 +1,48 @@ +From 69d11b6eebcfb1501193184333280ebd5985564e Mon Sep 17 00:00:00 2001 +From: Sergey Sharybin +Date: Thu, 9 Oct 2025 12:25:09 +0200 +Subject: [PATCH] Fix: LLVM_Util::supports_isa is not thread-safe + +The supports_isa() function might be called from threads, and prior +to this change it might have added entries to the global sCpuFeatures +variable. This happened when detect_cpu_features() is called with +TargetISA::UNKNOWN and the code was looking for the best ISA. This +could lead to situation when the host CPU is ARM, and the probing +happens for AVX512. + +This change ensures that the supports_isa() accesses sCpuFeatures +in the read-only manner. + +This was originally noticed as unreliable OSL render tests in Blender +reported at https://projects.blender.org/blender/blender/issues/147642 + +Signed-off-by: Sergey Sharybin +--- + src/liboslexec/llvm_util.cpp | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/liboslexec/llvm_util.cpp b/src/liboslexec/llvm_util.cpp +index f9b1296d..2d952567 100644 +--- a/src/liboslexec/llvm_util.cpp ++++ b/src/liboslexec/llvm_util.cpp +@@ -1443,7 +1443,16 @@ LLVM_Util::supports_isa(TargetISA target) + continue; + } + OSL_DEV_ONLY(std::cout << "Testing for cpu feature:" << f << std::endl); +- if (sCpuFeatures[f] == false) { ++ // The required CPU feature for the specified target might not be in ++ // the sCpuFeatures. This happens, for example, when the code is probing ++ // the best target ISA when the requested one is UNKNOWN. In this case ++ // it is possible that this function is called for the TargetISA::AVX512 ++ // on an ARM CPU. ++ // This function might be called from multiple threads, so it is important ++ // to keep the access to sCpuFeatures read-only. ++ const auto cpu_feature_it = sCpuFeatures.find(f); ++ if (cpu_feature_it == sCpuFeatures.end() ++ || cpu_feature_it->second == false) { + OSL_DEV_ONLY(std::cout << "MISSING cpu feature:" << f << std::endl); + return false; + } +-- +2.51.0 + diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index 8f2f112cd0b..7bdd22361cd 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -210,6 +210,25 @@ static IndexMask mask_first_distinct_edges(const Span edges, }); } +static void map_edge_to_span_index(const Span edges, + const Span edge_maps, + const uint32_t parallel_mask, + const OffsetIndices edge_offsets, + MutableSpan indices) +{ + threading::parallel_for_each(edge_maps.index_range(), [&](const int map_i) { + int edge_map_iter = 0; + for (const int edge_i : edges.index_range()) { + const int edge_map = calc_edges::edge_to_hash_map_i(edges[edge_i], parallel_mask); + if (map_i != edge_map) { + continue; + } + indices[edge_offsets[edge_map][edge_map_iter]] = edge_i; + edge_map_iter++; + } + }); +} + } // namespace calc_edges void mesh_calc_edges(Mesh &mesh, @@ -269,6 +288,8 @@ void mesh_calc_edges(Mesh &mesh, corner_edges.fill(-1); #endif + const int result_edges_num = edge_offsets.total_size(); + const OffsetIndices faces = mesh.faces(); const Span original_edges = mesh.edges(); const Span corner_verts = mesh.corner_verts(); @@ -277,13 +298,20 @@ void mesh_calc_edges(Mesh &mesh, * that case. TODO: make this optional. */ calc_edges::update_edge_indices_in_face_loops( faces, corner_verts, edge_maps, parallel_mask, edge_offsets, corner_edges); + + Array edge_map_to_result_index(result_edges_num); +#ifndef NDEBUG + edge_map_to_result_index.as_mutable_span().fill(-1); +#endif + calc_edges::map_edge_to_span_index( + original_edges, edge_maps, parallel_mask, edge_offsets, edge_map_to_result_index); + array_utils::gather(edge_map_to_result_index.as_span(), corner_edges.as_span(), corner_edges); + BLI_assert(!corner_edges.contains(-1)); BLI_assert(BKE_mesh_is_valid(&mesh)); return; } - const int result_edges_num = edge_offsets.total_size(); - IndexMaskMemory memory; IndexRange back_range_of_new_edges; IndexMask src_to_dst_mask; @@ -322,18 +350,11 @@ void mesh_calc_edges(Mesh &mesh, if (original_edges_are_distinct) { /* TODO: Do we can group edges by .low vertex? Or by hash, but with Span of edges by * group?... */ - threading::parallel_for_each(edge_maps.index_range(), [&](const int map_i) { - int edge_map_iter = 0; - for (const int edge_i : IndexRange(mesh.edges_num)) { - const int edge_map = calc_edges::edge_to_hash_map_i(original_edges[edge_i], - parallel_mask); - if (map_i != edge_map) { - continue; - } - edge_map_to_result_index[edge_offsets[edge_map][edge_map_iter]] = edge_i; - edge_map_iter++; - } - }); + calc_edges::map_edge_to_span_index(original_edges.take_front(mesh.edges_num), + edge_maps, + parallel_mask, + edge_offsets, + edge_map_to_result_index); } else { src_to_dst_mask.foreach_index(