Mesh: Draw: Replace extractor abstraction for indices buffers

Part of #116901.
Most of these loops were extremely simple, so function call overhead
would have been problematic in the existing code. However, they're
also so simple that they're most likely memory bound, so I wouldn't
expect a large performance change.
This commit is contained in:
Hans Goudey
2024-05-29 22:44:43 -04:00
committed by Hans Goudey
parent 070ffeea22
commit 2f3aacb1ac
3 changed files with 280 additions and 299 deletions

View File

@@ -549,6 +549,8 @@ static void mesh_extract_render_data_node_exec(void *__restrict task_data)
DRW_ibo_requested(buffers.ibo.points) ||
DRW_vbo_requested(buffers.vbo.edit_data) ||
DRW_vbo_requested(buffers.vbo.vnor) ||
DRW_vbo_requested(buffers.vbo.vert_idx) ||
DRW_vbo_requested(buffers.vbo.edge_idx) ||
(iter_type & (MR_ITER_LOOSE_EDGE | MR_ITER_LOOSE_VERT)) ||
(data_flag & MR_DATA_LOOSE_GEOM);
@@ -652,10 +654,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
EXTRACT_ADD_REQUESTED(vbo, fdots_pos);
EXTRACT_ADD_REQUESTED(vbo, fdots_uv);
EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data);
EXTRACT_ADD_REQUESTED(vbo, face_idx);
EXTRACT_ADD_REQUESTED(vbo, edge_idx);
EXTRACT_ADD_REQUESTED(vbo, vert_idx);
EXTRACT_ADD_REQUESTED(vbo, fdot_idx);
EXTRACT_ADD_REQUESTED(vbo, skin_roots);
for (int i = 0; i < GPU_MAX_ATTR; i++) {
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
@@ -677,7 +675,9 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
!DRW_ibo_requested(buffers.ibo.points) && !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.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))
{
return;
}
@@ -859,6 +859,34 @@ 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.face_idx) || DRW_vbo_requested(buffers.vbo.edge_idx) ||
DRW_vbo_requested(buffers.vbo.vert_idx) || DRW_vbo_requested(buffers.vbo.fdot_idx))
{
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);
if (DRW_vbo_requested(data.buffers.vbo.vert_idx)) {
extract_vert_index(data.mr, *data.buffers.vbo.vert_idx);
}
if (DRW_vbo_requested(data.buffers.vbo.edge_idx)) {
extract_edge_index(data.mr, *data.buffers.vbo.edge_idx);
}
if (DRW_vbo_requested(data.buffers.vbo.face_idx)) {
extract_face_index(data.mr, *data.buffers.vbo.face_idx);
}
if (DRW_vbo_requested(data.buffers.vbo.fdot_idx)) {
extract_face_dot_index(data.mr, *data.buffers.vbo.fdot_idx);
}
},
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. */
@@ -962,9 +990,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
EXTRACT_ADD_REQUESTED(vbo, vert_idx);
EXTRACT_ADD_REQUESTED(vbo, edge_idx);
EXTRACT_ADD_REQUESTED(vbo, face_idx);
EXTRACT_ADD_REQUESTED(vbo, edge_fac);
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
/* Make sure UVs are computed before edituv stuffs. */
@@ -982,7 +1007,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
!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.tan) && !DRW_vbo_requested(buffers.vbo.edit_data))
!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))
{
return;
}
@@ -1014,6 +1041,15 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
if (DRW_vbo_requested(buffers.vbo.tan)) {
extract_tangents_subdiv(mr, subdiv_cache, cache, *buffers.vbo.tan);
}
if (DRW_vbo_requested(buffers.vbo.vert_idx)) {
extract_vert_index_subdiv(subdiv_cache, mr, *buffers.vbo.vert_idx);
}
if (DRW_vbo_requested(buffers.vbo.edge_idx)) {
extract_edge_index_subdiv(subdiv_cache, mr, *buffers.vbo.edge_idx);
}
if (DRW_vbo_requested(buffers.vbo.face_idx)) {
extract_face_index_subdiv(subdiv_cache, mr, *buffers.vbo.face_idx);
}
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
uint32_t data_offset = 0;

View File

