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}
|
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
|
||||||
|
|||||||
@@ -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
|
} // 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(
|
||||||
|
|||||||
Reference in New Issue
Block a user