Mesh: Edit data draw extraction improvement
Part of #116901. Avoid the "extractor" abstraction for creation of edit mode overlay data vertex buffers. Use threading::parallel_for loops instead. Also prefer code duplication over linking things that are unrelated. This is the last "extractor" loop that runs by default in edit mode so there is a small performance improvement there. Besides that, the changes is the same as the other similar refactors. Pull Request: https://projects.blender.org/blender/blender/pulls/122386
This commit is contained in:
parent
9d3e2de76e
commit
48cc79f52d
@ -547,6 +547,7 @@ static void mesh_extract_render_data_node_exec(void *__restrict task_data)
|
||||
const bool calc_loose_geom = DRW_ibo_requested(buffers.ibo.lines) ||
|
||||
DRW_ibo_requested(buffers.ibo.lines_loose) ||
|
||||
DRW_ibo_requested(buffers.ibo.points) ||
|
||||
DRW_vbo_requested(buffers.vbo.edit_data) ||
|
||||
(iter_type & (MR_ITER_LOOSE_EDGE | MR_ITER_LOOSE_VERT)) ||
|
||||
(data_flag & MR_DATA_LOOSE_GEOM);
|
||||
|
||||
@ -645,7 +646,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
EXTRACT_ADD_REQUESTED(vbo, orco);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edge_fac);
|
||||
EXTRACT_ADD_REQUESTED(vbo, weights);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edit_data);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
|
||||
@ -678,7 +678,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_vbo_requested(buffers.vbo.pos) &&
|
||||
!DRW_vbo_requested(buffers.vbo.nor))
|
||||
!DRW_vbo_requested(buffers.vbo.nor) && !DRW_vbo_requested(buffers.vbo.edit_data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -797,6 +797,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_vbo_requested(buffers.vbo.edit_data)) {
|
||||
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_edit_data(data.mr, *data.buffers.vbo.edit_data);
|
||||
},
|
||||
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. */
|
||||
@ -904,7 +919,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
EXTRACT_ADD_REQUESTED(vbo, edge_idx);
|
||||
EXTRACT_ADD_REQUESTED(vbo, face_idx);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edge_fac);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edit_data);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
|
||||
/* Make sure UVs are computed before edituv stuffs. */
|
||||
EXTRACT_ADD_REQUESTED(vbo, uv);
|
||||
@ -921,7 +935,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_vbo_requested(buffers.vbo.pos) &&
|
||||
!DRW_vbo_requested(buffers.vbo.orco) && !DRW_vbo_requested(buffers.vbo.nor))
|
||||
!DRW_vbo_requested(buffers.vbo.orco) && !DRW_vbo_requested(buffers.vbo.nor) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edit_data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -947,6 +962,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
if (DRW_ibo_requested(buffers.ibo.points)) {
|
||||
extract_points_subdiv(mr, subdiv_cache, *buffers.ibo.points);
|
||||
}
|
||||
if (DRW_vbo_requested(buffers.vbo.edit_data)) {
|
||||
extract_edit_data_subdiv(mr, subdiv_cache, *buffers.vbo.edit_data);
|
||||
}
|
||||
|
||||
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
|
||||
uint32_t data_offset = 0;
|
||||
|
@ -377,6 +377,11 @@ void extract_points_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &points);
|
||||
|
||||
void extract_edit_data(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
void extract_edit_data_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &vbo);
|
||||
|
||||
extern const MeshExtract extract_fdots;
|
||||
extern const MeshExtract extract_lines_paint_mask;
|
||||
extern const MeshExtract extract_lines_adjacency;
|
||||
@ -392,7 +397,6 @@ extern const MeshExtract extract_vcol;
|
||||
extern const MeshExtract extract_orco;
|
||||
extern const MeshExtract extract_edge_fac;
|
||||
extern const MeshExtract extract_weights;
|
||||
extern const MeshExtract extract_edit_data;
|
||||
extern const MeshExtract extract_edituv_data;
|
||||
extern const MeshExtract extract_edituv_stretch_area;
|
||||
extern const MeshExtract extract_edituv_stretch_angle;
|
||||
|
@ -16,10 +16,6 @@
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Edit Mode Data / Flags
|
||||
* \{ */
|
||||
|
||||
static void mesh_render_data_edge_flag(const MeshRenderData &mr,
|
||||
const BMEdge *eed,
|
||||
EditLoopData &eattr)
|
||||
@ -115,267 +111,291 @@ static GPUVertFormat *get_edit_data_format()
|
||||
return &format;
|
||||
}
|
||||
|
||||
static void extract_edit_data_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
static void extract_edit_data_mesh(const MeshRenderData &mr, MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
GPUVertFormat *format = get_edit_data_format();
|
||||
GPU_vertbuf_init_with_format(vbo, format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.corners_num + mr.loose_indices_num);
|
||||
EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
|
||||
*(EditLoopData **)tls_data = vbo_data;
|
||||
}
|
||||
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());
|
||||
|
||||
static void extract_edit_data_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_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);
|
||||
|
||||
EditLoopData *data = vbo_data + l_index;
|
||||
memset(data, 0x0, sizeof(*data));
|
||||
mesh_render_data_face_flag(mr, f, {-1, -1, -1, -1}, *data);
|
||||
mesh_render_data_edge_flag(mr, l_iter->e, *data);
|
||||
mesh_render_data_vert_flag(mr, l_iter->v, *data);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_edit_data_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
EditLoopData *data = vbo_data + corner;
|
||||
memset(data, 0x0, sizeof(*data));
|
||||
BMFace *efa = bm_original_face_get(mr, face_index);
|
||||
BMVert *eve = bm_original_vert_get(mr, mr.corner_verts[corner]);
|
||||
BMEdge *eed = bm_original_edge_get(mr, mr.corner_edges[corner]);
|
||||
if (efa) {
|
||||
mesh_render_data_face_flag(mr, efa, {-1, -1, -1, -1}, *data);
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> corner_edges = mr.corner_edges;
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
EditLoopData &value = corners_data[corner];
|
||||
value = {};
|
||||
if (const BMFace *bm_face = bm_original_face_get(mr, face)) {
|
||||
mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
|
||||
}
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, corner_verts[corner])) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, value);
|
||||
}
|
||||
if (const BMEdge *bm_edge = bm_original_edge_get(mr, corner_edges[corner])) {
|
||||
mesh_render_data_edge_flag(mr, bm_edge, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eed) {
|
||||
mesh_render_data_edge_flag(mr, eed, *data);
|
||||
}
|
||||
if (eve) {
|
||||
mesh_render_data_vert_flag(mr, eve, *data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
static void extract_edit_data_iter_loose_edge_bm(const MeshRenderData &mr,
|
||||
const BMEdge *eed,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
EditLoopData *data = vbo_data + mr.corners_num + (loose_edge_i * 2);
|
||||
memset(data, 0x0, sizeof(*data) * 2);
|
||||
mesh_render_data_edge_flag(mr, eed, data[0]);
|
||||
data[1] = data[0];
|
||||
mesh_render_data_vert_flag(mr, eed->v1, data[0]);
|
||||
mesh_render_data_vert_flag(mr, eed->v2, data[1]);
|
||||
}
|
||||
|
||||
static void extract_edit_data_iter_loose_edge_mesh(const MeshRenderData &mr,
|
||||
const int2 edge,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
EditLoopData *data = vbo_data + mr.corners_num + loose_edge_i * 2;
|
||||
memset(data, 0x0, sizeof(*data) * 2);
|
||||
const int e_index = mr.loose_edges[loose_edge_i];
|
||||
BMEdge *eed = bm_original_edge_get(mr, e_index);
|
||||
BMVert *eve1 = bm_original_vert_get(mr, edge[0]);
|
||||
BMVert *eve2 = bm_original_vert_get(mr, edge[1]);
|
||||
if (eed) {
|
||||
mesh_render_data_edge_flag(mr, eed, data[0]);
|
||||
data[1] = data[0];
|
||||
}
|
||||
if (eve1) {
|
||||
mesh_render_data_vert_flag(mr, eve1, data[0]);
|
||||
}
|
||||
if (eve2) {
|
||||
mesh_render_data_vert_flag(mr, eve2, data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edit_data_iter_loose_vert_bm(const MeshRenderData &mr,
|
||||
const BMVert *eve,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
const int offset = mr.corners_num + (mr.loose_edges_num * 2);
|
||||
EditLoopData *data = vbo_data + offset + loose_vert_i;
|
||||
memset(data, 0x0, sizeof(*data));
|
||||
mesh_render_data_vert_flag(mr, eve, *data);
|
||||
}
|
||||
|
||||
static void extract_edit_data_iter_loose_vert_mesh(const MeshRenderData &mr,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
const int offset = mr.corners_num + (mr.loose_edges_num * 2);
|
||||
|
||||
EditLoopData *data = vbo_data + offset + loose_vert_i;
|
||||
memset(data, 0x0, sizeof(*data));
|
||||
const int v_index = mr.loose_verts[loose_vert_i];
|
||||
BMVert *eve = bm_original_vert_get(mr, v_index);
|
||||
if (eve) {
|
||||
mesh_render_data_vert_flag(mr, eve, *data);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
{
|
||||
const Span<int> loose_verts = mr.loose_verts;
|
||||
const Span<int2> edges = mr.edges;
|
||||
const Span<int> loose_edges = mr.loose_edges;
|
||||
if (loose_verts.is_empty() && loose_edges.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
|
||||
MutableSpan<EditLoopData> vbo_data(static_cast<EditLoopData *>(GPU_vertbuf_get_data(vbo)),
|
||||
subdiv_full_vbo_size(mr, subdiv_cache));
|
||||
const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
|
||||
|
||||
MutableSpan<EditLoopData> edge_data = vbo_data.slice(subdiv_cache.num_subdiv_loops,
|
||||
loose_edges.size() * verts_per_edge);
|
||||
threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
MutableSpan<EditLoopData> data = edge_data.slice(i * verts_per_edge, verts_per_edge);
|
||||
if (BMEdge *edge = mr.orig_index_edge ? bm_original_edge_get(mr, loose_edges[i]) :
|
||||
BM_edge_at_index(mr.bm, loose_edges[i]))
|
||||
{
|
||||
EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
|
||||
EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
|
||||
if (const BMEdge *bm_edge = bm_original_edge_get(mr, loose_edges[i])) {
|
||||
value_1 = {};
|
||||
mesh_render_data_edge_flag(mr, bm_edge, value_1);
|
||||
value_2 = value_1;
|
||||
}
|
||||
else {
|
||||
value_2 = value_1 = {};
|
||||
}
|
||||
const int2 edge = edges[loose_edges[i]];
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, value_1);
|
||||
}
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, value_2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const Span<int> loose_verts = mr.loose_verts;
|
||||
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
loose_vert_data[i] = {};
|
||||
if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
|
||||
mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_edit_data_bm(const MeshRenderData &mr, MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
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());
|
||||
|
||||
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<BMesh &>(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);
|
||||
EditLoopData &value = corners_data[index];
|
||||
value = {};
|
||||
mesh_render_data_face_flag(mr, &face, {-1, -1, -1, -1}, corners_data[index]);
|
||||
mesh_render_data_edge_flag(mr, loop->e, corners_data[index]);
|
||||
mesh_render_data_vert_flag(mr, loop->v, corners_data[index]);
|
||||
loop = loop->next;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const Span<int> loose_edges = mr.loose_edges;
|
||||
threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
|
||||
EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
|
||||
const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
|
||||
value_1 = {};
|
||||
mesh_render_data_edge_flag(mr, &edge, value_1);
|
||||
value_2 = value_1;
|
||||
mesh_render_data_vert_flag(mr, edge.v1, value_1);
|
||||
mesh_render_data_vert_flag(mr, edge.v2, value_2);
|
||||
}
|
||||
});
|
||||
|
||||
const Span<int> loose_verts = mr.loose_verts;
|
||||
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
loose_vert_data[i] = {};
|
||||
const BMVert &vert = *BM_vert_at_index(&const_cast<BMesh &>(bm), loose_verts[i]);
|
||||
mesh_render_data_vert_flag(mr, &vert, loose_vert_data[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void extract_edit_data(const MeshRenderData &mr, gpu::VertBuf &vbo)
|
||||
{
|
||||
GPUVertFormat *format = get_edit_data_format();
|
||||
GPU_vertbuf_init_with_format(&vbo, format);
|
||||
const int size = mr.corners_num + mr.loose_indices_num;
|
||||
GPU_vertbuf_data_alloc(&vbo, size);
|
||||
MutableSpan vbo_data(static_cast<EditLoopData *>(GPU_vertbuf_get_data(&vbo)), size);
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
extract_edit_data_mesh(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_edit_data_bm(mr, vbo_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edit_subdiv_data_mesh(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
const int corners_num = subdiv_cache.num_subdiv_loops;
|
||||
const int loose_edges_num = mr.loose_edges.size();
|
||||
const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)), corners_num);
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)), corners_num);
|
||||
|
||||
MutableSpan corners_data = vbo_data.take_front(corners_num);
|
||||
MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
|
||||
MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
|
||||
|
||||
threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
|
||||
for (const int subdiv_quad : range) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
|
||||
EditLoopData &value = corners_data[subdiv_corner];
|
||||
value = {};
|
||||
|
||||
if (const BMFace *bm_face = bm_original_face_get(mr, coarse_face)) {
|
||||
mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
|
||||
}
|
||||
|
||||
const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
|
||||
if (vert_origindex != -1) {
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, vert_origindex)) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, value);
|
||||
}
|
||||
}
|
||||
|
||||
const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
|
||||
if (edge_origindex != -1) {
|
||||
if (const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex)) {
|
||||
mesh_render_data_edge_flag(mr, bm_edge, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const Span<int2> edges = mr.edges;
|
||||
const Span<int> loose_edges = mr.loose_edges;
|
||||
threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
|
||||
if (const BMEdge *edge = bm_original_edge_get(mr, loose_edges[i])) {
|
||||
EditLoopData value{};
|
||||
mesh_render_data_edge_flag(mr, edge, value);
|
||||
data.fill(value);
|
||||
|
||||
mesh_render_data_vert_flag(mr, edge->v1, data.first());
|
||||
mesh_render_data_vert_flag(mr, edge->v2, data.last());
|
||||
}
|
||||
else {
|
||||
data.fill({});
|
||||
}
|
||||
const int2 edge = edges[loose_edges[i]];
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, data.first());
|
||||
}
|
||||
if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
|
||||
mesh_render_data_vert_flag(mr, bm_vert, data.last());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
MutableSpan<EditLoopData> vert_data = vbo_data.take_back(loose_verts.size());
|
||||
const Span<int> loose_verts = mr.loose_verts;
|
||||
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
EditLoopData value{};
|
||||
if (BMVert *vert = mr.orig_index_vert ? bm_original_vert_get(mr, loose_verts[i]) :
|
||||
BM_vert_at_index(mr.bm, loose_verts[i]))
|
||||
{
|
||||
mesh_render_data_vert_flag(mr, vert, value);
|
||||
loose_vert_data[i] = {};
|
||||
if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
|
||||
mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
|
||||
}
|
||||
vert_data[i] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_edit_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *data)
|
||||
static void extract_edit_subdiv_data_bm(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
GPU_vertbuf_init_with_format(vbo, get_edit_data_format());
|
||||
GPU_vertbuf_data_alloc(vbo, subdiv_full_vbo_size(mr, subdiv_cache));
|
||||
EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
|
||||
*(EditLoopData **)data = vbo_data;
|
||||
}
|
||||
const int corners_num = subdiv_cache.num_subdiv_loops;
|
||||
const int loose_edges_num = mr.loose_edges.size();
|
||||
const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)), corners_num);
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)), corners_num);
|
||||
|
||||
static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *coarse_quad)
|
||||
{
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index);
|
||||
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache.edges_orig_index);
|
||||
MutableSpan corners_data = vbo_data.take_front(corners_num);
|
||||
MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
|
||||
MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint i = start_loop_idx; i < end_loop_idx; i++) {
|
||||
const int vert_origindex = subdiv_loop_vert_index[i];
|
||||
const int edge_origindex = subdiv_loop_edge_index[i];
|
||||
BMesh &bm = *mr.bm;
|
||||
threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
|
||||
for (const int subdiv_quad : range) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
const BMFace *bm_face = BM_face_at_index(&bm, coarse_face);
|
||||
for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
|
||||
EditLoopData &value = corners_data[subdiv_corner];
|
||||
value = {};
|
||||
|
||||
EditLoopData *edit_loop_data = &vbo_data[i];
|
||||
memset(edit_loop_data, 0, sizeof(EditLoopData));
|
||||
mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
|
||||
|
||||
if (vert_origindex != -1) {
|
||||
const BMVert *eve = mr.orig_index_vert ? bm_original_vert_get(mr, vert_origindex) :
|
||||
BM_vert_at_index(mr.bm, vert_origindex);
|
||||
if (eve) {
|
||||
mesh_render_data_vert_flag(mr, eve, *edit_loop_data);
|
||||
const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
|
||||
if (vert_origindex != -1) {
|
||||
const BMVert *bm_vert = BM_vert_at_index(mr.bm, vert_origindex);
|
||||
mesh_render_data_vert_flag(mr, bm_vert, value);
|
||||
}
|
||||
|
||||
const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
|
||||
if (edge_origindex != -1) {
|
||||
const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex);
|
||||
mesh_render_data_edge_flag(mr, bm_edge, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (edge_origindex != -1) {
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
|
||||
mesh_render_data_edge_flag(mr, eed, *edit_loop_data);
|
||||
const Span<int> loose_edges = mr.loose_edges;
|
||||
threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
|
||||
const BMEdge *edge = BM_edge_at_index(&bm, loose_edges[i]);
|
||||
EditLoopData value{};
|
||||
mesh_render_data_edge_flag(mr, edge, value);
|
||||
data.fill(value);
|
||||
mesh_render_data_vert_flag(mr, edge->v1, data.first());
|
||||
mesh_render_data_vert_flag(mr, edge->v2, data.last());
|
||||
}
|
||||
});
|
||||
|
||||
/* coarse_quad can be null when called by the mesh iteration below. */
|
||||
if (coarse_quad) {
|
||||
/* The -1 parameter is for edit_uvs, which we don't do here. */
|
||||
mesh_render_data_face_flag(mr, coarse_quad, {-1, -1, -1, -1}, *edit_loop_data);
|
||||
const Span<int> loose_verts = mr.loose_verts;
|
||||
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
loose_vert_data[i] = {};
|
||||
const BMVert *vert = BM_vert_at_index(&bm, loose_verts[i]);
|
||||
mesh_render_data_vert_flag(mr, vert, loose_vert_data[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void extract_edit_data_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &vbo)
|
||||
{
|
||||
GPU_vertbuf_init_with_format(&vbo, get_edit_data_format());
|
||||
const int size = subdiv_full_vbo_size(mr, subdiv_cache);
|
||||
GPU_vertbuf_data_alloc(&vbo, size);
|
||||
MutableSpan vbo_data(static_cast<EditLoopData *>(GPU_vertbuf_get_data(&vbo)), size);
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
extract_edit_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_edit_subdiv_data_bm(mr, subdiv_cache, vbo_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const int coarse_quad_index)
|
||||
{
|
||||
BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index);
|
||||
extract_edit_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edit_data()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edit_data_init;
|
||||
extractor.iter_face_bm = extract_edit_data_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_edit_data_iter_face_mesh;
|
||||
extractor.iter_loose_edge_bm = extract_edit_data_iter_loose_edge_bm;
|
||||
extractor.iter_loose_edge_mesh = extract_edit_data_iter_loose_edge_mesh;
|
||||
extractor.iter_loose_vert_bm = extract_edit_data_iter_loose_vert_bm;
|
||||
extractor.iter_loose_vert_mesh = extract_edit_data_iter_loose_vert_mesh;
|
||||
extractor.init_subdiv = extract_edit_data_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_edit_data_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_edit_data_iter_subdiv_mesh;
|
||||
extractor.iter_loose_geom_subdiv = extract_edit_data_loose_geom_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(EditLoopData *);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edit_data);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_edit_data = create_extractor_edit_data();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
Loading…
Reference in New Issue
Block a user