From b04a72866d51b33428e74420d5fa8985b595a7b0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sat, 12 Aug 2023 16:37:02 -0400 Subject: [PATCH] Revert "Multires: Simplify grids normals update and grid to face map" This reverts commit c97178fa2eab80df3d5a31959083488c0c6a3068. This was committed to main by mistake, it was meant for a local branch. --- source/blender/blenkernel/BKE_pbvh_api.hh | 9 +- source/blender/blenkernel/BKE_subdiv_ccg.hh | 10 +- source/blender/blenkernel/intern/multires.cc | 11 +- source/blender/blenkernel/intern/paint.cc | 4 +- source/blender/blenkernel/intern/pbvh.cc | 66 +++-- .../blender/blenkernel/intern/pbvh_intern.hh | 2 +- .../blender/blenkernel/intern/subdiv_ccg.cc | 256 ++++++++++++------ 7 files changed, 240 insertions(+), 118 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh_api.hh b/source/blender/blenkernel/BKE_pbvh_api.hh index c99b78a9245..072329b9f4e 100644 --- a/source/blender/blenkernel/BKE_pbvh_api.hh +++ b/source/blender/blenkernel/BKE_pbvh_api.hh @@ -14,7 +14,6 @@ #include "BLI_bitmap.h" #include "BLI_compiler_compat.h" #include "BLI_ghash.h" -#include "BLI_index_mask.hh" #include "BLI_math_vector_types.hh" #include "BLI_offset_indices.hh" #include "BLI_vector.hh" @@ -211,7 +210,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, CCGElem **grids, int totgrid, CCGKey *key, - blender::Span gridfaces, + void **gridfaces, DMFlagMat *flagmats, unsigned int **grid_hidden, Mesh *me, @@ -444,12 +443,10 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags); void BKE_pbvh_update_visibility(PBVH *pbvh); void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg); void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]); -blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh, - blender::Span nodes, - blender::IndexMaskMemory &memory); +void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface); void BKE_pbvh_grids_update(PBVH *pbvh, CCGElem **grids, - blender::Span gridfaces, + void **gridfaces, DMFlagMat *flagmats, unsigned int **grid_hidden, CCGKey *key); diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.hh b/source/blender/blenkernel/BKE_subdiv_ccg.hh index 816dfbdb3b1..4401075cef7 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.hh +++ b/source/blender/blenkernel/BKE_subdiv_ccg.hh @@ -8,7 +8,6 @@ #pragma once -#include "BLI_array.hh" #include "BLI_bitmap.h" #include "BLI_offset_indices.hh" #include "BLI_sys_types.h" @@ -160,7 +159,7 @@ struct SubdivCCG { int num_faces; SubdivCCGFace *faces; /* Indexed by grid index, points to corresponding face from `faces`. */ - blender::Array grid_faces; + SubdivCCGFace **grid_faces; /* Edges which are adjacent to faces. * Used for faster grid stitching, in the cost of extra memory. @@ -236,14 +235,17 @@ void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg); void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg); /* Update normals of affected faces. */ -void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, const blender::IndexMask &face_mask); +void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, + CCGFace **effected_faces, + int num_effected_faces); /* Average grid coordinates and normals along the grid boundaries. */ void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg); /* Similar to above, but only updates given faces. */ void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg, - const blender::IndexMask &face_mask); + CCGFace **effected_faces, + int num_effected_faces); /* Get geometry counters at the current subdivision level. */ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg, diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index 3406237f4f7..9b02ace2097 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -1226,11 +1226,12 @@ void multires_stitch_grids(Object *ob) /* NOTE: Currently CCG does not keep track of faces, making it impossible * to use BKE_pbvh_get_grid_updates(). */ - blender::IndexMaskMemory memory; - blender::Vector nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr); - const blender::IndexMask mask = BKE_pbvh_get_grid_updates(pbvh, nodes, memory); - if (!mask.is_empty()) { - BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, mask); + CCGFace **faces; + int num_faces; + BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces); + if (num_faces) { + BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces); + MEM_freeN(faces); } } diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 8380448d9a1..51eaa9f2b91 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -2260,7 +2260,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg) subdiv_ccg->grids, subdiv_ccg->num_grids, &key, - subdiv_ccg->grid_faces, + (void **)subdiv_ccg->grid_faces, subdiv_ccg->grid_flag_mats, subdiv_ccg->grid_hidden, base_mesh, @@ -2349,7 +2349,7 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg) BKE_pbvh_grids_update(pbvh, subdiv_ccg->grids, - subdiv_ccg->grid_faces, + (void **)subdiv_ccg->grid_faces, subdiv_ccg->grid_flag_mats, subdiv_ccg->grid_hidden, &key); diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 3c4581c69c3..e957fe118ae 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -927,7 +927,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, CCGElem **grids, int totgrid, CCGKey *key, - blender::Span gridfaces, + void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden, Mesh *me, @@ -1742,21 +1742,49 @@ void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]) copy_v3_v3(bb_max, bb.bmax); } -blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh, - const Span nodes, - blender::IndexMaskMemory &memory) +void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface) { - using namespace blender; - Array faces_to_update(pbvh->faces_num, false); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const PBVHNode *node : nodes.slice(range)) { + GSet *face_set = BLI_gset_ptr_new(__func__); + PBVHNode *node; + PBVHIter iter; + + pbvh_iter_begin(&iter, pbvh, nullptr, nullptr); + + while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) { + if (node->flag & PBVH_UpdateNormals) { for (const int grid : node->prim_indices) { - const int face = pbvh->gridfaces[grid]; - faces_to_update[face] = true; + void *face = pbvh->gridfaces[grid]; + BLI_gset_add(face_set, face); + } + + if (clear) { + node->flag &= ~PBVH_UpdateNormals; + } } } - }); - return IndexMask::from_bools(faces_to_update, memory); + + pbvh_iter_end(&iter); + + const int tot = BLI_gset_len(face_set); + if (tot == 0) { + *r_totface = 0; + *r_gridfaces = nullptr; + BLI_gset_free(face_set, nullptr); + return; + } + + void **faces = static_cast(MEM_mallocN(sizeof(*faces) * tot, __func__)); + + GSetIterator gs_iter; + int i; + GSET_ITER_INDEX (gs_iter, face_set, i) { + faces[i] = BLI_gsetIterator_getKey(&gs_iter); + } + + BLI_gset_free(face_set, nullptr); + + *r_totface = tot; + *r_gridfaces = faces; } /***************************** PBVH Access ***********************************/ @@ -2817,7 +2845,6 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data) void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg) { - using namespace blender; /* Update normals */ Vector nodes = blender::bke::pbvh::search_gather( pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals)); @@ -2830,11 +2857,12 @@ void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg) pbvh_faces_update_normals(pbvh, nodes); } else if (pbvh->header.type == PBVH_GRIDS) { - IndexMaskMemory memory; - const IndexMask faces_to_update = BKE_pbvh_get_grid_updates(pbvh, nodes, memory); - BKE_subdiv_ccg_update_normals(subdiv_ccg, faces_to_update); - for (PBVHNode *node : nodes) { - node->flag &= ~PBVH_UpdateNormals; + CCGFace **faces; + int num_faces; + BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces); + if (num_faces > 0) { + BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); + MEM_freeN(faces); } } } @@ -2953,7 +2981,7 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh, void BKE_pbvh_grids_update(PBVH *pbvh, CCGElem **grids, - blender::Span gridfaces, + void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden, CCGKey *key) diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index 433131ae092..fa61c13a340 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -176,7 +176,7 @@ struct PBVH { /* Grid Data */ CCGKey gridkey; CCGElem **grids; - blender::Span gridfaces; + void **gridfaces; const DMFlagMat *grid_flag_mats; int totgrid; BLI_bitmap **grid_hidden; diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index 4f609d15fd2..30f84559424 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -13,7 +13,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_enumerable_thread_specific.hh" #include "BLI_ghash.h" #include "BLI_math_bits.h" #include "BLI_math_geom.h" @@ -41,7 +40,8 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg, void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG *subdiv_ccg, CCGKey *key, - const blender::IndexMask &face_mask); + CCGFace **effected_faces, + int num_effected_faces); /** \} */ @@ -152,7 +152,8 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv) if (num_faces) { subdiv_ccg->faces = static_cast( MEM_calloc_arrayN(num_faces, sizeof(SubdivCCGFace), "Subdiv CCG faces")); - subdiv_ccg->grid_faces.reinitialize(num_grids); + subdiv_ccg->grid_faces = static_cast( + MEM_calloc_arrayN(num_grids, sizeof(SubdivCCGFace *), "Subdiv CCG grid faces")); } } @@ -231,7 +232,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_ const float grid_size_1_inv = 1.0f / (grid_size - 1); const int element_size = element_size_bytes_get(subdiv_ccg); SubdivCCGFace *faces = subdiv_ccg->faces; - blender::MutableSpan grid_faces = subdiv_ccg->grid_faces; + SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces; const SubdivCCGFace *face = &faces[face_index]; for (int corner = 0; corner < face->num_grids; corner++) { const int grid_index = face->start_grid_index + corner; @@ -248,7 +249,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_ } } /* Assign grid's face. */ - grid_faces[grid_index] = face_index; + grid_faces[grid_index] = &faces[face_index]; /* Assign material flags. */ subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags( data->material_flags_evaluator, face_index); @@ -262,7 +263,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_ const float grid_size_1_inv = 1.0f / (grid_size - 1); const int element_size = element_size_bytes_get(subdiv_ccg); SubdivCCGFace *faces = subdiv_ccg->faces; - blender::MutableSpan grid_faces = subdiv_ccg->grid_faces; + SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces; const SubdivCCGFace *face = &faces[face_index]; for (int corner = 0; corner < face->num_grids; corner++) { const int grid_index = face->start_grid_index + corner; @@ -278,7 +279,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_ } } /* Assign grid's face. */ - grid_faces[grid_index] = face_index; + grid_faces[grid_index] = &faces[face_index]; /* Assign material flags. */ subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags( data->material_flags_evaluator, face_index); @@ -572,7 +573,7 @@ SubdivCCG *BKE_subdiv_to_ccg(Subdiv *subdiv, SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator) { BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG); - SubdivCCG *subdiv_ccg = MEM_new(__func__); + SubdivCCG *subdiv_ccg = MEM_cnew(__func__); subdiv_ccg->subdiv = subdiv; subdiv_ccg->level = bitscan_forward_i(settings->resolution - 1); subdiv_ccg->grid_size = BKE_subdiv_grid_size_from_level(subdiv_ccg->level); @@ -639,6 +640,7 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg) BKE_subdiv_free(subdiv_ccg->subdiv); } MEM_SAFE_FREE(subdiv_ccg->faces); + MEM_SAFE_FREE(subdiv_ccg->grid_faces); /* Free map of adjacent edges. */ for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) { SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i]; @@ -655,7 +657,7 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg) } MEM_SAFE_FREE(subdiv_ccg->adjacent_vertices); MEM_SAFE_FREE(subdiv_ccg->cache_.start_face_grid_index); - MEM_delete(subdiv_ccg); + MEM_freeN(subdiv_ccg); } void BKE_subdiv_ccg_key(CCGKey *key, const SubdivCCG *subdiv_ccg, int level) @@ -684,20 +686,32 @@ void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg) /** \name Normals * \{ */ +struct RecalcInnerNormalsData { + SubdivCCG *subdiv_ccg; + CCGKey *key; +}; + +struct RecalcInnerNormalsTLSData { + float (*face_normals)[3]; +}; + /* Evaluate high-res face normals, for faces which corresponds to grid elements * * {(x, y), {x + 1, y}, {x + 1, y + 1}, {x, y + 1}} * * The result is stored in normals storage from TLS. */ -static void subdiv_ccg_recalc_inner_face_normals( - SubdivCCG *subdiv_ccg, - CCGKey *key, - blender::MutableSpan face_normals, - const int grid_index) +static void subdiv_ccg_recalc_inner_face_normals(SubdivCCG *subdiv_ccg, + CCGKey *key, + RecalcInnerNormalsTLSData *tls, + const int grid_index) { const int grid_size = subdiv_ccg->grid_size; const int grid_size_1 = grid_size - 1; CCGElem *grid = subdiv_ccg->grids[grid_index]; + if (tls->face_normals == nullptr) { + tls->face_normals = static_cast( + MEM_malloc_arrayN(grid_size_1 * grid_size_1, sizeof(float[3]), "CCG TLS normals")); + } for (int y = 0; y < grid_size - 1; y++) { for (int x = 0; x < grid_size - 1; x++) { CCGElem *grid_elements[4] = { @@ -713,22 +727,22 @@ static void subdiv_ccg_recalc_inner_face_normals( CCG_elem_co(key, grid_elements[3]), }; const int face_index = y * grid_size_1 + x; - float *face_normal = face_normals[face_index]; + float *face_normal = tls->face_normals[face_index]; normal_quad_v3(face_normal, co[0], co[1], co[2], co[3]); } } } /* Average normals at every grid element, using adjacent faces normals. */ -static void subdiv_ccg_average_inner_face_normals( - SubdivCCG *subdiv_ccg, - CCGKey *key, - const blender::Span face_normals, - const int grid_index) +static void subdiv_ccg_average_inner_face_normals(SubdivCCG *subdiv_ccg, + CCGKey *key, + RecalcInnerNormalsTLSData *tls, + const int grid_index) { const int grid_size = subdiv_ccg->grid_size; const int grid_size_1 = grid_size - 1; CCGElem *grid = subdiv_ccg->grids[grid_index]; + const float(*face_normals)[3] = tls->face_normals; for (int y = 0; y < grid_size; y++) { for (int x = 0; x < grid_size; x++) { float normal_acc[3] = {0.0f, 0.0f, 0.0f}; @@ -758,25 +772,42 @@ static void subdiv_ccg_average_inner_face_normals( } } +static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v, + const int grid_index, + const TaskParallelTLS *__restrict tls_v) +{ + RecalcInnerNormalsData *data = static_cast(userdata_v); + RecalcInnerNormalsTLSData *tls = static_cast(tls_v->userdata_chunk); + subdiv_ccg_recalc_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); + subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); +} + +static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict /*userdata*/, + void *__restrict tls_v) +{ + RecalcInnerNormalsTLSData *tls = static_cast(tls_v); + MEM_SAFE_FREE(tls->face_normals); +} + /* Recalculate normals which corresponds to non-boundaries elements of grids. */ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg) { - using namespace blender; - const int grid_size_1 = subdiv_ccg->grid_size - 1; - - threading::EnumerableThreadSpecific> face_normals_tls( - [&]() { return Array(grid_size_1 * grid_size_1); }); - CCGKey key; BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); - - threading::parallel_for(IndexRange(subdiv_ccg->num_grids), 512, [&](const IndexRange range) { - MutableSpan face_normals = face_normals_tls.local(); - for (const int grid_index : range) { - subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, &key, face_normals, grid_index); - subdiv_ccg_average_inner_face_normals(subdiv_ccg, &key, face_normals, grid_index); - } - }); + RecalcInnerNormalsData data{}; + data.subdiv_ccg = subdiv_ccg; + data.key = &key; + RecalcInnerNormalsTLSData tls_data = {nullptr}; + TaskParallelSettings parallel_range_settings; + BLI_parallel_range_settings_defaults(¶llel_range_settings); + parallel_range_settings.userdata_chunk = &tls_data; + parallel_range_settings.userdata_chunk_size = sizeof(tls_data); + parallel_range_settings.func_free = subdiv_ccg_recalc_inner_normal_free; + BLI_task_parallel_range(0, + subdiv_ccg->num_grids, + &data, + subdiv_ccg_recalc_inner_normal_task, + ¶llel_range_settings); } void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg) @@ -789,48 +820,80 @@ void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg) BKE_subdiv_ccg_average_grids(subdiv_ccg); } -static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, - const blender::IndexMask &face_mask) +struct RecalcModifiedInnerNormalsData { + SubdivCCG *subdiv_ccg; + CCGKey *key; + SubdivCCGFace **effected_ccg_faces; +}; + +static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userdata_v, + const int face_index, + const TaskParallelTLS *__restrict tls_v) { - using namespace blender; - const int grid_size_1 = subdiv_ccg->grid_size - 1; - - threading::EnumerableThreadSpecific> face_normals_tls( - [&]() { return Array(grid_size_1 * grid_size_1); }); - - CCGKey key; - BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); - const SubdivCCGFace *faces = subdiv_ccg->faces; - face_mask.foreach_segment(GrainSize(512), [&](const IndexMaskSegment segment) { - MutableSpan face_normals = face_normals_tls.local(); - for (const int face_index : segment) { - const SubdivCCGFace &face = faces[face_index]; - const int num_face_grids = face.num_grids; - for (int i = 0; i < num_face_grids; i++) { - const int grid_index = face.start_grid_index + i; - subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, &key, face_normals, grid_index); - subdiv_ccg_average_inner_face_normals(subdiv_ccg, &key, face_normals, grid_index); - } - } - }); + RecalcModifiedInnerNormalsData *data = static_cast(userdata_v); + SubdivCCG *subdiv_ccg = data->subdiv_ccg; + CCGKey *key = data->key; + RecalcInnerNormalsTLSData *tls = static_cast(tls_v->userdata_chunk); + SubdivCCGFace **faces = data->effected_ccg_faces; + SubdivCCGFace *face = faces[face_index]; + const int num_face_grids = face->num_grids; + for (int i = 0; i < num_face_grids; i++) { + const int grid_index = face->start_grid_index + i; + subdiv_ccg_recalc_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); + subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); + } + subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); } -void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, const blender::IndexMask &face_mask) +static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict /*userdata*/, + void *__restrict tls_v) +{ + RecalcInnerNormalsTLSData *tls = static_cast(tls_v); + MEM_SAFE_FREE(tls->face_normals); +} + +static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, + CCGFace **effected_faces, + int num_effected_faces) +{ + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + RecalcModifiedInnerNormalsData data{}; + data.subdiv_ccg = subdiv_ccg; + data.key = &key; + data.effected_ccg_faces = (SubdivCCGFace **)effected_faces; + RecalcInnerNormalsTLSData tls_data = {nullptr}; + TaskParallelSettings parallel_range_settings; + BLI_parallel_range_settings_defaults(¶llel_range_settings); + parallel_range_settings.userdata_chunk = &tls_data; + parallel_range_settings.userdata_chunk_size = sizeof(tls_data); + parallel_range_settings.func_free = subdiv_ccg_recalc_modified_inner_normal_free; + BLI_task_parallel_range(0, + num_effected_faces, + &data, + subdiv_ccg_recalc_modified_inner_normal_task, + ¶llel_range_settings); +} + +void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, + CCGFace **effected_faces, + int num_effected_faces) { if (!subdiv_ccg->has_normal) { /* Grids don't have normals, can do early output. */ return; } - if (face_mask.is_empty()) { + if (num_effected_faces == 0) { /* No faces changed, so nothing to do here. */ return; } - subdiv_ccg_recalc_modified_inner_grid_normals(subdiv_ccg, face_mask); + subdiv_ccg_recalc_modified_inner_grid_normals(subdiv_ccg, effected_faces, num_effected_faces); CCGKey key; BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); - subdiv_ccg_average_faces_boundaries_and_corners(subdiv_ccg, &key, face_mask); + subdiv_ccg_average_faces_boundaries_and_corners( + subdiv_ccg, &key, effected_faces, num_effected_faces); } /** \} */ @@ -1164,7 +1227,8 @@ void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg) } static void subdiv_ccg_affected_face_adjacency(SubdivCCG *subdiv_ccg, - const blender::IndexMask &face_mask, + CCGFace **effected_faces, + int num_effected_faces, GSet *r_adjacent_vertices, GSet *r_adjacent_edges) { @@ -1177,8 +1241,9 @@ static void subdiv_ccg_affected_face_adjacency(SubdivCCG *subdiv_ccg, static_or_heap_storage_init(&face_vertices_storage); static_or_heap_storage_init(&face_edges_storage); - face_mask.foreach_index([&](const int face_index) { - SubdivCCGFace *face = &subdiv_ccg->faces[face_index]; + for (int i = 0; i < num_effected_faces; i++) { + SubdivCCGFace *face = (SubdivCCGFace *)effected_faces[i]; + int face_index = face - subdiv_ccg->faces; const int num_face_grids = face->num_grids; const int num_face_edges = num_face_grids; int *face_vertices = static_or_heap_storage_get(&face_vertices_storage, num_face_edges); @@ -1201,7 +1266,7 @@ static void subdiv_ccg_affected_face_adjacency(SubdivCCG *subdiv_ccg, SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[vertex_index]; BLI_gset_add(r_adjacent_vertices, adjacent_vertex); } - }); + } static_or_heap_storage_free(&face_vertices_storage); static_or_heap_storage_free(&face_edges_storage); @@ -1209,13 +1274,15 @@ static void subdiv_ccg_affected_face_adjacency(SubdivCCG *subdiv_ccg, void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG *subdiv_ccg, CCGKey *key, - const blender::IndexMask &face_mask) + CCGFace **effected_faces, + int num_effected_faces) { GSet *adjacent_vertices = BLI_gset_ptr_new(__func__); GSet *adjacent_edges = BLI_gset_ptr_new(__func__); GSetIterator gi; - subdiv_ccg_affected_face_adjacency(subdiv_ccg, face_mask, adjacent_vertices, adjacent_edges); + subdiv_ccg_affected_face_adjacency( + subdiv_ccg, effected_faces, num_effected_faces, adjacent_vertices, adjacent_edges); int *adjacent_vertex_index_map; int *adjacent_edge_index_map; @@ -1253,17 +1320,42 @@ void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG *subdiv_ccg, static_or_heap_storage_free(&index_heap); } -void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg, - const blender::IndexMask &face_mask) +struct StitchFacesInnerGridsData { + SubdivCCG *subdiv_ccg; + CCGKey *key; + CCGFace **effected_ccg_faces; +}; + +static void subdiv_ccg_stitch_face_inner_grids_task(void *__restrict userdata_v, + const int face_index, + const TaskParallelTLS *__restrict /*tls_v*/) +{ + StitchFacesInnerGridsData *data = static_cast(userdata_v); + SubdivCCG *subdiv_ccg = data->subdiv_ccg; + CCGKey *key = data->key; + CCGFace **effected_ccg_faces = data->effected_ccg_faces; + CCGFace *effected_ccg_face = effected_ccg_faces[face_index]; + SubdivCCGFace *face = (SubdivCCGFace *)effected_ccg_face; + subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); +} + +void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg, + CCGFace **effected_faces, + int num_effected_faces) { - using namespace blender; CCGKey key; BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); - - face_mask.foreach_index(GrainSize(512), [&](const int face_index) { - subdiv_ccg_average_inner_face_grids(subdiv_ccg, &key, &subdiv_ccg->faces[face_index]); - }); - + StitchFacesInnerGridsData data{}; + data.subdiv_ccg = subdiv_ccg; + data.key = &key; + data.effected_ccg_faces = effected_faces; + TaskParallelSettings parallel_range_settings; + BLI_parallel_range_settings_defaults(¶llel_range_settings); + BLI_task_parallel_range(0, + num_effected_faces, + &data, + subdiv_ccg_stitch_face_inner_grids_task, + ¶llel_range_settings); /* TODO(sergey): Only average elements which are adjacent to modified * faces. */ subdiv_ccg_average_all_boundaries_and_corners(subdiv_ccg, &key); @@ -1421,7 +1513,7 @@ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_cc BLI_INLINE int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord) { - SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_faces[coord->grid_index]]; + SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; const int face_grid_index = coord->grid_index; int next_face_grid_index = face_grid_index + 1 - face->start_grid_index; if (next_face_grid_index == face->num_grids) { @@ -1431,7 +1523,7 @@ int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord } BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord) { - SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_faces[coord->grid_index]]; + SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; const int face_grid_index = coord->grid_index; int prev_face_grid_index = face_grid_index - 1 - face->start_grid_index; if (prev_face_grid_index < 0) { @@ -1447,7 +1539,7 @@ static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg, const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { - const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_faces[coord->grid_index]]; + SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; const int num_adjacent_grids = face->num_grids; subdiv_ccg_neighbors_init( @@ -1475,7 +1567,7 @@ static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg, Subdiv *subdiv = subdiv_ccg->subdiv; OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_faces[coord->grid_index]]; + const SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; const int face_index = face - subdiv_ccg->faces; const int face_grid_index = coord->grid_index - face->start_grid_index; const int num_face_grids = face->num_grids; @@ -1562,7 +1654,7 @@ static int adjacent_edge_index_from_coord(const SubdivCCG *subdiv_ccg, const Sub { Subdiv *subdiv = subdiv_ccg->subdiv; OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_faces[coord->grid_index]]; + SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; const int face_grid_index = coord->grid_index - face->start_grid_index; const int face_index = face - subdiv_ccg->faces; @@ -1859,7 +1951,9 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index) { - return subdiv_ccg->grid_faces[grid_index]; + const SubdivCCGFace *face = subdiv_ccg->grid_faces[grid_index]; + const int face_index = face - subdiv_ccg->faces; + return face_index; } const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg)