Refactor: Remove domain from draw attribute request struct
Similar to b21cb20eeb.
This time the domain is removed. The idea is that the domain doesn't
change anything about how the attribute is stored on the vertex buffers
so it doesn't make sense as part of the request. If we continue that
logic to also remove the data type, we can avoid searching through the
geometry when creating the requests, instead handling invalid requests
when creating the buffers.
The complexity of the change comes from the fact that the request's
domain was used to determine whether the Curves drawing code needed to
interpolate the attribute to the evaluated points. This is now stored
separately in the curves cache. The change in the sculpt code is also
non-trivial since we delay more of the logic until after we have
looked up the attribute from the geometry.
Pull Request: https://projects.blender.org/blender/blender/pulls/138619
This commit is contained in:
@@ -40,12 +40,8 @@ class GenericRequest {
|
||||
public:
|
||||
std::string name;
|
||||
eCustomDataType type;
|
||||
bke::AttrDomain domain;
|
||||
GenericRequest(const StringRef name, const eCustomDataType type, const bke::AttrDomain domain)
|
||||
: name(name), type(type), domain(domain)
|
||||
{
|
||||
}
|
||||
BLI_STRUCT_EQUALITY_OPERATORS_3(GenericRequest, type, domain, name);
|
||||
GenericRequest(const StringRef name, const eCustomDataType type) : name(name), type(type) {}
|
||||
BLI_STRUCT_EQUALITY_OPERATORS_2(GenericRequest, type, name);
|
||||
};
|
||||
|
||||
enum class CustomRequest : int8_t {
|
||||
|
||||
@@ -17,9 +17,7 @@ static bool drw_attributes_has_request(const DRW_Attributes *requests,
|
||||
{
|
||||
for (int i = 0; i < requests->num_requests; i++) {
|
||||
const DRW_AttributeRequest &src_req = requests->requests[i];
|
||||
if (STREQ(src_req.attribute_name, req.attribute_name) && src_req.domain == req.domain &&
|
||||
src_req.cd_type == req.cd_type)
|
||||
{
|
||||
if (STREQ(src_req.attribute_name, req.attribute_name) && src_req.cd_type == req.cd_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -70,13 +68,11 @@ bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b)
|
||||
|
||||
void drw_attributes_add_request(DRW_Attributes *attrs,
|
||||
const char *name,
|
||||
const eCustomDataType type,
|
||||
const blender::bke::AttrDomain domain)
|
||||
const eCustomDataType type)
|
||||
{
|
||||
DRW_AttributeRequest req{};
|
||||
req.cd_type = type;
|
||||
STRNCPY(req.attribute_name, name);
|
||||
req.domain = domain;
|
||||
if (attrs->num_requests >= GPU_MAX_ATTR || drw_attributes_has_request(attrs, req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace blender::draw {
|
||||
|
||||
struct DRW_AttributeRequest {
|
||||
eCustomDataType cd_type;
|
||||
blender::bke::AttrDomain domain;
|
||||
char attribute_name[64];
|
||||
};
|
||||
|
||||
@@ -60,8 +59,7 @@ bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b);
|
||||
|
||||
void drw_attributes_add_request(DRW_Attributes *attrs,
|
||||
const char *name,
|
||||
eCustomDataType data_type,
|
||||
blender::bke::AttrDomain domain);
|
||||
eCustomDataType data_type);
|
||||
|
||||
bool drw_custom_data_match_attribute(const CustomData &custom_data,
|
||||
const char *name,
|
||||
|
||||
@@ -579,61 +579,60 @@ static void alloc_final_attribute_vbo(CurvesEvalCache &cache,
|
||||
cache.final.resolution * cache.curves_num);
|
||||
}
|
||||
|
||||
static void ensure_control_point_attribute(const Curves &curves,
|
||||
CurvesEvalCache &cache,
|
||||
const DRW_AttributeRequest &request,
|
||||
const int index,
|
||||
const GPUVertFormat &format)
|
||||
static gpu::VertBufPtr ensure_control_point_attribute(const Curves &curves_id,
|
||||
const StringRef name,
|
||||
const GPUVertFormat &format,
|
||||
bool &r_is_point_domain)
|
||||
{
|
||||
if (cache.proc_attributes_buf[index] != nullptr) {
|
||||
return;
|
||||
}
|
||||
gpu::VertBufPtr vbo = gpu::VertBufPtr(GPU_vertbuf_create_with_format_ex(
|
||||
format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY));
|
||||
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]);
|
||||
|
||||
cache.proc_attributes_buf[index] = GPU_vertbuf_create_with_format_ex(
|
||||
format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
|
||||
gpu::VertBuf &attr_vbo = *cache.proc_attributes_buf[index];
|
||||
|
||||
GPU_vertbuf_data_alloc(attr_vbo,
|
||||
request.domain == bke::AttrDomain::Point ? curves.geometry.point_num :
|
||||
curves.geometry.curve_num);
|
||||
|
||||
const bke::AttributeAccessor attributes = curves.geometry.wrap().attributes();
|
||||
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
|
||||
const bke::AttributeAccessor attributes = curves.wrap().attributes();
|
||||
|
||||
/* TODO(@kevindietrich): float4 is used for scalar attributes as the implicit conversion done
|
||||
* by OpenGL to float4 for a scalar `s` will produce a `float4(s, 0, 0, 1)`. However, following
|
||||
* the Blender convention, it should be `float4(s, s, s, 1)`. This could be resolved using a
|
||||
* similar texture state swizzle to map the attribute correctly as for volume attributes, so we
|
||||
* can control the conversion ourselves. */
|
||||
bke::AttributeReader<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
|
||||
request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f});
|
||||
const bke::AttributeReader<ColorGeometry4f> attribute = attributes.lookup<ColorGeometry4f>(name);
|
||||
if (!attribute) {
|
||||
GPU_vertbuf_data_alloc(*vbo, curves.curves_num());
|
||||
vbo->data<ColorGeometry4f>().fill({0.0f, 0.0f, 0.0f, 1.0f});
|
||||
r_is_point_domain = false;
|
||||
return vbo;
|
||||
}
|
||||
|
||||
MutableSpan<ColorGeometry4f> vbo_span = attr_vbo.data<ColorGeometry4f>();
|
||||
|
||||
attribute.varray.materialize(vbo_span);
|
||||
r_is_point_domain = attribute.domain == bke::AttrDomain::Point;
|
||||
GPU_vertbuf_data_alloc(*vbo, r_is_point_domain ? curves.points_num() : curves.curves_num());
|
||||
attribute.varray.materialize(vbo->data<ColorGeometry4f>());
|
||||
return vbo;
|
||||
}
|
||||
|
||||
static void ensure_final_attribute(const Curves &curves,
|
||||
CurvesEvalCache &cache,
|
||||
const DRW_AttributeRequest &request,
|
||||
const int index)
|
||||
const StringRef name,
|
||||
const int index,
|
||||
CurvesEvalCache &cache)
|
||||
{
|
||||
char sampler_name[32];
|
||||
drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name);
|
||||
drw_curves_get_attribute_sampler_name(name, sampler_name);
|
||||
|
||||
GPUVertFormat format = {0};
|
||||
/* All attributes use float4, see comment below. */
|
||||
GPU_vertformat_attr_add(&format, sampler_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
||||
|
||||
ensure_control_point_attribute(curves, cache, request, index, format);
|
||||
if (!cache.proc_attributes_buf[index]) {
|
||||
gpu::VertBufPtr vbo = ensure_control_point_attribute(
|
||||
curves, name, format, cache.proc_attributes_point_domain[index]);
|
||||
cache.proc_attributes_buf[index] = vbo.release();
|
||||
}
|
||||
|
||||
/* Existing final data may have been for a different attribute (with a different name or domain),
|
||||
* free the data. */
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache.final.attributes_buf[index]);
|
||||
|
||||
/* Ensure final data for points. */
|
||||
if (request.domain == bke::AttrDomain::Point) {
|
||||
if (cache.proc_attributes_point_domain[index]) {
|
||||
alloc_final_attribute_vbo(cache, format, index, sampler_name);
|
||||
}
|
||||
}
|
||||
@@ -819,7 +818,7 @@ static bool ensure_attributes(const Curves &curves,
|
||||
}
|
||||
|
||||
if (layer != -1 && domain.has_value()) {
|
||||
drw_attributes_add_request(&attrs_needed, name, CD_PROP_FLOAT2, *domain);
|
||||
drw_attributes_add_request(&attrs_needed, name, CD_PROP_FLOAT2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -840,7 +839,7 @@ static bool ensure_attributes(const Curves &curves,
|
||||
case CD_PROP_FLOAT:
|
||||
case CD_PROP_FLOAT2: {
|
||||
if (layer != -1 && domain.has_value()) {
|
||||
drw_attributes_add_request(&attrs_needed, name, type, *domain);
|
||||
drw_attributes_add_request(&attrs_needed, name, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -869,11 +868,10 @@ static bool ensure_attributes(const Curves &curves,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (request.domain == bke::AttrDomain::Point) {
|
||||
ensure_final_attribute(curves, request.attribute_name, i, cache.eval_cache);
|
||||
if (cache.eval_cache.proc_attributes_point_domain[i]) {
|
||||
need_tf_update = true;
|
||||
}
|
||||
|
||||
ensure_final_attribute(curves, cache.eval_cache, request, i);
|
||||
}
|
||||
|
||||
return need_tf_update;
|
||||
@@ -892,15 +890,12 @@ static void request_attribute(Curves &curves, const char *name)
|
||||
if (!meta_data) {
|
||||
return;
|
||||
}
|
||||
const bke::AttrDomain domain = meta_data->domain;
|
||||
const eCustomDataType type = meta_data->data_type;
|
||||
|
||||
drw_attributes_add_request(&attributes, name, type, domain);
|
||||
drw_attributes_add_request(&attributes, name, meta_data->data_type);
|
||||
|
||||
drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex);
|
||||
}
|
||||
|
||||
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32])
|
||||
void drw_curves_get_attribute_sampler_name(const StringRef layer_name, char r_sampler_name[32])
|
||||
{
|
||||
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
|
||||
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
|
||||
@@ -1062,17 +1057,12 @@ gpu::VertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
|
||||
*r_is_point_domain = false;
|
||||
return nullptr;
|
||||
}
|
||||
switch (final_cache.attr_used.requests[request_i].domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
*r_is_point_domain = true;
|
||||
return &final_cache.attributes_buf[request_i];
|
||||
case bke::AttrDomain::Curve:
|
||||
*r_is_point_domain = false;
|
||||
return &cache.eval_cache.proc_attributes_buf[request_i];
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
if (cache.eval_cache.proc_attributes_point_domain[request_i]) {
|
||||
*r_is_point_domain = true;
|
||||
return &final_cache.attributes_buf[request_i];
|
||||
}
|
||||
*r_is_point_domain = false;
|
||||
return &cache.eval_cache.proc_attributes_buf[request_i];
|
||||
}
|
||||
|
||||
static void create_edit_points_position_vbo(
|
||||
|
||||
@@ -305,7 +305,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object &object,
|
||||
case CD_PROP_FLOAT:
|
||||
case CD_PROP_FLOAT2: {
|
||||
if (layer != -1 && domain.has_value()) {
|
||||
drw_attributes_add_request(attributes, name, type, *domain);
|
||||
drw_attributes_add_request(attributes, name, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -700,10 +700,10 @@ static void request_active_and_default_color_attributes(const Object &object,
|
||||
int layer_index;
|
||||
eCustomDataType type;
|
||||
if (drw_custom_data_match_attribute(cd_vdata, name, &layer_index, &type)) {
|
||||
drw_attributes_add_request(&attributes, name, type, bke::AttrDomain::Point);
|
||||
drw_attributes_add_request(&attributes, name, type);
|
||||
}
|
||||
else if (drw_custom_data_match_attribute(cd_ldata, name, &layer_index, &type)) {
|
||||
drw_attributes_add_request(&attributes, name, type, bke::AttrDomain::Corner);
|
||||
drw_attributes_add_request(&attributes, name, type);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -316,7 +316,7 @@ static void pointcloud_extract_attribute(const PointCloud &pointcloud,
|
||||
* similar texture state swizzle to map the attribute correctly as for volume attributes, so we
|
||||
* can control the conversion ourselves. */
|
||||
bke::AttributeReader<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
|
||||
request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f});
|
||||
request.attribute_name, bke::AttrDomain::Point, {0.0f, 0.0f, 0.0f, 1.0f});
|
||||
|
||||
static const GPUVertFormat format = [&]() {
|
||||
GPUVertFormat format{};
|
||||
@@ -361,7 +361,7 @@ gpu::Batch **pointcloud_surface_shaded_get(PointCloud *pointcloud,
|
||||
continue;
|
||||
}
|
||||
|
||||
drw_attributes_add_request(&attrs_needed, name, meta_data->data_type, meta_data->domain);
|
||||
drw_attributes_add_request(&attrs_needed, name, meta_data->data_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ gpu::VertBuf **DRW_pointcloud_evaluated_attribute(PointCloud *pointcloud, const
|
||||
}
|
||||
{
|
||||
DRW_Attributes requests{};
|
||||
drw_attributes_add_request(&requests, name, meta_data->data_type, meta_data->domain);
|
||||
drw_attributes_add_request(&requests, name, meta_data->data_type);
|
||||
drw_attributes_merge(&cache.eval_cache.attr_used, &requests, cache.render_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,11 +124,9 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache)
|
||||
|
||||
const DRW_Attributes &attrs = cache->final.attr_used;
|
||||
for (int i = 0; i < attrs.num_requests; i++) {
|
||||
/* Only refine point attributes. */
|
||||
if (attrs.requests[i].domain == bke::AttrDomain::Curve) {
|
||||
if (!cache->proc_attributes_point_domain[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
drw_curves_cache_update_compute(
|
||||
cache, curves_num, cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
|
||||
}
|
||||
@@ -248,7 +246,7 @@ static CurvesEvalCache *curves_cache_get(Curves &curves,
|
||||
const DRW_Attributes &attrs = cache->final.attr_used;
|
||||
for (int i : IndexRange(attrs.num_requests)) {
|
||||
/* Only refine point attributes. */
|
||||
if (attrs.requests[i].domain != bke::AttrDomain::Curve) {
|
||||
if (cache->proc_attributes_point_domain[i]) {
|
||||
cache_update(cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
|
||||
}
|
||||
}
|
||||
@@ -341,7 +339,7 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
char sampler_name[32];
|
||||
drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name);
|
||||
|
||||
if (request.domain == bke::AttrDomain::Curve) {
|
||||
if (!curves_cache->proc_attributes_point_domain[i]) {
|
||||
if (!curves_cache->proc_attributes_buf[i]) {
|
||||
continue;
|
||||
}
|
||||
@@ -366,7 +364,7 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
* attributes. */
|
||||
const int index = attribute_index_in_material(gpu_material, request.attribute_name);
|
||||
if (index != -1) {
|
||||
curves_infos.is_point_attribute[index][0] = request.domain == bke::AttrDomain::Point;
|
||||
curves_infos.is_point_attribute[index][0] = curves_cache->proc_attributes_point_domain[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "GPU_shader.hh"
|
||||
|
||||
#include "draw_attributes.hh"
|
||||
@@ -84,6 +86,7 @@ struct CurvesEvalCache {
|
||||
/* For point attributes, which need subdivision, these buffers contain the input data.
|
||||
* For curve domain attributes, which do not need subdivision, these are the final data. */
|
||||
gpu::VertBuf *proc_attributes_buf[GPU_MAX_ATTR];
|
||||
std::array<bool, GPU_MAX_ATTR> proc_attributes_point_domain;
|
||||
|
||||
int curves_num;
|
||||
int points_num;
|
||||
@@ -98,6 +101,6 @@ bool curves_ensure_procedural_data(Curves *curves_id,
|
||||
int subdiv,
|
||||
int thickness_res);
|
||||
|
||||
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]);
|
||||
void drw_curves_get_attribute_sampler_name(StringRef layer_name, char r_sampler_name[32]);
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
@@ -307,7 +307,7 @@ static const GPUVertFormat &face_set_format()
|
||||
}
|
||||
|
||||
static GPUVertFormat attribute_format(const OrigMeshData &orig_mesh_data,
|
||||
const StringRefNull name,
|
||||
const StringRef name,
|
||||
const eCustomDataType data_type)
|
||||
{
|
||||
GPUVertFormat format = draw::init_format_for_attribute(data_type, "data");
|
||||
@@ -326,32 +326,10 @@ static GPUVertFormat attribute_format(const OrigMeshData &orig_mesh_data,
|
||||
is_render = orig_mesh_data.default_uv_map == name;
|
||||
}
|
||||
|
||||
DRW_cdlayer_attr_aliases_add(&format, prefix, data_type, name.c_str(), is_render, is_active);
|
||||
DRW_cdlayer_attr_aliases_add(&format, prefix, data_type, name, is_render, is_active);
|
||||
return format;
|
||||
}
|
||||
|
||||
static bool pbvh_attr_supported(const AttributeRequest &request)
|
||||
{
|
||||
if (std::holds_alternative<CustomRequest>(request)) {
|
||||
return true;
|
||||
}
|
||||
const GenericRequest &attr = std::get<GenericRequest>(request);
|
||||
if (!ELEM(attr.domain, bke::AttrDomain::Point, bke::AttrDomain::Face, bke::AttrDomain::Corner)) {
|
||||
/* blender::bke::pbvh::Tree drawing does not support edge domain attributes. */
|
||||
return false;
|
||||
}
|
||||
bool type_supported = false;
|
||||
bke::attribute_math::convert_to_static_type(attr.type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
using Converter = AttributeConverter<T>;
|
||||
using VBOType = typename Converter::VBOType;
|
||||
if constexpr (!std::is_void_v<VBOType>) {
|
||||
type_supported = true;
|
||||
}
|
||||
});
|
||||
return type_supported;
|
||||
}
|
||||
|
||||
inline short4 normal_float_to_short(const float3 &value)
|
||||
{
|
||||
short3 result;
|
||||
@@ -487,20 +465,6 @@ void extract_data_corner_bmesh(const Set<BMFace *, 0> &faces,
|
||||
}
|
||||
}
|
||||
|
||||
static const CustomData *get_cdata(const BMesh &bm, const bke::AttrDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
return &bm.vdata;
|
||||
case bke::AttrDomain::Corner:
|
||||
return &bm.ldata;
|
||||
case bke::AttrDomain::Face:
|
||||
return &bm.pdata;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static int count_visible_tris_bmesh(const Set<BMFace *, 0> &faces)
|
||||
{
|
||||
return std::count_if(faces.begin(), faces.end(), [&](const BMFace *face) {
|
||||
@@ -728,7 +692,7 @@ BLI_NOINLINE static void update_face_sets_mesh(const Object &object,
|
||||
BLI_NOINLINE static void update_generic_attribute_mesh(const Object &object,
|
||||
const OrigMeshData &orig_mesh_data,
|
||||
const IndexMask &node_mask,
|
||||
const GenericRequest &attr,
|
||||
const StringRef name,
|
||||
MutableSpan<gpu::VertBufPtr> vbos)
|
||||
{
|
||||
const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
|
||||
@@ -736,19 +700,20 @@ BLI_NOINLINE static void update_generic_attribute_mesh(const Object &object,
|
||||
const Mesh &mesh = DRW_object_get_data_for_drawing<Mesh>(object);
|
||||
const OffsetIndices<int> faces = mesh.faces();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
const StringRefNull name = attr.name;
|
||||
const bke::AttrDomain domain = attr.domain;
|
||||
const eCustomDataType data_type = attr.type;
|
||||
const bke::AttributeAccessor attributes = orig_mesh_data.attributes;
|
||||
const GVArraySpan attribute = *attributes.lookup_or_default(name, domain, data_type);
|
||||
const bke::GAttributeReader attr = attributes.lookup(name);
|
||||
if (!attr || attr.domain == bke::AttrDomain::Edge) {
|
||||
return;
|
||||
}
|
||||
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attr.varray.type());
|
||||
ensure_vbos_allocated_mesh(
|
||||
object, attribute_format(orig_mesh_data, name, data_type), node_mask, vbos);
|
||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||
bke::attribute_math::convert_to_static_type(attribute.type(), [&](auto dummy) {
|
||||
bke::attribute_math::convert_to_static_type(attr.varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
const Span<T> src = attribute.typed<T>();
|
||||
switch (domain) {
|
||||
const VArraySpan<T> src = attr.varray.typed<T>();
|
||||
switch (attr.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_mesh<T>(faces, corner_verts, src, nodes[i].faces(), *vbos[i]);
|
||||
break;
|
||||
@@ -1088,35 +1053,70 @@ BLI_NOINLINE static void update_face_sets_bmesh(const Object &object,
|
||||
}
|
||||
}
|
||||
|
||||
struct BMeshAttributeLookup {
|
||||
const int offset = -1;
|
||||
bke::AttrDomain domain;
|
||||
eCustomDataType type;
|
||||
operator bool() const
|
||||
{
|
||||
return offset != -1;
|
||||
}
|
||||
};
|
||||
|
||||
static BMeshAttributeLookup lookup_bmesh_attribute(const BMesh &bm, const StringRef name)
|
||||
{
|
||||
for (const CustomDataLayer &layer : Span(bm.vdata.layers, bm.vdata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Point, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.edata.layers, bm.edata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Edge, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.pdata.layers, bm.pdata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Face, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.ldata.layers, bm.ldata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Corner, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void update_generic_attribute_bmesh(const Object &object,
|
||||
const OrigMeshData &orig_mesh_data,
|
||||
const IndexMask &node_mask,
|
||||
const GenericRequest &attr,
|
||||
const StringRef name,
|
||||
const MutableSpan<gpu::VertBufPtr> vbos)
|
||||
{
|
||||
const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
|
||||
const Span<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
|
||||
const BMesh &bm = *object.sculpt->bm;
|
||||
const bke::AttrDomain domain = attr.domain;
|
||||
const eCustomDataType data_type = attr.type;
|
||||
const CustomData &custom_data = *get_cdata(bm, domain);
|
||||
const int offset = CustomData_get_offset_named(&custom_data, data_type, attr.name);
|
||||
const BMeshAttributeLookup attr = lookup_bmesh_attribute(bm, name);
|
||||
if (!attr || attr.domain == bke::AttrDomain::Edge) {
|
||||
return;
|
||||
}
|
||||
ensure_vbos_allocated_bmesh(
|
||||
object, attribute_format(orig_mesh_data, attr.name, data_type), node_mask, vbos);
|
||||
object, attribute_format(orig_mesh_data, name, attr.type), node_mask, vbos);
|
||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
bke::attribute_math::convert_to_static_type(attr.type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
const auto &faces = BKE_pbvh_bmesh_node_faces(&const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (domain) {
|
||||
switch (attr.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_vert_bmesh<T>(faces, offset, *vbos[i]);
|
||||
extract_data_vert_bmesh<T>(faces, attr.offset, *vbos[i]);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_face_bmesh<T>(faces, offset, *vbos[i]);
|
||||
extract_data_face_bmesh<T>(faces, attr.offset, *vbos[i]);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_corner_bmesh<T>(faces, offset, *vbos[i]);
|
||||
extract_data_corner_bmesh<T>(faces, attr.offset, *vbos[i]);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
@@ -1679,9 +1679,6 @@ Span<gpu::VertBufPtr> DrawCacheImpl::ensure_attribute_data(const Object &object,
|
||||
const AttributeRequest &attr,
|
||||
const IndexMask &node_mask)
|
||||
{
|
||||
if (!pbvh_attr_supported(attr)) {
|
||||
return {};
|
||||
}
|
||||
const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
|
||||
AttributeData &data = attribute_vbos_.lookup_or_add_default(attr);
|
||||
Vector<gpu::VertBufPtr> &vbos = data.vbos;
|
||||
@@ -1720,7 +1717,7 @@ Span<gpu::VertBufPtr> DrawCacheImpl::ensure_attribute_data(const Object &object,
|
||||
}
|
||||
else {
|
||||
update_generic_attribute_mesh(
|
||||
object, orig_mesh_data, mask, std::get<GenericRequest>(attr), vbos);
|
||||
object, orig_mesh_data, mask, std::get<GenericRequest>(attr).name, vbos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1771,7 +1768,7 @@ Span<gpu::VertBufPtr> DrawCacheImpl::ensure_attribute_data(const Object &object,
|
||||
}
|
||||
else {
|
||||
update_generic_attribute_bmesh(
|
||||
object, orig_mesh_data, mask, std::get<GenericRequest>(attr), vbos);
|
||||
object, orig_mesh_data, mask, std::get<GenericRequest>(attr).name, vbos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -177,11 +177,11 @@ Vector<SculptBatch> sculpt_batches_get(const Object *ob, SculptBatchFeature feat
|
||||
{
|
||||
if (ss.bm) {
|
||||
if (bmesh_attribute_exists(*ss.bm, *meta_data, name)) {
|
||||
attrs.append(pbvh::GenericRequest{name, meta_data->data_type, meta_data->domain});
|
||||
attrs.append(pbvh::GenericRequest{name, meta_data->data_type});
|
||||
}
|
||||
}
|
||||
else {
|
||||
attrs.append(pbvh::GenericRequest{name, meta_data->data_type, meta_data->domain});
|
||||
attrs.append(pbvh::GenericRequest{name, meta_data->data_type});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ Vector<SculptBatch> sculpt_batches_get(const Object *ob, SculptBatchFeature feat
|
||||
if (features & SCULPT_BATCH_UV) {
|
||||
const CustomData *corner_data = ss.bm ? &ss.bm->ldata : &mesh->corner_data;
|
||||
if (const char *name = CustomData_get_active_layer_name(corner_data, CD_PROP_FLOAT2)) {
|
||||
attrs.append(pbvh::GenericRequest{name, CD_PROP_FLOAT2, bke::AttrDomain::Corner});
|
||||
attrs.append(pbvh::GenericRequest{name, CD_PROP_FLOAT2});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ Vector<SculptBatch> sculpt_batches_per_material_get(const Object *ob,
|
||||
|
||||
for (int i = 0; i < draw_attrs.num_requests; i++) {
|
||||
const DRW_AttributeRequest &req = draw_attrs.requests[i];
|
||||
attrs.append(pbvh::GenericRequest{req.attribute_name, req.cd_type, req.domain});
|
||||
attrs.append(pbvh::GenericRequest{req.attribute_name, req.cd_type});
|
||||
}
|
||||
|
||||
/* UV maps are not in attribute requests. */
|
||||
@@ -223,7 +223,7 @@ Vector<SculptBatch> sculpt_batches_per_material_get(const Object *ob,
|
||||
int layer_i = CustomData_get_layer_index_n(&mesh.corner_data, CD_PROP_FLOAT2, i);
|
||||
CustomDataLayer *layer = layer_i != -1 ? mesh.corner_data.layers + layer_i : nullptr;
|
||||
if (layer) {
|
||||
attrs.append(pbvh::GenericRequest{layer->name, CD_PROP_FLOAT2, bke::AttrDomain::Corner});
|
||||
attrs.append(pbvh::GenericRequest{layer->name, CD_PROP_FLOAT2});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,46 +169,66 @@ static void extract_data_bmesh_loop(const BMesh &bm, const int cd_offset, gpu::V
|
||||
}
|
||||
}
|
||||
|
||||
static const CustomData *get_custom_data_for_domain(const BMesh &bm, bke::AttrDomain domain)
|
||||
{
|
||||
switch (domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
return &bm.vdata;
|
||||
case bke::AttrDomain::Corner:
|
||||
return &bm.ldata;
|
||||
case bke::AttrDomain::Face:
|
||||
return &bm.pdata;
|
||||
case bke::AttrDomain::Edge:
|
||||
return &bm.edata;
|
||||
default:
|
||||
return nullptr;
|
||||
struct BMeshAttributeLookup {
|
||||
const int offset = -1;
|
||||
bke::AttrDomain domain;
|
||||
eCustomDataType type;
|
||||
operator bool() const
|
||||
{
|
||||
return offset != -1;
|
||||
}
|
||||
};
|
||||
|
||||
static BMeshAttributeLookup lookup_bmesh_attribute(const BMesh &bm, const StringRef name)
|
||||
{
|
||||
for (const CustomDataLayer &layer : Span(bm.vdata.layers, bm.vdata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Point, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.edata.layers, bm.edata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Edge, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.pdata.layers, bm.pdata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Face, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
for (const CustomDataLayer &layer : Span(bm.ldata.layers, bm.ldata.totlayer)) {
|
||||
if (layer.name == name) {
|
||||
return {layer.offset, bke::AttrDomain::Corner, eCustomDataType(layer.type)};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static void extract_attribute_no_init(const MeshRenderData &mr,
|
||||
const DRW_AttributeRequest &request,
|
||||
const StringRef name,
|
||||
gpu::VertBuf &vbo)
|
||||
{
|
||||
if (mr.extract_type == MeshExtractType::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);
|
||||
const BMeshAttributeLookup attr = lookup_bmesh_attribute(*mr.bm, name);
|
||||
if (!attr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
bke::attribute_math::convert_to_static_type(attr.type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (request.domain) {
|
||||
switch (attr.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_bmesh_vert<T>(*mr.bm, cd_offset, vbo);
|
||||
extract_data_bmesh_vert<T>(*mr.bm, attr.offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_bmesh_edge<T>(*mr.bm, cd_offset, vbo);
|
||||
extract_data_bmesh_edge<T>(*mr.bm, attr.offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_bmesh_face<T>(*mr.bm, cd_offset, vbo);
|
||||
extract_data_bmesh_face<T>(*mr.bm, attr.offset, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
extract_data_bmesh_loop<T>(*mr.bm, cd_offset, vbo);
|
||||
extract_data_bmesh_loop<T>(*mr.bm, attr.offset, vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
@@ -218,25 +238,26 @@ static void extract_attribute_no_init(const MeshRenderData &mr,
|
||||
}
|
||||
else {
|
||||
const bke::AttributeAccessor attributes = mr.mesh->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);
|
||||
const bke::GAttributeReader attr = attributes.lookup(name);
|
||||
if (!attr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) {
|
||||
bke::attribute_math::convert_to_static_type(attr.varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<typename AttributeConverter<T>::VBOType>) {
|
||||
switch (request.domain) {
|
||||
switch (attr.domain) {
|
||||
case bke::AttrDomain::Point:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_verts, vbo);
|
||||
extract_data_mesh_mapped_corner(GVArraySpan(*attr).typed<T>(), mr.corner_verts, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Edge:
|
||||
extract_data_mesh_mapped_corner(attribute.typed<T>(), mr.corner_edges, vbo);
|
||||
extract_data_mesh_mapped_corner(GVArraySpan(*attr).typed<T>(), mr.corner_edges, vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Face:
|
||||
extract_data_mesh_face(mr.faces, attribute.typed<T>(), vbo);
|
||||
extract_data_mesh_face(mr.faces, GVArraySpan(*attr).typed<T>(), vbo);
|
||||
break;
|
||||
case bke::AttrDomain::Corner:
|
||||
vertbuf_data_extract_direct(attribute.typed<T>(), vbo);
|
||||
vertbuf_data_extract_direct(GVArraySpan(*attr).typed<T>(), vbo);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
@@ -250,7 +271,7 @@ gpu::VertBufPtr extract_attribute(const MeshRenderData &mr, const DRW_AttributeR
|
||||
{
|
||||
gpu::VertBuf *vbo = GPU_vertbuf_calloc();
|
||||
init_vbo_for_attribute(mr, *vbo, request, false, uint32_t(mr.corners_num));
|
||||
extract_attribute_no_init(mr, request, *vbo);
|
||||
extract_attribute_no_init(mr, request.attribute_name, *vbo);
|
||||
return gpu::VertBufPtr(vbo);
|
||||
}
|
||||
|
||||
@@ -267,7 +288,7 @@ gpu::VertBufPtr extract_attribute_subdiv(const MeshRenderData &mr,
|
||||
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_no_init(mr, request, *src_data);
|
||||
extract_attribute_no_init(mr, request.attribute_name, *src_data);
|
||||
|
||||
gpu::VertBuf *vbo = GPU_vertbuf_calloc();
|
||||
init_vbo_for_attribute(mr, *vbo, request, true, subdiv_cache.num_subdiv_loops);
|
||||
|
||||
Reference in New Issue
Block a user