From eb4f3516a662a6a8564f5cd67b47d8800c6e2aa8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 3 Jun 2024 22:58:49 -0400 Subject: [PATCH] Mesh: Draw: Replace extractor abstraction for attributes buffers Part of #116901. The last extractor removed. This was already written in a data-oriented manner so only the entry point changes in this commit. --- .../draw/intern/draw_cache_extract_mesh.cc | 123 +++++++----- .../intern/mesh_extractors/extract_mesh.hh | 10 +- .../extract_mesh_vbo_attributes.cc | 190 +++++------------- 3 files changed, 137 insertions(+), 186 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 0d1c5ea15fe..b86206b7064 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -584,6 +584,16 @@ static TaskNode *mesh_extract_render_data_node_create(TaskGraph *task_graph, /** \name Extract Loop * \{ */ +static bool any_attr_requested(const MeshBufferList &buffers) +{ + for (const int i : IndexRange(ARRAY_SIZE(buffers.vbo.attr))) { + if (DRW_vbo_requested(buffers.vbo.attr[i])) { + return true; + } + } + return false; +} + void mesh_buffer_cache_create_requested(TaskGraph &task_graph, MeshBatchCache &cache, MeshBufferCache &mbc, @@ -637,30 +647,17 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, MeshBufferList &buffers = mbc.buff; -#define EXTRACT_ADD_REQUESTED(type, name) \ - do { \ - if (DRW_##type##_requested(buffers.type.name)) { \ - extractors.append(&extract_##name); \ - } \ - } while (0) - - for (int i = 0; i < GPU_MAX_ATTR; i++) { - EXTRACT_ADD_REQUESTED(vbo, attr[i]); - } - EXTRACT_ADD_REQUESTED(vbo, attr_viewer); - -#undef EXTRACT_ADD_REQUESTED - - 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.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.edge_fac) && - !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) && + const bool attrs_requested = any_attr_requested(buffers); + if (!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.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.edge_fac) && !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.fdots_edituv_data) && !DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) && @@ -671,7 +668,8 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph, !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)) + !DRW_vbo_requested(buffers.vbo.orco) && !DRW_vbo_requested(buffers.vbo.mesh_analysis) && + !DRW_vbo_requested(buffers.vbo.attr_viewer) && !attrs_requested) { return; } @@ -1189,6 +1187,39 @@ 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 (attrs_requested) { + 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_attributes(data.mr, + {data.cache.attr_used.requests, GPU_MAX_ATTR}, + {data.buffers.vbo.attr, GPU_MAX_ATTR}); + }, + 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_vbo_requested(buffers.vbo.attr_viewer)) { + 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(task_data); + extract_attr_viewer(data.mr, *data.buffers.vbo.attr_viewer); + }, + new TaskData{*mr, buffers}, + [](void *task_data) { delete static_cast(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. */ @@ -1270,37 +1301,25 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, MeshBufferList &buffers = mbc.buff; -#define EXTRACT_ADD_REQUESTED(type, name) \ - do { \ - if (DRW_##type##_requested(buffers.type.name)) { \ - const MeshExtract *extractor = &extract_##name; \ - extractors.append(extractor); \ - } \ - } while (0) + const bool attrs_requested = any_attr_requested(buffers); - for (int i = 0; i < GPU_MAX_ATTR; i++) { - EXTRACT_ADD_REQUESTED(vbo, attr[i]); - } - -#undef EXTRACT_ADD_REQUESTED - - 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.edge_fac) && !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.fdots_nor) && - !DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots) && - !DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) && + if (!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.edge_fac) && + !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.fdots_nor) && !DRW_vbo_requested(buffers.vbo.fdots_pos) && + !DRW_ibo_requested(buffers.ibo.fdots) && !DRW_vbo_requested(buffers.vbo.uv) && + !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) && !DRW_vbo_requested(buffers.vbo.edituv_data) && !DRW_ibo_requested(buffers.ibo.edituv_tris) && !DRW_ibo_requested(buffers.ibo.edituv_lines) && !DRW_ibo_requested(buffers.ibo.edituv_points) && !DRW_ibo_requested(buffers.ibo.lines_paint_mask) && !DRW_ibo_requested(buffers.ibo.lines_adjacency) && - !DRW_vbo_requested(buffers.vbo.sculpt_data)) + !DRW_vbo_requested(buffers.vbo.sculpt_data) && !attrs_requested) { return; } @@ -1387,6 +1406,12 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache, if (DRW_ibo_requested(buffers.ibo.edituv_points)) { extract_edituv_points_subdiv(mr, subdiv_cache, *buffers.ibo.edituv_points); } + if (attrs_requested) { + extract_attributes_subdiv(mr, + subdiv_cache, + {cache.attr_used.requests, GPU_MAX_ATTR}, + {buffers.vbo.attr, GPU_MAX_ATTR}); + } 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 1807520060f..5a3e75d5eef 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -500,7 +500,13 @@ void extract_orco(const MeshRenderData &mr, gpu::VertBuf &vbo); void extract_mesh_analysis(const MeshRenderData &mr, gpu::VertBuf &vbo); -extern const MeshExtract extract_attr[GPU_MAX_ATTR]; -extern const MeshExtract extract_attr_viewer; +void extract_attributes(const MeshRenderData &mr, + const Span requests, + const Span vbos); +void extract_attributes_subdiv(const MeshRenderData &mr, + const DRWSubdivCache &subdiv_cache, + const Span requests, + const Span vbos); +void extract_attr_viewer(const MeshRenderData &mr, gpu::VertBuf &vbo); } // namespace blender::draw diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 77fdcab870b..63ee9feea5e 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -18,6 +18,7 @@ #include "attribute_convert.hh" #include "draw_attributes.hh" +#include "draw_cache_inline.hh" #include "draw_subdivision.hh" #include "extract_mesh.hh" @@ -249,159 +250,78 @@ static void extract_attribute(const MeshRenderData &mr, } } -static void extract_attr_init( - const MeshRenderData &mr, MeshBatchCache &cache, void *buf, void * /*tls_data*/, int index) +void extract_attributes(const MeshRenderData &mr, + const Span requests, + const Span vbos) { - const DRW_AttributeRequest &request = cache.attr_used.requests[index]; - gpu::VertBuf *vbo = static_cast(buf); - init_vbo_for_attribute(mr, vbo, request, false, uint32_t(mr.corners_num)); - extract_attribute(mr, request, *vbo); -} - -static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache, - const MeshRenderData &mr, - MeshBatchCache &cache, - void *buffer, - void * /*tls_data*/, - int index) -{ - const DRW_Attributes *attrs_used = &cache.attr_used; - const DRW_AttributeRequest &request = attrs_used->requests[index]; - - const Mesh *coarse_mesh = subdiv_cache.mesh; - - /* Prepare VBO for coarse data. The compute shader only expects floats. */ - gpu::VertBuf *src_data = GPU_vertbuf_calloc(); - GPUVertFormat coarse_format = draw::init_format_for_attribute(request.cd_type, "data"); - GPU_vertbuf_init_with_format_ex(src_data, &coarse_format, GPU_USAGE_STATIC); - GPU_vertbuf_data_alloc(src_data, uint32_t(coarse_mesh->corners_num)); - - extract_attribute(mr, request, *src_data); - - gpu::VertBuf *dst_buffer = static_cast(buffer); - init_vbo_for_attribute(mr, dst_buffer, request, true, subdiv_cache.num_subdiv_loops); - - /* Ensure data is uploaded properly. */ - GPU_vertbuf_tag_dirty(src_data); - bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) { - using T = decltype(dummy); - using Converter = AttributeConverter; - if constexpr (!std::is_void_v) { - draw_subdiv_interp_custom_data(subdiv_cache, - src_data, - dst_buffer, - Converter::gpu_component_type, - Converter::gpu_component_len, - 0); + for (const int i : vbos.index_range()) { + if (DRW_vbo_requested(vbos[i])) { + init_vbo_for_attribute(mr, vbos[i], requests[i], false, uint32_t(mr.corners_num)); + extract_attribute(mr, requests[i], *vbos[i]); } - }); - - GPU_vertbuf_discard(src_data); -} - -/* Wrappers around extract_attr_init so we can pass the index of the attribute that we want to - * extract. The overall API does not allow us to pass this in a convenient way. */ -#define EXTRACT_INIT_WRAPPER(index) \ - static void extract_attr_init##index( \ - const MeshRenderData &mr, MeshBatchCache &cache, void *buf, void *tls_data) \ - { \ - extract_attr_init(mr, cache, buf, tls_data, index); \ - } \ - static void extract_attr_init_subdiv##index(const DRWSubdivCache &subdiv_cache, \ - const MeshRenderData &mr, \ - MeshBatchCache &cache, \ - void *buf, \ - void *tls_data) \ - { \ - extract_attr_init_subdiv(subdiv_cache, mr, cache, buf, tls_data, index); \ } - -EXTRACT_INIT_WRAPPER(0) -EXTRACT_INIT_WRAPPER(1) -EXTRACT_INIT_WRAPPER(2) -EXTRACT_INIT_WRAPPER(3) -EXTRACT_INIT_WRAPPER(4) -EXTRACT_INIT_WRAPPER(5) -EXTRACT_INIT_WRAPPER(6) -EXTRACT_INIT_WRAPPER(7) -EXTRACT_INIT_WRAPPER(8) -EXTRACT_INIT_WRAPPER(9) -EXTRACT_INIT_WRAPPER(10) -EXTRACT_INIT_WRAPPER(11) -EXTRACT_INIT_WRAPPER(12) -EXTRACT_INIT_WRAPPER(13) -EXTRACT_INIT_WRAPPER(14) - -template -constexpr MeshExtract create_extractor_attr(ExtractInitFn fn, ExtractInitSubdivFn subdiv_fn) -{ - MeshExtract extractor = {nullptr}; - extractor.init = fn; - extractor.init_subdiv = subdiv_fn; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = 0; - extractor.use_threading = false; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.attr[Index]); - return extractor; } -static void extract_mesh_attr_viewer_init(const MeshRenderData &mr, - MeshBatchCache & /*cache*/, - void *buf, - void * /*tls_data*/) +void extract_attributes_subdiv(const MeshRenderData &mr, + const DRWSubdivCache &subdiv_cache, + const Span requests, + const Span vbos) +{ + for (const int i : vbos.index_range()) { + if (DRW_vbo_requested(vbos[i])) { + const DRW_AttributeRequest &request = requests[i]; + + const Mesh *coarse_mesh = subdiv_cache.mesh; + + /* Prepare VBO for coarse data. The compute shader only expects floats. */ + gpu::VertBuf *src_data = GPU_vertbuf_calloc(); + GPUVertFormat coarse_format = draw::init_format_for_attribute(request.cd_type, "data"); + GPU_vertbuf_init_with_format_ex(src_data, &coarse_format, GPU_USAGE_STATIC); + GPU_vertbuf_data_alloc(src_data, uint32_t(coarse_mesh->corners_num)); + + extract_attribute(mr, request, *src_data); + + gpu::VertBuf *dst_buffer = vbos[i]; + init_vbo_for_attribute(mr, dst_buffer, request, true, subdiv_cache.num_subdiv_loops); + + /* Ensure data is uploaded properly. */ + GPU_vertbuf_tag_dirty(src_data); + bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) { + using T = decltype(dummy); + using Converter = AttributeConverter; + if constexpr (!std::is_void_v) { + draw_subdiv_interp_custom_data(subdiv_cache, + src_data, + dst_buffer, + Converter::gpu_component_type, + Converter::gpu_component_len, + 0); + } + }); + + GPU_vertbuf_discard(src_data); + } + } +} + +void extract_attr_viewer(const MeshRenderData &mr, gpu::VertBuf &vbo) { - gpu::VertBuf *vbo = static_cast(buf); static GPUVertFormat format = {0}; if (format.attr_len == 0) { GPU_vertformat_attr_add(&format, "attribute_value", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); } - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr.corners_num); - MutableSpan attr{static_cast(GPU_vertbuf_get_data(vbo)), - mr.corners_num}; + 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); const StringRefNull attr_name = ".viewer"; const bke::AttributeAccessor attributes = mr.mesh->attributes(); const bke::AttributeReader attribute = attributes.lookup_or_default( attr_name, bke::AttrDomain::Corner, {1.0f, 0.0f, 1.0f, 1.0f}); - attribute.varray.materialize(attr); -} - -constexpr MeshExtract create_extractor_attr_viewer() -{ - MeshExtract extractor = {nullptr}; - extractor.init = extract_mesh_attr_viewer_init; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = 0; - extractor.use_threading = false; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.attr_viewer); - return extractor; + attribute.varray.materialize(vbo_data); } /** \} */ -#define CREATE_EXTRACTOR_ATTR(index) \ - create_extractor_attr(extract_attr_init##index, extract_attr_init_subdiv##index) - -const MeshExtract extract_attr[GPU_MAX_ATTR] = { - CREATE_EXTRACTOR_ATTR(0), - CREATE_EXTRACTOR_ATTR(1), - CREATE_EXTRACTOR_ATTR(2), - CREATE_EXTRACTOR_ATTR(3), - CREATE_EXTRACTOR_ATTR(4), - CREATE_EXTRACTOR_ATTR(5), - CREATE_EXTRACTOR_ATTR(6), - CREATE_EXTRACTOR_ATTR(7), - CREATE_EXTRACTOR_ATTR(8), - CREATE_EXTRACTOR_ATTR(9), - CREATE_EXTRACTOR_ATTR(10), - CREATE_EXTRACTOR_ATTR(11), - CREATE_EXTRACTOR_ATTR(12), - CREATE_EXTRACTOR_ATTR(13), - CREATE_EXTRACTOR_ATTR(14), -}; - -const MeshExtract extract_attr_viewer = create_extractor_attr_viewer(); - } // namespace blender::draw