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.
This commit is contained in:
Hans Goudey
2024-06-03 22:58:49 -04:00
committed by Hans Goudey
parent deedbee971
commit eb4f3516a6
3 changed files with 137 additions and 186 deletions

View File

@@ -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<TaskData *>(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<TaskData *>(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<TaskData *>(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<TaskData *>(task_data);
extract_attr_viewer(data.mr, *data.buffers.vbo.attr_viewer);
},
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. */
@@ -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;

View File

@@ -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<DRW_AttributeRequest> requests,
const Span<gpu::VertBuf *> vbos);
void extract_attributes_subdiv(const MeshRenderData &mr,
const DRWSubdivCache &subdiv_cache,
const Span<DRW_AttributeRequest> requests,
const Span<gpu::VertBuf *> vbos);
void extract_attr_viewer(const MeshRenderData &mr, gpu::VertBuf &vbo);
} // namespace blender::draw

View File

@@ -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<DRW_AttributeRequest> requests,
const Span<gpu::VertBuf *> vbos)
{
const DRW_AttributeRequest &request = cache.attr_used.requests[index];
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(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<gpu::VertBuf *>(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<T>;
if constexpr (!std::is_void_v<typename Converter::VBOType>) {
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<int Index>
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<DRW_AttributeRequest> requests,
const Span<gpu::VertBuf *> 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<T>;
if constexpr (!std::is_void_v<typename Converter::VBOType>) {
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<gpu::VertBuf *>(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<ColorGeometry4f> attr{static_cast<ColorGeometry4f *>(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<ColorGeometry4f *>(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<ColorGeometry4f>(
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<index>(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