Mesh: Draw: Replace extractor abstraction for paint mask lines buffer

Part of #116901.
A straightfoward change this time; the algorithm wasn't adjusted,
it was just put inside of a single loop. I did change some nested if
statements to continue statements to reduce indentation though.
This commit is contained in:
Hans Goudey
2024-06-02 22:18:57 -04:00
committed by Hans Goudey
parent d1049f6082
commit 405a11fb06
3 changed files with 130 additions and 144 deletions

View File

@@ -657,7 +657,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
}
EXTRACT_ADD_REQUESTED(vbo, attr_viewer);
EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
@@ -675,7 +674,8 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
!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.fdots_uv))
!DRW_vbo_requested(buffers.vbo.weights) && !DRW_vbo_requested(buffers.vbo.fdots_uv) &&
!DRW_ibo_requested(buffers.ibo.lines_paint_mask))
{
return;
}
@@ -961,6 +961,21 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
[](void *task_data) { delete static_cast<TaskData *>(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;
MeshBufferList &buffers;
};
TaskNode *task_node = BLI_task_graph_node_create(
&task_graph,
[](void *__restrict task_data) {
const TaskData &data = *static_cast<TaskData *>(task_data);
extract_lines_paint_mask(data.mr, *data.buffers.ibo.lines_paint_mask);
},
new TaskData{*mr, buffers},
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
}
if (use_thread) {
/* First run the requested extractors that do not support asynchronous ranges. */
@@ -1062,7 +1077,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
EXTRACT_ADD_REQUESTED(vbo, uv);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
EXTRACT_ADD_REQUESTED(vbo, sculpt_data);
@@ -1076,7 +1090,8 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
!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.fdots_nor) &&
!DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots))
!DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots) &&
!DRW_ibo_requested(buffers.ibo.lines_paint_mask))
{
return;
}
@@ -1130,6 +1145,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
extract_face_dots_subdiv(
subdiv_cache, *buffers.vbo.fdots_pos, buffers.vbo.fdots_nor, *buffers.ibo.fdots);
}
if (DRW_ibo_requested(buffers.ibo.lines_paint_mask)) {
extract_lines_paint_mask_subdiv(mr, subdiv_cache, *buffers.ibo.lines_paint_mask);
}
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
uint32_t data_offset = 0;

View File

@@ -442,7 +442,11 @@ void extract_face_dots(const MeshRenderData &mr, gpu::IndexBuf &face_dots);
void extract_face_dots_uv(const MeshRenderData &mr, gpu::VertBuf &vbo);
extern const MeshExtract extract_lines_paint_mask;
void extract_lines_paint_mask(const MeshRenderData &mr, gpu::IndexBuf &lines);
void extract_lines_paint_mask_subdiv(const MeshRenderData &mr,
const DRWSubdivCache &subdiv_cache,
gpu::IndexBuf &lines);
extern const MeshExtract extract_lines_adjacency;
extern const MeshExtract extract_edituv_tris;
extern const MeshExtract extract_edituv_lines;

View File

