Merge branch 'blender-v5.0-release'

This commit is contained in:
Sergey Sharybin
2025-10-15 16:14:19 +02:00
3 changed files with 90 additions and 17 deletions

View File

@@ -77,9 +77,13 @@ ExternalProject_Add(external_osl
URL_HASH ${OSL_HASH_TYPE}=${OSL_HASH} URL_HASH ${OSL_HASH_TYPE}=${OSL_HASH}
PREFIX ${BUILD_DIR}/osl PREFIX ${BUILD_DIR}/osl
PATCH_COMMAND ${PATCH_CMD} -p 1 -d PATCH_COMMAND
${BUILD_DIR}/osl/src/external_osl < ${PATCH_CMD} -p 1 -d
${PATCH_DIR}/osl.diff ${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 CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${LIBDIR}/osl -DCMAKE_INSTALL_PREFIX=${LIBDIR}/osl

View File

@@ -0,0 +1,48 @@
From 69d11b6eebcfb1501193184333280ebd5985564e Mon Sep 17 00:00:00 2001
From: Sergey Sharybin <sergey@blender.org>
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 <sergey@blender.org>
---
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

View File

@@ -210,6 +210,25 @@ static IndexMask mask_first_distinct_edges(const Span<int2> edges,
}); });
} }
static void map_edge_to_span_index(const Span<int2> edges,
const Span<EdgeMap> edge_maps,
const uint32_t parallel_mask,
const OffsetIndices<int> edge_offsets,
MutableSpan<int> 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 } // namespace calc_edges
void mesh_calc_edges(Mesh &mesh, void mesh_calc_edges(Mesh &mesh,
@@ -269,6 +288,8 @@ void mesh_calc_edges(Mesh &mesh,
corner_edges.fill(-1); corner_edges.fill(-1);
#endif #endif
const int result_edges_num = edge_offsets.total_size();
const OffsetIndices<int> faces = mesh.faces(); const OffsetIndices<int> faces = mesh.faces();
const Span<int2> original_edges = mesh.edges(); const Span<int2> original_edges = mesh.edges();
const Span<int> corner_verts = mesh.corner_verts(); const Span<int> corner_verts = mesh.corner_verts();
@@ -277,13 +298,20 @@ void mesh_calc_edges(Mesh &mesh,
* that case. TODO: make this optional. */ * that case. TODO: make this optional. */
calc_edges::update_edge_indices_in_face_loops( calc_edges::update_edge_indices_in_face_loops(
faces, corner_verts, edge_maps, parallel_mask, edge_offsets, corner_edges); faces, corner_verts, edge_maps, parallel_mask, edge_offsets, corner_edges);
Array<int> 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(!corner_edges.contains(-1));
BLI_assert(BKE_mesh_is_valid(&mesh)); BLI_assert(BKE_mesh_is_valid(&mesh));
return; return;
} }
const int result_edges_num = edge_offsets.total_size();
IndexMaskMemory memory; IndexMaskMemory memory;
IndexRange back_range_of_new_edges; IndexRange back_range_of_new_edges;
IndexMask src_to_dst_mask; IndexMask src_to_dst_mask;
@@ -322,18 +350,11 @@ void mesh_calc_edges(Mesh &mesh,
if (original_edges_are_distinct) { if (original_edges_are_distinct) {
/* TODO: Do we can group edges by .low vertex? Or by hash, but with Span<int> of edges by /* TODO: Do we can group edges by .low vertex? Or by hash, but with Span<int> of edges by
* group?... */ * group?... */
threading::parallel_for_each(edge_maps.index_range(), [&](const int map_i) { calc_edges::map_edge_to_span_index(original_edges.take_front(mesh.edges_num),
int edge_map_iter = 0; edge_maps,
for (const int edge_i : IndexRange(mesh.edges_num)) { parallel_mask,
const int edge_map = calc_edges::edge_to_hash_map_i(original_edges[edge_i], edge_offsets,
parallel_mask); edge_map_to_result_index);
if (map_i != edge_map) {
continue;
}
edge_map_to_result_index[edge_offsets[edge_map][edge_map_iter]] = edge_i;
edge_map_iter++;
}
});
} }
else { else {
src_to_dst_mask.foreach_index( src_to_dst_mask.foreach_index(