@@ -406,6 +406,21 @@ void extract_tangents_subdiv(const MeshRenderData &mr,
const MeshBatchCache &cache,
gpu::VertBuf &vbo);
void extract_vert_index(const MeshRenderData &mr, gpu::VertBuf &vbo);
void extract_edge_index(const MeshRenderData &mr, gpu::VertBuf &vbo);
void extract_face_index(const MeshRenderData &mr, gpu::VertBuf &vbo);
void extract_face_dot_index(const MeshRenderData &mr, gpu::VertBuf &vbo);
void extract_vert_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo);
void extract_edge_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo);
void extract_face_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo);
extern const MeshExtract extract_fdots;
extern const MeshExtract extract_lines_paint_mask;
extern const MeshExtract extract_lines_adjacency;
@@ -426,10 +441,6 @@ 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;
extern const MeshExtract extract_face_idx;
extern const MeshExtract extract_edge_idx;
extern const MeshExtract extract_vert_idx;
extern const MeshExtract extract_fdot_idx;
extern const MeshExtract extract_attr[GPU_MAX_ATTR];
extern const MeshExtract extract_attr_viewer;

View File

@@ -13,31 +13,15 @@
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Selection Index
* \{ */
static void extract_select_idx_init_impl(const MeshRenderData & /*mr*/,
const int len,
void *buf,
void *tls_data)
static MutableSpan<int> init_vbo_data(gpu::VertBuf &vbo, const int size)
{
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "index", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, len);
*(int32_t **)tls_data = (int32_t *)GPU_vertbuf_get_data(vbo);
}
static void extract_select_idx_init(const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void *tls_data)
{
extract_select_idx_init_impl(mr, mr.corners_num + mr.loose_indices_num, buf, tls_data);
GPU_vertbuf_init_with_format(&vbo, &format);
GPU_vertbuf_data_alloc(&vbo, size);
return {static_cast<int *>(GPU_vertbuf_get_data(&vbo)), size};
}
/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
@@ -45,168 +29,181 @@ static void extract_select_idx_init(const MeshRenderData &mr,
* index VBO's. We could upload the p/e/orig_index_vert as a buffer texture and sample it inside
* the shader to output original index. */
static void extract_face_idx_iter_face_bm(const MeshRenderData & /*mr*/,
const BMFace *f,
const int f_index,
void *data)
static void extract_vert_index_mesh(const MeshRenderData &mr, MutableSpan<int> vbo_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);
(*(int32_t **)data)[l_index] = f_index;
} while ((l_iter = l_iter->next) != l_first);
}
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_edge_idx_iter_face_bm(const MeshRenderData & /*mr*/,
const BMFace *f,
const int /*f_index*/,
void *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);
(*(int32_t **)data)[l_index] = BM_elem_index_get(l_iter->e);
} while ((l_iter = l_iter->next) != l_first);
}
static void extract_vert_idx_iter_face_bm(const MeshRenderData & /*mr*/,
const BMFace *f,
const int /*f_index*/,
void *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);
(*(int32_t **)data)[l_index] = BM_elem_index_get(l_iter->v);
} while ((l_iter = l_iter->next) != l_first);
}
static void extract_edge_idx_iter_loose_edge_bm(const MeshRenderData &mr,
const BMEdge *eed,
const int loose_edge_i,
void *data)
{
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = BM_elem_index_get(eed);
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = BM_elem_index_get(eed);
}
static void extract_vert_idx_iter_loose_edge_bm(const MeshRenderData &mr,
const BMEdge *eed,
const int loose_edge_i,
void *data)
{
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = BM_elem_index_get(eed->v1);
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = BM_elem_index_get(eed->v2);
}
static void extract_vert_idx_iter_loose_vert_bm(const MeshRenderData &mr,
const BMVert *eve,
const int loose_vert_i,
void *data)
{
const int offset = mr.corners_num + (mr.loose_edges_num * 2);
(*(int32_t **)data)[offset + loose_vert_i] = BM_elem_index_get(eve);
}
static void extract_face_idx_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *data)
{
for (const int corner : mr.faces[face_index]) {
(*(int32_t **)data)[corner] = (mr.orig_index_face) ? mr.orig_index_face[face_index] :
face_index;
if (mr.orig_index_vert) {
const Span<int> orig_index_vert(mr.orig_index_vert, mr.verts_num);
array_utils::gather(orig_index_vert, mr.corner_verts, corners_data);
extract_mesh_loose_edge_data(orig_index_vert, mr.edges, mr.loose_edges, loose_edge_data);
array_utils::gather(orig_index_vert, mr.loose_verts, loose_vert_data);
}
else {
array_utils::copy(mr.corner_verts, corners_data);
const Span<int2> edges = mr.edges;
const Span<int> loose_edges = mr.loose_edges;
threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
loose_edge_data[i * 2 + 0] = edges[loose_edges[i]][0];
loose_edge_data[i * 2 + 1] = edges[loose_edges[i]][1];
}
});
array_utils::copy(mr.loose_verts, loose_vert_data);
}
}
static void extract_edge_idx_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *data)
static void extract_vert_index_bm(const MeshRenderData &mr, MutableSpan<int> vbo_data)
{
for (const int corner : mr.faces[face_index]) {
const int edge = mr.corner_edges[corner];
(*(int32_t **)data)[corner] = (mr.orig_index_edge) ? mr.orig_index_edge[edge] : edge;
}
}
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_vert_idx_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *data)
{
for (const int corner : mr.faces[face_index]) {
const int vert = mr.corner_verts[corner];
(*(int32_t **)data)[corner] = (mr.orig_index_vert) ? mr.orig_index_vert[vert] : vert;
}
}
static void extract_edge_idx_iter_loose_edge_mesh(const MeshRenderData &mr,
const int2 /*edge*/,
const int loose_edge_i,
void *data)
{
const int e_index = mr.loose_edges[loose_edge_i];
const int e_orig = (mr.orig_index_edge) ? mr.orig_index_edge[e_index] : e_index;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = e_orig;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = e_orig;
}
static void extract_vert_idx_iter_loose_edge_mesh(const MeshRenderData &mr,
const int2 edge,
const int loose_edge_i,
void *data)
{
int v1_orig = (mr.orig_index_vert) ? mr.orig_index_vert[edge[0]] : edge[0];
int v2_orig = (mr.orig_index_vert) ? mr.orig_index_vert[edge[1]] : edge[1];
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = v1_orig;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = v2_orig;
}
static void extract_vert_idx_iter_loose_vert_mesh(const MeshRenderData &mr,
const int loose_vert_i,
void *data)
{
const int offset = mr.corners_num + (mr.loose_edges_num * 2);
const int v_index = mr.loose_verts[loose_vert_i];
const int v_orig = (mr.orig_index_vert) ? mr.orig_index_vert[v_index] : v_index;
(*(int32_t **)data)[offset + loose_vert_i] = v_orig;
}
static void extract_vert_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void * /*data*/)
{
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
/* Each element points to an element in the `ibo.points`. */
draw_subdiv_init_origindex_buffer(vbo,
(int32_t *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index),
subdiv_cache.num_subdiv_loops,
subdiv_full_vbo_size(mr, subdiv_cache));
if (!mr.orig_index_vert) {
return;
}
/* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
if (vbo_data[i] == -1) {
continue;
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);
corners_data[index] = BM_elem_index_get(loop->v);
loop = loop->next;
}
}
vbo_data[i] = mr.orig_index_vert[vbo_data[i]];
});
const Span<int> 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<BMesh &>(bm), loose_edges[i]);
loose_edge_data[i * 2 + 0] = BM_elem_index_get(edge.v1);
loose_edge_data[i * 2 + 1] = BM_elem_index_get(edge.v2);
}
});
array_utils::copy(mr.loose_verts, loose_vert_data);
}
void extract_vert_index(const MeshRenderData &mr, gpu::VertBuf &vbo)
{
MutableSpan<int> vbo_data = init_vbo_data(vbo, mr.corners_num + mr.loose_indices_num);
if (mr.extract_type == MR_EXTRACT_MESH) {
extract_vert_index_mesh(mr, vbo_data);
}
else {
extract_vert_index_bm(mr, vbo_data);
}
}
static void extract_edge_index_mesh(const MeshRenderData &mr, MutableSpan<int> 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);
const Span<int> loose_edges = mr.loose_edges;
if (mr.orig_index_edge) {
const Span<int> orig_index_edge(mr.orig_index_edge, mr.edges_num);
array_utils::gather(orig_index_edge, mr.corner_edges, corners_data);
threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
loose_edge_data[i * 2 + 0] = orig_index_edge[loose_edges[i]];
loose_edge_data[i * 2 + 1] = orig_index_edge[loose_edges[i]];
}
});
}
else {
array_utils::copy(mr.corner_edges, corners_data);
threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
loose_edge_data[i * 2 + 0] = loose_edges[i];
loose_edge_data[i * 2 + 1] = loose_edges[i];
}
});
}
}
static void extract_edge_index_bm(const MeshRenderData &mr, MutableSpan<int> 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);
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);
corners_data[index] = BM_elem_index_get(loop->e);
loop = loop->next;
}
}
});
const Span<int> loose_edges = mr.loose_edges;
threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
loose_edge_data[i * 2 + 0] = loose_edges[i];
loose_edge_data[i * 2 + 1] = loose_edges[i];
}
});
}
void extract_edge_index(const MeshRenderData &mr, gpu::VertBuf &vbo)
{
MutableSpan<int> vbo_data = init_vbo_data(vbo, mr.corners_num + mr.loose_edges.size() * 2);
if (mr.extract_type == MR_EXTRACT_MESH) {
extract_edge_index_mesh(mr, vbo_data);
}
else {
extract_edge_index_bm(mr, vbo_data);
}
}
static void extract_face_index_mesh(const MeshRenderData &mr, MutableSpan<int> vbo_data)
{
const OffsetIndices faces = mr.faces;
if (mr.orig_index_face) {
const Span<int> orig_index_face(mr.orig_index_face, mr.edges_num);
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
for (const int face : range) {
vbo_data.slice(faces[face]).fill(orig_index_face[face]);
}
});
}
else {
offset_indices::build_reverse_map(faces, vbo_data);
}
}
static void extract_face_index_bm(const MeshRenderData &mr, MutableSpan<int> vbo_data)
{
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 IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
vbo_data.slice(face_range).fill(face_index);
}
});
}
void extract_face_index(const MeshRenderData &mr, gpu::VertBuf &vbo)
{
MutableSpan<int> vbo_data = init_vbo_data(vbo, mr.corners_num);
if (mr.extract_type == MR_EXTRACT_MESH) {
extract_face_index_mesh(mr, vbo_data);
}
else {
extract_face_index_bm(mr, vbo_data);
}
}
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
void *buffer,
void * /*data*/)
gpu::VertBuf &vbo)
{
const Span<int> loose_verts = mr.loose_verts;
const Span<int> loose_edges = mr.loose_edges;
@@ -214,8 +211,7 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
return;
}
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
MutableSpan<int32_t> vbo_data(static_cast<int32_t *>(GPU_vertbuf_get_data(vbo)),
MutableSpan<int32_t> vbo_data(static_cast<int32_t *>(GPU_vertbuf_get_data(&vbo)),
subdiv_full_vbo_size(mr, subdiv_cache));
const Span<int2> coarse_edges = mr.edges;
@@ -238,32 +234,42 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
}
}
static void extract_edge_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void * /*data*/)
void extract_vert_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo)
{
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
draw_subdiv_init_origindex_buffer(
vbo,
static_cast<int32_t *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)),
subdiv_cache.num_subdiv_loops,
subdiv_loose_edges_num(mr, subdiv_cache) * 2);
/* Each element points to an element in the `ibo.points`. */
draw_subdiv_init_origindex_buffer(&vbo,
(int32_t *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index),
subdiv_cache.num_subdiv_loops,
subdiv_full_vbo_size(mr, subdiv_cache));
if (!mr.orig_index_vert) {
return;
}
/* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(&vbo));
for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
if (vbo_data[i] == -1) {
continue;
}
vbo_data[i] = mr.orig_index_vert[vbo_data[i]];
}
extract_vert_idx_loose_geom_subdiv(subdiv_cache, mr, vbo);
}
static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
void *buffer,
void * /*data*/)
gpu::VertBuf &vbo)
{
const Span<int> loose_edges = mr.loose_edges;
if (loose_edges.is_empty()) {
return;
}
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
MutableSpan<int32_t> vbo_data(static_cast<int32_t *>(GPU_vertbuf_get_data(vbo)),
MutableSpan<int32_t> vbo_data(static_cast<int32_t *>(GPU_vertbuf_get_data(&vbo)),
subdiv_full_vbo_size(mr, subdiv_cache));
const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
@@ -276,15 +282,24 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
}
}
static void extract_face_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void * /*data*/)
void extract_edge_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo)
{
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
draw_subdiv_init_origindex_buffer(
vbo, subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops, 0);
&vbo,
static_cast<int32_t *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)),
subdiv_cache.num_subdiv_loops,
subdiv_loose_edges_num(mr, subdiv_cache) * 2);
extract_edge_idx_loose_geom_subdiv(subdiv_cache, mr, vbo);
}
void extract_face_index_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
gpu::VertBuf &vbo)
{
draw_subdiv_init_origindex_buffer(
&vbo, subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops, 0);
if (!mr.orig_index_face) {
return;
@@ -293,108 +308,27 @@ static void extract_face_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
/* Remap the face indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #subdiv_loop_face_index which contains the coarse face indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(vbo));
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(&vbo));
for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
vbo_data[i] = mr.orig_index_face[vbo_data[i]];
}
}
constexpr MeshExtract create_extractor_face_idx()
void extract_face_dot_index(const MeshRenderData &mr, gpu::VertBuf &vbo)
{
MeshExtract extractor = {nullptr};
extractor.init = extract_select_idx_init;
extractor.iter_face_bm = extract_face_idx_iter_face_bm;
extractor.iter_face_mesh = extract_face_idx_iter_face_mesh;
extractor.init_subdiv = extract_face_idx_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(int32_t *);
extractor.use_threading = true;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.face_idx);
return extractor;
}
constexpr MeshExtract create_extractor_edge_idx()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_select_idx_init;
extractor.iter_face_bm = extract_edge_idx_iter_face_bm;
extractor.iter_face_mesh = extract_edge_idx_iter_face_mesh;
extractor.iter_loose_edge_bm = extract_edge_idx_iter_loose_edge_bm;
extractor.iter_loose_edge_mesh = extract_edge_idx_iter_loose_edge_mesh;
extractor.init_subdiv = extract_edge_idx_init_subdiv;
extractor.iter_loose_geom_subdiv = extract_edge_idx_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(int32_t *);
extractor.use_threading = true;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edge_idx);
return extractor;
}
constexpr MeshExtract create_extractor_vert_idx()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_select_idx_init;
extractor.iter_face_bm = extract_vert_idx_iter_face_bm;
extractor.iter_face_mesh = extract_vert_idx_iter_face_mesh;
extractor.iter_loose_edge_bm = extract_vert_idx_iter_loose_edge_bm;
extractor.iter_loose_edge_mesh = extract_vert_idx_iter_loose_edge_mesh;
extractor.iter_loose_vert_bm = extract_vert_idx_iter_loose_vert_bm;
extractor.iter_loose_vert_mesh = extract_vert_idx_iter_loose_vert_mesh;
extractor.init_subdiv = extract_vert_idx_init_subdiv;
extractor.iter_loose_geom_subdiv = extract_vert_idx_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(int32_t *);
extractor.use_threading = true;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.vert_idx);
return extractor;
}
static void extract_fdot_idx_init(const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void *tls_data)
{
extract_select_idx_init_impl(mr, mr.faces_num, buf, tls_data);
}
static void extract_fdot_idx_iter_face_bm(const MeshRenderData & /*mr*/,
const BMFace * /*f*/,
const int f_index,
void *data)
{
(*(int32_t **)data)[f_index] = f_index;
}
static void extract_fdot_idx_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *data)
{
if (mr.orig_index_face != nullptr) {
(*(int32_t **)data)[face_index] = mr.orig_index_face[face_index];
MutableSpan<int> vbo_data = init_vbo_data(vbo, mr.faces_num);
if (mr.extract_type == MR_EXTRACT_MESH) {
if (mr.orig_index_face) {
const Span<int> orig_index_face(mr.orig_index_face, mr.faces_num);
array_utils::copy(orig_index_face, vbo_data);
}
else {
array_utils::fill_index_range(vbo_data);
}
}
else {
(*(int32_t **)data)[face_index] = face_index;
array_utils::fill_index_range(vbo_data);
}
}
constexpr MeshExtract create_extractor_fdot_idx()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_fdot_idx_init;
extractor.iter_face_bm = extract_fdot_idx_iter_face_bm;
extractor.iter_face_mesh = extract_fdot_idx_iter_face_mesh;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(int32_t *);
extractor.use_threading = true;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdot_idx);
return extractor;
}
/** \} */
const MeshExtract extract_face_idx = create_extractor_face_idx();
const MeshExtract extract_edge_idx = create_extractor_edge_idx();
const MeshExtract extract_vert_idx = create_extractor_vert_idx();
const MeshExtract extract_fdot_idx = create_extractor_fdot_idx();
} // namespace blender::draw