diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 48ecb2e43b0..6627f2c3dba 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -650,7 +650,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area); EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); EXTRACT_ADD_REQUESTED(vbo, mesh_analysis); - EXTRACT_ADD_REQUESTED(vbo, fdots_pos); EXTRACT_ADD_REQUESTED(vbo, fdots_uv); EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data); EXTRACT_ADD_REQUESTED(vbo, skin_roots); @@ -671,12 +670,12 @@ 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.fdots) && - !DRW_vbo_requested(buffers.vbo.pos) && !DRW_vbo_requested(buffers.vbo.nor) && - !DRW_vbo_requested(buffers.vbo.vnor) && !DRW_vbo_requested(buffers.vbo.fdots_nor) && - !DRW_vbo_requested(buffers.vbo.tan) && !DRW_vbo_requested(buffers.vbo.edit_data) && - !DRW_vbo_requested(buffers.vbo.face_idx) && !DRW_vbo_requested(buffers.vbo.edge_idx) && - !DRW_vbo_requested(buffers.vbo.vert_idx) && !DRW_vbo_requested(buffers.vbo.fdot_idx) && - !DRW_vbo_requested(buffers.vbo.weights)) + !DRW_vbo_requested(buffers.vbo.pos) && !DRW_vbo_requested(buffers.vbo.fdots_pos) && + !DRW_vbo_requested(buffers.vbo.nor) && !DRW_vbo_requested(buffers.vbo.vnor) && + !DRW_vbo_requested(buffers.vbo.fdots_nor) && !DRW_vbo_requested(buffers.vbo.tan) && + !DRW_vbo_requested(buffers.vbo.edit_data) && !DRW_vbo_requested(buffers.vbo.face_idx) && + !DRW_vbo_requested(buffers.vbo.edge_idx) && !DRW_vbo_requested(buffers.vbo.vert_idx) && + !DRW_vbo_requested(buffers.vbo.fdot_idx) && !DRW_vbo_requested(buffers.vbo.weights)) { return; } @@ -727,6 +726,21 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, [](void *task_data) { delete static_cast(task_data); }); BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); } + if (DRW_vbo_requested(buffers.vbo.fdots_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_face_dots_position(data.mr, *data.mbc.buff.vbo.fdots_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_vbo_requested(buffers.vbo.nor)) { struct TaskData { MeshRenderData &mr; @@ -1010,13 +1024,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, EXTRACT_ADD_REQUESTED(vbo, attr[i]); } - /* We use only one extractor for face dots, as the work is done in a single compute shader. */ - if (DRW_vbo_requested(buffers.vbo.fdots_nor) || DRW_vbo_requested(buffers.vbo.fdots_pos) || - DRW_ibo_requested(buffers.ibo.fdots)) - { - extractors.append(&extract_fdots_pos); - } - EXTRACT_ADD_REQUESTED(ibo, edituv_points); EXTRACT_ADD_REQUESTED(ibo, edituv_tris); EXTRACT_ADD_REQUESTED(ibo, edituv_lines); @@ -1038,7 +1045,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, !DRW_vbo_requested(buffers.vbo.orco) && !DRW_vbo_requested(buffers.vbo.nor) && !DRW_vbo_requested(buffers.vbo.tan) && !DRW_vbo_requested(buffers.vbo.edit_data) && !DRW_vbo_requested(buffers.vbo.face_idx) && !DRW_vbo_requested(buffers.vbo.edge_idx) && - !DRW_vbo_requested(buffers.vbo.vert_idx) && !DRW_vbo_requested(buffers.vbo.weights)) + !DRW_vbo_requested(buffers.vbo.vert_idx) && !DRW_vbo_requested(buffers.vbo.weights) && + !DRW_vbo_requested(buffers.vbo.fdots_nor) && !DRW_vbo_requested(buffers.vbo.fdots_pos) && + !DRW_ibo_requested(buffers.ibo.fdots)) { return; } @@ -1082,6 +1091,13 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, if (DRW_vbo_requested(buffers.vbo.weights)) { extract_weights_subdiv(mr, subdiv_cache, cache, *buffers.vbo.weights); } + if (DRW_vbo_requested(buffers.vbo.fdots_nor) || DRW_vbo_requested(buffers.vbo.fdots_pos) || + DRW_ibo_requested(buffers.ibo.fdots)) + { + /* We use only one extractor for face dots, as the work is done in a single compute shader. */ + extract_face_dots_subdiv( + subdiv_cache, *buffers.vbo.fdots_pos, buffers.vbo.fdots_nor, *buffers.ibo.fdots); + } void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__); uint32_t data_offset = 0; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 72b215fa5b0..b78c8bc2026 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -362,6 +362,12 @@ void extract_positions_subdiv(const DRWSubdivCache &subdiv_cache, gpu::VertBuf &vbo, gpu::VertBuf *orco_vbo); +void extract_face_dots_position(const MeshRenderData &mr, gpu::VertBuf &vbo); +void extract_face_dots_subdiv(const DRWSubdivCache &subdiv_cache, + gpu::VertBuf &fdots_pos, + gpu::VertBuf *fdots_nor, + gpu::IndexBuf &fdots); + void extract_normals(const MeshRenderData &mr, bool use_hq, gpu::VertBuf &vbo); void extract_normals_subdiv(const DRWSubdivCache &subdiv_cache, gpu::VertBuf &pos_nor, @@ -443,7 +449,6 @@ extern const MeshExtract extract_edituv_data; extern const MeshExtract extract_edituv_stretch_area; extern const MeshExtract extract_edituv_stretch_angle; extern const MeshExtract extract_mesh_analysis; -extern const MeshExtract extract_fdots_pos; extern const MeshExtract extract_fdots_uv; extern const MeshExtract extract_fdots_edituv_data; extern const MeshExtract extract_skin_roots; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc index 48f292bd644..2313379044d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc @@ -14,10 +14,6 @@ namespace blender::draw { -/* ---------------------------------------------------------------------- */ -/** \name Extract Face-dots positions - * \{ */ - static GPUVertFormat *get_fdots_pos_format() { static GPUVertFormat format = {0}; @@ -36,103 +32,84 @@ static GPUVertFormat *get_fdots_nor_format_subdiv() return &format; } -static void extract_fdots_pos_init(const MeshRenderData &mr, - MeshBatchCache & /*cache*/, - void *buf, - void *tls_data) +static void extract_face_dot_positions_mesh(const MeshRenderData &mr, MutableSpan vbo_data) { - gpu::VertBuf *vbo = static_cast(buf); - GPUVertFormat *format = get_fdots_pos_format(); - GPU_vertbuf_init_with_format(vbo, format); - GPU_vertbuf_data_alloc(vbo, mr.faces_num); - void *vbo_data = GPU_vertbuf_get_data(vbo); - *(float(**)[3])tls_data = static_cast(vbo_data); + const Span positions = mr.vert_positions; + const OffsetIndices faces = mr.faces; + const Span corner_verts = mr.corner_verts; + if (mr.use_subsurf_fdots) { + const BitSpan facedot_tags = mr.mesh->runtime->subsurf_face_dot_tags; + threading::parallel_for(faces.index_range(), 4096, [&](const IndexRange range) { + for (const int face : range) { + const Span face_verts = corner_verts.slice(faces[face]); + const int *vert = std::find_if(face_verts.begin(), face_verts.end(), [&](const int vert) { + return facedot_tags[vert].test(); + }); + if (vert == face_verts.end()) { + vbo_data[face] = float3(0); + } + else { + vbo_data[face] = positions[*vert]; + } + } + }); + } + else { + threading::parallel_for(faces.index_range(), 4096, [&](const IndexRange range) { + for (const int face : range) { + vbo_data[face] = bke::mesh::face_center_calc(positions, corner_verts.slice(faces[face])); + } + }); + } } -static void extract_fdots_pos_iter_face_bm(const MeshRenderData &mr, - const BMFace *f, - const int f_index, - void *data) +static void extract_face_dot_positions_bm(const MeshRenderData &mr, MutableSpan vbo_data) { - float(*center)[3] = *static_cast(data); - - float *co = center[f_index]; - zero_v3(co); - - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); - } while ((l_iter = l_iter->next) != l_first); - mul_v3_fl(co, 1.0f / float(f->len)); -} - -static void extract_fdots_pos_iter_face_mesh(const MeshRenderData &mr, - const int face_index, - void *data) -{ - float(*center)[3] = *static_cast(data); - float *co = center[face_index]; - zero_v3(co); - - const BitSpan facedot_tags = mr.mesh->runtime->subsurf_face_dot_tags; - - for (const int corner : mr.faces[face_index]) { - const int vert = mr.corner_verts[corner]; - if (mr.use_subsurf_fdots) { - if (facedot_tags[vert]) { - copy_v3_v3(center[face_index], mr.vert_positions[vert]); - break; + const BMesh &bm = *mr.bm; + 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); + if (mr.bm_vert_coords.is_empty()) { + BM_face_calc_center_median(&face, vbo_data[face_index]); + } + else { + BM_face_calc_center_median_vcos(&bm, &face, vbo_data[face_index], mr.bm_vert_coords); } } - else { - add_v3_v3(center[face_index], mr.vert_positions[vert]); - } - } + }); +} - if (!mr.use_subsurf_fdots) { - mul_v3_fl(co, 1.0f / float(mr.faces[face_index].size())); +void extract_face_dots_position(const MeshRenderData &mr, gpu::VertBuf &vbo) +{ + GPUVertFormat *format = get_fdots_pos_format(); + 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)); + if (mr.extract_type == MR_EXTRACT_MESH) { + extract_face_dot_positions_mesh(mr, vbo_data); + } + else { + extract_face_dot_positions_bm(mr, vbo_data); } } -static void extract_fdots_init_subdiv(const DRWSubdivCache &subdiv_cache, - const MeshRenderData & /*mr*/, - MeshBatchCache &cache, - void *buffer, - void * /*data*/) +void extract_face_dots_subdiv(const DRWSubdivCache &subdiv_cache, + gpu::VertBuf &fdots_pos, + gpu::VertBuf *fdots_nor, + gpu::IndexBuf &fdots) { /* We "extract" positions, normals, and indices at once. */ - gpu::VertBuf *fdots_pos_vbo = static_cast(buffer); - gpu::VertBuf *fdots_nor_vbo = cache.final.buff.vbo.fdots_nor; - gpu::IndexBuf *fdots_pos_ibo = cache.final.buff.ibo.fdots; - /* The normals may not be requested. */ - if (fdots_nor_vbo) { + if (fdots_nor) { GPU_vertbuf_init_build_on_device( - fdots_nor_vbo, get_fdots_nor_format_subdiv(), subdiv_cache.num_coarse_faces); + fdots_nor, get_fdots_nor_format_subdiv(), subdiv_cache.num_coarse_faces); } GPU_vertbuf_init_build_on_device( - fdots_pos_vbo, get_fdots_pos_format(), subdiv_cache.num_coarse_faces); - GPU_indexbuf_init_build_on_device(fdots_pos_ibo, subdiv_cache.num_coarse_faces); - draw_subdiv_build_fdots_buffers(subdiv_cache, fdots_pos_vbo, fdots_nor_vbo, fdots_pos_ibo); + &fdots_pos, get_fdots_pos_format(), subdiv_cache.num_coarse_faces); + GPU_indexbuf_init_build_on_device(&fdots, subdiv_cache.num_coarse_faces); + draw_subdiv_build_fdots_buffers(subdiv_cache, &fdots_pos, fdots_nor, &fdots); } -constexpr MeshExtract create_extractor_fdots_pos() -{ - MeshExtract extractor = {nullptr}; - extractor.init = extract_fdots_pos_init; - extractor.init_subdiv = extract_fdots_init_subdiv; - extractor.iter_face_bm = extract_fdots_pos_iter_face_bm; - extractor.iter_face_mesh = extract_fdots_pos_iter_face_mesh; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = sizeof(float(*)[3]); - extractor.use_threading = true; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_pos); - return extractor; -} - -/** \} */ - -const MeshExtract extract_fdots_pos = create_extractor_fdots_pos(); - } // namespace blender::draw