From 8d4da6063a1edd467f885a4d863fbd68efb18158 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 22 May 2024 10:48:11 -0400 Subject: [PATCH] Draw: Replace extractor abstraction for mesh positions extraction Part of #116901. The remaining change was to change the BMesh iteration to not use the extractor callbacks. --- .../draw/intern/draw_cache_extract_mesh.cc | 29 +++- .../intern/mesh_extractors/extract_mesh.hh | 7 +- .../mesh_extractors/extract_mesh_vbo_pos.cc | 154 +++++++----------- 3 files changed, 87 insertions(+), 103 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index d30d297532c..ab10c8c3a29 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -616,7 +616,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, } \ } while (0) - EXTRACT_ADD_REQUESTED(vbo, pos); EXTRACT_ADD_REQUESTED(vbo, nor); EXTRACT_ADD_REQUESTED(vbo, uv); EXTRACT_ADD_REQUESTED(vbo, tan); @@ -656,7 +655,7 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, if (extractors.is_empty() && !DRW_ibo_requested(buffers.ibo.lines) && !DRW_ibo_requested(buffers.ibo.lines_loose) && !DRW_ibo_requested(buffers.ibo.tris) && - !DRW_ibo_requested(buffers.ibo.points)) + !DRW_ibo_requested(buffers.ibo.points) && !DRW_vbo_requested(buffers.vbo.pos)) { return; } @@ -692,6 +691,21 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, /* Simple heuristic. */ const bool use_thread = (mr->corners_num + mr->loose_indices_num) > MIN_RANGE_LEN; + if (DRW_vbo_requested(buffers.vbo.pos)) { + struct TaskData { + MeshRenderData &mr; + MeshBufferCache &mbc; + }; + TaskNode *task_node = BLI_task_graph_node_create( + &task_graph, + [](void *__restrict task_data) { + const TaskData &data = *static_cast(task_data); + extract_positions(data.mr, *data.mbc.buff.vbo.pos); + }, + new TaskData{*mr, mbc}, + [](void *task_data) { delete static_cast(task_data); }); + BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); + } if (DRW_ibo_requested(buffers.ibo.tris)) { struct TaskData { MeshRenderData &mr; @@ -833,11 +847,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, } \ } while (0) - /* Orcos are extracted at the same time as positions. */ - if (DRW_vbo_requested(buffers.vbo.pos) || DRW_vbo_requested(buffers.vbo.orco)) { - extractors.append(&extract_pos); - } - EXTRACT_ADD_REQUESTED(vbo, nor); for (int i = 0; i < GPU_MAX_ATTR; i++) { EXTRACT_ADD_REQUESTED(vbo, attr[i]); @@ -873,7 +882,8 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, if (extractors.is_empty() && !DRW_ibo_requested(buffers.ibo.lines) && !DRW_ibo_requested(buffers.ibo.lines_loose) && !DRW_ibo_requested(buffers.ibo.tris) && - !DRW_ibo_requested(buffers.ibo.points)) + !DRW_ibo_requested(buffers.ibo.points) && !DRW_vbo_requested(buffers.vbo.pos) && + !DRW_vbo_requested(buffers.vbo.orco)) { return; } @@ -883,6 +893,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, mr, mbc, MR_ITER_LOOSE_EDGE | MR_ITER_LOOSE_VERT, MR_DATA_LOOSE_GEOM); DRW_subdivide_loose_geom(subdiv_cache, mbc); + if (DRW_vbo_requested(buffers.vbo.pos) || DRW_vbo_requested(buffers.vbo.orco)) { + extract_positions_subdiv(subdiv_cache, mr, *buffers.vbo.pos, buffers.vbo.orco); + } if (DRW_ibo_requested(buffers.ibo.lines) || DRW_ibo_requested(buffers.ibo.lines_loose)) { extract_lines_subdiv( subdiv_cache, mr, buffers.ibo.lines, buffers.ibo.lines_loose, cache.no_loose_wire); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index e6a9d832e5e..fc30a58cf6d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -342,6 +342,12 @@ void extract_mesh_loose_edge_data(const Span vert_data, }); } +void extract_positions(const MeshRenderData &mr, gpu::VertBuf &vbo); +void extract_positions_subdiv(const DRWSubdivCache &subdiv_cache, + const MeshRenderData &mr, + gpu::VertBuf &vbo, + gpu::VertBuf *orco_vbo); + void extract_tris(const MeshRenderData &mr, const SortedFaceData &face_sorted, MeshBatchCache &cache, @@ -372,7 +378,6 @@ extern const MeshExtract extract_edituv_tris; extern const MeshExtract extract_edituv_lines; extern const MeshExtract extract_edituv_points; extern const MeshExtract extract_edituv_fdots; -extern const MeshExtract extract_pos; extern const MeshExtract extract_nor_hq; extern const MeshExtract extract_nor; extern const MeshExtract extract_uv; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos.cc index f011593e0ec..2035dfbe007 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos.cc @@ -14,10 +14,6 @@ namespace blender::draw { -/* ---------------------------------------------------------------------- */ -/** \name Extract Position and Vertex Normal - * \{ */ - static void extract_positions_mesh(const MeshRenderData &mr, MutableSpan vbo_data) { MutableSpan corners_data = vbo_data.take_front(mr.corners_num); @@ -34,65 +30,62 @@ static void extract_positions_mesh(const MeshRenderData &mr, MutableSpan }); } -static void extract_pos_init(const MeshRenderData &mr, - MeshBatchCache & /*cache*/, - void *buf, - void *tls_data) +static void extract_positions_bm(const MeshRenderData &mr, MutableSpan vbo_data) +{ + const BMesh &bm = *mr.bm; + MutableSpan corners_data = vbo_data.take_front(mr.corners_num); + MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2); + MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size()); + + threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) { + for (const int face_index : range) { + const BMFace &face = *BM_face_at_index(&const_cast(bm), face_index); + const BMLoop *loop = BM_FACE_FIRST_LOOP(&face); + for ([[maybe_unused]] const int i : IndexRange(face.len)) { + const int index = BM_elem_index_get(loop); + corners_data[index] = bm_vert_co_get(mr, loop->v); + loop = loop->next; + } + } + }); + + const Span loose_edges = mr.loose_edges; + threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) { + for (const int i : range) { + const BMEdge &edge = *BM_edge_at_index(&const_cast(bm), loose_edges[i]); + loose_edge_data[i * 2 + 0] = bm_vert_co_get(mr, edge.v1); + loose_edge_data[i * 2 + 1] = bm_vert_co_get(mr, edge.v2); + } + }); + + const Span loose_verts = mr.loose_verts; + threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) { + for (const int i : range) { + const BMVert &vert = *BM_vert_at_index(&const_cast(bm), loose_verts[i]); + loose_vert_data[i] = bm_vert_co_get(mr, &vert); + } + }); +} + +void extract_positions(const MeshRenderData &mr, gpu::VertBuf &vbo) { - gpu::VertBuf *vbo = static_cast(buf); static GPUVertFormat format = {0}; if (format.attr_len == 0) { GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr.corners_num + mr.loose_indices_num); + GPU_vertbuf_init_with_format(&vbo, &format); + GPU_vertbuf_data_alloc(&vbo, mr.corners_num + mr.loose_indices_num); - MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(vbo)), - GPU_vertbuf_get_vertex_len(vbo)); + MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), + GPU_vertbuf_get_vertex_len(&vbo)); if (mr.extract_type == MR_EXTRACT_MESH) { extract_positions_mesh(mr, vbo_data); } else { - *static_cast(tls_data) = vbo_data.data(); + extract_positions_bm(mr, vbo_data); } } -static void extract_pos_iter_face_bm(const MeshRenderData &mr, - const BMFace *f, - const int /*f_index*/, - void *_data) -{ - float3 *data = *static_cast(_data); - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const int l_index = BM_elem_index_get(l_iter); - data[l_index] = bm_vert_co_get(mr, l_iter->v); - } while ((l_iter = l_iter->next) != l_first); -} - -static void extract_pos_iter_loose_edge_bm(const MeshRenderData &mr, - const BMEdge *eed, - const int loose_edge_i, - void *_data) -{ - float3 *data = *static_cast(_data); - int index = mr.corners_num + loose_edge_i * 2; - data[index + 0] = bm_vert_co_get(mr, eed->v1); - data[index + 1] = bm_vert_co_get(mr, eed->v2); -} - -static void extract_pos_iter_loose_vert_bm(const MeshRenderData &mr, - const BMVert *eve, - const int loose_vert_i, - void *_data) -{ - float3 *data = *static_cast(_data); - const int offset = mr.corners_num + (mr.loose_edges_num * 2); - const int index = offset + loose_vert_i; - data[index] = bm_vert_co_get(mr, eve); -} - static GPUVertFormat *get_normals_format() { static GPUVertFormat format = {0}; @@ -131,10 +124,9 @@ static void extract_vertex_flags(const MeshRenderData &mr, char *flags) } } -static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, - const MeshRenderData &mr, - void *buffer, - void * /*data*/) +static void extract_loose_positions_subdiv(const DRWSubdivCache &subdiv_cache, + const MeshRenderData &mr, + gpu::VertBuf &vbo) { const Span loose_verts = mr.loose_verts; const int loose_edges_num = mr.loose_edges.size(); @@ -142,8 +134,6 @@ static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, return; } - gpu::VertBuf *vbo = static_cast(buffer); - /* TODO(@kevindietrich): replace this when compressed normals are supported. */ struct SubdivPosNorLoop { float pos[3]; @@ -152,7 +142,7 @@ static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, }; /* Make sure buffer is active for sending loose data. */ - GPU_vertbuf_use(vbo); + GPU_vertbuf_use(&vbo); const int resolution = subdiv_cache.resolution; const Span cached_positions = subdiv_cache.loose_edge_positions; @@ -169,7 +159,7 @@ static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, for (const int edge : IndexRange(edges_per_edge)) { copy_v3_v3(edge_data[0].pos, positions[edge + 0]); copy_v3_v3(edge_data[1].pos, positions[edge + 1]); - GPU_vertbuf_update_sub(vbo, + GPU_vertbuf_update_sub(&vbo, (edge_offset + edge * 2) * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data); @@ -183,24 +173,20 @@ static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, memset(&vert_data, 0, sizeof(SubdivPosNorLoop)); for (const int i : loose_verts.index_range()) { copy_v3_v3(vert_data.pos, positions[loose_verts[i]]); - GPU_vertbuf_update_sub(vbo, + GPU_vertbuf_update_sub(&vbo, (loose_verts_start + i) * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data); } } -static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache, - const MeshRenderData &mr, - MeshBatchCache &cache, - void *buffer, - void * /*data*/) +void extract_positions_subdiv(const DRWSubdivCache &subdiv_cache, + const MeshRenderData &mr, + gpu::VertBuf &vbo, + gpu::VertBuf *orco_vbo) { - gpu::VertBuf *vbo = static_cast(buffer); - - /* Initialize the vertex buffer, it was already allocated. */ GPU_vertbuf_init_build_on_device( - vbo, draw_subdiv_get_pos_nor_format(), subdiv_full_vbo_size(mr, subdiv_cache)); + &vbo, draw_subdiv_get_pos_nor_format(), subdiv_full_vbo_size(mr, subdiv_cache)); if (subdiv_cache.num_subdiv_loops == 0) { return; @@ -217,8 +203,6 @@ static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache, extract_vertex_flags(mr, flags); GPU_vertbuf_tag_dirty(flags_buffer); - gpu::VertBuf *orco_vbo = cache.final.buff.vbo.orco; - if (orco_vbo) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { @@ -231,7 +215,7 @@ static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache, GPU_vertbuf_init_build_on_device(orco_vbo, &format, subdiv_cache.num_subdiv_loops); } - draw_subdiv_extract_pos_nor(subdiv_cache, flags_buffer, vbo, orco_vbo); + draw_subdiv_extract_pos_nor(subdiv_cache, flags_buffer, &vbo, orco_vbo); if (subdiv_cache.use_custom_loop_normals) { const Mesh *coarse_mesh = subdiv_cache.mesh; @@ -252,7 +236,7 @@ static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache, draw_subdiv_interp_custom_data( subdiv_cache, src_custom_normals, dst_custom_normals, GPU_COMP_F32, 3, 0); - draw_subdiv_finalize_custom_normals(subdiv_cache, dst_custom_normals, vbo); + draw_subdiv_finalize_custom_normals(subdiv_cache, dst_custom_normals, &vbo); GPU_vertbuf_discard(src_custom_normals); GPU_vertbuf_discard(dst_custom_normals); @@ -267,39 +251,21 @@ static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache, vert_normals, get_normals_format(), subdiv_cache.num_subdiv_verts); draw_subdiv_accumulate_normals(subdiv_cache, - vbo, + &vbo, subdiv_cache.subdiv_vertex_face_adjacency_offsets, subdiv_cache.subdiv_vertex_face_adjacency, subdiv_loop_subdiv_vert_index, vert_normals); - draw_subdiv_finalize_normals(subdiv_cache, vert_normals, subdiv_loop_subdiv_vert_index, vbo); + draw_subdiv_finalize_normals(subdiv_cache, vert_normals, subdiv_loop_subdiv_vert_index, &vbo); GPU_vertbuf_discard(vert_normals); GPU_vertbuf_discard(subdiv_loop_subdiv_vert_index); } GPU_vertbuf_discard(flags_buffer); + + extract_loose_positions_subdiv(subdiv_cache, mr, vbo); } -constexpr MeshExtract create_extractor_pos() -{ - MeshExtract extractor = {nullptr}; - extractor.init = extract_pos_init; - extractor.iter_face_bm = extract_pos_iter_face_bm; - extractor.iter_loose_edge_bm = extract_pos_iter_loose_edge_bm; - extractor.iter_loose_vert_bm = extract_pos_iter_loose_vert_bm; - extractor.init_subdiv = extract_pos_init_subdiv; - extractor.iter_loose_geom_subdiv = extract_pos_loose_geom_subdiv; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = sizeof(float3 *); - extractor.use_threading = true; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos); - return extractor; -} - -/** \} */ - -const MeshExtract extract_pos = create_extractor_pos(); - } // namespace blender::draw