Fix #109583: Avoid non-threadsafe writing to custom normals data #112055
@ -155,9 +155,9 @@ void normals_calc_loop(Span<float3> vert_positions,
|
||||
Span<float3> poly_normals,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
const short2 *clnors_data,
|
||||
bool use_split_normals,
|
||||
float split_angle,
|
||||
short2 *clnors_data,
|
||||
CornerNormalSpaceArray *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_loop_normals);
|
||||
|
||||
|
@ -372,8 +372,8 @@ static void data_transfer_dtdata_type_preprocess(const Mesh *me_src,
|
||||
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr);
|
||||
(void)me_src;
|
||||
|
||||
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
|
||||
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
|
||||
const blender::short2 *custom_nors_dst = static_cast<const blender::short2 *>(
|
||||
CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL));
|
||||
|
||||
/* Cache loop nors into a temp CDLayer. */
|
||||
blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
|
||||
@ -399,9 +399,9 @@ static void data_transfer_dtdata_type_preprocess(const Mesh *me_src,
|
||||
me_dst->poly_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
custom_nors_dst,
|
||||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
custom_nors_dst,
|
||||
nullptr,
|
||||
{loop_nors_dst, me_dst->totloop});
|
||||
}
|
||||
|
@ -2281,8 +2281,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert});
|
||||
}
|
||||
if (loop_normals_needed) {
|
||||
blender::short2 *clnors = static_cast<blender::short2 *>(
|
||||
CustomData_get_layer_for_write(&mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
|
||||
const blender::short2 *clnors = static_cast<const blender::short2 *>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL));
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
@ -2298,9 +2298,9 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
clnors,
|
||||
(mesh->flag & ME_AUTOSMOOTH) != 0,
|
||||
mesh->smoothresh,
|
||||
clnors,
|
||||
nullptr,
|
||||
{reinterpret_cast<blender::float3 *>(r_loop_normals), corner_verts.size()});
|
||||
}
|
||||
|
@ -1884,9 +1884,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
||||
((mesh->flag & ME_AUTOSMOOTH) != 0);
|
||||
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
|
||||
|
||||
/* may be nullptr */
|
||||
blender::short2 *clnors = (blender::short2 *)CustomData_get_layer_for_write(
|
||||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop);
|
||||
const blender::short2 *clnors = static_cast<const blender::short2 *>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL));
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
@ -1903,9 +1902,9 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
||||
mesh->poly_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
clnors,
|
||||
use_split_normals,
|
||||
split_angle,
|
||||
clnors,
|
||||
nullptr,
|
||||
{reinterpret_cast<float3 *>(r_corner_normals), mesh->totloop});
|
||||
}
|
||||
|
@ -414,9 +414,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
result->poly_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
clnors,
|
||||
true,
|
||||
result->smoothresh,
|
||||
clnors,
|
||||
&lnors_spacearr,
|
||||
loop_normals);
|
||||
|
||||
|
@ -713,7 +713,6 @@ struct LoopSplitTaskDataCommon {
|
||||
* different elements in the arrays. */
|
||||
CornerNormalSpaceArray *lnors_spacearr;
|
||||
MutableSpan<float3> loop_normals;
|
||||
MutableSpan<short2> clnors_data;
|
||||
|
||||
/* Read-only. */
|
||||
Span<float3> positions;
|
||||
@ -725,6 +724,7 @@ struct LoopSplitTaskDataCommon {
|
||||
Span<int> loop_to_poly;
|
||||
Span<float3> poly_normals;
|
||||
Span<float3> vert_normals;
|
||||
Span<short2> clnors_data;
|
||||
};
|
||||
|
||||
#define INDEX_UNSET INT_MIN
|
||||
@ -936,7 +936,6 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
{
|
||||
CornerNormalSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
|
||||
MutableSpan<float3> loop_normals = common_data->loop_normals;
|
||||
MutableSpan<short2> clnors_data = common_data->clnors_data;
|
||||
|
||||
const Span<float3> positions = common_data->positions;
|
||||
const Span<int2> edges = common_data->edges;
|
||||
@ -946,6 +945,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
const Span<int2> edge_to_loops = common_data->edge_to_loops;
|
||||
const Span<int> loop_to_poly = common_data->loop_to_poly;
|
||||
const Span<float3> poly_normals = common_data->poly_normals;
|
||||
const Span<short2> clnors_data = common_data->clnors_data;
|
||||
|
||||
const int poly_index = loop_to_poly[ml_curr_index];
|
||||
const int ml_prev_index = poly_corner_prev(polys[poly_index], ml_curr_index);
|
||||
@ -966,11 +966,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
float3 vec_org;
|
||||
float3 lnor(0.0f);
|
||||
|
||||
/* We validate clnors data on the fly - cheapest way to do! */
|
||||
int2 clnors_avg(0);
|
||||
short2 *clnor_ref = nullptr;
|
||||
int clnors_count = 0;
|
||||
bool clnors_invalid = false;
|
||||
|
||||
Vector<int, 8> processed_corners;
|
||||
|
||||
@ -1019,22 +1015,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
const float fac = saacos(dot_v3v3(vec_curr, vec_prev));
|
||||
/* Accumulate */
|
||||
lnor += poly_normals[mpfan_curr_index] * fac;
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
/* Accumulate all clnors, if they are not all equal we have to fix that! */
|
||||
short2 *clnor = &clnors_data[mlfan_vert_index];
|
||||
if (clnors_count) {
|
||||
clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
|
||||
}
|
||||
else {
|
||||
clnor_ref = clnor;
|
||||
}
|
||||
clnors_avg[0] += (*clnor)[0];
|
||||
clnors_avg[1] += (*clnor)[1];
|
||||
clnors_count++;
|
||||
}
|
||||
}
|
||||
|
||||
processed_corners.append(mlfan_vert_index);
|
||||
|
||||
if (lnors_spacearr) {
|
||||
@ -1045,6 +1026,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
if (!lnors_spacearr->corners_by_space.is_empty()) {
|
||||
lnors_spacearr->corners_by_space[space_index] = processed_corners.as_span();
|
||||
}
|
||||
if (!clnors_data.is_empty()) {
|
||||
clnors_avg += int2(clnors_data[mlfan_vert_index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_EDGE_SHARP(edge_to_loops[corner_edges[mlfan_curr_index]]) || (edge == edge_orig)) {
|
||||
@ -1086,21 +1070,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
edge_vectors->clear();
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
if (clnors_invalid) {
|
||||
clnors_avg[0] /= clnors_count;
|
||||
clnors_avg[1] /= clnors_count;
|
||||
/* Fix/update all clnors of this fan with computed average value. */
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("Invalid clnors in this fan!\n");
|
||||
}
|
||||
clnors_data.fill_indices(processed_corners.as_span(),
|
||||
short2(clnors_avg[0], clnors_avg[1]));
|
||||
// print_v2("new clnors", clnors_avg);
|
||||
}
|
||||
/* Extra bonus: since small-stack is local to this function,
|
||||
* no more need to empty it at all cost! */
|
||||
|
||||
lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
|
||||
clnors_avg /= processed_corners.size();
|
||||
lnor_space_custom_data_to_normal(lnor_space, short2(clnors_avg), lnor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1274,9 +1245,9 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
const Span<float3> poly_normals,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
const short2 *clnors_data,
|
||||
bool use_split_normals,
|
||||
float split_angle,
|
||||
short2 *clnors_data,
|
||||
CornerNormalSpaceArray *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_loop_normals)
|
||||
{
|
||||
@ -1350,8 +1321,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
LoopSplitTaskDataCommon common_data;
|
||||
common_data.lnors_spacearr = r_lnors_spacearr;
|
||||
common_data.loop_normals = r_loop_normals;
|
||||
common_data.clnors_data = {reinterpret_cast<short2 *>(clnors_data),
|
||||
clnors_data ? corner_verts.size() : 0};
|
||||
common_data.clnors_data = {clnors_data, clnors_data ? corner_verts.size() : 0};
|
||||
common_data.positions = vert_positions;
|
||||
common_data.edges = edges;
|
||||
common_data.polys = polys;
|
||||
@ -1461,9 +1431,9 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
poly_normals,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
r_clnors_data.data(),
|
||||
use_split_normals,
|
||||
split_angle,
|
||||
r_clnors_data.data(),
|
||||
&lnors_spacearr,
|
||||
loop_normals);
|
||||
|
||||
@ -1583,9 +1553,9 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
poly_normals,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
r_clnors_data.data(),
|
||||
use_split_normals,
|
||||
split_angle,
|
||||
r_clnors_data.data(),
|
||||
&lnors_spacearr,
|
||||
loop_normals);
|
||||
}
|
||||
|
@ -1336,8 +1336,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
poly_normals_dst = mesh_dst->poly_normals();
|
||||
}
|
||||
if (need_lnors_dst) {
|
||||
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
|
||||
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, numloops_dst));
|
||||
const blender::short2 *custom_nors_dst = static_cast<const blender::short2 *>(
|
||||
CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL));
|
||||
|
||||
/* Cache loop normals into a temporary custom data layer. */
|
||||
loop_normals_dst = static_cast<blender::float3 *>(
|
||||
@ -1365,9 +1365,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
mesh_dst->poly_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
custom_nors_dst,
|
||||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
custom_nors_dst,
|
||||
nullptr,
|
||||
{loop_normals_dst, numloops_dst});
|
||||
}
|
||||
|
@ -336,8 +336,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
}
|
||||
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
|
||||
mr->loop_normals.reinitialize(mr->corner_verts.size());
|
||||
blender::short2 *clnors = static_cast<blender::short2 *>(
|
||||
CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop));
|
||||
const blender::short2 *clnors = static_cast<const blender::short2 *>(
|
||||
CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL));
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mr->me->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
blender::bke::mesh::normals_calc_loop(mr->vert_positions,
|
||||
@ -350,9 +350,9 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
mr->poly_normals,
|
||||
sharp_edges,
|
||||
mr->sharp_faces,
|
||||
clnors,
|
||||
is_auto_smooth,
|
||||
split_angle,
|
||||
clnors,
|
||||
nullptr,
|
||||
mr->loop_normals);
|
||||
}
|
||||
|
@ -552,9 +552,9 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
||||
result->poly_normals(),
|
||||
sharp_edges.span.data(),
|
||||
sharp_faces,
|
||||
clnors,
|
||||
true,
|
||||
result->smoothresh,
|
||||
clnors,
|
||||
nullptr,
|
||||
loop_normals);
|
||||
}
|
||||
|
@ -229,9 +229,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
|
||||
wn_data->poly_normals,
|
||||
wn_data->sharp_edges.data(),
|
||||
wn_data->sharp_faces,
|
||||
has_clnors ? clnors.data() : nullptr,
|
||||
true,
|
||||
split_angle,
|
||||
has_clnors ? clnors.data() : nullptr,
|
||||
&lnors_spacearr,
|
||||
loop_normals);
|
||||
|
||||
@ -360,9 +360,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
|
||||
poly_normals,
|
||||
wn_data->sharp_edges.data(),
|
||||
wn_data->sharp_faces,
|
||||
has_clnors ? clnors.data() : nullptr,
|
||||
true,
|
||||
split_angle,
|
||||
has_clnors ? clnors.data() : nullptr,
|
||||
nullptr,
|
||||
loop_normals);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user