Mesh: Draw: Replace extractor abstraction for face dots position buffer

Part of #116901.
This commit is contained in:
Hans Goudey
2024-06-01 10:32:47 -04:00
committed by Hans Goudey
parent ef91db222e
commit 4d72eac0ab
3 changed files with 99 additions and 101 deletions

View File

@@ -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<TaskData *>(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<TaskData *>(task_data);
extract_face_dots_position(data.mr, *data.mbc.buff.vbo.fdots_pos);
},
new TaskData{*mr, mbc},
[](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.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;

View File

@@ -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;

View File

@@ -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<float3> vbo_data)
{
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(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<float(*)[3]>(vbo_data);
const Span<float3> positions = mr.vert_positions;
const OffsetIndices faces = mr.faces;
const Span<int> 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<int> 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<float3> vbo_data)
{
float(*center)[3] = *static_cast<float(**)[3]>(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<float(**)[3]>(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<BMesh &>(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<float3 *>(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<gpu::VertBuf *>(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