diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 4e6dfbcf16f..8f0dfcb6e7f 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -645,7 +645,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, } while (0) EXTRACT_ADD_REQUESTED(vbo, edituv_data); - EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area); EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data); for (int i = 0; i < GPU_MAX_ATTR; i++) { @@ -670,7 +669,8 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, !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.fdots_uv) && - !DRW_vbo_requested(buffers.vbo.uv) && !DRW_ibo_requested(buffers.ibo.lines_paint_mask) && + !DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) && + !DRW_ibo_requested(buffers.ibo.lines_paint_mask) && !DRW_ibo_requested(buffers.ibo.lines_adjacency) && !DRW_vbo_requested(buffers.vbo.skin_roots) && !DRW_vbo_requested(buffers.vbo.sculpt_data) && !DRW_vbo_requested(buffers.vbo.orco) && !DRW_vbo_requested(buffers.vbo.mesh_analysis)) @@ -975,6 +975,25 @@ 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.edituv_stretch_area)) { + struct TaskData { + MeshRenderData &mr; + MeshBufferList &buffers; + MeshBatchCache &cache; + }; + TaskNode *task_node = BLI_task_graph_node_create( + &task_graph, + [](void *__restrict task_data) { + const TaskData &data = *static_cast(task_data); + extract_edituv_stretch_area(data.mr, + *data.buffers.vbo.edituv_stretch_area, + data.cache.tot_area, + data.cache.tot_uv_area); + }, + new TaskData{*mr, buffers, cache}, + [](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.lines_paint_mask)) { struct TaskData { MeshRenderData &mr; @@ -1164,7 +1183,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, EXTRACT_ADD_REQUESTED(ibo, edituv_tris); EXTRACT_ADD_REQUESTED(ibo, edituv_lines); EXTRACT_ADD_REQUESTED(vbo, edituv_data); - EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area); EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); #undef EXTRACT_ADD_REQUESTED @@ -1178,7 +1196,8 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, !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.fdots_nor) && !DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots) && - !DRW_vbo_requested(buffers.vbo.uv) && !DRW_ibo_requested(buffers.ibo.lines_paint_mask) && + !DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) && + !DRW_ibo_requested(buffers.ibo.lines_paint_mask) && !DRW_ibo_requested(buffers.ibo.lines_adjacency) && !DRW_vbo_requested(buffers.vbo.sculpt_data)) { @@ -1247,6 +1266,10 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, /* Make sure UVs are computed before edituv stuffs. */ extract_uv_maps_subdiv(subdiv_cache, cache, *buffers.vbo.uv); } + if (DRW_vbo_requested(buffers.vbo.edituv_stretch_area)) { + extract_edituv_stretch_area_subdiv( + mr, subdiv_cache, *buffers.vbo.edituv_stretch_area, cache.tot_area, cache.tot_uv_area); + } 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 426b68c205c..98c656a893b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -456,6 +456,15 @@ void extract_uv_maps(const MeshRenderData &mr, const MeshBatchCache &cache, gpu: void extract_uv_maps_subdiv(const DRWSubdivCache &subdiv_cache, const MeshBatchCache &cache, gpu::VertBuf &vbo); +void extract_edituv_stretch_area(const MeshRenderData &mr, + gpu::VertBuf &vbo, + float &tot_area, + float &tot_uv_area); +void extract_edituv_stretch_area_subdiv(const MeshRenderData &mr, + const DRWSubdivCache &subdiv_cache, + gpu::VertBuf &vbo, + float &tot_area, + float &tot_uv_area); void extract_skin_roots(const MeshRenderData &mr, gpu::VertBuf &vbo); @@ -473,7 +482,6 @@ extern const MeshExtract extract_edituv_lines; extern const MeshExtract extract_edituv_points; extern const MeshExtract extract_edituv_fdots; extern const MeshExtract extract_edituv_data; -extern const MeshExtract extract_edituv_stretch_area; extern const MeshExtract extract_edituv_stretch_angle; extern const MeshExtract extract_fdots_edituv_data; extern const MeshExtract extract_attr[GPU_MAX_ATTR]; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc index e383ffda4dd..3578a579ae8 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc @@ -10,6 +10,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_attribute.hh" #include "BKE_mesh.hh" #include "extract_mesh.hh" @@ -18,25 +19,6 @@ namespace blender::draw { -/* ---------------------------------------------------------------------- */ -/** \name Extract Edit UV area stretch - * \{ */ - -static void extract_edituv_stretch_area_init(const MeshRenderData &mr, - MeshBatchCache & /*cache*/, - void *buf, - void * /*tls_data*/) -{ - gpu::VertBuf *vbo = static_cast(buf); - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr.corners_num); -} - BLI_INLINE float area_ratio_get(float area, float uvarea) { if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) { @@ -51,130 +33,131 @@ BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio) return (ratio > 1.0f) ? (1.0f / ratio) : ratio; } -static void compute_area_ratio(const MeshRenderData &mr, - float *r_area_ratio, - float &r_tot_area, - float &r_tot_uv_area) +struct AreaInfo { + float tot_area = 0.0f; + float tot_uv_area = 0.0f; +}; +static AreaInfo compute_area_ratio(const MeshRenderData &mr, MutableSpan r_area_ratio) { - float tot_area = 0.0f, tot_uv_area = 0.0f; - if (mr.extract_type == MR_EXTRACT_BMESH) { - CustomData *cd_ldata = &mr.bm->ldata; - int uv_ofs = CustomData_get_offset(cd_ldata, CD_PROP_FLOAT2); - - BMFace *efa; - BMIter f_iter; - int f; - BM_ITER_MESH_INDEX (efa, &f_iter, mr.bm, BM_FACES_OF_MESH, f) { - float area = BM_face_calc_area(efa); - float uvarea = BM_face_calc_area_uv(efa, uv_ofs); - tot_area += area; - tot_uv_area += uvarea; - r_area_ratio[f] = area_ratio_get(area, uvarea); - } - } - else { - BLI_assert(mr.extract_type == MR_EXTRACT_MESH); - const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr.mesh->corner_data, - CD_PROP_FLOAT2); - for (int face_index = 0; face_index < mr.faces_num; face_index++) { - const IndexRange face = mr.faces[face_index]; - const float area = bke::mesh::face_area_calc(mr.vert_positions, mr.corner_verts.slice(face)); - float uvarea = area_poly_v2(reinterpret_cast(&uv_data[face.start()]), - face.size()); - tot_area += area; - tot_uv_area += uvarea; - r_area_ratio[face_index] = area_ratio_get(area, uvarea); - } + const BMesh &bm = *mr.bm; + const int uv_offset = CustomData_get_offset(&bm.ldata, CD_PROP_FLOAT2); + return threading::parallel_reduce( + IndexRange(bm.totface), + 1024, + AreaInfo{}, + [&](const IndexRange range, AreaInfo info) { + for (const int face_index : range) { + const BMFace &face = *BM_face_at_index(&const_cast(bm), face_index); + const float area = BM_face_calc_area(&face); + const float uvarea = BM_face_calc_area_uv(&face, uv_offset); + info.tot_area += area; + info.tot_uv_area += uvarea; + r_area_ratio[face_index] = area_ratio_get(area, uvarea); + } + return info; + }, + [](const AreaInfo &a, const AreaInfo &b) { + return AreaInfo{a.tot_area + b.tot_area, a.tot_uv_area + b.tot_uv_area}; + }); } - r_tot_area = tot_area; - r_tot_uv_area = tot_uv_area; + const Span positions = mr.vert_positions; + const OffsetIndices faces = mr.faces; + const Span corner_verts = mr.corner_verts; + const Mesh &mesh = *mr.mesh; + const bke::AttributeAccessor attributes = mesh.attributes(); + const StringRef name = CustomData_get_active_layer_name(&mesh.corner_data, CD_PROP_FLOAT2); + const VArraySpan uv_map = *attributes.lookup(name, bke::AttrDomain::Corner); + + return threading::parallel_reduce( + faces.index_range(), + 1024, + AreaInfo{}, + [&](const IndexRange range, AreaInfo info) { + for (const int face_index : range) { + const IndexRange face = faces[face_index]; + const float area = bke::mesh::face_area_calc(positions, corner_verts.slice(face)); + float uvarea = area_poly_v2(reinterpret_cast(&uv_map[face.start()]), + face.size()); + info.tot_area += area; + info.tot_uv_area += uvarea; + r_area_ratio[face_index] = area_ratio_get(area, uvarea); + } + return info; + }, + [](const AreaInfo &a, const AreaInfo &b) { + return AreaInfo{a.tot_area + b.tot_area, a.tot_uv_area + b.tot_uv_area}; + }); } -static void extract_edituv_stretch_area_finish(const MeshRenderData &mr, - MeshBatchCache &cache, - void *buf, - void * /*data*/) +void extract_edituv_stretch_area(const MeshRenderData &mr, + gpu::VertBuf &vbo, + float &tot_area, + float &tot_uv_area) { - gpu::VertBuf *vbo = static_cast(buf); - float *area_ratio = static_cast(MEM_mallocN(sizeof(float) * mr.faces_num, __func__)); - compute_area_ratio(mr, area_ratio, cache.tot_area, cache.tot_uv_area); + Array area_ratio(mr.faces_num); + const AreaInfo info = compute_area_ratio(mr, area_ratio); + tot_area = info.tot_area; + tot_uv_area = info.tot_uv_area; - /* Copy face data for each loop. */ - float *loop_stretch = (float *)GPU_vertbuf_get_data(vbo); - - if (mr.extract_type == MR_EXTRACT_BMESH) { - BMFace *efa; - BMIter f_iter; - int f, l_index = 0; - BM_ITER_MESH_INDEX (efa, &f_iter, mr.bm, BM_FACES_OF_MESH, f) { - for (int i = 0; i < efa->len; i++, l_index++) { - loop_stretch[l_index] = area_ratio[f]; - } - } - } - else { - BLI_assert(mr.extract_type == MR_EXTRACT_MESH); - for (int face_index = 0; face_index < mr.faces_num; face_index++) { - for (const int l_index : mr.faces[face_index]) { - loop_stretch[l_index] = area_ratio[face_index]; - } - } - } - - MEM_freeN(area_ratio); -} - -static void extract_edituv_stretch_area_init_subdiv(const DRWSubdivCache &subdiv_cache, - const MeshRenderData &mr, - MeshBatchCache &cache, - void *buffer, - void * /*data*/) -{ - - /* Initialize final buffer. */ - gpu::VertBuf *vbo = static_cast(buffer); static GPUVertFormat format = {0}; if (format.attr_len == 0) { GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); } + GPU_vertbuf_init_with_format(&vbo, &format); + GPU_vertbuf_data_alloc(&vbo, mr.corners_num); + MutableSpan vbo_data(static_cast(GPU_vertbuf_get_data(&vbo)), mr.corners_num); - GPU_vertbuf_init_build_on_device(vbo, &format, subdiv_cache.num_subdiv_loops); - - /* Initialize coarse data buffer. */ - - gpu::VertBuf *coarse_data = GPU_vertbuf_calloc(); - - /* We use the same format as we just copy data around. */ - GPU_vertbuf_init_with_format(coarse_data, &format); - GPU_vertbuf_data_alloc(coarse_data, mr.corners_num); - - compute_area_ratio(mr, - static_cast(GPU_vertbuf_get_data(coarse_data)), - cache.tot_area, - cache.tot_uv_area); - - draw_subdiv_build_edituv_stretch_area_buffer(subdiv_cache, coarse_data, vbo); - - GPU_vertbuf_discard(coarse_data); + const int64_t bytes = area_ratio.as_span().size_in_bytes() + vbo_data.size_in_bytes(); + threading::memory_bandwidth_bound_task(bytes, [&]() { + if (mr.extract_type == MR_EXTRACT_BMESH) { + 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); + const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len); + vbo_data.slice(face_range).fill(area_ratio[face_index]); + } + }); + } + else { + BLI_assert(mr.extract_type == MR_EXTRACT_MESH); + const OffsetIndices faces = mr.faces; + threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) { + for (const int face : range) { + vbo_data.slice(faces[face]).fill(area_ratio[face]); + } + }); + } + }); } -constexpr MeshExtract create_extractor_edituv_stretch_area() +void extract_edituv_stretch_area_subdiv(const MeshRenderData &mr, + const DRWSubdivCache &subdiv_cache, + gpu::VertBuf &vbo, + float &tot_area, + float &tot_uv_area) { - MeshExtract extractor = {nullptr}; - extractor.init = extract_edituv_stretch_area_init; - extractor.finish = extract_edituv_stretch_area_finish; - extractor.init_subdiv = extract_edituv_stretch_area_init_subdiv; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = 0; - extractor.use_threading = false; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_stretch_area); - return extractor; + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + GPU_vertbuf_init_build_on_device(&vbo, &format, subdiv_cache.num_subdiv_loops); + + gpu::VertBuf *coarse_vbo = GPU_vertbuf_calloc(); + GPU_vertbuf_init_with_format(coarse_vbo, &format); + GPU_vertbuf_data_alloc(coarse_vbo, mr.faces_num); + MutableSpan coarse_vbo_data(static_cast(GPU_vertbuf_get_data(coarse_vbo)), + mr.faces_num); + const AreaInfo info = compute_area_ratio(mr, coarse_vbo_data); + tot_area = info.tot_area; + tot_uv_area = info.tot_uv_area; + + GPU_vertbuf_init_build_on_device(&vbo, &format, subdiv_cache.num_subdiv_loops); + draw_subdiv_build_edituv_stretch_area_buffer(subdiv_cache, coarse_vbo, &vbo); + + GPU_vertbuf_discard(coarse_vbo); } -/** \} */ - -const MeshExtract extract_edituv_stretch_area = create_extractor_edituv_stretch_area(); - } // namespace blender::draw