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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user