Commit: 98bdd08507b95e2e0cb4b9bac4fd0d3b28cbd207 Author: Joseph Eagar Date: Fri Dec 30 21:38:01 2022 -0800 Branches: temp-pbvh-split https://developer.blender.org/rB98bdd08507b95e2e0cb4b9bac4fd0d3b28cbd207
Merge branch 'master' into temp-pbvh-split =================================================================== =================================================================== diff --cc source/blender/blenkernel/intern/pbvh.c index b012cb7c098,a6a362b1daf..1239a29b353 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@@ -941,10 -1018,8 +1018,10 @@@ void BKE_pbvh_free(PBVH *pbvh if (node->bm_other_verts) { BLI_gset_free(node->bm_other_verts, NULL); } + } + if (node->flag & (PBVH_Leaf | PBVH_TexLeaf)) { - pbvh_pixels_free(node); + pbvh_node_pixels_free(node); } } diff --cc source/blender/blenkernel/intern/pbvh_intern.h index 34eb969adac,ee728a698dd..444a28d077c --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@@ -148,10 -148,9 +148,11 @@@ struct PBVH int *prim_indices; int totprim; int totvert; + int faces_num; /* Do not use directly, use BKE_pbvh_num_faces. */ int leaf_limit; + int pixel_leaf_limit; + int depth_limit; /* Mesh data */ struct Mesh *mesh; diff --cc source/blender/blenkernel/intern/pbvh_pixels.cc index a0c796168ed,e21103c9f19..084d30b271f --- a/source/blender/blenkernel/intern/pbvh_pixels.cc +++ b/source/blender/blenkernel/intern/pbvh_pixels.cc @@@ -22,10 -20,15 +22,11 @@@ #include "bmesh.h" #include "pbvh_intern.h" + #include "pbvh_uv_islands.hh" -namespace blender::bke::pbvh::pixels { +#include <atomic> -/** - * During debugging this check could be enabled. - * It will write to each image pixel that is covered by the PBVH. - */ -constexpr bool USE_WATERTIGHT_CHECK = false; +namespace blender::bke::pbvh::pixels { /** * Calculate the delta of two neighbor UV coordinates in the given image buffer. @@@ -53,317 -56,13 +54,322 @@@ static float2 calc_barycentric_delta_x( return calc_barycentric_delta(uvs, start_uv, end_uv); } +int count_node_pixels(PBVHNode &node) +{ + if (!node.pixels.node_data) { + return 0; + } + + NodeData &data = BKE_pbvh_pixels_node_data_get(node); + + int totpixel = 0; + + for (UDIMTilePixels &tile : data.tiles) { + for (PackedPixelRow &row : tile.pixel_rows) { + totpixel += row.num_pixels; + } + } + + return totpixel; +} + +struct SplitQueueData { + ThreadQueue *new_nodes; + TaskPool *pool; + + PBVH *pbvh; + Mesh *mesh; + Image *image; + ImageUser *image_user; +}; + +struct SplitNodePair { + SplitNodePair *parent; + PBVHNode node; + int children_offset = 0; + int depth = 0; + int source_index = -1; + bool is_old = false; + SplitQueueData *tdata; + + SplitNodePair(SplitNodePair *node_parent = nullptr) : parent(node_parent) + { + memset(static_cast<void *>(&node), 0, sizeof(PBVHNode)); + } +}; + +static void split_thread_job(TaskPool *__restrict pool, void *taskdata); + +static void split_pixel_node(PBVH *pbvh, + SplitNodePair *split, + Mesh *mesh, + Image *image, + ImageUser *image_user, + SplitQueueData *tdata) +{ + BB cb; + PBVHNode *node = &split->node; + + cb = node->vb; + + if (count_node_pixels(*node) <= pbvh->pixel_leaf_limit || split->depth >= pbvh->depth_limit) { + BKE_pbvh_pixels_node_data_get(split->node).rebuild_undo_regions(); + return; + } + + /* Find widest axis and its midpoint */ + const int axis = BB_widest_axis(&cb); + const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f; + + node->flag = (PBVHNodeFlags)((int)node->flag & (int)~PBVH_TexLeaf); + + SplitNodePair *split1 = MEM_new<SplitNodePair>("split_pixel_node split1", split); + SplitNodePair *split2 = MEM_new<SplitNodePair>("split_pixel_node split1", split); + + split1->depth = split->depth + 1; + split2->depth = split->depth + 1; + + PBVHNode *child1 = &split1->node; + PBVHNode *child2 = &split2->node; + + child1->flag = PBVH_TexLeaf; + child2->flag = PBVH_TexLeaf; + + child1->vb = cb; + child1->vb.bmax[axis] = mid; + + child2->vb = cb; + child2->vb.bmin[axis] = mid; + + NodeData &data = BKE_pbvh_pixels_node_data_get(split->node); + + NodeData *data1 = MEM_new<NodeData>(__func__); + NodeData *data2 = MEM_new<NodeData>(__func__); + child1->pixels.node_data = static_cast<void *>(data1); + child2->pixels.node_data = static_cast<void *>(data2); + - data1->triangles = data.triangles; - data2->triangles = data.triangles; ++ data1->uv_primitives = data.uv_primitives; ++ data2->uv_primitives = data.uv_primitives; + + data1->tiles.resize(data.tiles.size()); + data2->tiles.resize(data.tiles.size()); + + for (int i : IndexRange(data.tiles.size())) { + UDIMTilePixels &tile = data.tiles[i]; + UDIMTilePixels &tile1 = data1->tiles[i]; + UDIMTilePixels &tile2 = data2->tiles[i]; + + tile1.tile_number = tile2.tile_number = tile.tile_number; + tile1.flags.dirty = tile2.flags.dirty = 0; + } + + ImageUser image_user2 = *image_user; + + for (int i : IndexRange(data.tiles.size())) { + const UDIMTilePixels &tile = data.tiles[i]; + + image_user2.tile = tile.tile_number; + + ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user2, nullptr); + if (image_buffer == nullptr) { + continue; + } + + const MVert *mvert = BKE_pbvh_get_verts(pbvh); ++ PBVHData &pbvh_data = BKE_pbvh_pixels_data_get(*pbvh); + + for (const PackedPixelRow &row : tile.pixel_rows) { + UDIMTilePixels *tile1 = &data1->tiles[i]; + UDIMTilePixels *tile2 = &data2->tiles[i]; + - TrianglePaintInput &tri = data.triangles->paint_input[row.triangle_index]; ++ UVPrimitivePaintInput &uv_prim = data.uv_primitives.paint_input[row.uv_primitive_index]; ++ int3 tri = pbvh_data.geom_primitives.vert_indices[uv_prim.geometry_primitive_index]; + + float verts[3][3]; + - copy_v3_v3(verts[0], mvert[tri.vert_indices[0]].co); - copy_v3_v3(verts[1], mvert[tri.vert_indices[1]].co); - copy_v3_v3(verts[2], mvert[tri.vert_indices[2]].co); ++ copy_v3_v3(verts[0], mvert[tri[0]].co); ++ copy_v3_v3(verts[1], mvert[tri[1]].co); ++ copy_v3_v3(verts[2], mvert[tri[2]].co); + - float2 delta = tri.delta_barycentric_coord_u; ++ float2 delta = uv_prim.delta_barycentric_coord_u; + float2 uv1 = row.start_barycentric_coord; + float2 uv2 = row.start_barycentric_coord + delta * (float)row.num_pixels; + + float co1[3]; + float co2[3]; + + interp_barycentric_tri_v3(verts, uv1[0], uv1[1], co1); + interp_barycentric_tri_v3(verts, uv2[0], uv2[1], co2); + + /* Are we spanning the midpoint? */ + if ((co1[axis] <= mid) != (co2[axis] <= mid)) { + PackedPixelRow row1 = row; + float t; + + if (mid < co1[axis]) { + t = 1.0f - (mid - co2[axis]) / (co1[axis] - co2[axis]); + + SWAP(UDIMTilePixels *, tile1, tile2); + } + else { + t = (mid - co1[axis]) / (co2[axis] - co1[axis]); + } + + int num_pixels = (int)floorf((float)row.num_pixels * t); + + if (num_pixels) { + row1.num_pixels = num_pixels; + tile1->pixel_rows.append(row1); + } + + if (num_pixels != row.num_pixels) { + PackedPixelRow row2 = row; + + row2.num_pixels = row.num_pixels - num_pixels; + + row2.start_barycentric_coord = row.start_barycentric_coord + - tri.delta_barycentric_coord_u * (float)num_pixels; ++ uv_prim.delta_barycentric_coord_u * (float)num_pixels; + row2.start_image_coordinate = row.start_image_coordinate; + row2.start_image_coordinate[0] += num_pixels; + + tile2->pixel_rows.append(row2); + } + } + else if (co1[axis] <= mid && co2[axis] <= mid) { + tile1->pixel_rows.append(row); + } + else { + tile2->pixel_rows.append(row); + } + } + + BKE_image_release_ibuf(image, image_buffer, nullptr); + } + + data.undo_regions.clear(); + + if (node->flag & PBVH_Leaf) { + data.clear_data(); + } + else { - pbvh_pixels_free(node); ++ pbvh_node_pixels_free(node); + } + + BLI_thread_queue_push(tdata->new_nodes, static_cast<void *>(split1)); + BLI_thread_queue_push(tdata->new_nodes, static_cast<void *>(split2)); + + BLI_task_pool_push(tdata->pool, split_thread_job, static_cast<void *>(split1), false, nullptr); + BLI_task_pool_push(tdata->pool, split_thread_job, static_cast<void *>(split2), false, nullptr); +} + +static void split_flush_final_nodes(SplitQueueData *tdata) +{ + PBVH *pbvh = tdata->pbvh; + Vector<SplitNodePair *> splits; + + while (!BLI_thread_queue_is_empty(tdata->new_nodes)) { + SplitNodePair *newsplit = static_cast<SplitNodePair *>(BLI_thread_queue_pop(tdata->new_nodes)); + + splits.append(newsplit); + + if (newsplit->is_old) { + continue; + } + + if (!newsplit->parent->children_offset) { + newsplit->parent->children_offset = pbvh->totnode; + + pbvh_grow_nodes(pbvh, pbvh->totnode + 2); + newsplit->source_index = newsplit->parent->children_offset; + } + else { + newsplit->source_index = newsplit->parent->children_offset + 1; + } + } + + for (SplitNodePair *split : splits) { + BLI_assert(split->source_index != -1); + + split->node.children_offset = split->children_offset; + pbvh->nodes[split->source_index] = split->node; + } + + for (SplitNodePair *split : splits) { + MEM_delete<SplitNodePair>(split); + } +} + +static void split_thread_job(TaskPool *__restrict pool, void *taskdata) +{ + + SplitQueueData *tdata = static_cast<SplitQueueData *>(BLI_task_pool_user_data(pool)); + SplitNodePair *split = static_cast<SplitNodePair *>(taskdata); + + split_pixel_node(tdata->pbvh, split, tdata->mesh, tdata->image, tdata->image_user, tdata); +} + +static void split_pixel_nodes(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image_user) +{ + if (G.debug_value == 891) { + return; + } + + if (!pbvh->depth_limit) { + @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs