Merge branch 'blender-v5.0-release'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
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<int> faces = mesh.faces();
|
||||
const Span<int2> original_edges = mesh.edges();
|
||||
const Span<int> 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<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(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<int> 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(
|
||||
|
||||
Reference in New Issue
Block a user