Cleanup: Consolidate draw attribute extraction
Use the same attribute conversion class for PBVH and regular mesh attribute extraction. This makes the GPU formats we use for each attribute type more explicit and centralizes the conversions from the attribute types to the GPU types. It's also a bit more aligned to how we could use implicit sharing for GPU vertex buffer data. Unfortunately it isn't possible to use this same code for curves and point clouds because they use textures for their evaluated data, and 3-wide vectors (e.g. `float3`) aren't supported on GPUs with our current texture abstraction. For generic attributes, the long term approach will probably be to use an SSBO instead. Pull Request: https://projects.blender.org/blender/blender/pulls/114340
This commit is contained in:
@@ -35,6 +35,7 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
intern/attribute_convert.cc
|
||||
intern/draw_cache.cc
|
||||
intern/draw_cache_extract_mesh.cc
|
||||
intern/draw_cache_extract_mesh_render_data.cc
|
||||
@@ -229,6 +230,7 @@ set(SRC
|
||||
DRW_engine.h
|
||||
DRW_pbvh.hh
|
||||
DRW_select_buffer.hh
|
||||
intern/attribute_convert.hh
|
||||
intern/DRW_gpu_wrapper.hh
|
||||
intern/DRW_render.h
|
||||
intern/draw_attributes.hh
|
||||
|
||||
56
source/blender/draw/intern/attribute_convert.cc
Normal file
56
source/blender/draw/intern/attribute_convert.cc
Normal file
@@ -0,0 +1,56 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
|
||||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
#include "attribute_convert.hh"
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
GPUVertFormat init_format_for_attribute(const eCustomDataType data_type,
|
||||
const StringRefNull vbo_name)
|
||||
{
|
||||
GPUVertFormat format{};
|
||||
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
GPU_vertformat_attr_add(&format,
|
||||
vbo_name.c_str(),
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
Converter::gpu_fetch_mode);
|
||||
});
|
||||
return format;
|
||||
}
|
||||
|
||||
void vertbuf_data_extract_direct(const GSpan attribute, GPUVertBuf &vbo)
|
||||
{
|
||||
bke::attribute_math::convert_to_static_type(attribute.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
const Span<T> src = attribute.typed<T>();
|
||||
MutableSpan data(static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo)), attribute.size());
|
||||
if constexpr (std::is_same_v<T, VBOType>) {
|
||||
array_utils::copy(src, data);
|
||||
}
|
||||
else {
|
||||
threading::parallel_for(src.index_range(), 8192, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
data[i] = Converter::convert(src[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
144
source/blender/draw/intern/attribute_convert.hh
Normal file
144
source/blender/draw/intern/attribute_convert.hh
Normal file
@@ -0,0 +1,144 @@
|
||||
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_generic_span.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "DNA_customdata_types.h" /* #eCustomDataType. */
|
||||
|
||||
#include "GPU_vertex_format.h"
|
||||
|
||||
/**
|
||||
* Component length of 3 is used for scalars because implicit conversion is done by OpenGL from a
|
||||
* scalar `s` will produce `vec4(s, 0, 0, 1)`. However, following the Blender convention, it should
|
||||
* be `vec4(s, s, s, 1)`.
|
||||
*/
|
||||
constexpr int COMPONENT_LEN_SCALAR = 3;
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/**
|
||||
* Utility to convert from the type used in the attributes to the types for GPU vertex buffers.
|
||||
*/
|
||||
template<typename T> struct AttributeConverter {
|
||||
using VBOType = void;
|
||||
};
|
||||
|
||||
template<> struct AttributeConverter<bool> {
|
||||
using VBOType = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOType convert(const bool &value)
|
||||
{
|
||||
return VBOType(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int8_t> {
|
||||
using VBOType = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOType convert(const int8_t &value)
|
||||
{
|
||||
return VecBase<int, COMPONENT_LEN_SCALAR>(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int> {
|
||||
using VBOType = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOType convert(const int &value)
|
||||
{
|
||||
return int3(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int2> {
|
||||
using VBOType = int2;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = 2;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOType convert(const int2 &value)
|
||||
{
|
||||
return int2(value.x, value.y);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float> {
|
||||
using VBOType = VecBase<float, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOType convert(const float &value)
|
||||
{
|
||||
return VBOType(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float2> {
|
||||
using VBOType = float2;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 2;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOType convert(const float2 &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float3> {
|
||||
using VBOType = float3;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 3;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOType convert(const float3 &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<ColorGeometry4b> {
|
||||
/* 16 bits are required to store the color in linear space without precision loss. */
|
||||
using VBOType = ushort4;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_U16;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
|
||||
static VBOType convert(const ColorGeometry4b &value)
|
||||
{
|
||||
return {unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]),
|
||||
unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]),
|
||||
unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]),
|
||||
ushort(value.a * 257)};
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<ColorGeometry4f> {
|
||||
using VBOType = ColorGeometry4f;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOType convert(const ColorGeometry4f &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<math::Quaternion> {
|
||||
using VBOType = float4;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOType convert(const math::Quaternion &value)
|
||||
{
|
||||
return float4(value.w, value.x, value.y, value.z);
|
||||
}
|
||||
};
|
||||
|
||||
GPUVertFormat init_format_for_attribute(eCustomDataType data_type, StringRefNull vbo_name);
|
||||
|
||||
void vertbuf_data_extract_direct(GSpan attribute, GPUVertBuf &vbo);
|
||||
|
||||
} // namespace blender::draw
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "DRW_engine.h"
|
||||
#include "DRW_pbvh.hh"
|
||||
|
||||
#include "attribute_convert.hh"
|
||||
#include "bmesh.h"
|
||||
#include "draw_pbvh.h"
|
||||
#include "gpu_private.h"
|
||||
@@ -57,10 +58,7 @@
|
||||
#define MAX_PBVH_BATCH_KEY 512
|
||||
#define MAX_PBVH_VBOS 16
|
||||
|
||||
using blender::char3;
|
||||
using blender::float2;
|
||||
using blender::float3;
|
||||
using blender::float4;
|
||||
using blender::FunctionRef;
|
||||
using blender::IndexRange;
|
||||
using blender::Map;
|
||||
@@ -72,131 +70,8 @@ using blender::StringRef;
|
||||
using blender::StringRefNull;
|
||||
using blender::uchar3;
|
||||
using blender::uchar4;
|
||||
using blender::ushort3;
|
||||
using blender::ushort4;
|
||||
using blender::Vector;
|
||||
|
||||
/**
|
||||
* Component length of 3 is used for scalars because implicit conversion is done by OpenGL from a
|
||||
* scalar `s` will produce `vec4(s, 0, 0, 1)`. However, following the Blender convention, it should
|
||||
* be `vec4(s, s, s, 1)`.
|
||||
*/
|
||||
constexpr int COMPONENT_LEN_SCALAR = 3;
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/** Similar to #AttributeTypeConverter. */
|
||||
template<typename T> struct AttributeConverter {
|
||||
using VBOT = void;
|
||||
};
|
||||
|
||||
template<> struct AttributeConverter<bool> {
|
||||
using VBOT = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOT convert(const bool &value)
|
||||
{
|
||||
return VBOT(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int8_t> {
|
||||
using VBOT = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOT convert(const int8_t &value)
|
||||
{
|
||||
return VecBase<int, COMPONENT_LEN_SCALAR>(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int> {
|
||||
using VBOT = VecBase<int, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOT convert(const int &value)
|
||||
{
|
||||
return int3(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int2> {
|
||||
using VBOT = int2;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32;
|
||||
static constexpr int gpu_component_len = 2;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT;
|
||||
static VBOT convert(const int2 &value)
|
||||
{
|
||||
return int2(value.x, value.y);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float> {
|
||||
using VBOT = VecBase<float, COMPONENT_LEN_SCALAR>;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOT convert(const float &value)
|
||||
{
|
||||
return VBOT(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float2> {
|
||||
using VBOT = float2;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 2;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOT convert(const float2 &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<float3> {
|
||||
using VBOT = float3;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 3;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOT convert(const float3 &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<ColorGeometry4b> {
|
||||
/* 16 bits are required to store the color in linear space without precision loss. */
|
||||
using VBOT = ushort4;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_U16;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
|
||||
static VBOT convert(const ColorGeometry4b &value)
|
||||
{
|
||||
return {unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]),
|
||||
unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]),
|
||||
unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]),
|
||||
ushort(value.a * 257)};
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<ColorGeometry4f> {
|
||||
using VBOT = ColorGeometry4f;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOT convert(const ColorGeometry4f &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<blender::math::Quaternion> {
|
||||
using VBOT = float4;
|
||||
static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32;
|
||||
static constexpr int gpu_component_len = 4;
|
||||
static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT;
|
||||
static VBOT convert(const blender::math::Quaternion &value)
|
||||
{
|
||||
return float4(value.w, value.x, value.y, value.z);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
static bool pbvh_attr_supported(int type, const eAttrDomain domain)
|
||||
{
|
||||
using namespace blender;
|
||||
@@ -211,8 +86,8 @@ static bool pbvh_attr_supported(int type, const eAttrDomain domain)
|
||||
bke::attribute_math::convert_to_static_type(eCustomDataType(type), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
if constexpr (!std::is_void_v<VBOT>) {
|
||||
using VBOType = typename Converter::VBOType;
|
||||
if constexpr (!std::is_void_v<VBOType>) {
|
||||
type_supported = true;
|
||||
}
|
||||
});
|
||||
@@ -257,13 +132,13 @@ template<typename T>
|
||||
void extract_data_vert_faces(const PBVH_GPU_Args &args, const Span<T> attribute, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
const Span<int> corner_verts = args.corner_verts;
|
||||
const Span<MLoopTri> looptris = args.mlooptri;
|
||||
const Span<int> looptri_faces = args.looptri_faces;
|
||||
const bool *hide_poly = args.hide_poly;
|
||||
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
for (const int looptri_i : args.prim_indices) {
|
||||
if (hide_poly && hide_poly[looptri_faces[looptri_i]]) {
|
||||
continue;
|
||||
@@ -280,12 +155,12 @@ template<typename T>
|
||||
void extract_data_face_faces(const PBVH_GPU_Args &args, const Span<T> attribute, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
|
||||
const Span<int> looptri_faces = args.looptri_faces;
|
||||
const bool *hide_poly = args.hide_poly;
|
||||
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
for (const int looptri_i : args.prim_indices) {
|
||||
const int face = looptri_faces[looptri_i];
|
||||
if (hide_poly && hide_poly[face]) {
|
||||
@@ -300,13 +175,13 @@ template<typename T>
|
||||
void extract_data_corner_faces(const PBVH_GPU_Args &args, const Span<T> attribute, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
|
||||
const Span<MLoopTri> looptris = args.mlooptri;
|
||||
const Span<int> looptri_faces = args.looptri_faces;
|
||||
const bool *hide_poly = args.hide_poly;
|
||||
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
for (const int looptri_i : args.prim_indices) {
|
||||
if (hide_poly && hide_poly[looptri_faces[looptri_i]]) {
|
||||
continue;
|
||||
@@ -338,8 +213,8 @@ template<typename T>
|
||||
void extract_data_vert_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
for (const BMFace *f : *args.bm_faces) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
@@ -359,8 +234,8 @@ template<typename T>
|
||||
void extract_data_face_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
for (const BMFace *f : *args.bm_faces) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
@@ -375,8 +250,8 @@ template<typename T>
|
||||
void extract_data_corner_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = blender::draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
VBOT *data = static_cast<VBOT *>(GPU_vertbuf_get_data(&vbo));
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
for (const BMFace *f : *args.bm_faces) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
@@ -736,10 +611,10 @@ struct PBVHBatches {
|
||||
bke::attribute_math::convert_to_static_type(eCustomDataType(vbo.type), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = draw::AttributeConverter<T>;
|
||||
using VBOT = typename Converter::VBOT;
|
||||
std::fill_n(static_cast<VBOT *>(GPU_vertbuf_get_data(vbo.vert_buf)),
|
||||
using VBOType = typename Converter::VBOType;
|
||||
std::fill_n(static_cast<VBOType *>(GPU_vertbuf_get_data(vbo.vert_buf)),
|
||||
GPU_vertbuf_get_vertex_len(vbo.vert_buf),
|
||||
VBOT());
|
||||
VBOType());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1094,8 +969,7 @@ struct PBVHBatches {
|
||||
PBVHVbo vbo(domain, type, name);
|
||||
GPUVertFormat format;
|
||||
|
||||
bool need_aliases = !ELEM(
|
||||
type, CD_PBVH_CO_TYPE, CD_PBVH_NO_TYPE, CD_PBVH_FSET_TYPE, CD_PBVH_MASK_TYPE);
|
||||
bool need_aliases = false;
|
||||
|
||||
GPU_vertformat_clear(&format);
|
||||
|
||||
@@ -1112,15 +986,7 @@ struct PBVHBatches {
|
||||
GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
}
|
||||
else {
|
||||
bke::attribute_math::convert_to_static_type(eCustomDataType(type), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = draw::AttributeConverter<T>;
|
||||
GPU_vertformat_attr_add(&format,
|
||||
"data",
|
||||
Converter::gpu_component_type,
|
||||
Converter::gpu_component_len,
|
||||
Converter::gpu_fetch_mode);
|
||||
});
|
||||
format = draw::init_format_for_attribute(eCustomDataType(type), "data");
|
||||
need_aliases = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "attribute_convert.hh"
|
||||
#include "draw_attributes.hh"
|
||||
#include "draw_subdivision.h"
|
||||
#include "extract_mesh.hh"
|
||||
@@ -28,142 +27,19 @@ namespace blender::draw {
|
||||
/** \name Extract Attributes
|
||||
* \{ */
|
||||
|
||||
static CustomData *get_custom_data_for_domain(const MeshRenderData &mr, eAttrDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->vdata : &mr.me->vert_data;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata : &mr.me->loop_data;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->pdata : &mr.me->face_data;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->edata : &mr.me->edge_data;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility to convert from the type used in the attributes to the types for the VBO.
|
||||
* This is mostly used to promote integers and booleans to floats, as other types (float, float2,
|
||||
* etc.) directly map to available GPU types. Booleans are still converted as attributes are vec4
|
||||
* in the shader.
|
||||
*/
|
||||
template<typename AttributeType, typename VBOType> struct AttributeTypeConverter {
|
||||
static VBOType convert_value(AttributeType value)
|
||||
{
|
||||
if constexpr (std::is_same_v<AttributeType, VBOType>) {
|
||||
return value;
|
||||
}
|
||||
|
||||
/* This should only concern bools which are converted to floats. */
|
||||
return static_cast<VBOType>(value);
|
||||
}
|
||||
};
|
||||
|
||||
struct gpuMeshCol {
|
||||
ushort r, g, b, a;
|
||||
};
|
||||
|
||||
template<> struct AttributeTypeConverter<MPropCol, gpuMeshCol> {
|
||||
static gpuMeshCol convert_value(MPropCol value)
|
||||
{
|
||||
gpuMeshCol result;
|
||||
result.r = unit_float_to_ushort_clamp(value.color[0]);
|
||||
result.g = unit_float_to_ushort_clamp(value.color[1]);
|
||||
result.b = unit_float_to_ushort_clamp(value.color[2]);
|
||||
result.a = unit_float_to_ushort_clamp(value.color[3]);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct AttributeTypeConverter<ColorGeometry4b, gpuMeshCol> {
|
||||
static gpuMeshCol convert_value(ColorGeometry4b value)
|
||||
{
|
||||
gpuMeshCol result;
|
||||
result.r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]);
|
||||
result.g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]);
|
||||
result.b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]);
|
||||
result.a = unit_float_to_ushort_clamp(value.a * (1.0f / 255.0f));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/* Return the number of component for the attribute's value type, or 0 if is it unsupported. */
|
||||
static uint gpu_component_size_for_attribute_type(eCustomDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CD_PROP_BOOL:
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_FLOAT:
|
||||
/* TODO(@kevindietrich): should be 1 when scalar attributes conversion is handled by us. See
|
||||
* comment #extract_attr_init. */
|
||||
return 3;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
return 2;
|
||||
case CD_PROP_FLOAT3:
|
||||
return 3;
|
||||
case CD_PROP_COLOR:
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
case CD_PROP_QUATERNION:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static GPUVertFetchMode get_fetch_mode_for_type(eCustomDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_INT32_2D:
|
||||
return GPU_FETCH_INT_TO_FLOAT;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return GPU_FETCH_INT_TO_FLOAT_UNIT;
|
||||
default:
|
||||
return GPU_FETCH_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
static GPUVertCompType get_comp_type_for_type(eCustomDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32_2D:
|
||||
case CD_PROP_INT32:
|
||||
return GPU_COMP_I32;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
/* This should be u8,
|
||||
* but u16 is required to store the color in linear space without precision loss */
|
||||
return GPU_COMP_U16;
|
||||
default:
|
||||
return GPU_COMP_F32;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_vbo_for_attribute(const MeshRenderData &mr,
|
||||
GPUVertBuf *vbo,
|
||||
const DRW_AttributeRequest &request,
|
||||
bool build_on_device,
|
||||
uint32_t len)
|
||||
{
|
||||
GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type);
|
||||
GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type);
|
||||
const uint comp_size = gpu_component_size_for_attribute_type(request.cd_type);
|
||||
/* We should not be here if the attribute type is not supported. */
|
||||
BLI_assert(comp_size != 0);
|
||||
|
||||
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
|
||||
GPU_vertformat_safe_attr_name(request.attribute_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
|
||||
/* Attributes use auto-name. */
|
||||
SNPRINTF(attr_name, "a%s", attr_safe_name);
|
||||
|
||||
GPUVertFormat format = {0};
|
||||
GPUVertFormat format = init_format_for_attribute(request.cd_type, attr_name);
|
||||
GPU_vertformat_deinterleave(&format);
|
||||
GPU_vertformat_attr_add(&format, attr_name, comp_type, comp_size, fetch_mode);
|
||||
|
||||
if (mr.active_color_name && STREQ(request.attribute_name, mr.active_color_name)) {
|
||||
GPU_vertformat_alias_add(&format, "ac");
|
||||
@@ -181,164 +57,214 @@ static void init_vbo_for_attribute(const MeshRenderData &mr,
|
||||
}
|
||||
}
|
||||
|
||||
template<typename AttributeType, typename VBOType>
|
||||
static void fill_vertbuf_with_attribute(const MeshRenderData &mr,
|
||||
VBOType *vbo_data,
|
||||
const DRW_AttributeRequest &request)
|
||||
template<typename T>
|
||||
static void extract_data_mesh_mapped_corner(const Span<T> attribute,
|
||||
const Span<int> indices,
|
||||
GPUVertBuf &vbo)
|
||||
{
|
||||
const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain);
|
||||
BLI_assert(custom_data);
|
||||
const int layer_index = request.layer_index;
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
MutableSpan data(static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo)), indices.size());
|
||||
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> corner_edges = mr.corner_edges;
|
||||
|
||||
const AttributeType *attr_data = static_cast<const AttributeType *>(
|
||||
CustomData_get_layer_n(custom_data, request.cd_type, layer_index));
|
||||
|
||||
using Converter = AttributeTypeConverter<AttributeType, VBOType>;
|
||||
|
||||
switch (request.domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) {
|
||||
*vbo_data = Converter::convert_value(attr_data[corner_verts[ml_index]]);
|
||||
}
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) {
|
||||
*vbo_data = Converter::convert_value(attr_data[ml_index]);
|
||||
}
|
||||
break;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) {
|
||||
*vbo_data = Converter::convert_value(attr_data[corner_edges[ml_index]]);
|
||||
}
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
for (int face_index = 0; face_index < mr.face_len; face_index++) {
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
const VBOType value = Converter::convert_value(attr_data[face_index]);
|
||||
for (int l = 0; l < face.size(); l++) {
|
||||
*vbo_data++ = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename AttributeType, typename VBOType>
|
||||
static void fill_vertbuf_with_attribute_bm(const MeshRenderData &mr,
|
||||
VBOType *&vbo_data,
|
||||
const DRW_AttributeRequest &request)
|
||||
{
|
||||
const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain);
|
||||
BLI_assert(custom_data);
|
||||
const int layer_index = request.layer_index;
|
||||
|
||||
const int cd_ofs = CustomData_get_n_offset(custom_data, request.cd_type, layer_index);
|
||||
|
||||
using Converter = AttributeTypeConverter<AttributeType, VBOType>;
|
||||
|
||||
BMIter f_iter;
|
||||
BMFace *efa;
|
||||
BM_ITER_MESH (efa, &f_iter, mr.bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
|
||||
do {
|
||||
const AttributeType *attr_data = nullptr;
|
||||
if (request.domain == ATTR_DOMAIN_POINT) {
|
||||
attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs));
|
||||
}
|
||||
else if (request.domain == ATTR_DOMAIN_CORNER) {
|
||||
attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs));
|
||||
}
|
||||
else if (request.domain == ATTR_DOMAIN_FACE) {
|
||||
attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(efa, cd_ofs));
|
||||
}
|
||||
else if (request.domain == ATTR_DOMAIN_EDGE) {
|
||||
attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->e, cd_ofs));
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
continue;
|
||||
}
|
||||
*vbo_data = Converter::convert_value(*attr_data);
|
||||
vbo_data++;
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename AttributeType, typename VBOType = AttributeType>
|
||||
static void extract_attr_generic(const MeshRenderData &mr,
|
||||
GPUVertBuf *vbo,
|
||||
const DRW_AttributeRequest &request)
|
||||
{
|
||||
VBOType *vbo_data = static_cast<VBOType *>(GPU_vertbuf_get_data(vbo));
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
fill_vertbuf_with_attribute_bm<AttributeType>(mr, vbo_data, request);
|
||||
if constexpr (std::is_same_v<T, VBOType>) {
|
||||
array_utils::gather(attribute, indices, data);
|
||||
}
|
||||
else {
|
||||
fill_vertbuf_with_attribute<AttributeType>(mr, vbo_data, request);
|
||||
threading::parallel_for(indices.index_range(), 8192, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
data[i] = Converter::convert(attribute[indices[i]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_mesh_vert(const MeshRenderData &mr,
|
||||
const Span<T> attribute,
|
||||
GPUVertBuf &vbo)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_mesh_edge(const MeshRenderData &mr,
|
||||
const Span<T> attribute,
|
||||
GPUVertBuf &vbo)
|
||||
{
|
||||
extract_data_mapped_corner(attribute, mr.corner_edges, vbo);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_mesh_face(const OffsetIndices<int> faces,
|
||||
const Span<T> attribute,
|
||||
GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
MutableSpan data(static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo)), faces.total_size());
|
||||
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
data.slice(faces[i]).fill(Converter::convert(attribute[i]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_bmesh_vert(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
|
||||
const T *src = static_cast<const T *>(POINTER_OFFSET(loop->v->head.data, cd_offset));
|
||||
*data = Converter::convert(*src);
|
||||
loop = loop->next;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_bmesh_edge(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
|
||||
const T &src = *static_cast<const T *>(POINTER_OFFSET(loop->e->head.data, cd_offset));
|
||||
*data = Converter::convert(src);
|
||||
loop = loop->next;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_bmesh_face(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
const T &src = *static_cast<const T *>(POINTER_OFFSET(face->head.data, cd_offset));
|
||||
std::fill_n(data, face->len, Converter::convert(src));
|
||||
data += face->len;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void extract_data_bmesh_loop(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo)
|
||||
{
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
VBOType *data = static_cast<VBOType *>(GPU_vertbuf_get_data(&vbo));
|
||||
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
|
||||
const T &src = *static_cast<const T *>(POINTER_OFFSET(loop->head.data, cd_offset));
|
||||
*data = Converter::convert(src);
|
||||
loop = loop->next;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const CustomData *get_custom_data_for_domain(const BMesh &bm, eAttrDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return &bm.vdata;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return &bm.ldata;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return &bm.pdata;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return &bm.edata;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_attr(const MeshRenderData &mr,
|
||||
GPUVertBuf *vbo,
|
||||
const DRW_AttributeRequest &request)
|
||||
const DRW_AttributeRequest &request,
|
||||
GPUVertBuf &vbo)
|
||||
{
|
||||
/* TODO(@kevindietrich): float3 is used for scalar attributes as the implicit conversion done by
|
||||
* OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the
|
||||
* Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a similar
|
||||
* texture as for volume attribute, so we can control the conversion ourselves. */
|
||||
switch (request.cd_type) {
|
||||
case CD_PROP_BOOL:
|
||||
extract_attr_generic<bool, float3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_INT8:
|
||||
extract_attr_generic<int8_t, int3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_INT32:
|
||||
extract_attr_generic<int32_t, int3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
extract_attr_generic<int2>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_FLOAT:
|
||||
extract_attr_generic<float, float3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_FLOAT2:
|
||||
extract_attr_generic<float2>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_FLOAT3:
|
||||
extract_attr_generic<float3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_QUATERNION:
|
||||
case CD_PROP_COLOR:
|
||||
extract_attr_generic<float4>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
extract_attr_generic<ColorGeometry4b, gpuMeshCol>(mr, vbo, request);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
const CustomData &custom_data = *get_custom_data_for_domain(*mr.bm, request.domain);
|
||||
const char *name = request.attribute_name;
|
||||
const int cd_offset = CustomData_get_offset_named(&custom_data, request.cd_type, name);
|
||||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (request.domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
extract_data_bmesh_vert<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
extract_data_bmesh_edge<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
extract_data_bmesh_face<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
extract_data_bmesh_loop<T>(*mr.bm, cd_offset, vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
const bke::AttributeAccessor attributes = mr.me->attributes();
|
||||
const StringRef name = request.attribute_name;
|
||||
const eCustomDataType data_type = request.cd_type;
|
||||
const GVArraySpan attribute = *attributes.lookup_or_default(name, request.domain, data_type);
|
||||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
switch (request.domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_verts, vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_edges, vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
extract_data_mesh_face(mr.faces, attribute.typed<T>(), vbo);
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
vertbuf_data_extract_direct(attribute.typed<T>(), vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_attr_init(
|
||||
const MeshRenderData &mr, MeshBatchCache &cache, void *buf, void * /*tls_data*/, int index)
|
||||
{
|
||||
const DRW_Attributes *attrs_used = &cache.attr_used;
|
||||
const DRW_AttributeRequest &request = attrs_used->requests[index];
|
||||
|
||||
const DRW_AttributeRequest &request = cache.attr_used.requests[index];
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
|
||||
init_vbo_for_attribute(mr, vbo, request, false, uint32_t(mr.loop_len));
|
||||
|
||||
extract_attr(mr, vbo, request);
|
||||
extract_attr(mr, request, *vbo);
|
||||
}
|
||||
|
||||
static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
@@ -353,26 +279,29 @@ static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
|
||||
Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
|
||||
GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type);
|
||||
GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type);
|
||||
const uint32_t dimensions = gpu_component_size_for_attribute_type(request.cd_type);
|
||||
|
||||
/* Prepare VBO for coarse data. The compute shader only expects floats. */
|
||||
GPUVertBuf *src_data = GPU_vertbuf_calloc();
|
||||
GPUVertFormat coarse_format = {0};
|
||||
GPU_vertformat_attr_add(&coarse_format, "data", comp_type, dimensions, fetch_mode);
|
||||
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->totloop));
|
||||
|
||||
extract_attr(mr, src_data, request);
|
||||
extract_attr(mr, request, *src_data);
|
||||
|
||||
GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(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);
|
||||
draw_subdiv_interp_custom_data(
|
||||
subdiv_cache, src_data, dst_buffer, comp_type, int(dimensions), 0);
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user