diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 56f54592554..709c19e0b44 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -224,6 +224,14 @@ void mesh_render_data_loop_edge_flag(const MeshRenderData &mr, const BMUVOffsets &offsets, EditLoopData &eattr); +/* In the GPU vertex buffers, the value for each vertex is duplicated to each of its vertex + * corners. So the edges on the GPU connect face corners rather than vertices. */ +inline uint2 edge_from_corners(const IndexRange face, const int corner) +{ + const int corner_next = bke::mesh::face_corner_next(face, corner); + return uint2(corner, corner_next); +} + template void extract_mesh_loose_edge_data(const Span vert_data, const Span edges, diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index 3d4b4a5075d..24de7148e15 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -154,33 +154,46 @@ void extract_edituv_tris_subdiv(const MeshRenderData &mr, static void extract_edituv_lines_bm(const MeshRenderData &mr, const bool sync_selection, - GPUIndexBufBuilder &builder) + gpu::IndexBuf &ibo) { - const BMesh &bm = *mr.bm; + GPUIndexBufBuilder builder; + /* The entire data array might not be used. It might be beneficial to count the number of visible + * edges first, especially if that allows parallelizing filling the data array. */ + GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.corners_num, mr.corners_num); + MutableSpan data = GPU_indexbuf_get_data(&builder).cast(); + int line_index = 0; + const BMFace *face; BMIter f_iter; - BM_ITER_MESH (face, &f_iter, &const_cast(bm), BM_FACES_OF_MESH) { + BM_ITER_MESH (face, &f_iter, mr.bm, BM_FACES_OF_MESH) { if (skip_bm_face(*face, sync_selection)) { continue; } const BMLoop *loop = BM_FACE_FIRST_LOOP(face); for ([[maybe_unused]] const int i : IndexRange(face->len)) { - GPU_indexbuf_add_line_verts( - &builder, BM_elem_index_get(loop), BM_elem_index_get(loop->next)); + data[line_index++] = uint2(BM_elem_index_get(loop), BM_elem_index_get(loop->next)); loop = loop->next; } } + + GPU_indexbuf_build_in_place_ex(&builder, 0, mr.corners_num, false, &ibo); } static void extract_edituv_lines_mesh(const MeshRenderData &mr, const bool sync_selection, - GPUIndexBufBuilder &builder) + gpu::IndexBuf &ibo) { const OffsetIndices faces = mr.faces; const Span corner_edges = mr.corner_edges; const Span orig_index_edge = mr.orig_index_edge ? Span(mr.orig_index_edge, mr.edges_num) : Span(); + + GPUIndexBufBuilder builder; + GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.corners_num, mr.corners_num); + MutableSpan data = GPU_indexbuf_get_data(&builder).cast(); + int line_index = 0; + if (mr.bm) { for (const int face_index : faces.index_range()) { const IndexRange face = faces[face_index]; @@ -196,8 +209,7 @@ static void extract_edituv_lines_mesh(const MeshRenderData &mr, if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) { continue; } - const int corner_next = bke::mesh::face_corner_next(face, corner); - GPU_indexbuf_add_line_verts(&builder, corner, corner_next); + data[line_index++] = edge_from_corners(face, corner); } } } @@ -222,39 +234,42 @@ static void extract_edituv_lines_mesh(const MeshRenderData &mr, if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) { continue; } - const int corner_next = bke::mesh::face_corner_next(face, corner); - GPU_indexbuf_add_line_verts(&builder, corner, corner_next); + data[line_index++] = edge_from_corners(face, corner); } }); } + + GPU_indexbuf_build_in_place_ex(&builder, 0, mr.corners_num, false, &ibo); } void extract_edituv_lines(const MeshRenderData &mr, gpu::IndexBuf &ibo) { const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - GPUIndexBufBuilder builder; - GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.corners_num, mr.corners_num); if (mr.extract_type == MeshExtractType::BMesh) { - extract_edituv_lines_bm(mr, sync_selection, builder); + extract_edituv_lines_bm(mr, sync_selection, ibo); } else { - extract_edituv_lines_mesh(mr, sync_selection, builder); + extract_edituv_lines_mesh(mr, sync_selection, ibo); } - - GPU_indexbuf_build_in_place(&builder, &ibo); } static void extract_edituv_lines_subdiv_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection, - GPUIndexBufBuilder &builder) + gpu::IndexBuf &ibo) { const BMesh &bm = *mr.bm; const Span subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data(); const Span subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops); + GPUIndexBufBuilder builder; + GPU_indexbuf_init( + &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops); + MutableSpan data = GPU_indexbuf_get_data(&builder).cast(); + int line_index = 0; + for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) { const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4]; const BMFace &face_orig = *BM_face_at_index(&const_cast(bm), coarse_face); @@ -267,17 +282,24 @@ static void extract_edituv_lines_subdiv_bm(const MeshRenderData &mr, if (coarse_edge == -1) { continue; } - const int subdiv_corner_next = bke::mesh::face_corner_next(subdiv_face, subdiv_corner); - GPU_indexbuf_add_line_verts(&builder, subdiv_corner, subdiv_corner_next); + data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner); } } + + GPU_indexbuf_build_in_place_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false, &ibo); } static void extract_edituv_lines_subdiv_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection, - GPUIndexBufBuilder &builder) + gpu::IndexBuf &ibo) { + GPUIndexBufBuilder builder; + GPU_indexbuf_init( + &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops); + MutableSpan data = GPU_indexbuf_get_data(&builder).cast(); + int line_index = 0; + /* NOTE: #subdiv_loop_edge_index already has the #CD_ORIGINDEX layer baked in. */ const Span subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data(); const Span subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, @@ -309,10 +331,11 @@ static void extract_edituv_lines_subdiv_mesh(const MeshRenderData &mr, if (coarse_edge == -1) { continue; } - const int subdiv_corner_next = bke::mesh::face_corner_next(subdiv_face, subdiv_corner); - GPU_indexbuf_add_line_verts(&builder, subdiv_corner, subdiv_corner_next); + data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner); } } + + GPU_indexbuf_build_in_place_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false, &ibo); } void extract_edituv_lines_subdiv(const MeshRenderData &mr, @@ -321,17 +344,12 @@ void extract_edituv_lines_subdiv(const MeshRenderData &mr, { const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - GPUIndexBufBuilder builder; - GPU_indexbuf_init( - &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops); if (mr.extract_type == MeshExtractType::BMesh) { - extract_edituv_lines_subdiv_bm(mr, subdiv_cache, sync_selection, builder); + extract_edituv_lines_subdiv_bm(mr, subdiv_cache, sync_selection, ibo); } else { - extract_edituv_lines_subdiv_mesh(mr, subdiv_cache, sync_selection, builder); + extract_edituv_lines_subdiv_mesh(mr, subdiv_cache, sync_selection, ibo); } - - GPU_indexbuf_build_in_place(&builder, &ibo); } /** \} */ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index d29c4ae123e..cf7e760ca98 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -38,14 +38,6 @@ static IndexMask calc_mesh_edge_visibility(const MeshRenderData &mr, return visible; } -/* In the GPU vertex buffers, the value for each vertex is duplicated to each of its vertex - * corners. So the edges on the GPU connect face corners rather than vertices. */ -static uint2 edge_from_corners(const IndexRange face, const int corner) -{ - const int corner_next = bke::mesh::face_corner_next(face, corner); - return uint2(corner, corner_next); -} - static void fill_loose_lines_ibo(const MeshRenderData &mr, const IndexMask &visible, MutableSpan data)