Mesh: Avoid function call overhead when extracting UV lines indices

Similar to other changes from #116901.
This commit is contained in:
Hans Goudey
2025-03-12 18:20:42 -04:00
committed by Hans Goudey
parent 083878c46b
commit 284ac406d6
3 changed files with 55 additions and 37 deletions

View File

@@ -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<typename T>
void extract_mesh_loose_edge_data(const Span<T> vert_data,
const Span<int2> edges,

View File

@@ -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<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
int line_index = 0;
const BMFace *face;
BMIter f_iter;
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(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<int> corner_edges = mr.corner_edges;
const Span<int> orig_index_edge = mr.orig_index_edge ?
Span<int>(mr.orig_index_edge, mr.edges_num) :
Span<int>();
GPUIndexBufBuilder builder;
GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.corners_num, mr.corners_num);
MutableSpan<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
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<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
const Span<int> 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<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
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<BMesh &>(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<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
int line_index = 0;
/* NOTE: #subdiv_loop_edge_index already has the #CD_ORIGINDEX layer baked in. */
const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
const Span<int> 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);
}
/** \} */

View File

@@ -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<uint2> data)