@@ -17,164 +17,128 @@
#include "extract_mesh.hh"
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Paint Mask Line Indices
* \{ */
struct MeshExtract_LinePaintMask_Data {
GPUIndexBufBuilder elb;
/** One bit per edge set if face is selected. */
BLI_bitmap *select_map;
};
static void extract_lines_paint_mask_init(const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void * /*ibo*/,
void *tls_data)
void extract_lines_paint_mask(const MeshRenderData &mr, gpu::IndexBuf &lines)
{
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(tls_data);
data->select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr.edges_num, mr.corners_num);
}
const OffsetIndices faces = mr.faces;
const Span<int> corner_edges = mr.corner_edges;
const Span<bool> hide_edge = mr.hide_edge;
const Span<bool> select_poly = mr.select_poly;
const Span<int> orig_index_edge = mr.orig_index_edge ?
Span<int>(mr.orig_index_edge, mr.edges_num) :
Span<int>();
static void extract_lines_paint_mask_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *_data)
{
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data);
const IndexRange face = mr.faces[face_index];
GPUIndexBufBuilder builder;
const int max_index = mr.corners_num;
GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.edges_num, max_index);
MutableSpan<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
for (const int corner : face) {
const int e_index = mr.corner_edges[corner];
if (!((mr.use_hide && !mr.hide_edge.is_empty() && mr.hide_edge[e_index]) ||
((mr.orig_index_edge) && (mr.orig_index_edge[e_index] == ORIGINDEX_NONE))))
{
const int corner_next = bke::mesh::face_corner_next(face, corner);
if (!mr.select_poly.is_empty() && mr.select_poly[face_index]) {
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) {
/* Hide edge as it has more than 2 selected loop. */
GPU_indexbuf_set_line_restart(&data->elb, e_index);
BLI_bitmap *select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
for (const int face_index : range) {
const IndexRange face = faces[face_index];
for (const int corner : face) {
const int edge = corner_edges[corner];
if ((!hide_edge.is_empty() && hide_edge[edge]) ||
(!orig_index_edge.is_empty() && (orig_index_edge[edge] == ORIGINDEX_NONE)))
{
data[edge] = uint2(gpu::RESTART_INDEX);
continue;
}
else {
/* First selected loop. Set edge visible, overwriting any unselected loop. */
GPU_indexbuf_set_line_verts(&data->elb, e_index, corner, corner_next);
}
}
else {
/* Set these unselected loop only if this edge has no other selected loop. */
if (!BLI_BITMAP_TEST(data->select_map, e_index)) {
GPU_indexbuf_set_line_verts(&data->elb, e_index, corner, corner_next);
}
}
}
else {
GPU_indexbuf_set_line_restart(&data->elb, e_index);
}
}
}
static void extract_lines_paint_mask_finish(const MeshRenderData & /*mr*/,
MeshBatchCache & /*cache*/,
void *buf,
void *_data)
{
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data);
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
GPU_indexbuf_build_in_place(&data->elb, ibo);
MEM_freeN(data->select_map);
}
static void extract_lines_paint_mask_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void * /*buf*/,
void *tls_data)
{
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(tls_data);
data->select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
GPU_indexbuf_init(&data->elb,
GPU_PRIM_LINES,
subdiv_cache.num_subdiv_edges,
subdiv_cache.num_subdiv_loops * 2);
}
static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
void *_data,
uint subdiv_quad_index,
const int coarse_quad_index)
{
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data);
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache.edges_orig_index);
int *subdiv_loop_subdiv_edge_index = subdiv_cache.subdiv_loop_subdiv_edge_index;
const IndexRange subdiv_face(subdiv_quad_index * 4, 4);
for (const int corner : subdiv_face) {
const uint coarse_edge_index = uint(subdiv_loop_edge_index[corner]);
const uint subdiv_edge_index = uint(subdiv_loop_subdiv_edge_index[corner]);
if (coarse_edge_index == -1u) {
GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
}
else {
if (!((mr.use_hide && !mr.hide_edge.is_empty() && mr.hide_edge[coarse_edge_index]) ||
((mr.orig_index_edge) && (mr.orig_index_edge[coarse_edge_index] == ORIGINDEX_NONE))))
{
const int corner_next = bke::mesh::face_corner_next(subdiv_face, corner);
if (!mr.select_poly.is_empty() && mr.select_poly[coarse_quad_index]) {
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) {
const int corner_next = bke::mesh::face_corner_next(face, corner);
if (!select_poly.is_empty() && select_poly[face_index]) {
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(select_map, edge)) {
/* Hide edge as it has more than 2 selected loop. */
GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
data[edge] = uint2(gpu::RESTART_INDEX);
}
else {
/* First selected loop. Set edge visible, overwriting any unselected loop. */
GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, corner, corner_next);
data[edge] = uint2(corner, corner_next);
}
}
else {
/* Set these unselected loop only if this edge has no other selected loop. */
if (!BLI_BITMAP_TEST(data->select_map, coarse_edge_index)) {
GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, corner, corner_next);
if (!BLI_BITMAP_TEST(select_map, edge)) {
data[edge] = uint2(corner, corner_next);
}
}
}
else {
GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
}
});
GPU_indexbuf_build_in_place_ex(&builder, 0, max_index, true, &lines);
MEM_freeN(select_map);
}
void extract_lines_paint_mask_subdiv(const MeshRenderData &mr,
const DRWSubdivCache &subdiv_cache,
gpu::IndexBuf &lines)
{
const Span<bool> hide_edge = mr.hide_edge;
const Span<bool> select_poly = mr.select_poly;
const Span<int> orig_index_edge = mr.orig_index_edge ?
Span<int>(mr.orig_index_edge, mr.edges_num) :
Span<int>();
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
subdiv_cache.num_subdiv_loops);
const Span<int> subdiv_loop_subdiv_edge_index(subdiv_cache.subdiv_loop_subdiv_edge_index,
subdiv_cache.num_subdiv_loops);
const Span<int> subdiv_loop_edge_index(
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)),
subdiv_cache.num_subdiv_edges);
GPUIndexBufBuilder builder;
const int max_index = subdiv_cache.num_subdiv_loops;
GPU_indexbuf_init(&builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_edges, max_index);
MutableSpan<uint2> data = GPU_indexbuf_get_data(&builder).cast<uint2>();
BLI_bitmap *select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
const int quads_num = subdiv_cache.num_subdiv_quads;
threading::parallel_for(IndexRange(quads_num), 4096, [&](const IndexRange range) {
for (const int subdiv_quad_index : range) {
const int coarse_quad_index = subdiv_loop_face_index[subdiv_quad_index * 4];
const IndexRange subdiv_face(subdiv_quad_index * 4, 4);
for (const int corner : subdiv_face) {
const uint coarse_edge_index = uint(subdiv_loop_edge_index[corner]);
const uint subdiv_edge_index = uint(subdiv_loop_subdiv_edge_index[corner]);
if (coarse_edge_index == -1u) {
data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
continue;
}
if ((!hide_edge.is_empty() && hide_edge[coarse_edge_index]) ||
(!orig_index_edge.is_empty() &&
(orig_index_edge[coarse_edge_index] == ORIGINDEX_NONE)))
{
data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
continue;
}
const int corner_next = bke::mesh::face_corner_next(subdiv_face, corner);
if (!select_poly.is_empty() && select_poly[coarse_quad_index]) {
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(select_map, coarse_edge_index)) {
/* Hide edge as it has more than 2 selected loop. */
data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
}
else {
/* First selected loop. Set edge visible, overwriting any unselected loop. */
data[subdiv_edge_index] = uint2(corner, corner_next);
}
}
else {
/* Set these unselected loop only if this edge has no other selected loop. */
if (!BLI_BITMAP_TEST(select_map, coarse_edge_index)) {
data[subdiv_edge_index] = uint2(corner, corner_next);
}
}
}
}
}
});
GPU_indexbuf_build_in_place_ex(&builder, 0, max_index, true, &lines);
MEM_freeN(select_map);
}
static void extract_lines_paint_mask_finish_subdiv(const DRWSubdivCache & /*subdiv_cache*/,
const MeshRenderData &mr,
MeshBatchCache &cache,
void *buf,
void *_data)
{
extract_lines_paint_mask_finish(mr, cache, buf, _data);
}
constexpr MeshExtract create_extractor_lines_paint_mask()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_lines_paint_mask_init;
extractor.iter_face_mesh = extract_lines_paint_mask_iter_face_mesh;
extractor.finish = extract_lines_paint_mask_finish;
extractor.init_subdiv = extract_lines_paint_mask_init_subdiv;
extractor.iter_subdiv_mesh = extract_lines_paint_mask_iter_subdiv_mesh;
extractor.finish_subdiv = extract_lines_paint_mask_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data);
extractor.use_threading = false;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_paint_mask);
return extractor;
}
/** \} */
const MeshExtract extract_lines_paint_mask = create_extractor_lines_paint_mask();
} // namespace blender::draw