1
1

Compare commits

...

102 Commits

Author SHA1 Message Date
e1c1c65578 cleanup 2021-10-31 14:28:01 +01:00
2154631e85 cleanups 2021-10-31 14:20:04 +01:00
71b7e59e28 remove print 2021-10-31 14:09:16 +01:00
7106fe299e cleanup 2021-10-31 14:06:48 +01:00
4b8e52bdbc add timeit include 2021-10-31 13:50:05 +01:00
462d3bde6e fix 2021-10-31 13:36:24 +01:00
e354ff5b86 cleanup 2021-10-31 13:27:43 +01:00
27da814444 add test 2021-10-31 13:08:01 +01:00
493571c3c3 add some noexcepts 2021-10-31 13:02:49 +01:00
a6eb04cce4 cleanups 2021-10-31 12:39:46 +01:00
139f69b3b9 Merge branch 'master' into virtual-array-value-type 2021-10-31 12:33:45 +01:00
8a1cc2f291 Merge branch 'master' into virtual-array-value-type 2021-10-30 23:04:24 +02:00
572fa82cc9 cleanup 2021-10-30 23:04:04 +02:00
c8ab4dcce1 cleanup 2021-10-30 23:02:05 +02:00
55a6af1c1e cleanup 2021-10-30 22:52:28 +02:00
0827245a91 cleanup 2021-10-30 22:49:26 +02:00
2f284f42b6 progress 2021-10-30 22:38:35 +02:00
1131bf6ec6 progress 2021-10-30 22:32:48 +02:00
2b0e890a55 comments 2021-10-30 22:20:04 +02:00
c4d3380d2e progress 2021-10-30 21:36:11 +02:00
05cef9da88 cleanup 2021-10-30 21:20:15 +02:00
43a53f97c4 cleanup tests 2021-10-30 21:17:24 +02:00
1d7a893d12 cleanup 2021-10-30 21:07:33 +02:00
5e60ba93f7 progress 2021-10-30 21:05:56 +02:00
65258dc98f progress 2021-10-30 21:02:49 +02:00
d449e66c1d cleanup 2021-10-30 20:59:26 +02:00
01fe332b9d progress 2021-10-30 20:54:00 +02:00
d6b0f3a3a4 progress 2021-10-30 20:42:37 +02:00
928b7b5340 cleanup 2021-10-30 20:35:26 +02:00
aa22839aa1 progress 2021-10-30 20:31:53 +02:00
78daf1b697 progress 2021-10-30 20:24:20 +02:00
dcd9b21d07 progress 2021-10-30 20:21:48 +02:00
42b350ed7f progress 2021-10-30 20:14:43 +02:00
e79c7e088e progress 2021-10-30 19:59:35 +02:00
99c5b788eb progress 2021-10-30 19:55:53 +02:00
a2b5a74d49 progress 2021-10-30 19:46:17 +02:00
84626dfa16 progress 2021-10-30 19:40:58 +02:00
3d0abb3be9 progress 2021-10-30 19:31:19 +02:00
9b6c13e66c progress 2021-10-30 19:10:44 +02:00
7f4273d373 progress 2021-10-30 18:50:28 +02:00
d1b8d6acd3 progress 2021-10-30 18:39:34 +02:00
2267f19486 progress 2021-10-30 18:18:27 +02:00
acd8874205 progress 2021-10-30 18:13:52 +02:00
a69bd34fad fix 2021-10-30 16:56:05 +02:00
2516fc953a Merge branch 'blender-v3.0-release' 2021-10-30 16:54:06 +02:00
50f93cbf52 cleanup 2021-10-25 00:35:58 +02:00
8af541dcfd Geometry Nodes: Refactor virtual array system.
Differential Revision: https://developer.blender.org/D12986
2021-10-25 00:16:40 +02:00
f8c0682a67 progress 2021-10-24 23:58:16 +02:00
b40e753c81 fix 2021-10-24 23:20:32 +02:00
2cff0676af cleanup 2021-10-24 23:13:25 +02:00
b0444a347b cleanup 2021-10-24 23:11:47 +02:00
becfc547b9 cleanup 2021-10-24 23:08:22 +02:00
6a558a18f9 progress 2021-10-24 23:02:51 +02:00
c066102f30 progress 2021-10-24 22:55:05 +02:00
ba49545060 progress 2021-10-24 22:50:52 +02:00
ca70c0521a progress 2021-10-24 22:44:54 +02:00
4323b3f592 progress 2021-10-24 22:28:43 +02:00
d1e6606d4d progress 2021-10-24 22:10:47 +02:00
b64ad0b30a cleanup 2021-10-24 22:00:32 +02:00
ed4b15ecd3 cleanup 2021-10-24 21:57:56 +02:00
f79a673bf1 cleanup 2021-10-24 21:44:08 +02:00
1438f16663 fix 2021-10-24 21:09:58 +02:00
d613451c3a Merge branch 'master' into virtual-array-value-type 2021-10-24 20:56:50 +02:00
3f8ac0e5ef Merge branch 'master' into virtual-array-value-type 2021-10-24 17:27:01 +02:00
56bd1f46bd fixes 2021-10-24 17:20:54 +02:00
1e4cbec720 fix 2021-10-24 17:09:24 +02:00
f9b669c588 fixes 2021-10-24 16:45:02 +02:00
1ac0a2db11 cleanup 2021-10-24 16:38:23 +02:00
771cce22f1 cleanup 2021-10-24 16:34:50 +02:00
c1a1046ed7 cleanup 2021-10-24 16:29:33 +02:00
f430e7850a cleanup 2021-10-24 16:24:58 +02:00
116eb09681 fix 2021-10-24 16:23:35 +02:00
841d393c15 cleanup 2021-10-24 16:23:17 +02:00
bc1acbcc5a cleanup 2021-10-24 16:15:11 +02:00
cd49f68db6 cleanup 2021-10-24 16:08:02 +02:00
5b51065347 cleanup 2021-10-24 16:05:15 +02:00
e736fe67c9 cleanup 2021-10-24 15:59:12 +02:00
1d20f60616 fixes 2021-10-24 15:27:21 +02:00
91b58c95ac fixes 2021-10-24 14:57:51 +02:00
955b01e359 fix assignment operators 2021-10-24 13:59:19 +02:00
1b3758f205 cleanup 2021-10-24 13:59:11 +02:00
33870b21f3 fix output attribute 2021-10-24 13:05:45 +02:00
e49f70745b fix dst fields 2021-10-24 12:56:11 +02:00
c48a99542d compiling works again 2021-10-24 02:26:08 +02:00
68b5670268 more renaming 2021-10-23 22:50:37 +02:00
dea268de72 progress 2021-10-23 22:42:30 +02:00
399463c548 progress 2021-10-23 22:35:12 +02:00
1d94de4ac3 progress 2021-10-23 20:22:49 +02:00
0453361d20 progress 2021-10-23 20:11:19 +02:00
b21a3ae6ad rename to *Impl 2021-10-23 19:15:29 +02:00
edb8ccf31f support converting VMutableArray to VArray 2021-10-23 19:14:14 +02:00
7af712c343 add mutable virtual array 2021-10-23 19:06:53 +02:00
a9e0cb6ec8 rename to VMutableArrayImpl 2021-10-23 18:53:34 +02:00
5a7b30f8f9 cleanup 2021-10-23 18:52:44 +02:00
024c07af84 more virtual array tests 2021-10-23 18:10:11 +02:00
c256298924 rename VArray to VArrayImpl 2021-10-23 16:48:22 +02:00
a11950531f add comments 2021-10-23 16:36:28 +02:00
ae01d1db98 add extra type info 2021-10-23 16:08:20 +02:00
f3a5b31196 fix assign any 2021-10-23 15:54:56 +02:00
8d1a5fcfea add tests 2021-10-23 15:45:49 +02:00
39c4103f9e move methods 2021-10-23 15:22:28 +02:00
4e03ac6b25 initial Any type 2021-10-23 14:50:11 +02:00
97 changed files with 3585 additions and 2478 deletions

View File

@@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit {
* Note that this can be used to fill the new attribute with the default
*/
struct AttributeInitVArray : public AttributeInit {
const blender::fn::GVArray *varray;
blender::fn::GVArray varray;
AttributeInitVArray(const blender::fn::GVArray *varray)
: AttributeInit(Type::VArray), varray(varray)
AttributeInitVArray(blender::fn::GVArray varray)
: AttributeInit(Type::VArray), varray(std::move(varray))
{
}
};
@@ -150,9 +150,7 @@ namespace blender::bke {
using fn::CPPType;
using fn::GVArray;
using fn::GVArrayPtr;
using fn::GVMutableArray;
using fn::GVMutableArrayPtr;
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
@@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
*/
struct ReadAttributeLookup {
/* The virtual array that is used to read from this attribute. */
GVArrayPtr varray;
GVArray varray;
/* Domain the attribute lives on in the geometry. */
AttributeDomain domain;
/* Convenience function to check if the attribute has been found. */
operator bool() const
{
return this->varray.get() != nullptr;
return this->varray;
}
};
@@ -180,7 +178,7 @@ struct ReadAttributeLookup {
*/
struct WriteAttributeLookup {
/* The virtual array that is used to read from and write to the attribute. */
GVMutableArrayPtr varray;
GVMutableArray varray;
/* Domain the attributes lives on in the geometry. */
AttributeDomain domain;
/* Call this after changing the attribute to invalidate caches that depend on this attribute. */
@@ -189,7 +187,7 @@ struct WriteAttributeLookup {
/* Convenience function to check if the attribute has been found. */
operator bool() const
{
return this->varray.get() != nullptr;
return this->varray;
}
};
@@ -209,7 +207,7 @@ class OutputAttribute {
using SaveFn = std::function<void(OutputAttribute &)>;
private:
GVMutableArrayPtr varray_;
GVMutableArray varray_;
AttributeDomain domain_ = ATTR_DOMAIN_AUTO;
SaveFn save_;
std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_;
@@ -219,7 +217,7 @@ class OutputAttribute {
public:
OutputAttribute();
OutputAttribute(OutputAttribute &&other);
OutputAttribute(GVMutableArrayPtr varray,
OutputAttribute(GVMutableArray varray,
AttributeDomain domain,
SaveFn save,
const bool ignore_old_values);
@@ -229,7 +227,7 @@ class OutputAttribute {
operator bool() const;
GVMutableArray &operator*();
GVMutableArray *operator->();
fn::GVMutableArray *operator->();
GVMutableArray &varray();
AttributeDomain domain() const;
const CPPType &cpp_type() const;
@@ -247,16 +245,14 @@ class OutputAttribute {
template<typename T> class OutputAttribute_Typed {
private:
OutputAttribute attribute_;
std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_;
VMutableArray<T> *varray_ = nullptr;
VMutableArray<T> varray_;
public:
OutputAttribute_Typed();
OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute))
{
if (attribute_) {
optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray());
varray_ = &**optional_varray_;
varray_ = attribute_.varray().template typed<T>();
}
}
@@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed {
operator bool() const
{
return varray_ != nullptr;
return varray_;
}
VMutableArray<T> &operator*()
{
return *varray_;
return varray_;
}
VMutableArray<T> *operator->()
{
return varray_;
return &varray_;
}
VMutableArray<T> &varray()
{
return *varray_;
return varray_;
}
AttributeDomain domain() const
@@ -351,18 +347,17 @@ class CustomDataAttributes {
std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const;
blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const;
template<typename T>
blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id,
const T &default_value) const
blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
return blender::fn::GVArray_Typed<T>(std::move(varray));
GVArray varray = this->get_for_read(attribute_id, type, &default_value);
return varray.typed<T>();
}
std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
@@ -460,7 +455,7 @@ inline bool AttributeIDRef::should_be_kept() const
inline OutputAttribute::OutputAttribute() = default;
inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default;
inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
inline OutputAttribute::OutputAttribute(GVMutableArray varray,
AttributeDomain domain,
SaveFn save,
const bool ignore_old_values)
@@ -473,22 +468,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
inline OutputAttribute::operator bool() const
{
return varray_.get() != nullptr;
return varray_;
}
inline GVMutableArray &OutputAttribute::operator*()
{
return *varray_;
return varray_;
}
inline GVMutableArray *OutputAttribute::operator->()
inline fn::GVMutableArray *OutputAttribute::operator->()
{
return varray_.get();
return &varray_;
}
inline GVMutableArray &OutputAttribute::varray()
{
return *varray_;
return varray_;
}
inline AttributeDomain OutputAttribute::domain() const
@@ -498,7 +493,7 @@ inline AttributeDomain OutputAttribute::domain() const
inline const CPPType &OutputAttribute::cpp_type() const
{
return varray_->type();
return varray_.type();
}
inline CustomDataType OutputAttribute::custom_data_type() const

View File

@@ -119,10 +119,21 @@ class GeometryComponent {
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
* interpolate from one domain to another.
* Returns null if the interpolation is not implemented. */
virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
std::unique_ptr<blender::fn::GVArray> varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const;
blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
}
template<typename T>
blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain)
.template typed<T>();
}
/* Returns true when the attribute has been deleted. */
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
@@ -146,16 +157,15 @@ class GeometryComponent {
/* Get a virtual array to read the data of an attribute on the given domain and data type.
* Returns null when the attribute does not exist or cannot be converted to the requested domain
* and data type. */
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type) const;
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type) const;
/* Get a virtual array to read the data of an attribute on the given domain. The data type is
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
* requested domain. */
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain) const;
/* Get a virtual array to read data of an attribute with the given data type. The domain is
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
@@ -165,25 +175,22 @@ class GeometryComponent {
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
* virtual array will contain a default value. This never returns null. */
std::unique_ptr<blender::fn::GVArray> attribute_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr) const;
blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr) const;
/* Should be used instead of the method above when the requested data type is known at compile
* time for better type safety. */
template<typename T>
blender::fn::GVArray_Typed<T> attribute_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const T &default_value) const
blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
std::unique_ptr varray = this->attribute_get_for_read(
attribute_id, domain, type, &default_value);
return blender::fn::GVArray_Typed<T>(std::move(varray));
return this->attribute_get_for_read(attribute_id, domain, type, &default_value)
.template typed<T>();
}
/**
@@ -234,6 +241,11 @@ class GeometryComponent {
private:
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
virtual blender::fn::GVArray attribute_try_adapt_domain_impl(
const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const;
};
template<typename T>
@@ -391,10 +403,6 @@ class MeshComponent : public GeometryComponent {
Mesh *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
std::unique_ptr<blender::fn::GVArray> varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
bool is_empty() const final;
@@ -405,6 +413,11 @@ class MeshComponent : public GeometryComponent {
private:
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
blender::fn::GVArray attribute_try_adapt_domain_impl(
const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
};
/** A geometry component that stores a point cloud. */
@@ -469,10 +482,6 @@ class CurveComponent : public GeometryComponent {
CurveEval *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
std::unique_ptr<blender::fn::GVArray> varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
bool is_empty() const final;
@@ -485,6 +494,11 @@ class CurveComponent : public GeometryComponent {
private:
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
blender::fn::GVArray attribute_try_adapt_domain_impl(
const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
};
class InstanceReference {
@@ -759,9 +773,9 @@ class AttributeFieldInput : public fn::FieldInput {
return name_;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
std::string socket_inspection_name() const override;
@@ -776,9 +790,9 @@ class IDAttributeFieldInput : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
std::string socket_inspection_name() const override;
@@ -815,9 +829,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
return fn::Field<T>{field_input};
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
std::string socket_inspection_name() const override;

View File

@@ -187,14 +187,14 @@ class Spline {
blender::MutableSpan<T> dst) const
{
this->sample_with_index_factors(
blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst));
blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst));
}
template<typename T>
void sample_with_index_factors(blender::Span<T> src,
blender::Span<float> index_factors,
blender::MutableSpan<T> dst) const
{
this->sample_with_index_factors(blender::VArray_For_Span(src), index_factors, dst);
this->sample_with_index_factors(blender::VArray<T>::ForSpan(src), index_factors, dst);
}
/**
@@ -202,13 +202,11 @@ class Spline {
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
* exceed the lifetime of the input data.
*/
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
const blender::fn::GVArray &src) const = 0;
blender::fn::GVArrayPtr interpolate_to_evaluated(blender::fn::GSpan data) const;
template<typename T>
blender::fn::GVArray_Typed<T> interpolate_to_evaluated(blender::Span<T> data) const
virtual blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0;
blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const;
template<typename T> blender::VArray<T> interpolate_to_evaluated(blender::Span<T> data) const
{
return blender::fn::GVArray_Typed<T>(this->interpolate_to_evaluated(blender::fn::GSpan(data)));
return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed<T>();
}
protected:
@@ -338,7 +336,7 @@ class BezierSpline final : public Spline {
};
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
virtual blender::fn::GVArray interpolate_to_evaluated(
const blender::fn::GVArray &src) const override;
void evaluate_segment(const int index,
@@ -475,7 +473,7 @@ class NURBSpline final : public Spline {
blender::Span<blender::float3> evaluated_positions() const final;
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
protected:
void correct_end_tangents() const final;
@@ -526,7 +524,7 @@ class PolySpline final : public Spline {
blender::Span<blender::float3> evaluated_positions() const final;
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
protected:
void correct_end_tangents() const final;

View File

@@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef;
using blender::bke::OutputAttribute;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray_For_SingleValue;
using blender::fn::GVMutableArray_For_GMutableSpan;
using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
namespace blender::bke {
@@ -207,7 +205,7 @@ fn::GMutableSpan OutputAttribute::as_span()
{
if (!optional_span_varray_) {
const bool materialize_old_values = !ignore_old_values_;
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_,
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_,
materialize_old_values);
}
fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_;
@@ -249,8 +247,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
if (data == nullptr) {
return false;
}
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), data);
return true;
}
case AttributeInit::Type::MoveArray: {
@@ -305,8 +303,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
if (data == nullptr) {
return false;
}
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), data);
return true;
}
case AttributeInit::Type::MoveArray: {
@@ -337,8 +335,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
return layer.name == attribute_id.name();
}
GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
const GeometryComponent &component) const
GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
if (custom_data == nullptr) {
@@ -503,7 +500,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
continue;
}
GSpan data{*type, layer.data, domain_size};
return {std::make_unique<GVArray_For_GSpan>(data), domain_};
return {GVArray::ForSpan(data), domain_};
}
return {};
}
@@ -533,7 +530,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
continue;
}
GMutableSpan data{*type, layer.data, domain_size};
return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_};
return {GVMutableArray::ForSpan(data), domain_};
}
return {};
}
@@ -749,25 +746,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
* value if the attribute doesn't exist. If no default value is provided, the default value for the
* type will be used.
*/
GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const
GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const
{
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
std::optional<GSpan> attribute = this->get_for_read(attribute_id);
if (!attribute) {
const int domain_size = this->size_;
return std::make_unique<GVArray_For_SingleValue>(
return GVArray::ForSingle(
*type, domain_size, (default_value == nullptr) ? type->default_value() : default_value);
}
if (attribute->type() == *type) {
return std::make_unique<GVArray_For_GSpan>(*attribute);
return GVArray::ForSpan(*attribute);
}
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
return conversions.try_convert(GVArray::ForSpan(*attribute), *type);
}
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
@@ -906,8 +903,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
return {};
}
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain(
std::unique_ptr<blender::fn::GVArray> varray,
blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl(
const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
@@ -1094,15 +1091,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
return result;
}
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray,
const blender::fn::CPPType &to_type)
{
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
return conversions.try_convert(std::move(varray), to_type);
}
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
const AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type) const
@@ -1112,7 +1109,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
return {};
}
std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
blender::fn::GVArray varray = std::move(attribute.varray);
if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) {
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
if (!varray) {
@@ -1122,7 +1119,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
BLI_assert(cpp_type != nullptr);
if (varray->type() != *cpp_type) {
if (varray.type() != *cpp_type) {
varray = try_adapt_data_type(std::move(varray), *cpp_type);
if (!varray) {
return {};
@@ -1132,7 +1129,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
return varray;
}
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
const AttributeIDRef &attribute_id, const AttributeDomain domain) const
{
if (!this->attribute_domain_supported(domain)) {
@@ -1160,7 +1157,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
}
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
BLI_assert(type != nullptr);
if (attribute.varray->type() == *type) {
if (attribute.varray.type() == *type) {
return attribute;
}
const blender::nodes::DataTypeConversions &conversions =
@@ -1168,14 +1165,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
}
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
const AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const
blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const
{
std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
attribute_id, domain, data_type);
blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type);
if (varray) {
return varray;
}
@@ -1184,11 +1179,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read
default_value = type->default_value();
}
const int domain_size = this->attribute_domain_size(domain);
return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
}
class GVMutableAttribute_For_OutputAttribute
: public blender::fn::GVMutableArray_For_GMutableSpan {
: public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
public:
GeometryComponent *component;
std::string attribute_name;
@@ -1197,7 +1192,7 @@ class GVMutableAttribute_For_OutputAttribute
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
GeometryComponent &component,
const AttributeIDRef &attribute_id)
: blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component)
: blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
{
if (attribute_id.is_named()) {
this->attribute_name = attribute_id.name();
@@ -1223,7 +1218,8 @@ static void save_output_attribute(OutputAttribute &output_attribute)
using namespace blender::bke;
GVMutableAttribute_For_OutputAttribute &varray =
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(
*output_attribute.varray().get_implementation());
GeometryComponent &component = *varray.component;
AttributeIDRef attribute_id;
@@ -1251,7 +1247,7 @@ static void save_output_attribute(OutputAttribute &output_attribute)
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
for (const int i : IndexRange(varray.size())) {
varray.get(i, buffer);
write_attribute.varray->set_by_relocate(i, buffer);
write_attribute.varray.set_by_relocate(i, buffer);
}
if (write_attribute.tag_modified_fn) {
write_attribute.tag_modified_fn();
@@ -1294,9 +1290,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
if (!attribute) {
if (default_value) {
const int64_t domain_size = component.attribute_domain_size(domain);
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
component.attribute_try_create_builtin(attribute_name,
AttributeInitVArray(&default_varray));
component.attribute_try_create_builtin(
attribute_name,
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
}
else {
component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
@@ -1311,9 +1307,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
/* Builtin attribute is on different domain. */
return {};
}
GVMutableArrayPtr varray = std::move(attribute.varray);
if (varray->type() == *cpp_type) {
GVMutableArray varray = std::move(attribute.varray);
if (varray.type() == *cpp_type) {
/* Builtin attribute matches exactly. */
return OutputAttribute(std::move(varray),
domain,
@@ -1333,9 +1328,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
if (!attribute) {
if (default_value) {
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
component.attribute_try_create(
attribute_id, domain, data_type, AttributeInitVArray(&default_varray));
attribute_id,
domain,
data_type,
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
}
else {
component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
@@ -1347,7 +1344,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
return {};
}
}
if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
if (attribute.domain == domain && attribute.varray.type() == *cpp_type) {
/* Existing generic attribute matches exactly. */
return OutputAttribute(std::move(attribute.varray),
@@ -1366,11 +1363,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
}
else {
/* Fill the temporary array with values from the existing attribute. */
GVArrayPtr old_varray = component.attribute_get_for_read(
GVArray old_varray = component.attribute_get_for_read(
attribute_id, domain, data_type, default_value);
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
old_varray.materialize_to_uninitialized(IndexRange(domain_size), data);
}
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>(
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id);
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
@@ -1394,21 +1391,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
namespace blender::bke {
const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const
GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
if (attribute) {
return scope.add(std::move(attribute));
return attribute;
}
}
return nullptr;
return {};
}
std::string AttributeFieldInput::socket_inspection_name() const
@@ -1441,25 +1438,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
}
}
const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const
GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const StringRef name = get_random_id_attribute_name(domain);
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
if (attribute) {
BLI_assert(attribute->size() == component.attribute_domain_size(domain));
return scope.add(std::move(attribute));
BLI_assert(attribute.size() == component.attribute_domain_size(domain));
return attribute;
}
/* Use the index as the fallback if no random ID attribute exists. */
return fn::IndexFieldInput::get_index_varray(mask, scope);
}
return nullptr;
return {};
}
std::string IDAttributeFieldInput::socket_inspection_name() const
@@ -1479,19 +1476,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
}
const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
GVArrayPtr attribute = component.attribute_try_get_for_read(
GVArray attribute = component.attribute_try_get_for_read(
anonymous_id_.get(), domain, data_type);
return scope.add(std::move(attribute));
return attribute;
}
return nullptr;
return {};
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const

View File

@@ -24,9 +24,6 @@
namespace blender::bke {
using fn::GVArrayPtr;
using fn::GVMutableArrayPtr;
/**
* Utility to group together multiple functions that are used to access custom data on geometry
* components in a generic way.
@@ -86,7 +83,7 @@ class BuiltinAttributeProvider {
{
}
virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0;
virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0;
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0;
virtual bool try_delete(GeometryComponent &component) const = 0;
virtual bool try_create(GeometryComponent &UNUSED(component),
@@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
*/
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
private:
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
const AttributeDomain domain_;
const CustomDataType attribute_type_;
const CustomDataType stored_type_;
@@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
* if the stored type is the same as the attribute type.
*/
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
using UpdateOnRead = void (*)(const GeometryComponent &component);
using UpdateOnWrite = void (*)(GeometryComponent &component);
const CustomDataType stored_type_;
@@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final;
GVArray try_get_for_read(const GeometryComponent &component) const final;
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final;
bool try_delete(GeometryComponent &component) const final;
bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final;

View File

@@ -32,8 +32,6 @@
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVArray_Typed;
using blender::fn::GVArrayPtr;
namespace blender::bke {
@@ -218,7 +216,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
Span<float3> normals = spline.evaluated_normals();
Span<float3> profile_positions = profile.evaluated_positions();
GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
for (const int i_ring : IndexRange(info.spline_vert_len)) {
float4x4 point_matrix = float4x4::from_normalized_axis_data(
positions[i_ring], normals[i_ring], tangents[i_ring]);
@@ -486,8 +484,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src,
const ResultInfo &info,
ResultAttributeData &dst)
{
GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
GSpan interpolated = interpolated_gvarray->get_internal_span();
GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
GSpan interpolated = interpolated_gvarray.get_internal_span();
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
@@ -552,8 +550,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src,
const ResultInfo &info,
ResultAttributeData &dst)
{
GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
GSpan interpolated = interpolated_gvarray->get_internal_span();
GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
GSpan interpolated = interpolated_gvarray.get_internal_span();
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);

View File

@@ -28,10 +28,8 @@
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray;
using blender::fn::GVArray_GSpan;
using blender::fn::GVArrayPtr;
using blender::fn::GVMutableArray_For_GMutableSpan;
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
@@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve,
}
}
static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray)
static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(curve.splines().size());
adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA
* attributes. The goal is to avoid copying the spline value for every one of its control points
* unless it is necessary (in that case the materialize functions will be called).
*/
template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
GVArrayPtr original_varray_;
template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> {
GVArray original_varray_;
/* Store existing data materialized if it was not already a span. This is expected
* to be worth it because a single spline's value will likely be accessed many times. */
fn::GVArray_Span<T> original_data_;
VArray_Span<T> original_data_;
Array<int> offsets_;
public:
VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets)
: VArray<T>(offsets.last()),
VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets)
: VArrayImpl<T>(offsets.last()),
original_varray_(std::move(original_varray)),
original_data_(*original_varray_),
original_data_(original_varray_.typed<T>()),
offsets_(std::move(offsets))
{
}
T get_impl(const int64_t index) const final
T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return original_data_[indices.spline_index];
}
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
const int total_size = offsets_.last();
if (mask.is_range() && mask.as_range() == IndexRange(total_size)) {
@@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
}
}
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
T *dst = r_span.data();
const int total_size = offsets_.last();
@@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
}
};
static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray)
static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
Array<int> offsets = curve.control_point_offsets();
new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>(
offsets.last(), std::move(varray), std::move(offsets));
new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray),
std::move(offsets));
});
return new_varray;
}
} // namespace blender::bke
GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
if (!varray) {
return {};
}
if (varray->size() == 0) {
if (varray.is_empty()) {
return {};
}
if (from_domain == to_domain) {
@@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
namespace blender::bke {
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data);
using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data);
using AsReadAttribute = GVArray (*)(const CurveEval &data);
using AsWriteAttribute = GVMutableArray (*)(CurveEval &data);
const AsReadAttribute as_read_attribute_;
const AsWriteAttribute as_write_attribute_;
@@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
GVArray try_get_for_read(const GeometryComponent &component) const final
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution)
}
}
static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve)
static GVArray make_resolution_read_attribute(const CurveEval &curve)
{
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>(
curve.splines());
return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines());
}
static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve)
static GVMutableArray make_resolution_write_attribute(CurveEval &curve)
{
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr,
int,
get_spline_resolution,
set_spline_resolution>>(
curve.splines());
return VMutableArray<int>::
ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines());
}
static bool get_cyclic_value(const SplinePtr &spline)
@@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value)
}
}
static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve)
static GVArray make_cyclic_read_attribute(const CurveEval &curve)
{
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>(
curve.splines());
return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines());
}
static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve)
static GVMutableArray make_cyclic_write_attribute(CurveEval &curve)
{
return std::make_unique<
fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>(
return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>(
curve.splines());
}
@@ -623,9 +615,9 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data,
}
}
static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
const CustomDataType data_type,
const Span<SplinePtr> splines)
static GVArray varray_from_initializer(const AttributeInit &initializer,
const CustomDataType data_type,
const Span<SplinePtr> splines)
{
switch (initializer.type) {
case AttributeInit::Type::Default:
@@ -634,16 +626,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
BLI_assert_unreachable();
return {};
case AttributeInit::Type::VArray:
return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
return static_cast<const AttributeInitVArray &>(initializer).varray;
case AttributeInit::Type::MoveArray:
int total_size = 0;
for (const SplinePtr &spline : splines) {
total_size += spline->size();
}
return std::make_unique<fn::GVArray_For_GSpan>(
GSpan(*bke::custom_data_type_to_cpp_type(data_type),
static_cast<const AttributeInitMove &>(initializer).data,
total_size));
return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type),
static_cast<const AttributeInitMove &>(initializer).data,
total_size));
}
BLI_assert_unreachable();
return {};
@@ -691,11 +682,11 @@ static bool create_point_attribute(GeometryComponent &component,
/* We just created the attribute, it should exist. */
BLI_assert(write_attribute);
GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines);
GVArray source_varray = varray_from_initializer(initializer, data_type, splines);
/* TODO: When we can call a variant of #set_all with a virtual array argument,
* this theoretically unnecessary materialize step could be removed. */
GVArray_GSpan source_varray_span{*source_varray};
write_attribute.varray->set_all(source_varray_span.data());
GVArray_GSpan source_varray_span{source_varray};
write_attribute.varray.set_all(source_varray_span.data());
if (initializer.type == AttributeInit::Type::MoveArray) {
MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
@@ -723,29 +714,29 @@ static bool remove_point_attribute(GeometryComponent &component,
/**
* Virtual array for any control point data accessed with spans and an offset array.
*/
template<typename T> class VArray_For_SplinePoints : public VArray<T> {
template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> {
private:
const Array<Span<T>> data_;
Array<int> offsets_;
public:
VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
: VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
: VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
T get_impl(const int64_t index) const final
T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return data_[indices.spline_index][indices.point_index];
}
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
}
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span);
}
@@ -754,30 +745,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> {
/**
* Mutable virtual array for any control point data accessed with spans and an offset array.
*/
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> {
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
private:
Array<MutableSpan<T>> data_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
: VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
: VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
T get_impl(const int64_t index) const final
T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return data_[indices.spline_index][indices.point_index];
}
void set_impl(const int64_t index, T value) final
void set(const int64_t index, T value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
data_[indices.spline_index][indices.point_index] = value;
}
void set_all_impl(Span<T> src) final
void set_all(Span<T> src) final
{
for (const int spline_index : data_.index_range()) {
const int offset = offsets_[spline_index];
@@ -786,30 +777,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
}
}
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
}
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize_to_uninitialized(
{(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
}
};
template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets)
template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
{
return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>(
offsets.last(), std::move(spans), std::move(offsets));
return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
}
template<typename T>
GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets)
VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
{
return std::make_unique<
fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>(
offsets.last(), std::move(spans), std::move(offsets));
return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
std::move(offsets));
}
/**
@@ -820,24 +809,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off
* \note There is no need to check the handle type to avoid changing auto handles, since
* retrieving write access to the position data will mark them for recomputation anyway.
*/
class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
: VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
: VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
{
}
float3 get_impl(const int64_t index) const final
float3 get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return splines_[indices.spline_index]->positions()[indices.point_index];
}
void set_impl(const int64_t index, float3 value) final
void set(const int64_t index, float3 value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
@@ -852,7 +841,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
}
}
void set_all_impl(Span<float3> src) final
void set_all(Span<float3> src) final
{
for (const int spline_index : splines_.index_range()) {
Spline &spline = *splines_[spline_index];
@@ -885,21 +874,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
return spans;
}
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
Array<Span<float3>> spans = this->get_position_spans();
point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
}
void materialize_to_uninitialized_impl(const IndexMask mask,
MutableSpan<float3> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
Array<Span<float3>> spans = this->get_position_spans();
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
}
};
class VArray_For_BezierHandle final : public VArray<float3> {
class VArray_For_BezierHandle final : public VArrayImpl<float3> {
private:
Span<SplinePtr> splines_;
Array<int> offsets_;
@@ -907,7 +895,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
public:
VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
: VArray<float3>(offsets.last()),
: VArrayImpl<float3>(offsets.last()),
splines_(std::move(splines)),
offsets_(std::move(offsets)),
is_right_(is_right)
@@ -929,7 +917,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
return float3(0);
}
float3 get_impl(const int64_t index) const final
float3 get(const int64_t index) const final
{
return get_internal(index, splines_, offsets_, is_right_);
}
@@ -976,19 +964,18 @@ class VArray_For_BezierHandle final : public VArray<float3> {
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
}
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_internal(mask, splines_, offsets_, is_right_, r_span);
}
void materialize_to_uninitialized_impl(const IndexMask mask,
MutableSpan<float3> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span);
}
};
class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
@@ -998,19 +985,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
Array<int> offsets,
const bool is_right)
: VMutableArray<float3>(offsets.last()),
: VMutableArrayImpl<float3>(offsets.last()),
splines_(splines),
offsets_(std::move(offsets)),
is_right_(is_right)
{
}
float3 get_impl(const int64_t index) const final
float3 get(const int64_t index) const final
{
return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
}
void set_impl(const int64_t index, float3 value) final
void set(const int64_t index, float3 value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
@@ -1026,7 +1013,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
}
}
void set_all_impl(Span<float3> src) final
void set_all(Span<float3> src) final
{
for (const int spline_index : splines_.index_range()) {
Spline &spline = *splines_[spline_index];
@@ -1049,13 +1036,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
}
}
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
}
void materialize_to_uninitialized_impl(const IndexMask mask,
MutableSpan<float3> r_span) const final
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_to_uninitialized_internal(
mask, splines_, offsets_, is_right_, r_span);
@@ -1097,7 +1083,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
GVArray try_get_for_read(const GeometryComponent &component) const override
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -1110,7 +1096,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
Span<SplinePtr> splines = curve->splines();
if (splines.size() == 1) {
return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first()));
return GVArray::ForSpan(get_span_(*splines.first()));
}
Array<int> offsets = curve->control_point_offsets();
@@ -1119,7 +1105,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_span_(*splines[i]);
}
return point_data_gvarray(spans, offsets);
return point_data_varray(spans, offsets);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@@ -1144,8 +1130,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
MutableSpan<SplinePtr> splines = curve->splines();
if (splines.size() == 1) {
return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>(
get_mutable_span_(*splines.first())),
return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())),
domain_,
std::move(tag_modified_fn)};
}
@@ -1156,7 +1141,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_mutable_span_(*splines[i]);
}
return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn};
return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
}
bool try_delete(GeometryComponent &component) const final
@@ -1248,10 +1233,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
};
Array<int> offsets = curve->control_point_offsets();
return {std::make_unique<
fn::GVMutableArray_For_EmbeddedVMutableArray<float3,
VMutableArray_For_SplinePosition>>(
offsets.last(), curve->splines(), std::move(offsets)),
return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
std::move(offsets)),
domain_,
tag_modified_fn};
}
@@ -1273,7 +1256,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
GVArray try_get_for_read(const GeometryComponent &component) const override
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -1285,8 +1268,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
}
Array<int> offsets = curve->control_point_offsets();
return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>(
offsets.last(), curve->splines(), std::move(offsets), is_right_);
return VArray<float3>::For<VArray_For_BezierHandle>(
curve->splines(), std::move(offsets), is_right_);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@@ -1303,12 +1286,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
Array<int> offsets = curve->control_point_offsets();
return {
std::make_unique<
fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>(
offsets.last(), curve->splines(), std::move(offsets), is_right_),
domain_,
tag_modified_fn};
return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
curve->splines(), std::move(offsets), is_right_),
domain_,
tag_modified_fn};
}
bool try_delete(GeometryComponent &UNUSED(component)) const final
@@ -1387,7 +1368,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT};
return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
}
ReadAttributeLookup attribute = {};
@@ -1399,7 +1380,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
@@ -1440,7 +1421,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT};
return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
}
WriteAttributeLookup attribute = {};
@@ -1452,7 +1433,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}

View File

@@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
GVArray try_get_for_read(const GeometryComponent &component) const final
{
const InstancesComponent &instances_component = static_cast<const InstancesComponent &>(
component);
Span<float4x4> transforms = instances_component.instance_transforms();
return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>(
transforms);
return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
{
InstancesComponent &instances_component = static_cast<InstancesComponent &>(component);
MutableSpan<float4x4> transforms = instances_component.instance_transforms();
return {
std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4,
float3,
get_transform_position,
set_transform_position>>(transforms),
domain_};
return {VMutableArray<float3>::ForDerivedSpan<float4x4,
get_transform_position,
set_transform_position>(transforms),
domain_};
}
bool try_delete(GeometryComponent &UNUSED(component)) const final
@@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
GVArray try_get_for_read(const GeometryComponent &component) const final
{
const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
if (instances.instance_ids().is_empty()) {
return {};
}
return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids());
return VArray<int>::ForSpan(instances.instance_ids());
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
@@ -450,8 +447,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
if (instances.instance_ids().is_empty()) {
return {};
}
return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()),
domain_};
return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_};
}
bool try_delete(GeometryComponent &component) const final
@@ -477,8 +473,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
break;
}
case AttributeInit::Type::VArray: {
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data());
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), ids.data());
break;
}
case AttributeInit::Type::MoveArray: {

View File

@@ -32,8 +32,6 @@
/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
using blender::fn::GVArray;
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
@@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
/* We compute all interpolated values at once, because for this interpolation, one has to
* iterate over all loops anyway. */
Array<T> values(mesh.totvert);
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
Array<T> values(mesh.totloop);
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
});
return new_varray;
}
@@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totvert);
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totloop);
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totloop);
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totvert);
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
}
}
static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray)
static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
{
GVArrayPtr new_varray;
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values);
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va
} // namespace blender::bke
blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
blender::fn::GVArrayPtr varray,
blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl(
const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
if (!varray) {
return {};
}
if (varray->size() == 0) {
if (varray.size() == 0) {
return {};
}
if (from_domain == to_domain) {
@@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_CORNER: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray);
default:
break;
}
@@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_POINT: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray);
default:
break;
}
@@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_FACE: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray);
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray);
default:
break;
}
@@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_EDGE: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray);
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray));
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray);
default:
break;
}
@@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com
namespace blender::bke {
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size)
static GVArray make_derived_read_attribute(const void *data, const int domain_size)
{
return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>(
Span<StructT>((const StructT *)data, domain_size));
}
@@ -906,23 +904,22 @@ template<typename StructT,
typename ElemT,
ElemT (*GetFunc)(const StructT &),
void (*SetFunc)(StructT &, ElemT)>
static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size)
static GVMutableArray make_derived_write_attribute(void *data, const int domain_size)
{
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(
return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>(
MutableSpan<StructT>((StructT *)data, domain_size));
}
template<typename T>
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
static GVArray make_array_read_attribute(const void *data, const int domain_size)
{
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
}
template<typename T>
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
{
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
MutableSpan<T>((T *)data, domain_size));
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
}
static float3 get_vertex_position(const MVert &vert)
@@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value)
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
}
class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
private:
MDeformVert *dverts_;
const int dvert_index_;
public:
VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
: VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
: VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
float get_impl(const int64_t index) const override
float get(const int64_t index) const override
{
return get_internal(dverts_, dvert_index_, index);
}
void set_impl(const int64_t index, const float value) override
void set(const int64_t index, const float value) override
{
MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
weight->weight = value;
@@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
}
};
class VArray_For_VertexWeights final : public VArray<float> {
class VArray_For_VertexWeights final : public VArrayImpl<float> {
private:
const MDeformVert *dverts_;
const int dvert_index_;
public:
VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index)
: VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
: VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
float get_impl(const int64_t index) const override
float get(const int64_t index) const override
{
return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
}
@@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
}
if (mesh->dvert == nullptr) {
static const float default_value = 0.0f;
return {std::make_unique<fn::GVArray_For_SingleValueRef>(
CPPType::get<float>(), mesh->totvert, &default_value),
ATTR_DOMAIN_POINT};
return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
}
return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>(
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
return {VArray<float>::For<VArray_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
@@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
}
return {
std::make_unique<
fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>(
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
@@ -1184,7 +1177,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
{
}
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
GVArray try_get_for_read(const GeometryComponent &component) const final
{
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
@@ -1197,8 +1190,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
return std::make_unique<fn::GVArray_For_Span<float3>>(
Span<float3>((const float3 *)data, mesh->totpoly));
return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly));
}
Array<float3> normals(mesh->totpoly);
@@ -1207,7 +1199,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
}
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
return VArray<float3>::ForContainer(std::move(normals));
}
WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final

View File

@@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con
namespace blender::bke {
template<typename T>
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
static GVArray make_array_read_attribute(const void *data, const int domain_size)
{
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
}
template<typename T>
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
{
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
MutableSpan<T>((T *)data, domain_size));
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
}
/**

View File

@@ -364,12 +364,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
result.attribute_try_create(
entry.key, domain_output, data_type_output, AttributeInitDefault());
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id);
if (!write_attribute || &write_attribute.varray->type() != cpp_type ||
if (!write_attribute || &write_attribute.varray.type() != cpp_type ||
write_attribute.domain != domain_output) {
continue;
}
fn::GVMutableArray_GSpan dst_span{*write_attribute.varray};
fn::GVMutableArray_GSpan dst_span{write_attribute.varray};
int offset = 0;
for (const GeometryInstanceGroup &set_group : set_groups) {
@@ -381,11 +381,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
if (domain_size == 0) {
continue; /* Domain size is 0, so no need to increment the offset. */
}
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
GVArray source_attribute = component.attribute_try_get_for_read(
attribute_id, domain_output, data_type_output);
if (source_attribute) {
fn::GVArray_GSpan src_span{*source_attribute};
fn::GVArray_GSpan src_span{source_attribute};
const void *src_buffer = src_span.data();
for (const int UNUSED(i) : set_group.transforms.index_range()) {
void *dst_buffer = dst_span[offset];

View File

@@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_
eAttributeMapMode mode)
{
if (src_attribute && dst_attribute) {
this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
}
}

View File

@@ -30,14 +30,12 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::VArray;
using blender::attribute_math::convert_to_static_type;
using blender::bke::AttributeIDRef;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVArray;
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray_Typed;
using blender::fn::GVArrayPtr;
Spline::Type Spline::type() const
{
@@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const
}
/* Rotate the generated normals with the interpolated tilt data. */
GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts());
VArray<float> tilts = this->interpolate_to_evaluated(this->tilts());
for (const int i : normals.index_range()) {
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
}
@@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated)
}
}
GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const
GVArray Spline::interpolate_to_evaluated(GSpan data) const
{
return this->interpolate_to_evaluated(GVArray_For_GSpan(data));
return this->interpolate_to_evaluated(GVArray::ForSpan(data));
}
/**
@@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src,
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
const GVArray_Typed<T> src_typed = src.typed<T>();
const VArray<T> src_typed = src.typed<T>();
MutableSpan<T> dst_typed = dst.typed<T>();
if (src.size() == 1) {
dst_typed.fill(src_typed[0]);

View File

@@ -25,9 +25,8 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::VArray;
using blender::fn::GVArray;
using blender::fn::GVArray_For_ArrayContainer;
using blender::fn::GVArrayPtr;
void BezierSpline::copy_settings(Spline &dst) const
{
@@ -697,26 +696,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline,
}
}
GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const
GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
if (src.is_single()) {
return src.shallow_copy();
return src;
}
const int eval_size = this->evaluated_points_size();
if (eval_size == 1) {
return src.shallow_copy();
return src;
}
GVArrayPtr new_varray;
GVArray new_varray;
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
Array<T> values(eval_size);
interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values);
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
new_varray = VArray<T>::ForContainer(std::move(values));
}
});

View File

@@ -26,10 +26,8 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::VArray;
using blender::fn::GVArray;
using blender::fn::GVArray_For_ArrayContainer;
using blender::fn::GVArray_Typed;
using blender::fn::GVArrayPtr;
void NURBSpline::copy_settings(Spline &dst) const
{
@@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights,
mixer.finalize();
}
GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const
GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
if (src.is_single()) {
return src.shallow_copy();
return src;
}
Span<BasisCache> basis_cache = this->calculate_basis_cache();
GVArrayPtr new_varray;
GVArray new_varray;
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
Array<T> values(this->evaluated_points_size());
interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values);
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
new_varray = VArray<T>::ForContainer(std::move(values));
}
});
@@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const
evaluated_position_cache_.resize(eval_size);
/* TODO: Avoid copying the evaluated data from the temporary array. */
GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
evaluated->materialize(evaluated_position_cache_);
VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
evaluated.materialize(evaluated_position_cache_);
position_cache_dirty_ = false;
return evaluated_position_cache_;

View File

@@ -23,7 +23,6 @@ using blender::float3;
using blender::MutableSpan;
using blender::Span;
using blender::fn::GVArray;
using blender::fn::GVArrayPtr;
void PolySpline::copy_settings(Spline &UNUSED(dst)) const
{
@@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const
* the original data. Therefore the lifetime of the returned virtual array must not be longer than
* the source data.
*/
GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const
GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
return src.shallow_copy();
return src;
}

View File

@@ -0,0 +1,320 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bli
*
* A #blender::Any is a type-safe container for single values of any copy constructible type.
* It is similar to #std::any but provides the following two additional features:
* - Adjustable inline buffer capacity and alignment. #std::any has a small inline buffer in most
* implementations as well, but its size is not guaranteed.
* - Can store additional user-defined type information without increasing the stack size of #Any.
*/
#include <algorithm>
#include <utility>
#include "BLI_memory_utils.hh"
namespace blender {
namespace detail {
/**
* Contains function pointers that manage the memory in an #Any.
* Additional type specific #ExtraInfo can be embedded here as well.
*/
template<typename ExtraInfo> struct AnyTypeInfo {
void (*copy_construct)(void *dst, const void *src);
void (*move_construct)(void *dst, void *src);
void (*destruct)(void *src);
const void *(*get)(const void *src);
ExtraInfo extra_info;
/**
* Used when #T is stored directly in the inline buffer of the #Any.
*/
template<typename T> static const AnyTypeInfo &get_for_inline()
{
static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
[](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
[](void *src) { ((T *)src)->~T(); },
[](const void *src) { return src; },
ExtraInfo::template get<T>()};
return funcs;
}
/**
* Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
* instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
*/
template<typename T> static const AnyTypeInfo &get_for_unique_ptr()
{
using Ptr = std::unique_ptr<T>;
static AnyTypeInfo funcs = {
[](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); },
[](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); },
[](void *src) { ((Ptr *)src)->~Ptr(); },
[](const void *src) -> const void * { return &**(const Ptr *)src; },
ExtraInfo::template get<T>()};
return funcs;
}
/**
* Used when the #Any does not contain any type currently.
*/
static const AnyTypeInfo &get_for_empty()
{
static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {},
[](void *UNUSED(dst), void *UNUSED(src)) {},
[](void *UNUSED(src)) {},
[](const void *UNUSED(src)) -> const void * { return nullptr; },
ExtraInfo{}};
return funcs;
}
};
/**
* Dummy extra info that is used when no additional type information should be stored in the #Any.
*/
struct NoExtraInfo {
template<typename T> static NoExtraInfo get()
{
return {};
}
};
} // namespace detail
template<
/**
* Either void or a struct that contains data members for additional type information.
* The struct has to have a static `ExtraInfo get<T>()` method that initializes the struct
* based on a type.
*/
typename ExtraInfo = void,
/**
* Size of the inline buffer. This allows types that are small enough to be stored directly
* inside the #Any without an additional allocation.
*/
size_t InlineBufferCapacity = 8,
/**
* Required minimum alignment of the inline buffer. If this is smaller than the alignment
* requirement of a used type, a separate allocation is necessary.
*/
size_t Alignment = 8>
class Any {
private:
/* Makes it possible to use void in the template parameters. */
using RealExtraInfo =
std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>;
using Info = detail::AnyTypeInfo<RealExtraInfo>;
/**
* Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr
* to the value.
*/
AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{};
/**
* Information about the type that is currently stored.
*/
const Info *info_ = &Info::get_for_empty();
public:
/** Only copy constructible types can be stored in #Any. */
template<typename T> static constexpr inline bool is_allowed_v = std::is_copy_constructible_v<T>;
/**
* Checks if the type will be stored in the inline buffer or if it requires a separate
* allocation.
*/
template<typename T>
static constexpr inline bool is_inline_v = std::is_nothrow_move_constructible_v<T> &&
sizeof(T) <= InlineBufferCapacity &&
alignof(T) <= Alignment;
/**
* Checks if #T is the same type as this #Any, because in this case the behavior of e.g. the
* assignment operator is different.
*/
template<typename T>
static constexpr inline bool is_same_any_v = std::is_same_v<std::decay_t<T>, Any>;
private:
template<typename T> const Info &get_info() const
{
using DecayT = std::decay_t<T>;
static_assert(is_allowed_v<DecayT>);
if constexpr (is_inline_v<DecayT>) {
return Info::template get_for_inline<DecayT>();
}
else {
return Info::template get_for_unique_ptr<DecayT>();
}
}
public:
Any() = default;
Any(const Any &other) : info_(other.info_)
{
info_->copy_construct(&buffer_, &other.buffer_);
}
/**
* \note: The #other #Any will not be empty afterwards if it was not before. Just its value is in
* a moved-from state.
*/
Any(Any &&other) noexcept : info_(other.info_)
{
info_->move_construct(&buffer_, &other.buffer_);
}
/**
* Constructs a new #Any that contains the given type #T from #args. The #std::in_place_type_t is
* used to disambiguate this and the copy/move constructors.
*/
template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args)
{
using DecayT = std::decay_t<T>;
static_assert(is_allowed_v<DecayT>);
info_ = &this->template get_info<DecayT>();
if constexpr (is_inline_v<DecayT>) {
/* Construct the value directly in the inline buffer. */
new (&buffer_) DecayT(std::forward<Args>(args)...);
}
else {
/* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
* buffer. */
new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
}
}
/**
* Constructs a new #Any that contains the given value.
*/
template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>>
Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value))
{
}
~Any()
{
info_->destruct(&buffer_);
}
/**
* \note: Only needed because the template below does not count as copy assignment operator.
*/
Any &operator=(const Any &other)
{
if (this == &other) {
return *this;
}
this->~Any();
new (this) Any(other);
return *this;
}
/** Assign any value to the #Any. */
template<typename T> Any &operator=(T &&other)
{
if constexpr (is_same_any_v<T>) {
if (this == &other) {
return *this;
}
}
this->~Any();
new (this) Any(std::forward<T>(other));
return *this;
}
/** Destruct any existing value to make it empty. */
void reset()
{
info_->destruct(&buffer_);
info_ = &Info::get_for_empty();
}
operator bool() const
{
return this->has_value();
}
bool has_value() const
{
return info_ != &Info::get_for_empty();
}
template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args)
{
this->~Any();
new (this) Any(std::in_place_type<T>, std::forward<Args>(args)...);
return this->get<T>();
}
/** Return true when the value that is currently stored is a #T. */
template<typename T> bool is() const
{
return info_ == &this->template get_info<T>();
}
/** Get a pointer to the stored value. */
void *get()
{
return const_cast<void *>(info_->get(&buffer_));
}
/** Get a pointer to the stored value. */
const void *get() const
{
return info_->get(&buffer_);
}
/**
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
* correct type.
*/
template<typename T> std::decay_t<T> &get()
{
BLI_assert(this->is<T>());
return *static_cast<std::decay_t<T> *>(this->get());
}
/**
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
* correct type.
*/
template<typename T> const std::decay_t<T> &get() const
{
BLI_assert(this->is<T>());
return *static_cast<const std::decay_t<T> *>(this->get());
}
/**
* Get extra information that has been stored for the contained type.
*/
const RealExtraInfo &extra_info() const
{
return info_->extra_info;
}
};
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -165,6 +165,7 @@ set(SRC
BLI_alloca.h
BLI_allocator.hh
BLI_any.hh
BLI_args.h
BLI_array.h
BLI_array.hh
@@ -411,6 +412,7 @@ blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(WITH_GTESTS)
set(TEST_SRC
tests/BLI_any_test.cc
tests/BLI_array_store_test.cc
tests/BLI_array_test.cc
tests/BLI_array_utils_test.cc

View File

@@ -0,0 +1,108 @@
/* Apache License, Version 2.0 */
#include "BLI_any.hh"
#include "BLI_map.hh"
#include "testing/testing.h"
namespace blender::tests {
TEST(any, DefaultConstructor)
{
Any a;
EXPECT_FALSE(a.has_value());
}
TEST(any, AssignInt)
{
Any<> a = 5;
EXPECT_TRUE(a.has_value());
EXPECT_TRUE(a.is<int>());
EXPECT_FALSE(a.is<float>());
const int &value = a.get<int>();
EXPECT_EQ(value, 5);
a = 10;
EXPECT_EQ(value, 10);
Any b = a;
EXPECT_TRUE(b.has_value());
EXPECT_EQ(b.get<int>(), 10);
Any c = std::move(a);
EXPECT_TRUE(c);
EXPECT_EQ(c.get<int>(), 10);
EXPECT_EQ(a.get<int>(), 10); /* NOLINT: bugprone-use-after-move */
a.reset();
EXPECT_FALSE(a);
}
TEST(any, AssignMap)
{
Any<> a = Map<int, int>();
EXPECT_TRUE(a.has_value());
EXPECT_TRUE((a.is<Map<int, int>>()));
EXPECT_FALSE((a.is<Map<int, float>>()));
Map<int, int> &map = a.get<Map<int, int>>();
map.add(4, 2);
EXPECT_EQ((a.get<Map<int, int>>().lookup(4)), 2);
Any b = a;
EXPECT_TRUE(b);
EXPECT_EQ((b.get<Map<int, int>>().lookup(4)), 2);
Any c = std::move(a);
c = c;
EXPECT_TRUE(b);
EXPECT_EQ((c.get<Map<int, int>>().lookup(4)), 2);
EXPECT_TRUE((a.get<Map<int, int>>().is_empty())); /* NOLINT: bugprone-use-after-move */
}
TEST(any, AssignAny)
{
Any<> a = 5;
Any<> b = std::string("hello");
Any c;
Any z;
EXPECT_FALSE(z.has_value());
z = a;
EXPECT_TRUE(z.has_value());
EXPECT_EQ(z.get<int>(), 5);
z = b;
EXPECT_EQ(z.get<std::string>(), "hello");
z = c;
EXPECT_FALSE(z.has_value());
z = Any(std::in_place_type<Any<>>, a);
EXPECT_FALSE(z.is<int>());
EXPECT_TRUE(z.is<Any<>>());
EXPECT_EQ(z.get<Any<>>().get<int>(), 5);
}
struct ExtraSizeInfo {
size_t size;
template<typename T> static ExtraSizeInfo get()
{
return {sizeof(T)};
}
};
TEST(any, ExtraInfo)
{
using MyAny = Any<ExtraSizeInfo>;
MyAny a = 5;
EXPECT_EQ(a.extra_info().size, sizeof(int));
a = std::string("hello");
EXPECT_EQ(a.extra_info().size, sizeof(std::string));
}
} // namespace blender::tests

View File

@@ -12,7 +12,7 @@ namespace blender::tests {
TEST(virtual_array, Span)
{
std::array<int, 5> data = {3, 4, 5, 6, 7};
VArray_For_Span<int> varray{data};
VArray<int> varray = VArray<int>::ForSpan(data);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray.get(0), 3);
EXPECT_EQ(varray.get(4), 7);
@@ -23,7 +23,7 @@ TEST(virtual_array, Span)
TEST(virtual_array, Single)
{
VArray_For_Single<int> varray{10, 4};
VArray<int> varray = VArray<int>::ForSingle(10, 4);
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray.get(0), 10);
EXPECT_EQ(varray.get(3), 10);
@@ -35,7 +35,7 @@ TEST(virtual_array, Array)
{
Array<int> array = {1, 2, 3, 5, 8};
{
VArray_For_ArrayContainer varray{array};
VArray<int> varray = VArray<int>::ForContainer(array);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
@@ -43,7 +43,7 @@ TEST(virtual_array, Array)
EXPECT_TRUE(varray.is_span());
}
{
VArray_For_ArrayContainer varray{std::move(array)};
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
@@ -51,7 +51,7 @@ TEST(virtual_array, Array)
EXPECT_TRUE(varray.is_span());
}
{
VArray_For_ArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */
VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */
EXPECT_TRUE(varray.is_empty());
}
}
@@ -59,7 +59,7 @@ TEST(virtual_array, Array)
TEST(virtual_array, Vector)
{
Vector<int> vector = {9, 8, 7, 6};
VArray_For_ArrayContainer varray{std::move(vector)};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 9);
EXPECT_EQ(varray[3], 6);
@@ -68,7 +68,7 @@ TEST(virtual_array, Vector)
TEST(virtual_array, StdVector)
{
std::vector<int> vector = {5, 6, 7, 8};
VArray_For_ArrayContainer varray{std::move(vector)};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
EXPECT_EQ(varray[1], 6);
@@ -77,7 +77,7 @@ TEST(virtual_array, StdVector)
TEST(virtual_array, StdArray)
{
std::array<int, 4> array = {2, 3, 4, 5};
VArray_For_ArrayContainer varray{array};
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 2);
EXPECT_EQ(varray[1], 3);
@@ -86,7 +86,7 @@ TEST(virtual_array, StdArray)
TEST(virtual_array, VectorSet)
{
VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
VArray_For_ArrayContainer varray{std::move(vector_set)};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set));
EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
@@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet)
TEST(virtual_array, Func)
{
auto func = [](int64_t index) { return (int)(index * index); };
VArray_For_Func<int, decltype(func)> varray{10, func};
VArray<int> varray = VArray<int>::ForFunc(10, func);
EXPECT_EQ(varray.size(), 10);
EXPECT_EQ(varray[0], 0);
EXPECT_EQ(varray[3], 9);
@@ -108,7 +108,7 @@ TEST(virtual_array, Func)
TEST(virtual_array, AsSpan)
{
auto func = [](int64_t index) { return (int)(10 * index); };
VArray_For_Func<int, decltype(func)> func_varray{10, func};
VArray<int> func_varray = VArray<int>::ForFunc(10, func);
VArray_Span span_varray{func_varray};
EXPECT_EQ(span_varray.size(), 10);
Span<int> span = span_varray;
@@ -134,13 +134,14 @@ TEST(virtual_array, DerivedSpan)
vector.append({3, 4, 5});
vector.append({1, 1, 1});
{
VArray_For_DerivedSpan<std::array<int, 3>, int, get_x> varray{vector};
VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
}
{
VMutableArray_For_DerivedSpan<std::array<int, 3>, int, get_x, set_x> varray{vector};
VMutableArray<int> varray =
VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
@@ -151,4 +152,32 @@ TEST(virtual_array, DerivedSpan)
}
}
TEST(virtual_array, MutableToImmutable)
{
std::array<int, 4> array = {4, 2, 6, 4};
{
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
VArray<int> varray = mutable_varray;
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
EXPECT_EQ(mutable_varray.size(), 4);
}
{
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
EXPECT_EQ(mutable_varray.size(), 4);
VArray<int> varray = std::move(mutable_varray);
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
EXPECT_EQ(mutable_varray.size(), 0);
}
{
VArray<int> varray = VMutableArray<int>::ForSpan(array);
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
}
}
} // namespace blender::tests

View File

@@ -72,7 +72,7 @@ static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type(
void ExtraColumns::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
for (const auto &item : columns_.items()) {
for (const auto item : columns_.items()) {
SpreadsheetColumnID column_id;
column_id.name = (char *)item.key.c_str();
fn(column_id, true);
@@ -159,12 +159,12 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
if (!attribute) {
return {};
}
const fn::GVArray *varray = scope_.add(std::move(attribute.varray));
fn::GVArray varray = std::move(attribute.varray);
if (attribute.domain != domain_) {
return {};
}
int domain_size = varray->size();
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type());
int domain_size = varray.size();
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type());
switch (type) {
case CD_PROP_FLOAT:
return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
@@ -172,7 +172,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_float = value;
});
case CD_PROP_INT32:
@@ -182,7 +182,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
int value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_int = value;
},
STREQ(column_id.name, "id") ? 5.5f : 0.0f);
@@ -192,7 +192,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
bool value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_bool = value;
});
case CD_PROP_FLOAT2: {
@@ -201,7 +201,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float2 value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_float2 = value;
});
}
@@ -211,7 +211,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float3 value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_float3 = value;
});
}
@@ -221,7 +221,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
ColorGeometry4f value;
varray->get(index, &value);
varray.get(index, &value);
r_cell_value.value_color = value;
});
}
@@ -644,7 +644,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet,
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
const int domain_size = component.attribute_domain_size(domain);
for (const auto &item : fields_to_show.items()) {
for (const auto item : fields_to_show.items()) {
StringRef name = item.key;
const GField &field = item.value;

View File

@@ -248,9 +248,9 @@ class FieldInput : public FieldNode {
* Get the value of this specific input based on the given context. The returned virtual array,
* should live at least as long as the passed in #scope. May return null.
*/
virtual const GVArray *get_varray_for_context(const FieldContext &context,
IndexMask mask,
ResourceScope &scope) const = 0;
virtual GVArray get_varray_for_context(const FieldContext &context,
IndexMask mask,
ResourceScope &scope) const = 0;
virtual std::string socket_inspection_name() const;
blender::StringRef debug_name() const;
@@ -268,9 +268,9 @@ class FieldContext {
public:
~FieldContext() = default;
virtual const GVArray *get_varray_for_input(const FieldInput &field_input,
IndexMask mask,
ResourceScope &scope) const;
virtual GVArray get_varray_for_input(const FieldInput &field_input,
IndexMask mask,
ResourceScope &scope) const;
};
/**
@@ -289,8 +289,8 @@ class FieldEvaluator : NonMovable, NonCopyable {
const FieldContext &context_;
const IndexMask mask_;
Vector<GField> fields_to_evaluate_;
Vector<GVMutableArray *> dst_varrays_;
Vector<const GVArray *> evaluated_varrays_;
Vector<GVMutableArray> dst_varrays_;
Vector<GVArray> evaluated_varrays_;
Vector<OutputPointerInfo> output_pointer_infos_;
bool is_evaluated_ = false;
@@ -317,13 +317,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
* \param field: Field to add to the evaluator.
* \param dst: Mutable virtual array that the evaluated result for this field is be written into.
*/
int add_with_destination(GField field, GVMutableArray &dst);
int add_with_destination(GField field, GVMutableArray dst);
/** Same as #add_with_destination but typed. */
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst)
{
GVMutableArray &varray = scope_.construct<GVMutableArray_For_VMutableArray<T>>(dst);
return this->add_with_destination(GField(std::move(field)), varray);
return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst)));
}
/**
@@ -342,11 +341,10 @@ class FieldEvaluator : NonMovable, NonCopyable {
*/
template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst)
{
GVMutableArray &varray = scope_.construct<GVMutableArray_For_MutableSpan<T>>(dst);
return this->add_with_destination(std::move(field), varray);
return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst));
}
int add(GField field, const GVArray **varray_ptr);
int add(GField field, GVArray *varray_ptr);
/**
* \param field: Field to add to the evaluator.
@@ -354,14 +352,14 @@ class FieldEvaluator : NonMovable, NonCopyable {
* assigned to the given position.
* \return Index of the field in the evaluator which can be used in the #get_evaluated methods.
*/
template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
template<typename T> int add(Field<T> field, VArray<T> *varray_ptr)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_varrays_.append(nullptr);
output_pointer_infos_.append(
OutputPointerInfo{varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) {
*(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(varray);
}});
dst_varrays_.append({});
output_pointer_infos_.append(OutputPointerInfo{
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
*(VArray<T> *)dst = varray.typed<T>();
}});
return field_index;
}
@@ -378,14 +376,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
const GVArray &get_evaluated(const int field_index) const
{
BLI_assert(is_evaluated_);
return *evaluated_varrays_[field_index];
return evaluated_varrays_[field_index];
}
template<typename T> const VArray<T> &get_evaluated(const int field_index)
template<typename T> VArray<T> get_evaluated(const int field_index)
{
const GVArray &varray = this->get_evaluated(field_index);
GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(varray);
return *typed_varray;
return this->get_evaluated(field_index).typed<T>();
}
/**
@@ -396,11 +392,11 @@ class FieldEvaluator : NonMovable, NonCopyable {
IndexMask get_evaluated_as_mask(const int field_index);
};
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
Span<GVMutableArray *> dst_varrays = {});
Vector<GVArray> evaluate_fields(ResourceScope &scope,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
Span<GVMutableArray> dst_varrays = {});
/* -------------------------------------------------------------------- */
/** \name Utility functions for simple field creation and evaluation
@@ -429,11 +425,11 @@ class IndexFieldInput final : public FieldInput {
public:
IndexFieldInput();
static GVArray *get_index_varray(IndexMask mask, ResourceScope &scope);
static GVArray get_index_varray(IndexMask mask, ResourceScope &scope);
const GVArray *get_varray_for_context(const FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final;
GVArray get_varray_for_context(const FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final;
uint64_t hash() const override;
bool is_equal_to(const fn::FieldNode &other) const override;

View File

@@ -125,8 +125,7 @@ template<typename T> class GVectorArray_TypedMutableRef {
void extend(const int64_t index, const VArray<T> &values)
{
GVArray_For_VArray<T> array{values};
this->extend(index, array);
vector_array_->extend(index, values);
}
MutableSpan<T> operator[](const int64_t index)

File diff suppressed because it is too large Load Diff

View File

@@ -100,31 +100,31 @@ class GVVectorArray {
}
};
class GVArray_For_GVVectorArrayIndex : public GVArray {
class GVArray_For_GVVectorArrayIndex : public GVArrayImpl {
private:
const GVVectorArray &vector_array_;
const int64_t index_;
public:
GVArray_For_GVVectorArrayIndex(const GVVectorArray &vector_array, const int64_t index)
: GVArray(vector_array.type(), vector_array.get_vector_size(index)),
: GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)),
vector_array_(vector_array),
index_(index)
{
}
protected:
void get_impl(const int64_t index_in_vector, void *r_value) const override;
void get_to_uninitialized_impl(const int64_t index_in_vector, void *r_value) const override;
void get(const int64_t index_in_vector, void *r_value) const override;
void get_to_uninitialized(const int64_t index_in_vector, void *r_value) const override;
};
class GVVectorArray_For_SingleGVArray : public GVVectorArray {
private:
const GVArray &array_;
GVArray varray_;
public:
GVVectorArray_For_SingleGVArray(const GVArray &array, const int64_t size)
: GVVectorArray(array.type(), size), array_(array)
GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size)
: GVVectorArray(varray.type(), size), varray_(std::move(varray))
{
}

View File

@@ -40,7 +40,7 @@ class MFParamsBuilder {
const MFSignature *signature_;
IndexMask mask_;
int64_t min_array_size_;
Vector<const GVArray *> virtual_arrays_;
Vector<GVArray> virtual_arrays_;
Vector<GMutableSpan> mutable_spans_;
Vector<const GVVectorArray *> virtual_vector_arrays_;
Vector<GVectorArray *> vector_arrays_;
@@ -68,24 +68,22 @@ class MFParamsBuilder {
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
{
this->add_readonly_single_input(
scope_.construct<GVArray_For_SingleValueRef>(CPPType::get<T>(), min_array_size_, value),
expected_name);
GVArray::ForSingleRef(CPPType::get<T>(), min_array_size_, value), expected_name);
}
void add_readonly_single_input(const GSpan span, StringRef expected_name = "")
{
this->add_readonly_single_input(scope_.construct<GVArray_For_GSpan>(span), expected_name);
this->add_readonly_single_input(GVArray::ForSpan(span), expected_name);
}
void add_readonly_single_input(GPointer value, StringRef expected_name = "")
{
this->add_readonly_single_input(
scope_.construct<GVArray_For_SingleValueRef>(*value.type(), min_array_size_, value.get()),
expected_name);
GVArray::ForSingleRef(*value.type(), min_array_size_, value.get()), expected_name);
}
void add_readonly_single_input(const GVArray &ref, StringRef expected_name = "")
void add_readonly_single_input(GVArray varray, StringRef expected_name = "")
{
this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_);
virtual_arrays_.append(&ref);
this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name);
BLI_assert(varray.size() >= min_array_size_);
virtual_arrays_.append(varray);
}
void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "")
@@ -221,16 +219,16 @@ class MFParams {
{
}
template<typename T> const VArray<T> &readonly_single_input(int param_index, StringRef name = "")
template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "")
{
const GVArray &array = this->readonly_single_input(param_index, name);
return builder_->scope_.construct<GVArray_Typed<T>>(array);
const GVArray &varray = this->readonly_single_input(param_index, name);
return varray.typed<T>();
}
const GVArray &readonly_single_input(int param_index, StringRef name = "")
{
this->assert_correct_param(param_index, name, MFParamType::SingleInput);
int data_index = builder_->signature_->data_index(param_index);
return *builder_->virtual_arrays_[data_index];
return builder_->virtual_arrays_[data_index];
}
/**

View File

@@ -81,19 +81,18 @@ static FieldTreeInfo preprocess_field_tree(Span<GFieldRef> entry_fields)
/**
* Retrieves the data from the context that is passed as input into the field.
*/
static Vector<const GVArray *> get_field_context_inputs(
static Vector<GVArray> get_field_context_inputs(
ResourceScope &scope,
const IndexMask mask,
const FieldContext &context,
const Span<std::reference_wrapper<const FieldInput>> field_inputs)
{
Vector<const GVArray *> field_context_inputs;
Vector<GVArray> field_context_inputs;
for (const FieldInput &field_input : field_inputs) {
const GVArray *varray = context.get_varray_for_input(field_input, mask, scope);
if (varray == nullptr) {
GVArray varray = context.get_varray_for_input(field_input, mask, scope);
if (!varray) {
const CPPType &type = field_input.cpp_type();
varray = &scope.construct<GVArray_For_SingleValueRef>(
type, mask.min_array_size(), type.default_value());
varray = GVArray::ForSingleDefault(type, mask.min_array_size());
}
field_context_inputs.append(varray);
}
@@ -105,7 +104,7 @@ static Vector<const GVArray *> get_field_context_inputs(
* for different indices.
*/
static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
Span<const GVArray *> field_context_inputs)
Span<GVArray> field_context_inputs)
{
Set<GFieldRef> found_fields;
Stack<GFieldRef> fields_to_check;
@@ -114,8 +113,8 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
* start the tree search at the non-constant input fields and traverse through all fields that
* depend on them. */
for (const int i : field_context_inputs.index_range()) {
const GVArray *varray = field_context_inputs[i];
if (varray->is_single()) {
const GVArray &varray = field_context_inputs[i];
if (varray.is_single()) {
continue;
}
const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i];
@@ -278,29 +277,42 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
* \return The computed virtual arrays for each provided field. If #dst_varrays is passed, the
* provided virtual arrays are returned.
*/
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
Span<GVMutableArray *> dst_varrays)
Vector<GVArray> evaluate_fields(ResourceScope &scope,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
Span<GVMutableArray> dst_varrays)
{
Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr);
Vector<GVArray> r_varrays(fields_to_evaluate.size());
Array<bool> is_output_written_to_dst(fields_to_evaluate.size(), false);
const int array_size = mask.min_array_size();
/* Destination arrays are optional. Create a small utility method to access them. */
auto get_dst_varray_if_available = [&](int index) -> GVMutableArray * {
if (dst_varrays.is_empty()) {
return nullptr;
if (mask.is_empty()) {
for (const int i : fields_to_evaluate.index_range()) {
const CPPType &type = fields_to_evaluate[i].cpp_type();
r_varrays[i] = GVArray::ForEmpty(type);
}
BLI_assert(dst_varrays[index] == nullptr || dst_varrays[index]->size() >= array_size);
return dst_varrays[index];
return r_varrays;
}
/* Destination arrays are optional. Create a small utility method to access them. */
auto get_dst_varray = [&](int index) -> GVMutableArray {
if (dst_varrays.is_empty()) {
return {};
}
const GVMutableArray &varray = dst_varrays[index];
if (!varray) {
return {};
}
BLI_assert(varray.size() >= array_size);
return varray;
};
/* Traverse the field tree and prepare some data that is used in later steps. */
FieldTreeInfo field_tree_info = preprocess_field_tree(fields_to_evaluate);
/* Get inputs that will be passed into the field when evaluated. */
Vector<const GVArray *> field_context_inputs = get_field_context_inputs(
Vector<GVArray> field_context_inputs = get_field_context_inputs(
scope, mask, context, field_tree_info.deduplicated_field_inputs);
/* Finish fields that output an input varray directly. For those we don't have to do any further
@@ -312,7 +324,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
}
const FieldInput &field_input = static_cast<const FieldInput &>(field.node());
const int field_input_index = field_tree_info.deduplicated_field_inputs.index_of(field_input);
const GVArray *varray = field_context_inputs[field_input_index];
const GVArray &varray = field_context_inputs[field_input_index];
r_varrays[out_index] = varray;
}
@@ -325,7 +337,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Vector<GFieldRef> constant_fields_to_evaluate;
Vector<int> constant_field_indices;
for (const int i : fields_to_evaluate.index_range()) {
if (r_varrays[i] != nullptr) {
if (r_varrays[i]) {
/* Already done. */
continue;
}
@@ -357,8 +369,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
for (const GVArray *varray : field_context_inputs) {
mf_params.add_readonly_single_input(*varray);
for (const GVArray &varray : field_context_inputs) {
mf_params.add_readonly_single_input(varray);
}
for (const int i : varying_fields_to_evaluate.index_range()) {
@@ -367,9 +379,9 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
const int out_index = varying_field_indices[i];
/* Try to get an existing virtual array that the result should be written into. */
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
GVMutableArray dst_varray = get_dst_varray(out_index);
void *buffer;
if (output_varray == nullptr || !output_varray->is_span()) {
if (!dst_varray || !dst_varray.is_span()) {
/* Allocate a new buffer for the computed result. */
buffer = scope.linear_allocator().allocate(type.size() * array_size, type.alignment());
@@ -379,14 +391,14 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
[buffer, mask, &type]() { type.destruct_indices(buffer, mask); });
}
r_varrays[out_index] = &scope.construct<GVArray_For_GSpan>(
GSpan{type, buffer, array_size});
r_varrays[out_index] = GVArray::ForSpan({type, buffer, array_size});
}
else {
/* Write the result into the existing span. */
buffer = output_varray->get_internal_span().data();
buffer = dst_varray.get_internal_span().data();
r_varrays[out_index] = output_varray;
r_varrays[out_index] = dst_varray;
is_output_written_to_dst[out_index] = true;
}
/* Pass output buffer to the procedure executor. */
@@ -404,15 +416,12 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, constant_fields_to_evaluate);
MFProcedureExecutor procedure_executor{"Procedure", procedure};
/* Run the code below even when the mask is empty, so that outputs are properly prepared.
* Higher level code can detect this as well and just skip evaluating the field. */
const int mask_size = mask.is_empty() ? 0 : 1;
MFParamsBuilder mf_params{procedure_executor, mask_size};
MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
for (const GVArray *varray : field_context_inputs) {
mf_params.add_readonly_single_input(*varray);
for (const GVArray &varray : field_context_inputs) {
mf_params.add_readonly_single_input(varray);
}
for (const int i : constant_fields_to_evaluate.index_range()) {
@@ -421,55 +430,52 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
/* Allocate memory where the computed value will be stored in. */
void *buffer = scope.linear_allocator().allocate(type.size(), type.alignment());
if (!type.is_trivially_destructible() && mask_size > 0) {
BLI_assert(mask_size == 1);
if (!type.is_trivially_destructible()) {
/* Destruct value in the end. */
scope.add_destruct_call([buffer, &type]() { type.destruct(buffer); });
}
/* Pass output buffer to the procedure executor. */
mf_params.add_uninitialized_single_output({type, buffer, mask_size});
mf_params.add_uninitialized_single_output({type, buffer, 1});
/* Create virtual array that can be used after the procedure has been executed below. */
const int out_index = constant_field_indices[i];
r_varrays[out_index] = &scope.construct<GVArray_For_SingleValueRef>(
type, array_size, buffer);
r_varrays[out_index] = GVArray::ForSingleRef(type, array_size, buffer);
}
procedure_executor.call(IndexRange(mask_size), mf_params, mf_context);
procedure_executor.call(IndexRange(1), mf_params, mf_context);
}
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above has
* written the computed data in the right place already. */
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above
* has written the computed data in the right place already. */
if (!dst_varrays.is_empty()) {
for (const int out_index : fields_to_evaluate.index_range()) {
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
if (output_varray == nullptr) {
GVMutableArray dst_varray = get_dst_varray(out_index);
if (!dst_varray) {
/* Caller did not provide a destination for this output. */
continue;
}
const GVArray *computed_varray = r_varrays[out_index];
BLI_assert(computed_varray->type() == output_varray->type());
if (output_varray == computed_varray) {
const GVArray &computed_varray = r_varrays[out_index];
BLI_assert(computed_varray.type() == dst_varray.type());
if (is_output_written_to_dst[out_index]) {
/* The result has been written into the destination provided by the caller already. */
continue;
}
/* Still have to copy over the data in the destination provided by the caller. */
if (output_varray->is_span()) {
if (dst_varray.is_span()) {
/* Materialize into a span. */
computed_varray->materialize_to_uninitialized(mask,
output_varray->get_internal_span().data());
computed_varray.materialize_to_uninitialized(mask, dst_varray.get_internal_span().data());
}
else {
/* Slower materialize into a different structure. */
const CPPType &type = computed_varray->type();
const CPPType &type = computed_varray.type();
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
for (const int i : mask) {
computed_varray->get_to_uninitialized(i, buffer);
output_varray->set_by_relocate(i, buffer);
computed_varray.get_to_uninitialized(i, buffer);
dst_varray.set_by_relocate(i, buffer);
}
}
r_varrays[out_index] = output_varray;
r_varrays[out_index] = dst_varray;
}
}
return r_varrays;
@@ -485,8 +491,8 @@ void evaluate_constant_field(const GField &field, void *r_value)
ResourceScope scope;
FieldContext context;
Vector<const GVArray *> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
varrays[0]->get_to_uninitialized(0, r_value);
Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
varrays[0].get_to_uninitialized(0, r_value);
}
/**
@@ -512,9 +518,9 @@ GField make_field_constant_if_possible(GField field)
return GField{operation, 0};
}
const GVArray *FieldContext::get_varray_for_input(const FieldInput &field_input,
IndexMask mask,
ResourceScope &scope) const
GVArray FieldContext::get_varray_for_input(const FieldInput &field_input,
IndexMask mask,
ResourceScope &scope) const
{
/* By default ask the field input to create the varray. Another field context might overwrite
* the context here. */
@@ -526,17 +532,15 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
category_ = Category::Generated;
}
GVArray *IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &scope)
GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope))
{
auto index_func = [](int i) { return i; };
return &scope.construct<
fn::GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
mask.min_array_size(), mask.min_array_size(), index_func);
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
}
const GVArray *IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
IndexMask mask,
ResourceScope &scope) const
GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
IndexMask mask,
ResourceScope &scope) const
{
/* TODO: Investigate a similar method to IndexRange::as_span() */
return get_index_varray(mask, scope);
@@ -631,27 +635,26 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
return indices;
}
int FieldEvaluator::add_with_destination(GField field, GVMutableArray &dst)
int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_varrays_.append(&dst);
dst_varrays_.append(dst);
output_pointer_infos_.append({});
return field_index;
}
int FieldEvaluator::add_with_destination(GField field, GMutableSpan dst)
{
GVMutableArray &varray = scope_.construct<GVMutableArray_For_GMutableSpan>(dst);
return this->add_with_destination(std::move(field), varray);
return this->add_with_destination(std::move(field), GVMutableArray::ForSpan(dst));
}
int FieldEvaluator::add(GField field, const GVArray **varray_ptr)
int FieldEvaluator::add(GField field, GVArray *varray_ptr)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_varrays_.append(nullptr);
output_pointer_infos_.append(OutputPointerInfo{
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
*(const GVArray **)dst = &varray;
*(GVArray *)dst = varray;
}});
return field_index;
}
@@ -676,7 +679,7 @@ void FieldEvaluator::evaluate()
for (const int i : fields_to_evaluate_.index_range()) {
OutputPointerInfo &info = output_pointer_infos_[i];
if (info.dst != nullptr) {
info.set(info.dst, *evaluated_varrays_[i], scope_);
info.set(info.dst, evaluated_varrays_[i], scope_);
}
}
is_evaluated_ = true;
@@ -684,17 +687,16 @@ void FieldEvaluator::evaluate()
IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index)
{
const GVArray &varray = this->get_evaluated(field_index);
GVArray_Typed<bool> typed_varray{varray};
VArray<bool> varray = this->get_evaluated(field_index).typed<bool>();
if (typed_varray->is_single()) {
if (typed_varray->get_internal_single()) {
return IndexRange(typed_varray.size());
if (varray.is_single()) {
if (varray.get_internal_single()) {
return IndexRange(varray.size());
}
return IndexRange(0);
}
return scope_.add_value(indices_from_selection(*typed_varray)).as_span();
return scope_.add_value(indices_from_selection(varray)).as_span();
}
} // namespace blender::fn

View File

@@ -60,15 +60,14 @@ void GVectorArray::extend(const int64_t index, const GVArray &values)
void GVectorArray::extend(const int64_t index, const GSpan values)
{
GVArray_For_GSpan varray{values};
this->extend(index, varray);
this->extend(index, GVArray::ForSpan(values));
}
void GVectorArray::extend(IndexMask mask, const GVVectorArray &values)
{
for (const int i : mask) {
GVArray_For_GVVectorArrayIndex array{values, i};
this->extend(i, array);
this->extend(i, GVArray(&array));
}
}

View File

@@ -19,52 +19,10 @@
namespace blender::fn {
/* -------------------------------------------------------------------- */
/** \name #GVArray_For_ShallowCopy
/** \name #GVArrayImpl
* \{ */
class GVArray_For_ShallowCopy : public GVArray {
private:
const GVArray &varray_;
public:
GVArray_For_ShallowCopy(const GVArray &varray)
: GVArray(varray.type(), varray.size()), varray_(varray)
{
}
private:
void get_impl(const int64_t index, void *r_value) const override
{
varray_.get(index, r_value);
}
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
{
varray_.get_to_uninitialized(index, r_value);
}
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
{
varray_.materialize_to_uninitialized(mask, dst);
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArray
* \{ */
void GVArray::materialize(void *dst) const
{
this->materialize(IndexMask(size_), dst);
}
void GVArray::materialize(const IndexMask mask, void *dst) const
{
this->materialize_impl(mask, dst);
}
void GVArray::materialize_impl(const IndexMask mask, void *dst) const
void GVArrayImpl::materialize(const IndexMask mask, void *dst) const
{
for (const int64_t i : mask) {
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
@@ -72,18 +30,7 @@ void GVArray::materialize_impl(const IndexMask mask, void *dst) const
}
}
void GVArray::materialize_to_uninitialized(void *dst) const
{
this->materialize_to_uninitialized(IndexMask(size_), dst);
}
void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const
{
BLI_assert(mask.min_array_size() <= size_);
this->materialize_to_uninitialized_impl(mask, dst);
}
void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const
void GVArrayImpl::materialize_to_uninitialized(const IndexMask mask, void *dst) const
{
for (const int64_t i : mask) {
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
@@ -91,83 +38,75 @@ void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst)
}
}
void GVArray::get_impl(const int64_t index, void *r_value) const
void GVArrayImpl::get(const int64_t index, void *r_value) const
{
type_->destruct(r_value);
this->get_to_uninitialized_impl(index, r_value);
this->get_to_uninitialized(index, r_value);
}
bool GVArray::is_span_impl() const
bool GVArrayImpl::is_span() const
{
return false;
}
GSpan GVArray::get_internal_span_impl() const
GSpan GVArrayImpl::get_internal_span() const
{
BLI_assert(false);
return GSpan(*type_);
}
bool GVArray::is_single_impl() const
bool GVArrayImpl::is_single() const
{
return false;
}
void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const
void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const
{
BLI_assert(false);
}
const void *GVArray::try_get_internal_varray_impl() const
bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const
{
return nullptr;
return false;
}
/**
* Creates a new `std::unique_ptr<GVArray>` based on this `GVArray`.
* The lifetime of the returned virtual array must not be longer than the lifetime of this virtual
* array.
*/
GVArrayPtr GVArray::shallow_copy() const
bool GVArrayImpl::may_have_ownership() const
{
if (this->is_span()) {
return std::make_unique<GVArray_For_GSpan>(this->get_internal_span());
}
if (this->is_single()) {
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
this->get_internal_single(buffer);
std::unique_ptr new_varray = std::make_unique<GVArray_For_SingleValue>(*type_, size_, buffer);
type_->destruct(buffer);
return new_varray;
}
return std::make_unique<GVArray_For_ShallowCopy>(*this);
/* Use true as default to avoid accidentally creating subclasses that have this set to false but
* actually own data. Subclasses should set the to false instead. */
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVMutableArray
/** \name #GVMutableArrayImpl
* \{ */
void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value)
GVMutableArrayImpl::GVMutableArrayImpl(const CPPType &type, const int64_t size)
: GVArrayImpl(type, size)
{
}
void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
{
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
type_->copy_construct(value, buffer);
this->set_by_move_impl(index, buffer);
this->set_by_move(index, buffer);
type_->destruct(buffer);
}
void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value)
void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
{
this->set_by_move_impl(index, value);
this->set_by_move(index, value);
type_->destruct(value);
}
void GVMutableArray::set_all_impl(const void *src)
void GVMutableArrayImpl::set_all(const void *src)
{
if (this->is_span()) {
const GMutableSpan span = this->get_internal_span();
type_->copy_assign_n(src, span.data(), size_);
const GSpan span = this->get_internal_span();
type_->copy_assign_n(src, const_cast<void *>(span.data()), size_);
}
else {
for (int64_t i : IndexRange(size_)) {
@@ -176,149 +115,223 @@ void GVMutableArray::set_all_impl(const void *src)
}
}
void *GVMutableArray::try_get_internal_mutable_varray_impl()
{
return nullptr;
}
void GVMutableArray::fill(const void *value)
{
if (this->is_span()) {
const GMutableSpan span = this->get_internal_span();
type_->fill_assign_n(value, span.data(), size_);
const GSpan span = this->get_internal_span();
this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size());
}
else {
for (int64_t i : IndexRange(size_)) {
for (int64_t i : IndexRange(this->size())) {
this->set_by_copy(i, value);
}
}
}
bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const
{
return false;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArray_For_GSpan
/** \name #GVArrayImpl_For_GSpan
* \{ */
void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span)
: GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
{
}
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size)
: GVArrayImpl(type, size), element_size_(type.size())
{
}
void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
{
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const
void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
{
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
bool GVArray_For_GSpan::is_span_impl() const
bool GVArrayImpl_For_GSpan::is_span() const
{
return true;
}
GSpan GVArray_For_GSpan::get_internal_span_impl() const
GSpan GVArrayImpl_For_GSpan::get_internal_span() const
{
return GSpan(*type_, data_, size_);
}
class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
public:
using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan;
private:
bool may_have_ownership() const override
{
return false;
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVMutableArray_For_GMutableSpan
/** \name #GVMutableArrayImpl_For_GMutableSpan
* \{ */
void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span)
: GVMutableArrayImpl(span.type(), span.size()),
data_(span.data()),
element_size_(span.type().size())
{
}
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type,
const int64_t size)
: GVMutableArrayImpl(type, size), element_size_(type.size())
{
}
void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const
{
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index,
void *r_value) const
void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index,
void *r_value) const
{
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value)
void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value)
{
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value)
void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value)
{
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value)
void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value)
{
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
bool GVMutableArray_For_GMutableSpan::is_span_impl() const
bool GVMutableArrayImpl_For_GMutableSpan::is_span() const
{
return true;
}
GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const
GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const
{
return GSpan(*type_, data_, size_);
}
/** \} */
class GVMutableArrayImpl_For_GMutableSpan_final final
: public GVMutableArrayImpl_For_GMutableSpan {
public:
using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan;
/* -------------------------------------------------------------------- */
/** \name #GVArray_For_SingleValueRef
* \{ */
void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const
{
type_->copy_assign(value_, r_value);
}
void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index),
void *r_value) const
{
type_->copy_construct(value_, r_value);
}
bool GVArray_For_SingleValueRef::is_span_impl() const
{
return size_ == 1;
}
GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const
{
return GSpan{*type_, value_, 1};
}
bool GVArray_For_SingleValueRef::is_single_impl() const
{
return true;
}
void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const
{
type_->copy_assign(value_, r_value);
}
private:
bool may_have_ownership() const override
{
return false;
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArray_For_SingleValue
/** \name #GVArrayImpl_For_SingleValueRef
* \{ */
GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type,
const int64_t size,
const void *value)
: GVArray_For_SingleValueRef(type, size)
{
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
type.copy_construct(value, (void *)value_);
}
/* Generic virtual array where each element has the same value. The value is not owned. */
class GVArrayImpl_For_SingleValueRef : public GVArrayImpl {
protected:
const void *value_ = nullptr;
GVArray_For_SingleValue::~GVArray_For_SingleValue()
{
type_->destruct((void *)value_);
MEM_freeN((void *)value_);
}
public:
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
: GVArrayImpl(type, size), value_(value)
{
}
protected:
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size)
{
}
void get(const int64_t UNUSED(index), void *r_value) const override
{
type_->copy_assign(value_, r_value);
}
void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override
{
type_->copy_construct(value_, r_value);
}
bool is_span() const override
{
return size_ == 1;
}
GSpan get_internal_span() const override
{
return GSpan{*type_, value_, 1};
}
bool is_single() const override
{
return true;
}
void get_internal_single(void *r_value) const override
{
type_->copy_assign(value_, r_value);
}
};
class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_SingleValueRef {
public:
using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef;
private:
bool may_have_ownership() const override
{
return false;
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArrayImpl_For_SingleValue
* \{ */
/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
class GVArrayImpl_For_SingleValue : public GVArrayImpl_For_SingleValueRef,
NonCopyable,
NonMovable {
public:
GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
: GVArrayImpl_For_SingleValueRef(type, size)
{
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
type.copy_construct(value, (void *)value_);
}
~GVArrayImpl_For_SingleValue() override
{
type_->destruct((void *)value_);
MEM_freeN((void *)value_);
}
};
/** \} */
@@ -326,7 +339,7 @@ GVArray_For_SingleValue::~GVArray_For_SingleValue()
/** \name #GVArray_GSpan
* \{ */
GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray)
GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray))
{
size_ = varray_.size();
if (varray_.is_span()) {
@@ -353,8 +366,8 @@ GVArray_GSpan::~GVArray_GSpan()
/** \name #GVMutableArray_GSpan
* \{ */
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span)
: GMutableSpan(varray.type()), varray_(varray)
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span)
: GMutableSpan(varray.type()), varray_(std::move(varray))
{
size_ = varray_.size();
if (varray_.is_span()) {
@@ -405,48 +418,314 @@ void GVMutableArray_GSpan::disable_not_applied_warning()
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArray_For_SlicedGVArray
/** \name #GVArrayImpl_For_SlicedGVArray
* \{ */
void GVArray_For_SlicedGVArray::get_impl(const int64_t index, void *r_value) const
class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl {
protected:
GVArray varray_;
int64_t offset_;
public:
GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice)
: GVArrayImpl(varray.type(), slice.size()),
varray_(std::move(varray)),
offset_(slice.start())
{
BLI_assert(slice.one_after_last() <= varray_.size());
}
void get(const int64_t index, void *r_value) const override
{
varray_.get(index + offset_, r_value);
}
void get_to_uninitialized(const int64_t index, void *r_value) const override
{
varray_.get_to_uninitialized(index + offset_, r_value);
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArrayCommon
* \{ */
GVArrayCommon::GVArrayCommon() = default;
GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_)
{
varray_.get(index + offset_, r_value);
impl_ = this->impl_from_storage();
}
void GVArray_For_SlicedGVArray::get_to_uninitialized_impl(const int64_t index, void *r_value) const
GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
{
varray_.get_to_uninitialized(index + offset_, r_value);
impl_ = this->impl_from_storage();
other.storage_.reset();
other.impl_ = nullptr;
}
GVArrayCommon::GVArrayCommon(const GVArrayImpl *impl) : impl_(impl)
{
storage_ = impl_;
}
GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
{
if (impl) {
storage_ = std::move(impl);
}
}
GVArrayCommon::~GVArrayCommon() = default;
void GVArrayCommon::materialize(void *dst) const
{
this->materialize(IndexMask(impl_->size()), dst);
}
void GVArrayCommon::materialize(const IndexMask mask, void *dst) const
{
impl_->materialize(mask, dst);
}
void GVArrayCommon::materialize_to_uninitialized(void *dst) const
{
this->materialize_to_uninitialized(IndexMask(impl_->size()), dst);
}
void GVArrayCommon::materialize_to_uninitialized(const IndexMask mask, void *dst) const
{
BLI_assert(mask.min_array_size() <= impl_->size());
impl_->materialize_to_uninitialized(mask, dst);
}
bool GVArrayCommon::may_have_ownership() const
{
return impl_->may_have_ownership();
}
void GVArrayCommon::copy_from(const GVArrayCommon &other)
{
if (this == &other) {
return;
}
storage_ = other.storage_;
impl_ = this->impl_from_storage();
}
void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept
{
if (this == &other) {
return;
}
storage_ = std::move(other.storage_);
impl_ = this->impl_from_storage();
other.storage_.reset();
other.impl_ = nullptr;
}
/* Returns true when the virtual array is stored as a span internally. */
bool GVArrayCommon::is_span() const
{
if (this->is_empty()) {
return true;
}
return impl_->is_span();
}
/* Returns the internally used span of the virtual array. This invokes undefined behavior is the
* virtual array is not stored as a span internally. */
GSpan GVArrayCommon::get_internal_span() const
{
BLI_assert(this->is_span());
if (this->is_empty()) {
return GSpan(impl_->type());
}
return impl_->get_internal_span();
}
/* Returns true when the virtual array returns the same value for every index. */
bool GVArrayCommon::is_single() const
{
if (impl_->size() == 1) {
return true;
}
return impl_->is_single();
}
/* Copies the value that is used for every element into `r_value`, which is expected to point to
* initialized memory. This invokes undefined behavior if the virtual array would not return the
* same value for every index. */
void GVArrayCommon::get_internal_single(void *r_value) const
{
BLI_assert(this->is_single());
if (impl_->size() == 1) {
impl_->get(0, r_value);
return;
}
impl_->get_internal_single(r_value);
}
/* Same as `get_internal_single`, but `r_value` points to initialized memory. */
void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const
{
impl_->type().default_construct(r_value);
this->get_internal_single(r_value);
}
const GVArrayImpl *GVArrayCommon::impl_from_storage() const
{
return storage_.extra_info().get_varray(storage_.get());
}
IndexRange GVArrayCommon::index_range() const
{
return IndexRange(this->size());
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVArray_Slice
/** \name #GVArray
* \{ */
GVArray_Slice::GVArray_Slice(const GVArray &varray, const IndexRange slice)
GVArray::GVArray(const GVArray &other) = default;
GVArray::GVArray(GVArray &&other) noexcept = default;
GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl)
{
if (varray.is_span()) {
/* Create a new virtual for the sliced span. */
const GSpan span = varray.get_internal_span();
const GSpan sliced_span = span.slice(slice.start(), slice.size());
varray_span_.emplace(sliced_span);
varray_ = &*varray_span_;
}
else if (varray.is_single()) {
/* Can just use the existing virtual array, because it's the same value for the indices in the
* slice anyway. */
varray_ = &varray;
}
else {
/* Generic version when none of the above method works.
* We don't necessarily want to materialize the input varray because there might be
* large distances between the required indices. Then we would materialize many elements that
* are not accessed later on.
*/
varray_any_.emplace(varray, slice);
varray_ = &*varray_any_;
}
GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl))
{
}
GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
{
return GVArray::For<GVArrayImpl_For_SingleValue>(type, size, value);
}
GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
{
return GVArray::For<GVArrayImpl_For_SingleValueRef_final>(type, size, value);
}
GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size)
{
return GVArray::ForSingleRef(type, size, type.default_value());
}
GVArray GVArray::ForSpan(GSpan span)
{
return GVArray::For<GVArrayImpl_For_GSpan_final>(span);
}
class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
protected:
GArray<> array_;
public:
GVArrayImpl_For_GArray(GArray<> array)
: GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array))
{
}
};
GVArray GVArray::ForGArray(GArray<> array)
{
return GVArray::For<GVArrayImpl_For_GArray>(array);
}
GVArray GVArray::ForEmpty(const CPPType &type)
{
return GVArray::ForSpan(GSpan(type));
}
GVArray GVArray::slice(IndexRange slice) const
{
return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice);
}
GVArray &GVArray::operator=(const GVArray &other)
{
this->copy_from(other);
return *this;
}
GVArray &GVArray::operator=(GVArray &&other) noexcept
{
this->move_from(std::move(other));
return *this;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #GVMutableArray
* \{ */
GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
GVMutableArray::GVMutableArray(GVMutableArrayImpl *impl) : GVArrayCommon(impl)
{
}
GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
: GVArrayCommon(std::move(impl))
{
}
GVMutableArray GVMutableArray::ForSpan(GMutableSpan span)
{
return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span);
}
GVMutableArray::operator GVArray() const &
{
GVArray varray;
varray.copy_from(*this);
return varray;
}
GVMutableArray::operator GVArray() &&noexcept
{
GVArray varray;
varray.move_from(std::move(*this));
return varray;
}
GVMutableArray &GVMutableArray::operator=(const GVMutableArray &other)
{
this->copy_from(other);
return *this;
}
GVMutableArray &GVMutableArray::operator=(GVMutableArray &&other) noexcept
{
this->move_from(std::move(other));
return *this;
}
GVMutableArrayImpl *GVMutableArray::get_implementation() const
{
return this->get_impl();
}
/* Copy the values from the source buffer to all elements in the virtual array. */
void GVMutableArray::set_all(const void *src)
{
this->get_impl()->set_all(src);
}
GMutableSpan GVMutableArray::get_internal_span() const
{
BLI_assert(this->is_span());
const GSpan span = impl_->get_internal_span();
return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
}
/** \} */

View File

@@ -18,13 +18,13 @@
namespace blender::fn {
void GVArray_For_GVVectorArrayIndex::get_impl(const int64_t index_in_vector, void *r_value) const
void GVArray_For_GVVectorArrayIndex::get(const int64_t index_in_vector, void *r_value) const
{
vector_array_.get_vector_element(index_, index_in_vector, r_value);
}
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t index_in_vector,
void *r_value) const
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in_vector,
void *r_value) const
{
type_->default_construct(r_value);
vector_array_.get_vector_element(index_, index_in_vector, r_value);
@@ -32,14 +32,14 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t ind
int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const
{
return array_.size();
return varray_.size();
}
void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index),
const int64_t index_in_vector,
void *r_value) const
{
array_.get(index_in_vector, r_value);
varray_.get(index_in_vector, r_value);
}
bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const

View File

@@ -54,7 +54,6 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
const IndexRange input_slice_range{input_slice_start, input_slice_size};
MFParamsBuilder sub_params{fn_, sub_mask.min_array_size()};
ResourceScope &scope = sub_params.resource_scope();
/* All parameters are sliced so that the wrapped multi-function does not have to take care of
* the index offset. */
@@ -63,8 +62,7 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
switch (param_type.category()) {
case MFParamType::SingleInput: {
const GVArray &varray = params.readonly_single_input(param_index);
const GVArray &sliced_varray = scope.construct<GVArray_Slice>(varray, input_slice_range);
sub_params.add_readonly_single_input(sliced_varray);
sub_params.add_readonly_single_input(varray.slice(input_slice_range));
break;
}
case MFParamType::SingleMutable: {

View File

@@ -66,6 +66,7 @@ struct VariableValue_GVArray : public VariableValue {
VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data)
{
BLI_assert(data);
}
};
@@ -756,7 +757,7 @@ class VariableState : NonCopyable, NonMovable {
switch (value_->type) {
case ValueType::GVArray: {
const GVArray_Typed<bool> varray{this->value_as<VariableValue_GVArray>()->data};
const VArray<bool> varray = this->value_as<VariableValue_GVArray>()->data.typed<bool>();
for (const int i : mask) {
r_indices[varray[i]].append(i);
}

View File

@@ -34,14 +34,12 @@ class IndexFieldInput final : public FieldInput {
{
}
const GVArray *get_varray_for_context(const FieldContext &UNUSED(context),
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const FieldContext &UNUSED(context),
IndexMask mask,
ResourceScope &UNUSED(scope)) const final
{
auto index_func = [](int i) { return i; };
return &scope.construct<
GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
mask.min_array_size(), mask.min_array_size(), index_func);
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
}
};
@@ -240,20 +238,20 @@ TEST(field, TwoFunctionsTwoOutputs)
FieldContext field_context;
FieldEvaluator field_evaluator{field_context, &mask};
const VArray<int> *result_1 = nullptr;
const VArray<int> *result_2 = nullptr;
VArray<int> result_1;
VArray<int> result_2;
field_evaluator.add(result_field_1, &result_1);
field_evaluator.add(result_field_2, &result_2);
field_evaluator.evaluate();
EXPECT_EQ(result_1->get(2), 4);
EXPECT_EQ(result_1->get(4), 8);
EXPECT_EQ(result_1->get(6), 12);
EXPECT_EQ(result_1->get(8), 16);
EXPECT_EQ(result_2->get(2), 24);
EXPECT_EQ(result_2->get(4), 28);
EXPECT_EQ(result_2->get(6), 32);
EXPECT_EQ(result_2->get(8), 36);
EXPECT_EQ(result_1.get(2), 4);
EXPECT_EQ(result_1.get(4), 8);
EXPECT_EQ(result_1.get(6), 12);
EXPECT_EQ(result_1.get(8), 16);
EXPECT_EQ(result_2.get(2), 24);
EXPECT_EQ(result_2.get(4), 28);
EXPECT_EQ(result_2.get(6), 32);
EXPECT_EQ(result_2.get(8), 36);
}
TEST(field, SameFieldTwice)
@@ -264,16 +262,16 @@ TEST(field, SameFieldTwice)
FieldContext field_context;
IndexMask mask{IndexRange(2)};
ResourceScope scope;
Vector<const GVArray *> results = evaluate_fields(
Vector<GVArray> results = evaluate_fields(
scope, {constant_field, constant_field}, mask, field_context);
GVArray_Typed<int> varray1{*results[0]};
GVArray_Typed<int> varray2{*results[1]};
VArray<int> varray1 = results[0].typed<int>();
VArray<int> varray2 = results[1].typed<int>();
EXPECT_EQ(varray1->get(0), 10);
EXPECT_EQ(varray1->get(1), 10);
EXPECT_EQ(varray2->get(0), 10);
EXPECT_EQ(varray2->get(1), 10);
EXPECT_EQ(varray1.get(0), 10);
EXPECT_EQ(varray1.get(1), 10);
EXPECT_EQ(varray2.get(0), 10);
EXPECT_EQ(varray2.get(1), 10);
}
TEST(field, IgnoredOutput)
@@ -283,12 +281,12 @@ TEST(field, IgnoredOutput)
FieldContext field_context;
FieldEvaluator field_evaluator{field_context, 10};
const VArray<int> *results = nullptr;
VArray<int> results;
field_evaluator.add(field, &results);
field_evaluator.evaluate();
EXPECT_EQ(results->get(0), 5);
EXPECT_EQ(results->get(3), 5);
EXPECT_EQ(results.get(0), 5);
EXPECT_EQ(results.get(3), 5);
}
} // namespace blender::fn::tests

View File

@@ -9,6 +9,43 @@
namespace blender::fn::tests {
TEST(multi_function_procedure, ConstantOutput)
{
/**
* procedure(int *var2) {
* var1 = 5;
* var2 = var1 + var1;
* }
*/
CustomMF_Constant<int> constant_fn{5};
CustomMF_SI_SI_SO<int, int, int> add_fn{"Add", [](int a, int b) { return a + b; }};
MFProcedure procedure;
MFProcedureBuilder builder{procedure};
auto [var1] = builder.add_call<1>(constant_fn);
auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
builder.add_destruct(*var1);
builder.add_return();
builder.add_output_parameter(*var2);
EXPECT_TRUE(procedure.validate());
MFProcedureExecutor executor{"My Procedure", procedure};
MFParamsBuilder params{executor, 2};
MFContextBuilder context;
Array<int> output_array(2);
params.add_uninitialized_single_output(output_array.as_mutable_span());
executor.call(IndexRange(2), params, context);
EXPECT_EQ(output_array[0], 10);
EXPECT_EQ(output_array[1], 10);
}
TEST(multi_function_procedure, SimpleTest)
{
/**

View File

@@ -50,23 +50,23 @@ static void copy_attributes_to_points(CurveEval &curve,
/* Copy builtin control point attributes. */
if (source_attribute_ids.contains("tilt")) {
const fn::GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
"tilt", ATTR_DOMAIN_POINT, 0.0f);
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
for (const int i : range) {
copy_attribute_to_points<float>(
*tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
}
});
source_attribute_ids.remove_contained("tilt");
}
if (source_attribute_ids.contains("radius")) {
const fn::GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
"radius", ATTR_DOMAIN_POINT, 1.0f);
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
for (const int i : range) {
copy_attribute_to_points<float>(
*radius_attribute, point_to_vert_maps[i], splines[i]->radii());
radius_attribute, point_to_vert_maps[i], splines[i]->radii());
}
});
source_attribute_ids.remove_contained("radius");
@@ -82,7 +82,7 @@ static void copy_attributes_to_points(CurveEval &curve,
continue;
}
const fn::GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(
const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read(
attribute_id, ATTR_DOMAIN_POINT);
/* Some attributes might not exist if they were builtin attribute on domains that don't
* have any elements, i.e. a face attribute on the output of the line primitive node. */
@@ -90,7 +90,7 @@ static void copy_attributes_to_points(CurveEval &curve,
continue;
}
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type());
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type());
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
@@ -101,10 +101,10 @@ static void copy_attributes_to_points(CurveEval &curve,
BLI_assert(spline_attribute);
/* Copy attribute based on the map for this spline. */
attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) {
attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
using T = decltype(dummy);
copy_attribute_to_points<T>(
mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
});
}
});

View File

@@ -57,13 +57,8 @@ using fn::GPointer;
using fn::GSpan;
using fn::GVArray;
using fn::GVArray_GSpan;
using fn::GVArray_Span;
using fn::GVArray_Typed;
using fn::GVArrayPtr;
using fn::GVMutableArray;
using fn::GVMutableArray_GSpan;
using fn::GVMutableArray_Typed;
using fn::GVMutableArrayPtr;
using geometry_nodes_eval_log::NodeWarningType;
/**
@@ -316,21 +311,21 @@ class GeoNodeExecParams {
* \note This will add an error message if the string socket is active and
* the input attribute does not exist.
*/
GVArrayPtr get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const CustomDataType type,
const void *default_value) const;
GVArray get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const CustomDataType type,
const void *default_value) const;
template<typename T>
GVArray_Typed<T> get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const T &default_value) const
VArray<T> get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const T &default_value) const
{
const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>());
GVArrayPtr varray = this->get_input_attribute(name, component, domain, type, &default_value);
return GVArray_Typed<T>(std::move(varray));
GVArray varray = this->get_input_attribute(name, component, domain, type, &default_value);
return varray.typed<T>();
}
/**

View File

@@ -21,7 +21,6 @@
namespace blender::nodes {
using fn::CPPType;
using fn::GVArray;
struct ConversionFunctions {
const fn::MultiFunction *multi_function;
@@ -73,9 +72,9 @@ class DataTypeConversions {
const void *from_value,
void *to_value) const;
fn::GVArrayPtr try_convert(fn::GVArrayPtr varray, const CPPType &to_type) const;
fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
fn::GVMutableArrayPtr try_convert(fn::GVMutableArrayPtr varray, const CPPType &to_type) const;
fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
};
const DataTypeConversions &get_implicit_type_conversions();

View File

@@ -179,9 +179,9 @@ static void align_rotations_on_component(GeometryComponent &component,
return;
}
GVArray_Typed<float> factors = params.get_input_attribute<float>(
VArray<float> factors = params.get_input_attribute<float>(
"Factor", component, ATTR_DOMAIN_POINT, 1.0f);
GVArray_Typed<float3> vectors = params.get_input_attribute<float3>(
VArray<float3> vectors = params.get_input_attribute<float3>(
"Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1});
float3 local_main_axis{0, 0, 0};

View File

@@ -156,7 +156,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
const int operation = static_cast<int>(storage.operation);
GVArrayPtr attribute_input = component.attribute_try_get_for_read(
GVArray attribute_input = component.attribute_try_get_for_read(
attribute_name, domain, data_type);
OutputAttribute attribute_result = component.attribute_try_get_for_output_only(
@@ -185,7 +185,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
}
}
MutableSpan<float3> results = attribute_result.as_span<float3>();
clamp_attribute<float3>(attribute_input->typed<float3>(), results, min, max);
clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max);
break;
}
case CD_PROP_FLOAT: {
@@ -193,10 +193,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const float max = params.get_input<float>("Max_001");
MutableSpan<float> results = attribute_result.as_span<float>();
if (operation == NODE_CLAMP_RANGE && min > max) {
clamp_attribute<float>(attribute_input->typed<float>(), results, max, min);
clamp_attribute<float>(attribute_input.typed<float>(), results, max, min);
}
else {
clamp_attribute<float>(attribute_input->typed<float>(), results, min, max);
clamp_attribute<float>(attribute_input.typed<float>(), results, min, max);
}
break;
}
@@ -205,10 +205,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const int max = params.get_input<int>("Max_002");
MutableSpan<int> results = attribute_result.as_span<int>();
if (operation == NODE_CLAMP_RANGE && min > max) {
clamp_attribute<int>(attribute_input->typed<int>(), results, max, min);
clamp_attribute<int>(attribute_input.typed<int>(), results, max, min);
}
else {
clamp_attribute<int>(attribute_input->typed<int>(), results, min, max);
clamp_attribute<int>(attribute_input.typed<int>(), results, min, max);
}
break;
}
@@ -231,7 +231,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
}
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
clamp_attribute<ColorGeometry4f>(
attribute_input->typed<ColorGeometry4f>(), results, min, max);
attribute_input.typed<ColorGeometry4f>(), results, min, max);
break;
}
default: {

View File

@@ -85,7 +85,7 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
return;
}
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
VArray<float> attribute_in = component.attribute_get_for_read<float>(
input_name, result_domain, 0.0f);
MutableSpan<ColorGeometry4f> results = attribute_result.as_span();

View File

@@ -95,11 +95,11 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa
if (!attribute_result) {
return;
}
GVArray_Typed<float> attribute_x = params.get_input_attribute<float>(
VArray<float> attribute_x = params.get_input_attribute<float>(
"X", component, result_domain, 0.0f);
GVArray_Typed<float> attribute_y = params.get_input_attribute<float>(
VArray<float> attribute_y = params.get_input_attribute<float>(
"Y", component, result_domain, 0.0f);
GVArray_Typed<float> attribute_z = params.get_input_attribute<float>(
VArray<float> attribute_z = params.get_input_attribute<float>(
"Z", component, result_domain, 0.0f);
for (const int i : IndexRange(attribute_result->size())) {

View File

@@ -257,9 +257,9 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
const CustomDataType input_data_type = get_data_type(component, params, *node_storage);
GVArrayPtr attribute_a = params.get_input_attribute(
GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, input_data_type, nullptr);
GVArrayPtr attribute_b = params.get_input_attribute(
GVArray attribute_b = params.get_input_attribute(
"B", component, result_domain, input_data_type, nullptr);
if (!attribute_a || !attribute_b) {
@@ -276,47 +276,47 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
if (operation == NODE_FLOAT_COMPARE_EQUAL) {
if (input_data_type == CD_PROP_FLOAT) {
do_equal_operation_float(
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_FLOAT3) {
do_equal_operation_float3(
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_COLOR) {
do_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
attribute_b->typed<ColorGeometry4f>(),
do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
attribute_b.typed<ColorGeometry4f>(),
threshold,
result_span);
}
else if (input_data_type == CD_PROP_BOOL) {
do_equal_operation_bool(
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
}
}
else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) {
if (input_data_type == CD_PROP_FLOAT) {
do_not_equal_operation_float(
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_FLOAT3) {
do_not_equal_operation_float3(
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_COLOR) {
do_not_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
attribute_b->typed<ColorGeometry4f>(),
do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
attribute_b.typed<ColorGeometry4f>(),
threshold,
result_span);
}
else if (input_data_type == CD_PROP_BOOL) {
do_not_equal_operation_bool(
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
}
}
}
else {
do_math_operation(
attribute_a->typed<float>(), attribute_b->typed<float>(), operation, result_span);
attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span);
}
attribute_result.save();

View File

@@ -104,7 +104,7 @@ static void attribute_convert_calc(GeometryComponent &component,
return;
}
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
GVArray source_attribute = component.attribute_try_get_for_read(
source_name, result_domain, result_type);
if (!source_attribute) {
params.error_message_add(NodeWarningType::Error,
@@ -118,7 +118,7 @@ static void attribute_convert_calc(GeometryComponent &component,
return;
}
GVArray_GSpan source_span{*source_attribute};
GVArray_GSpan source_span{source_attribute};
GMutableSpan result_span = result_attribute.as_span();
BLI_assert(source_span.size() == result_span.size());

View File

@@ -136,10 +136,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
switch (result_type) {
case CD_PROP_FLOAT: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
VArray<float> attribute_in = component.attribute_get_for_read<float>(
input_name, result_domain, float(0.0f));
MutableSpan<float> results = attribute_result.as_span<float>();
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]);
}
@@ -148,10 +148,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
case CD_PROP_FLOAT3: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
GVArray_Typed<float3> attribute_in = component.attribute_get_for_read<float3>(
VArray<float3> attribute_in = component.attribute_get_for_read<float3>(
input_name, result_domain, float3(0.0f));
MutableSpan<float3> results = attribute_result.as_span<float3>();
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]);
}
@@ -160,11 +160,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
case CD_PROP_COLOR: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb;
GVArray_Typed<ColorGeometry4f> attribute_in =
component.attribute_get_for_read<ColorGeometry4f>(
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>(
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]);
}

View File

@@ -362,7 +362,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
const AttributeDomain domain = get_result_domain(component, input_name, result_name);
GVArrayPtr attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
if (!attribute_input) {
params.error_message_add(NodeWarningType::Error,
@@ -381,12 +381,12 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
switch (data_type) {
case CD_PROP_FLOAT: {
map_range_float(attribute_input->typed<float>(), attribute_result.as_span<float>(), params);
map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params);
break;
}
case CD_PROP_FLOAT3: {
map_range_float3(
attribute_input->typed<float3>(), attribute_result.as_span<float3>(), params);
attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params);
break;
}
default:

View File

@@ -250,7 +250,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
return;
}
GVArray_Typed<float> attribute_a = params.get_input_attribute<float>(
VArray<float> attribute_a = params.get_input_attribute<float>(
"A", component, result_domain, 0.0f);
MutableSpan<float> result_span = attribute_result.as_span();
@@ -258,10 +258,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
/* Note that passing the data with `get_internal_span<float>()` works
* because the attributes were accessed with #CD_PROP_FLOAT. */
if (operation_use_input_b(operation)) {
GVArray_Typed<float> attribute_b = params.get_input_attribute<float>(
VArray<float> attribute_b = params.get_input_attribute<float>(
"B", component, result_domain, 0.0f);
if (operation_use_input_c(operation)) {
GVArray_Typed<float> attribute_c = params.get_input_attribute<float>(
VArray<float> attribute_c = params.get_input_attribute<float>(
"C", component, result_domain, 0.0f);
do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation);
}

View File

@@ -144,25 +144,28 @@ static void do_mix_operation(const CustomDataType result_type,
GVMutableArray &attribute_result)
{
if (result_type == CD_PROP_FLOAT) {
VMutableArray<float> result = attribute_result.typed<float>();
do_mix_operation_float(blend_mode,
attribute_factor,
attribute_a.typed<float>(),
attribute_b.typed<float>(),
attribute_result.typed<float>());
result);
}
else if (result_type == CD_PROP_FLOAT3) {
VMutableArray<float3> result = attribute_result.typed<float3>();
do_mix_operation_float3(blend_mode,
attribute_factor,
attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
attribute_result.typed<float3>());
result);
}
else if (result_type == CD_PROP_COLOR) {
VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>();
do_mix_operation_color4f(blend_mode,
attribute_factor,
attribute_a.typed<ColorGeometry4f>(),
attribute_b.typed<ColorGeometry4f>(),
attribute_result.typed<ColorGeometry4f>());
result);
}
}
@@ -203,19 +206,19 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
return;
}
GVArray_Typed<float> attribute_factor = params.get_input_attribute<float>(
VArray<float> attribute_factor = params.get_input_attribute<float>(
"Factor", component, result_domain, 0.5f);
GVArrayPtr attribute_a = params.get_input_attribute(
GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, result_type, nullptr);
GVArrayPtr attribute_b = params.get_input_attribute(
GVArray attribute_b = params.get_input_attribute(
"B", component, result_domain, result_type, nullptr);
do_mix_operation(result_type,
node_storage->blend_type,
attribute_factor,
*attribute_a,
*attribute_b,
*attribute_result);
attribute_a,
attribute_b,
attribute_result.varray());
attribute_result.save();
}

View File

@@ -153,7 +153,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
if (!position_attribute || (!distance_attribute && !location_attribute)) {
return;
}
GVArray_Typed<float3> positions{*position_attribute.varray};
VArray<float3> positions = position_attribute.varray.typed<float3>();
const NodeGeometryAttributeProximity &storage =
*(const NodeGeometryAttributeProximity *)params.node().storage;

View File

@@ -180,13 +180,13 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo
const int domain_size = component.attribute_domain_size(domain);
/* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
GVArrayPtr hash_attribute = component.attribute_try_get_for_read("id", domain);
GVArray hash_attribute = component.attribute_try_get_for_read("id", domain);
Array<uint32_t> hashes(domain_size);
if (hash_attribute) {
BLI_assert(hashes.size() == hash_attribute->size());
const CPPType &cpp_type = hash_attribute->type();
BLI_assert(hashes.size() == hash_attribute.size());
const CPPType &cpp_type = hash_attribute.type();
BLI_assert(cpp_type.is_hashable());
GVArray_GSpan items{*hash_attribute};
GVArray_GSpan items{hash_attribute};
threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
hashes[i] = cpp_type.hash(items[i]);

View File

@@ -82,7 +82,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec
return;
}
GVArray_Typed<float3> mapping_attribute = component.attribute_get_for_read<float3>(
VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>(
mapping_name, result_domain, {0, 0, 0});
MutableSpan<ColorGeometry4f> colors = attribute_out.as_span();

View File

@@ -106,9 +106,9 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa
const AttributeDomain result_domain = get_result_domain(
component, params, result_name_x, result_name_y, result_name_z);
GVArray_Typed<float3> attribute_input = params.get_input_attribute<float3>(
VArray<float3> attribute_input = params.get_input_attribute<float3>(
"Vector", component, result_domain, {0, 0, 0});
VArray_Span<float3> input_span{*attribute_input};
VArray_Span<float3> input_span{attribute_input};
OutputAttribute_Typed<float> attribute_result_x =
component.attribute_try_get_for_output_only<float>(result_name_x, result_domain);

View File

@@ -407,13 +407,13 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) {
/* Point-cloud point is closer. */
const int index = pointcloud_indices[i];
pointcloud_src_attribute.varray->get(index, buffer);
pointcloud_src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
else {
/* Mesh element is closer. */
const int index = mesh_indices[i];
mesh_src_attribute.varray->get(index, buffer);
mesh_src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -424,7 +424,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
src_name, data_type);
for (const int i : IndexRange(tot_samples)) {
const int index = pointcloud_indices[i];
src_attribute.varray->get(index, buffer);
src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -434,7 +434,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
data_type);
for (const int i : IndexRange(tot_samples)) {
const int index = mesh_indices[i];
src_attribute.varray->get(index, buffer);
src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -460,7 +460,7 @@ static void transfer_attribute(const GeoNodeExecParams &params,
const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain :
input_domain;
GVArray_Typed<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
"position", dst_domain, {0, 0, 0});
switch (mapping) {

View File

@@ -187,7 +187,7 @@ static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNod
static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
VMutableArray<float3> &result,
const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -218,7 +218,7 @@ static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
const VArray<float3> &input_c,
VMutableArray<float3> &result,
const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -251,7 +251,7 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
const VArray<float> &input_c,
VMutableArray<float3> &result,
const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -283,7 +283,7 @@ static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
const VArray<float3> &input_b,
VMutableArray<float> &result,
const VMutableArray<float> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -313,7 +313,7 @@ static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
const VArray<float> &input_b,
VMutableArray<float3> &result,
const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -342,7 +342,7 @@ static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
}
static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
VMutableArray<float3> &result,
const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -369,7 +369,7 @@ static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
}
static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a,
VMutableArray<float> &result,
const VMutableArray<float> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -437,13 +437,13 @@ static void attribute_vector_math_calc(GeometryComponent &component,
const AttributeDomain result_domain = get_result_domain(
component, params, operation, result_name);
GVArrayPtr attribute_a = params.get_input_attribute(
GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, read_type_a, nullptr);
if (!attribute_a) {
return;
}
GVArrayPtr attribute_b;
GVArrayPtr attribute_c;
GVArray attribute_b;
GVArray attribute_c;
if (use_input_b) {
attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr);
if (!attribute_b) {
@@ -476,26 +476,26 @@ static void attribute_vector_math_calc(GeometryComponent &component,
case NODE_VECTOR_MATH_MODULO:
case NODE_VECTOR_MATH_MINIMUM:
case NODE_VECTOR_MATH_MAXIMUM:
do_math_operation_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
attribute_b->typed<float3>(),
attribute_result->typed<float3>(),
do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_DOT_PRODUCT:
case NODE_VECTOR_MATH_DISTANCE:
do_math_operation_fl3_fl3_to_fl(attribute_a->typed<float3>(),
attribute_b->typed<float3>(),
attribute_result->typed<float>(),
do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
attribute_result.varray().typed<float>(),
operation);
break;
case NODE_VECTOR_MATH_LENGTH:
do_math_operation_fl3_to_fl(
attribute_a->typed<float3>(), attribute_result->typed<float>(), operation);
attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation);
break;
case NODE_VECTOR_MATH_SCALE:
do_math_operation_fl3_fl_to_fl3(attribute_a->typed<float3>(),
attribute_b->typed<float>(),
attribute_result->typed<float3>(),
do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(),
attribute_b.typed<float>(),
attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_NORMALIZE:
@@ -507,22 +507,22 @@ static void attribute_vector_math_calc(GeometryComponent &component,
case NODE_VECTOR_MATH_COSINE:
case NODE_VECTOR_MATH_TANGENT:
do_math_operation_fl3_to_fl3(
attribute_a->typed<float3>(), attribute_result->typed<float3>(), operation);
attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation);
break;
case NODE_VECTOR_MATH_WRAP:
case NODE_VECTOR_MATH_FACEFORWARD:
case NODE_VECTOR_MATH_MULTIPLY_ADD:
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
attribute_b->typed<float3>(),
attribute_c->typed<float3>(),
attribute_result->typed<float3>(),
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
attribute_c.typed<float3>(),
attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_REFRACT:
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a->typed<float3>(),
attribute_b->typed<float3>(),
attribute_c->typed<float>(),
attribute_result->typed<float3>(),
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
attribute_c.typed<float>(),
attribute_result.varray().typed<float3>(),
operation);
break;
}

View File

@@ -220,12 +220,12 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
const AttributeDomain result_domain = get_result_domain(component, params, result_name);
const bool invert = params.get_input<bool>("Invert");
GVArrayPtr attribute_vector = params.get_input_attribute(
GVArray attribute_vector = params.get_input_attribute(
"Vector", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_vector) {
return;
}
GVArrayPtr attribute_center = params.get_input_attribute(
GVArray attribute_center = params.get_input_attribute(
"Center", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_center) {
return;
@@ -238,21 +238,21 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
GVArrayPtr attribute_rotation = params.get_input_attribute(
GVArray attribute_rotation = params.get_input_attribute(
"Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_rotation) {
return;
}
do_vector_rotate_euler(attribute_vector->typed<float3>(),
attribute_center->typed<float3>(),
attribute_rotation->typed<float3>(),
do_vector_rotate_euler(attribute_vector.typed<float3>(),
attribute_center.typed<float3>(),
attribute_rotation.typed<float3>(),
attribute_result.as_span<float3>(),
invert);
attribute_result.save();
return;
}
GVArrayPtr attribute_angle = params.get_input_attribute(
GVArray attribute_angle = params.get_input_attribute(
"Angle", component, result_domain, CD_PROP_FLOAT, nullptr);
if (!attribute_angle) {
return;
@@ -260,40 +260,40 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
switch (mode) {
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: {
GVArrayPtr attribute_axis = params.get_input_attribute(
GVArray attribute_axis = params.get_input_attribute(
"Axis", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_axis) {
return;
}
do_vector_rotate_around_axis(attribute_vector->typed<float3>(),
attribute_center->typed<float3>(),
attribute_axis->typed<float3>(),
attribute_angle->typed<float>(),
do_vector_rotate_around_axis(attribute_vector.typed<float3>(),
attribute_center.typed<float3>(),
attribute_axis.typed<float3>(),
attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
} break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X:
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
attribute_center->typed<float3>(),
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
attribute_center.typed<float3>(),
float3(1.0f, 0.0f, 0.0f),
attribute_angle->typed<float>(),
attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
attribute_center->typed<float3>(),
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
attribute_center.typed<float3>(),
float3(0.0f, 1.0f, 0.0f),
attribute_angle->typed<float>(),
attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
attribute_center->typed<float3>(),
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
attribute_center.typed<float3>(),
float3(0.0f, 0.0f, 1.0f),
attribute_angle->typed<float>(),
attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);

View File

@@ -61,7 +61,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
GVArray spline_attribute = curve_component.attribute_get_for_read(
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
@@ -70,7 +70,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
/* Only copy the attributes of splines in the offsets. */
for (const int i : offsets.index_range()) {
spline_attribute->get(offsets[i], result[i]);
spline_attribute.get(offsets[i], result[i]);
}
result_attribute.save();
@@ -130,7 +130,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]);
spline_span.type().copy_assign(spline_span[0], point_span[i]);
}
for (const auto item : end_data.point_attributes.items()) {
@@ -139,7 +139,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]);
spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]);
}
}
});

View File

@@ -44,7 +44,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
MutableSpan<SplinePtr> splines = curve.splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
VArray<bool> selection = curve_component.attribute_get_for_read(
selection_name, ATTR_DOMAIN_CURVE, true);
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {

View File

@@ -84,7 +84,7 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
MutableSpan<SplinePtr> splines = curve.splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
VArray<bool> selection = curve_component.attribute_get_for_read(
selection_name, ATTR_DOMAIN_POINT, true);
const BezierSpline::HandleType new_handle_type = handle_type_from_input_type(type);

View File

@@ -255,7 +255,7 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
const CurveEval &curve = *curve_component->get_for_read();
const std::string selection_name = params.extract_input<std::string>("Selection");
GVArray_Typed<bool> selection = curve_component->attribute_get_for_read(
VArray<bool> selection = curve_component->attribute_get_for_read(
selection_name, ATTR_DOMAIN_CURVE, true);
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();

View File

@@ -25,10 +25,6 @@
#include "node_geometry_util.hh"
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray_For_Span;
using blender::fn::GVArray_Typed;
namespace blender::nodes {
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
@@ -363,14 +359,13 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
}
const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
GVArray_Typed<int> cuts = params.get_input_attribute<int>(
"Cuts", component, ATTR_DOMAIN_POINT, 0);
if (cuts->is_single() && cuts->get_internal_single() < 1) {
VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0);
if (cuts.is_single() && cuts.get_internal_single() < 1) {
params.set_output("Geometry", geometry_set);
return;
}
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), *cuts);
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
}

View File

@@ -121,7 +121,7 @@ static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &poin
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
BLI_assert(attribute);
return attribute.varray->get_internal_span();
return attribute.varray.get_internal_span();
}
template<typename T>
@@ -177,8 +177,8 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
const int size = offsets[i + 1] - offsets[i];
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size));
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size));
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
const AttributeIDRef attribute_id = item.key;
@@ -188,7 +188,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
spline.interpolate_to_evaluated(spline_span)
->materialize(point_span.slice(offset, size).data());
.materialize(point_span.slice(offset, size).data());
}
data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents());
@@ -230,7 +230,7 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
uniform_samples,
point_span.slice(offset, size));
}
@@ -263,20 +263,20 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
GVArray spline_attribute = curve_component.attribute_get_for_read(
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
const CPPType &type = spline_attribute->type();
const CPPType &type = spline_attribute.type();
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type);
GMutableSpan result = result_attribute.as_span();
for (const int i : IndexRange(spline_attribute->size())) {
for (const int i : spline_attribute.index_range()) {
const int offset = offsets[i];
const int size = offsets[i + 1] - offsets[i];
if (size != 0) {
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
spline_attribute->get(i, buffer);
spline_attribute.get(i, buffer);
type.fill_assign_n(buffer, result[offset], size);
}
}

View File

@@ -137,7 +137,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
Vector<int64_t> copied_splines;
if (input_curve.attributes.get_for_read(name)) {
GVArray_Typed<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
for (const int i : input_splines.index_range()) {
if (selection[i] == invert) {
output_curve->add_spline(input_splines[i]->copy());
@@ -151,7 +151,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
for (const int i : input_splines.index_range()) {
const Spline &spline = *input_splines[i];
GVArray_Typed<bool> selection = spline.attributes.get_for_read<bool>(name, false);
VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false);
indices_to_copy.clear();
for (const int i_point : IndexRange(spline.size())) {
@@ -202,7 +202,7 @@ static void delete_point_cloud_selection(const PointCloudComponent &in_component
const StringRef selection_name,
const bool invert)
{
const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
selection_name, ATTR_DOMAIN_POINT, false);
VArray_Span<bool> selection{selection_attribute};
@@ -590,7 +590,7 @@ static void delete_mesh_selection(MeshComponent &component,
const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name);
/* This already checks if the attribute exists, and displays a warning in that case. */
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
VArray<bool> selection = component.attribute_get_for_read<bool>(
selection_name, selection_domain, false);
/* Check if there is anything to delete. */

View File

@@ -72,7 +72,7 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
Mesh *mesh = mesh_component.get_for_write();
if (mesh != nullptr) {
GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
mask_name, ATTR_DOMAIN_FACE, true);
assign_material_to_faces(*mesh, face_mask, material);
}

View File

@@ -44,7 +44,7 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
params.error_message_add(NodeWarningType::Error,
TIP_("No attribute with name \"") + selection_name + "\"");
}
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
VArray<bool> selection = component.attribute_get_for_read<bool>(
selection_name, ATTR_DOMAIN_EDGE, true);
Vector<int64_t> selected_edge_indices;

View File

@@ -106,9 +106,9 @@ static void sample_mesh_surface(const Mesh &mesh,
float looptri_density_factor = 1.0f;
if (density_factors != nullptr) {
const float v0_density_factor = std::max(0.0f, density_factors->get(v0_loop));
const float v1_density_factor = std::max(0.0f, density_factors->get(v1_loop));
const float v2_density_factor = std::max(0.0f, density_factors->get(v2_loop));
const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]);
const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]);
const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]);
looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
}
const float area = area_tri_v3(v0_pos, v1_pos, v2_pos);
@@ -315,7 +315,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
}
const AttributeDomain source_domain = attribute_info->domain;
GVArrayPtr source_attribute = source_component.attribute_get_for_read(
GVArray source_attribute = source_component.attribute_get_for_read(
attribute_id, source_domain, output_data_type, nullptr);
if (!source_attribute) {
i_instance += set_group.transforms.size();
@@ -329,7 +329,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
GMutableSpan instance_span = out_span.slice(offset, bary_coords.size());
interpolate_attribute(
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span);
mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span);
i_instance++;
}
@@ -337,7 +337,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Span<T> source_span{*source_attribute};
VArray_Span source_span{source_attribute.typed<T>()};
});
}
@@ -445,7 +445,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
VArray<float> density_factors = component.attribute_get_for_read<float>(
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
const Mesh &mesh = *component.get_for_read();
for (const float4x4 &transform : set_group.transforms) {
@@ -455,7 +455,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
sample_mesh_surface(mesh,
transform,
density,
&*density_factors,
&density_factors,
seed,
positions,
bary_coords,
@@ -514,7 +514,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group
const GeometrySet &set = set_group.geometry_set;
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
const Mesh &mesh = *component.get_for_read();
const GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
const VArray<float> density_factors = component.attribute_get_for_read<float>(
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {

View File

@@ -171,13 +171,12 @@ static void add_instances_from_component(InstancesComponent &instances,
const int domain_size = src_geometry.attribute_domain_size(domain);
GVArray_Typed<float3> positions = src_geometry.attribute_get_for_read<float3>(
VArray<float3> positions = src_geometry.attribute_get_for_read<float3>(
"position", domain, {0, 0, 0});
GVArray_Typed<float3> rotations = src_geometry.attribute_get_for_read<float3>(
VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>(
"rotation", domain, {0, 0, 0});
GVArray_Typed<float3> scales = src_geometry.attribute_get_for_read<float3>(
"scale", domain, {1, 1, 1});
GVArray_Typed<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1});
VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
/* The initial size of the component might be non-zero if there are two component types. */
const int start_len = instances.instances_amount();

View File

@@ -169,9 +169,9 @@ static void point_rotate_on_component(GeometryComponent &component,
const int domain_size = rotations.size();
if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) {
GVArray_Typed<float3> axis = params.get_input_attribute<float3>(
VArray<float3> axis = params.get_input_attribute<float3>(
"Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1});
GVArray_Typed<float> angles = params.get_input_attribute<float>(
VArray<float> angles = params.get_input_attribute<float>(
"Angle", component, ATTR_DOMAIN_POINT, 0);
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
@@ -182,7 +182,7 @@ static void point_rotate_on_component(GeometryComponent &component,
}
}
else {
GVArray_Typed<float3> eulers = params.get_input_attribute<float3>(
VArray<float3> eulers = params.get_input_attribute<float3>(
"Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {

View File

@@ -78,7 +78,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT :
CD_PROP_FLOAT3;
GVArrayPtr attribute = params.get_input_attribute(
GVArray attribute = params.get_input_attribute(
"Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr);
if (!attribute) {
return;
@@ -86,13 +86,13 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
MutableSpan<float3> scale_span = scale_attribute.as_span();
if (data_type == CD_PROP_FLOAT) {
GVArray_Typed<float> factors{*attribute};
VArray<float> factors = attribute.typed<float>();
for (const int i : scale_span.index_range()) {
scale_span[i] = scale_span[i] * factors[i];
}
}
else if (data_type == CD_PROP_FLOAT3) {
GVArray_Typed<float3> factors{*attribute};
VArray<float3> factors = attribute.typed<float3>();
for (const int i : scale_span.index_range()) {
scale_span[i] = scale_span[i] * factors[i];
}

View File

@@ -55,7 +55,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
{
for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) {
ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id);
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
/* Only copy point attributes. Theoretically this could interpolate attributes on other
* domains to the point domain, but that would conflict with attributes that are built-in
@@ -69,7 +69,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Span<T> span{*attribute.varray};
VArray_Span span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
copy_data_based_on_mask(span, masks, invert, out_span);
});
@@ -103,7 +103,7 @@ static void separate_points_from_component(const GeometryComponent &in_component
return;
}
const GVArray_Typed<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
mask_name, ATTR_DOMAIN_POINT, false);
VArray_Span<bool> masks{mask_attribute};

View File

@@ -43,10 +43,10 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
if (!position_attribute) {
return;
}
GVArray_Typed<float3> attribute = params.get_input_attribute<float3>(
VArray<float3> attribute = params.get_input_attribute<float3>(
"Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
for (const int i : IndexRange(attribute.size())) {
for (const int i : attribute.index_range()) {
position_attribute->set(i, position_attribute->get(i) + attribute[i]);
}

View File

@@ -172,12 +172,12 @@ static void gather_point_data_from_component(const GeoNodeExecParams &params,
Vector<float3> &r_positions,
Vector<float> &r_radii)
{
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
GVArray_Typed<float> radii = params.get_input_attribute<float>(
VArray<float> radii = params.get_input_attribute<float>(
"Radius", component, ATTR_DOMAIN_POINT, 0.0f);
for (const int i : IndexRange(positions.size())) {
for (const int i : positions.index_range()) {
r_positions.append(positions[i]);
r_radii.append(radii[i]);
}

View File

@@ -197,11 +197,11 @@ static void raycast_from_points(const GeoNodeExecParams &params,
(GeometryNodeRaycastMapMode)storage.mapping);
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
"position", result_domain, {0, 0, 0});
GVArray_Typed<float3> ray_directions = params.get_input_attribute<float3>(
VArray<float3> ray_directions = params.get_input_attribute<float3>(
"Ray Direction", dst_component, result_domain, {0, 0, 0});
GVArray_Typed<float> ray_lengths = params.get_input_attribute<float>(
VArray<float> ray_lengths = params.get_input_attribute<float>(
"Ray Length", dst_component, result_domain, 0);
OutputAttribute_Typed<bool> hit_attribute =
@@ -218,10 +218,10 @@ static void raycast_from_points(const GeoNodeExecParams &params,
Array<int> hit_indices;
Array<float3> hit_positions_internal;
if (!hit_attribute_names.is_empty()) {
hit_indices.reinitialize(ray_origins->size());
hit_indices.reinitialize(ray_origins.size());
if (!hit_position_attribute) {
hit_positions_internal.reinitialize(ray_origins->size());
hit_positions_internal.reinitialize(ray_origins.size());
}
}
const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>();

View File

@@ -169,10 +169,10 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
span_count++;
const PointCloudComponent *component =
geometry_set.get_component_for_read<PointCloudComponent>();
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
total_size += varray->size();
positions_span = varray->get_internal_span();
total_size += varray.size();
positions_span = varray.get_internal_span();
}
if (geometry_set.has_curve()) {
@@ -200,18 +200,18 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
if (geometry_set.has_mesh()) {
const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>();
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}
if (geometry_set.has_pointcloud()) {
const PointCloudComponent *component =
geometry_set.get_component_for_read<PointCloudComponent>();
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}
@@ -235,16 +235,16 @@ static void read_positions(const GeometryComponent &component,
Span<float4x4> transforms,
Vector<float3> *r_coords)
{
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
/* NOTE: could use convex hull operation here to
* cut out some vertices, before accumulating,
* but can also be done by the user beforehand. */
r_coords->reserve(r_coords->size() + positions.size() * transforms.size());
r_coords->reserve(r_coords->size() + positions->size() * transforms.size());
for (const float4x4 &transform : transforms) {
for (const int i : positions.index_range()) {
for (const int i : positions->index_range()) {
const float3 position = positions[i];
const float3 transformed_position = transform * position;
r_coords->append(transformed_position);

View File

@@ -64,9 +64,9 @@ class EndpointFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -111,9 +111,9 @@ class EndpointFieldInput final : public fn::FieldInput {
}
current_point += spline->size();
}
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
return VArray<bool>::ForContainer(std::move(selection));
}
return nullptr;
return {};
};
uint64_t hash() const override

View File

@@ -59,10 +59,10 @@ struct FilletParam {
GeometryNodeCurveFilletMode mode;
/* Number of points to be added. */
const VArray<int> *counts;
VArray<int> counts;
/* Radii for fillet arc at all vertices. */
const VArray<float> *radii;
VArray<float> radii;
/* Whether or not fillets are allowed to overlap. */
bool limit_radius;
@@ -160,7 +160,7 @@ static Array<int> calculate_counts(const FilletParam &fillet_param,
Array<int> counts(size, 1);
if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
for (const int i : IndexRange(size)) {
counts[i] = (*fillet_param.counts)[spline_offset + i];
counts[i] = fillet_param.counts[spline_offset + i];
}
}
if (!cyclic) {
@@ -178,12 +178,12 @@ static Array<float> calculate_radii(const FilletParam &fillet_param,
Array<float> radii(size, 0.0f);
if (fillet_param.limit_radius) {
for (const int i : IndexRange(size)) {
radii[i] = std::max((*fillet_param.radii)[spline_offset + i], 0.0f);
radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f);
}
}
else {
for (const int i : IndexRange(size)) {
radii[i] = (*fillet_param.radii)[spline_offset + i];
radii[i] = fillet_param.radii[spline_offset + i];
}
}
@@ -590,13 +590,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
field_evaluator.evaluate();
fillet_param.radii = &field_evaluator.get_evaluated<float>(0);
if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) {
fillet_param.radii = field_evaluator.get_evaluated<float>(0);
if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) {
return;
}
if (mode == GEO_NODE_CURVE_FILLET_POLY) {
fillet_param.counts = &field_evaluator.get_evaluated<int>(1);
fillet_param.counts = field_evaluator.get_evaluated<int>(1);
}
fillet_param.limit_radius = limit_radius;

View File

@@ -96,9 +96,9 @@ class HandleTypeFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -106,22 +106,22 @@ class HandleTypeFieldInput final : public fn::FieldInput {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
return nullptr;
return {};
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve == nullptr) {
return nullptr;
return {};
}
if (domain == ATTR_DOMAIN_POINT) {
Array<bool> selection(mask.min_array_size());
select_by_handle_type(*curve, type_, mode_, selection);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
return VArray<bool>::ForContainer(std::move(selection));
}
}
return nullptr;
return {};
};
uint64_t hash() const override

View File

@@ -130,22 +130,22 @@ static Array<float> curve_parameter_point_domain(const CurveEval &curve)
return parameters;
}
static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
const IndexMask mask,
const AttributeDomain domain,
ResourceScope &scope)
static GVArray construct_curve_parameter_gvarray(const CurveEval &curve,
const IndexMask mask,
const AttributeDomain domain,
ResourceScope &UNUSED(scope))
{
if (domain == ATTR_DOMAIN_POINT) {
Array<float> parameters = curve_parameter_point_domain(curve);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
return VArray<float>::ForContainer(std::move(parameters));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float> parameters = curve_parameter_spline_domain(curve, mask);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
return VArray<float>::ForContainer(std::move(parameters));
}
return nullptr;
return {};
}
class CurveParameterFieldInput final : public fn::FieldInput {
@@ -155,9 +155,9 @@ class CurveParameterFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -173,7 +173,7 @@ class CurveParameterFieldInput final : public fn::FieldInput {
}
}
}
return nullptr;
return {};
}
uint64_t hash() const override

View File

@@ -26,10 +26,6 @@
#include "node_geometry_util.hh"
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray_For_Span;
using blender::fn::GVArray_Typed;
namespace blender::nodes {
static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b)
@@ -122,7 +118,7 @@ static SplinePtr resample_spline(const Spline &src, const int count)
std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write(
attribute_id);
if (output_attribute) {
src.sample_with_index_factors(*src.interpolate_to_evaluated(*input_attribute),
src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute),
uniform_samples,
*output_attribute);
return true;
@@ -145,8 +141,8 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
dst->positions().copy_from(src.evaluated_positions());
dst->positions().copy_from(src.evaluated_positions());
src.interpolate_to_evaluated(src.radii())->materialize(dst->radii());
src.interpolate_to_evaluated(src.tilts())->materialize(dst->tilts());
src.interpolate_to_evaluated(src.radii()).materialize(dst->radii());
src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts());
src.attributes.foreach_attribute(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
@@ -154,7 +150,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
if (dst->attributes.create(attribute_id, meta_data.data_type)) {
std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id);
if (dst_attribute) {
src.interpolate_to_evaluated(*src_attribute)->materialize(dst_attribute->data());
src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data());
return true;
}
}

View File

@@ -25,10 +25,6 @@
#include "node_geometry_util.hh"
using blender::fn::GVArray_For_GSpan;
using blender::fn::GVArray_For_Span;
using blender::fn::GVArray_Typed;
namespace blender::nodes {
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)

View File

@@ -113,7 +113,7 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points,
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
BLI_assert(attribute);
return attribute.varray->get_internal_span();
return attribute.varray.get_internal_span();
}
template<typename T>
@@ -194,7 +194,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
const int size = offsets[i + 1] - offsets[i];
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
const AttributeIDRef attribute_id = item.key;
@@ -203,7 +203,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
spline.interpolate_to_evaluated(spline_span)->materialize(dst.slice(offset, size).data());
spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data());
}
if (!data.tangents.is_empty()) {
@@ -233,7 +233,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
spline.sample_with_index_factors<float3>(
spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size));
spline.sample_with_index_factors<float>(*spline.interpolate_to_evaluated(spline.radii()),
spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()),
uniform_samples,
data.radii.slice(offset, size));
@@ -244,7 +244,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
uniform_samples,
dst.slice(offset, size));
}

View File

@@ -216,9 +216,9 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
using T = decltype(dummy);
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
linear_trim_to_output_data<T>(
start, end, eval_data->get_internal_span(), dst->typed<T>());
start, end, eval_data.get_internal_span(), dst->typed<T>());
});
return true;
},
@@ -227,13 +227,13 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
linear_trim_to_output_data<float3>(
start, end, spline.evaluated_positions(), new_spline.positions());
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
linear_trim_to_output_data<float>(
start, end, evaluated_radii->get_internal_span(), new_spline.radii());
start, end, evaluated_radii.get_internal_span(), new_spline.radii());
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
linear_trim_to_output_data<float>(
start, end, evaluated_tilts->get_internal_span(), new_spline.tilts());
start, end, evaluated_tilts.get_internal_span(), new_spline.tilts());
return new_spline;
}
@@ -427,8 +427,8 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id);
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
using T = decltype(dummy);
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
to_single_point_data<T>(trim, eval_data->get_internal_span(), dst->typed<T>());
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
to_single_point_data<T>(trim, eval_data.get_internal_span(), dst->typed<T>());
});
return true;
},
@@ -436,11 +436,11 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
to_single_point_data<float3>(trim, spline.evaluated_positions(), new_spline.positions());
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
to_single_point_data<float>(trim, evaluated_radii->get_internal_span(), new_spline.radii());
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
to_single_point_data<float>(trim, evaluated_radii.get_internal_span(), new_spline.radii());
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
to_single_point_data<float>(trim, evaluated_tilts->get_internal_span(), new_spline.tilts());
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
to_single_point_data<float>(trim, evaluated_tilts.get_internal_span(), new_spline.tilts());
return new_spline;
}

View File

@@ -138,7 +138,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
if (!domains.contains(attribute.domain)) {
continue;
}
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
attribute_id, attribute.domain, data_type);
@@ -149,7 +149,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Span<T> span{*attribute.varray};
VArray_Span<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
out_span.copy_from(span);
});
@@ -178,7 +178,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
if (domain != attribute.domain) {
continue;
}
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
attribute_id, attribute.domain, data_type);
@@ -189,7 +189,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Span<T> span{*attribute.varray};
VArray_Span<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
copy_data(span, out_span, mask);
});

View File

@@ -311,14 +311,14 @@ BLI_NOINLINE static void propagate_existing_attributes(
}
const AttributeDomain source_domain = attribute_info->domain;
GVArrayPtr source_attribute = mesh_component.attribute_get_for_read(
GVArray source_attribute = mesh_component.attribute_get_for_read(
attribute_id, source_domain, output_data_type, nullptr);
if (!source_attribute) {
continue;
}
interpolate_attribute(
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, out_span);
mesh, bary_coords, looptri_indices, source_domain, source_attribute, out_span);
attribute_out.save();
}

View File

@@ -31,19 +31,18 @@ static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Normal")).field_source();
}
static GVArrayPtr mesh_face_normals(const Mesh &mesh,
const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
const IndexMask mask)
static VArray<float3> mesh_face_normals(const Mesh &mesh,
const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
const IndexMask mask)
{
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
CustomData_has_layer(&mesh.pdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
return std::make_unique<fn::GVArray_For_Span<float3>>(
Span<float3>((const float3 *)data, polys.size()));
return VArray<float3>::ForSpan({(const float3 *)data, polys.size()});
}
auto normal_fn = [verts, polys, loops](const int i) -> float3 {
@@ -53,24 +52,21 @@ static GVArrayPtr mesh_face_normals(const Mesh &mesh,
return normal;
};
return std::make_unique<
fn::GVArray_For_EmbeddedVArray<float3, VArray_For_Func<float3, decltype(normal_fn)>>>(
mask.min_array_size(), mask.min_array_size(), normal_fn);
return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn);
}
static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
const IndexMask mask)
static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
const IndexMask mask)
{
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) &&
CustomData_has_layer(&mesh.vdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
return std::make_unique<fn::GVArray_For_Span<float3>>(
Span<float3>((const float3 *)data, mesh.totvert));
return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert});
}
/* If the normals are dirty, they must be recalculated for the output of this node's field
@@ -91,14 +87,14 @@ static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
nullptr,
(float(*)[3])normals.data());
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
return VArray<float3>::ForContainer(std::move(normals));
}
static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
const Mesh &mesh,
const IndexMask mask,
const AttributeDomain domain,
ResourceScope &scope)
ResourceScope &UNUSED(scope))
{
Span<MVert> verts{mesh.mvert, mesh.totvert};
Span<MEdge> edges{mesh.medge, mesh.totedge};
@@ -107,18 +103,18 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
switch (domain) {
case ATTR_DOMAIN_FACE: {
return scope.add_value(mesh_face_normals(mesh, verts, polys, loops, mask)).get();
return mesh_face_normals(mesh, verts, polys, loops, mask);
}
case ATTR_DOMAIN_POINT: {
return scope.add_value(mesh_vertex_normals(mesh, verts, polys, loops, mask)).get();
return mesh_vertex_normals(mesh, verts, polys, loops, mask);
}
case ATTR_DOMAIN_EDGE: {
/* In this case, start with vertex normals and convert to the edge domain, since the
* conversion from edges to vertices is very simple. Use the full mask since the edges
* might use the vertex normal from any index. */
GVArrayPtr vert_normals = mesh_vertex_normals(
GVArray vert_normals = mesh_vertex_normals(
mesh, verts, polys, loops, IndexRange(verts.size()));
Span<float3> vert_normals_span = vert_normals->get_internal_span().typed<float3>();
Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>();
Array<float3> edge_normals(mask.min_array_size());
/* Use "manual" domain interpolation instead of the GeometryComponent API to avoid
@@ -130,23 +126,21 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
.normalized();
}
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(
std::move(edge_normals));
return VArray<float3>::ForContainer(std::move(edge_normals));
}
case ATTR_DOMAIN_CORNER: {
/* The normals on corners are just the mesh's face normals, so start with the face normal
* array and copy the face normal for each of its corners. */
GVArrayPtr face_normals = mesh_face_normals(
VArray<float3> face_normals = mesh_face_normals(
mesh, verts, polys, loops, IndexRange(polys.size()));
/* In this case using the mesh component's generic domain interpolation is fine, the data
* will still be normalized, since the face normal is just copied to every corner. */
GVArrayPtr loop_normals = mesh_component.attribute_try_adapt_domain(
return mesh_component.attribute_try_adapt_domain<float3>(
std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
return scope.add_value(std::move(loop_normals)).get();
}
default:
return nullptr;
return {};
}
}
@@ -204,9 +198,9 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
return normals;
}
static const GVArray *construct_curve_normal_gvarray(const CurveComponent &component,
static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component,
const AttributeDomain domain,
ResourceScope &scope)
ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
@@ -220,20 +214,18 @@ static const GVArray *construct_curve_normal_gvarray(const CurveComponent &compo
* This is only possible when there is only one poly spline. */
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_normals());
return VArray<float3>::ForSpan(spline.evaluated_normals());
}
Array<float3> normals = curve_normal_point_domain(*curve);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
return VArray<float3>::ForContainer(std::move(normals));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float3> point_normals = curve_normal_point_domain(*curve);
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
std::move(point_normals));
GVArrayPtr spline_normals = component.attribute_try_adapt_domain(
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
return scope.add_value(std::move(spline_normals)).get();
VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
return component.attribute_try_adapt_domain<float3>(
std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
}
return nullptr;
@@ -246,9 +238,9 @@ class NormalFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -260,7 +252,7 @@ class NormalFieldInput final : public fn::FieldInput {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return nullptr;
return {};
}
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope);
@@ -270,7 +262,7 @@ class NormalFieldInput final : public fn::FieldInput {
return construct_curve_normal_gvarray(curve_component, domain, scope);
}
}
return nullptr;
return {};
}
uint64_t hash() const override

View File

@@ -25,31 +25,25 @@ static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Float>(N_("Length")).field_source();
}
static const GVArray *construct_spline_length_gvarray(const CurveComponent &component,
const AttributeDomain domain,
ResourceScope &scope)
static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
const AttributeDomain domain,
ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
return nullptr;
return {};
}
Span<SplinePtr> splines = curve->splines();
auto length_fn = [splines](int i) { return splines[i]->length(); };
if (domain == ATTR_DOMAIN_CURVE) {
return &scope.construct<
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
splines.size(), splines.size(), length_fn);
return VArray<float>::ForFunc(splines.size(), length_fn);
}
if (domain == ATTR_DOMAIN_POINT) {
GVArrayPtr length = std::make_unique<
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
splines.size(), splines.size(), length_fn);
return scope
.add_value(component.attribute_try_adapt_domain(
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT))
.get();
VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn);
return component.attribute_try_adapt_domain<float>(
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
}
return nullptr;
@@ -62,9 +56,9 @@ class SplineLengthFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -76,7 +70,7 @@ class SplineLengthFieldInput final : public fn::FieldInput {
return construct_spline_length_gvarray(curve_component, domain, scope);
}
}
return nullptr;
return {};
}
uint64_t hash() const override

View File

@@ -84,9 +84,9 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
return tangents;
}
static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &component,
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
const AttributeDomain domain,
ResourceScope &scope)
ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
@@ -100,20 +100,19 @@ static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &comp
* This is only possible when there is only one poly spline. */
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_tangents());
return VArray<float3>::ForSpan(spline.evaluated_tangents());
}
Array<float3> tangents = curve_tangent_point_domain(*curve);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(tangents));
return VArray<float3>::ForContainer(std::move(tangents));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float3> point_tangents = curve_tangent_point_domain(*curve);
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
std::move(point_tangents));
GVArrayPtr spline_tangents = component.attribute_try_adapt_domain(
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
return scope.add_value(std::move(spline_tangents)).get();
return component.attribute_try_adapt_domain<float3>(
VArray<float3>::ForContainer(std::move(point_tangents)),
ATTR_DOMAIN_POINT,
ATTR_DOMAIN_CURVE);
}
return nullptr;
@@ -126,9 +125,9 @@ class TangentFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -141,7 +140,7 @@ class TangentFieldInput final : public fn::FieldInput {
return construct_curve_tangent_gvarray(curve_component, domain, scope);
}
}
return nullptr;
return {};
}
uint64_t hash() const override

View File

@@ -80,10 +80,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
select_len);
FieldEvaluator field_evaluator{field_context, domain_size};
const VArray<bool> *pick_instance = nullptr;
const VArray<int> *indices = nullptr;
const VArray<float3> *rotations = nullptr;
const VArray<float3> *scales = nullptr;
VArray<bool> pick_instance;
VArray<int> indices;
VArray<float3> rotations;
VArray<float3> scales;
/* The evaluator could use the component's stable IDs as a destination directly, but only the
* selected indices should be copied. */
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
@@ -92,7 +92,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
field_evaluator.evaluate();
GVArray_Typed<float3> positions = src_component.attribute_get_for_read<float3>(
VArray<float3> positions = src_component.attribute_get_for_read<float3>(
"position", domain, {0, 0, 0});
const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>();
@@ -101,7 +101,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
Array<int> handle_mapping;
/* Only fill #handle_mapping when it may be used below. */
if (src_instances != nullptr &&
(!pick_instance->is_single() || pick_instance->get_internal_single())) {
(!pick_instance.is_single() || pick_instance.get_internal_single())) {
Span<InstanceReference> src_references = src_instances->references();
handle_mapping.reinitialize(src_references.size());
for (const int src_instance_handle : src_references.index_range()) {
@@ -121,17 +121,16 @@ static void add_instances_from_component(InstancesComponent &dst_component,
/* Compute base transform for every instances. */
float4x4 &dst_transform = dst_transforms[range_i];
dst_transform = float4x4::from_loc_eul_scale(
positions[i], rotations->get(i), scales->get(i));
dst_transform = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
/* Reference that will be used by this new instance. */
int dst_handle = empty_reference_handle;
const bool use_individual_instance = pick_instance->get(i);
const bool use_individual_instance = pick_instance[i];
if (use_individual_instance) {
if (src_instances != nullptr) {
const int src_instances_amount = src_instances->instances_amount();
const int original_index = indices->get(i);
const int original_index = indices[i];
/* Use #mod_i instead of `%` to get the desirable wrap around behavior where -1
* refers to the last element. */
const int index = mod_i(original_index, std::max(src_instances_amount, 1));
@@ -155,10 +154,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
});
GVArrayPtr id_attribute = src_component.attribute_try_get_for_read(
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
if (id_attribute) {
GVArray_Typed<int> ids{*id_attribute};
VArray<int> ids = src_component
.attribute_try_get_for_read("id", ATTR_DOMAIN_POINT, CD_PROP_INT32)
.typed<int>();
if (ids) {
VArray_Span<int> ids_span{ids};
MutableSpan<int> dst_ids = dst_component.instance_ids_ensure();
for (const int64_t i : selection.index_range()) {
@@ -166,8 +165,8 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
}
if (pick_instance->is_single()) {
if (pick_instance->get_internal_single()) {
if (pick_instance.is_single()) {
if (pick_instance.get_internal_single()) {
if (instance.has_realized_data()) {
params.error_message_add(
NodeWarningType::Info,

View File

@@ -27,8 +27,6 @@
#include "node_geometry_util.hh"
using blender::fn::GVArray_For_GSpan;
namespace blender::nodes {
static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
@@ -190,10 +188,10 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
if (domain_size == 0) {
continue;
}
GVArrayPtr read_attribute = component->attribute_get_for_read(
GVArray read_attribute = component->attribute_get_for_read(
attribute_id, domain, data_type, nullptr);
GVArray_GSpan src_span{*read_attribute};
GVArray_GSpan src_span{read_attribute};
const void *src_buffer = src_span.data();
void *dst_buffer = dst_span[offset];
cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size);
@@ -319,8 +317,7 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
spline->size() * type.size(), type.alignment(), __func__);
const DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions();
conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type)
->materialize(converted_buffer);
conversions.try_convert(GVArray::ForSpan(*attribute), type).materialize(converted_buffer);
spline->attributes.remove(attribute_id);
spline->attributes.create_by_move(attribute_id, data_type, converted_buffer);
@@ -333,14 +330,14 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
/* In this case the attribute did not exist, but there is a spline domain attribute
* we can retrieve a value from, as a spline to point domain conversion. So fill the
* new attribute with the value for this spline. */
GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read(
GVArray current_curve_attribute = current_curve->attributes.get_for_read(
attribute_id, data_type, nullptr);
BLI_assert(spline->attributes.get_for_read(attribute_id));
std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id);
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
current_curve_attribute->get(spline_index_in_component, buffer);
current_curve_attribute.get(spline_index_in_component, buffer);
type.fill_assign_n(buffer, new_attribute->data(), new_attribute->size());
}
}
@@ -376,8 +373,8 @@ static void ensure_spline_attribute(const AttributeIDRef &attribute_id,
if (size == 0) {
continue;
}
GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
GVArray_GSpan src_span{*read_attribute};
GVArray read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
GVArray_GSpan src_span{read_attribute};
const void *src_buffer = src_span.data();
type.copy_assign_n(src_buffer, result_attribute[offset], size);

View File

@@ -64,36 +64,33 @@ class MaterialSelectionFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_MESH) {
return nullptr;
return {};
}
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return nullptr;
return {};
}
if (domain == ATTR_DOMAIN_FACE) {
Array<bool> selection(mask.min_array_size());
select_mesh_by_material(*mesh, material_, mask, selection);
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
return VArray<bool>::ForContainer(std::move(selection));
}
Array<bool> selection(mesh->totpoly);
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>(
std::move(selection));
GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain(
std::move(face_selection), ATTR_DOMAIN_FACE, domain);
return scope.add_value(std::move(final_selection)).get();
return mesh_component.attribute_try_adapt_domain<bool>(
VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
}
return nullptr;

View File

@@ -113,14 +113,14 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const CustomDataType data_type = entry.value.data_type;
GVArrayPtr src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
OutputAttribute dst = point_component.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Typed<T> src_typed{*src};
copy_attribute_to_points(*src_typed, selection, dst.as_span().typed<T>());
VArray<T> src_typed = src.typed<T>();
copy_attribute_to_points(src_typed, selection, dst.as_span().typed<T>());
});
dst.save();
}

View File

@@ -74,15 +74,15 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set,
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const CustomDataType data_type = entry.value.data_type;
GVArrayPtr src = point_component->attribute_get_for_read(
GVArray src = point_component->attribute_get_for_read(
attribute_id, ATTR_DOMAIN_POINT, data_type);
OutputAttribute dst = mesh_component.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
GVArray_Typed<T> src_typed{*src};
VArray_Span<T> src_typed_span{*src_typed};
VArray<T> src_typed = src.typed<T>();
VArray_Span<T> src_typed_span{src_typed};
copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>());
});
dst.save();

View File

@@ -165,7 +165,7 @@ static void gather_point_data_from_component(GeoNodeExecParams &params,
Vector<float3> &r_positions,
Vector<float> &r_radii)
{
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
Field<float> radius_field = params.get_input<Field<float>>("Radius");
@@ -173,7 +173,7 @@ static void gather_point_data_from_component(GeoNodeExecParams &params,
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
r_positions.resize(r_positions.size() + domain_size);
positions->materialize(r_positions.as_mutable_span().take_back(domain_size));
positions.materialize(r_positions.as_mutable_span().take_back(domain_size));
r_radii.resize(r_radii.size() + domain_size);
fn::FieldEvaluator evaluator{field_context, domain_size};

View File

@@ -540,10 +540,10 @@ class NearestTransferFunction : public fn::MultiFunction {
attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) {
using T = decltype(dummy);
if (use_mesh_ && use_points_) {
GVArray_Typed<T> src_mesh{*mesh_data_};
GVArray_Typed<T> src_point{*point_data_};
copy_with_indices_and_comparison(*src_mesh,
*src_point,
VArray<T> src_mesh = mesh_data_->typed<T>();
VArray<T> src_point = point_data_->typed<T>();
copy_with_indices_and_comparison(src_mesh,
src_point,
mesh_distances,
point_distances,
mask,
@@ -552,12 +552,12 @@ class NearestTransferFunction : public fn::MultiFunction {
dst.typed<T>());
}
else if (use_points_) {
GVArray_Typed<T> src_point{*point_data_};
copy_with_indices(*src_point, mask, point_indices, dst.typed<T>());
VArray<T> src_point = point_data_->typed<T>();
copy_with_indices(src_point, mask, point_indices, dst.typed<T>());
}
else if (use_mesh_) {
GVArray_Typed<T> src_mesh{*mesh_data_};
copy_with_indices(*src_mesh, mask, mesh_indices, dst.typed<T>());
VArray<T> src_mesh = mesh_data_->typed<T>();
copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>());
}
});
}
@@ -640,14 +640,14 @@ class IndexTransferFieldInput : public FieldInput {
category_ = Category::Generated;
}
const GVArray *get_varray_for_context(const FieldContext &context,
const IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const FieldContext &context,
const IndexMask mask,
ResourceScope &UNUSED(scope)) const final
{
const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context);
if (geometry_context == nullptr) {
return nullptr;
return {};
}
FieldEvaluator index_evaluator{*geometry_context, &mask};
@@ -661,7 +661,7 @@ class IndexTransferFieldInput : public FieldInput {
const GeometryComponent *component = find_best_match_component(
src_geometry_, geometry_context->geometry_component().type(), domain_);
if (component == nullptr) {
return nullptr;
return {};
}
GeometryComponentFieldContext target_context{*component, domain_};
@@ -676,11 +676,11 @@ class IndexTransferFieldInput : public FieldInput {
attribute_math::convert_to_static_type(src_data.type(), [&](auto dummy) {
using T = decltype(dummy);
GVArray_Typed<T> src{src_data};
copy_with_indices_clamped(*src, mask, indices, dst.as_mutable_span().typed<T>());
copy_with_indices_clamped(
src_data.typed<T>(), mask, indices, dst.as_mutable_span().typed<T>());
});
return &scope.construct<fn::GVArray_For_GArray>(std::move(dst));
return GVArray::ForGArray(std::move(dst));
}
};

View File

@@ -113,11 +113,11 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name
return nullptr;
}
GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const CustomDataType type,
const void *default_value) const
GVArray GeoNodeExecParams::get_input_attribute(const StringRef name,
const GeometryComponent &component,
const AttributeDomain domain,
const CustomDataType type,
const void *default_value) const
{
const bNodeSocket *found_socket = this->find_available_socket(name);
BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */
@@ -129,13 +129,13 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
}
if (found_socket == nullptr) {
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
if (found_socket->type == SOCK_STRING) {
const std::string name = this->get_input<std::string>(found_socket->identifier);
/* Try getting the attribute without the default value. */
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, type);
GVArray attribute = component.attribute_try_get_for_read(name, domain, type);
if (attribute) {
return attribute;
}
@@ -147,36 +147,36 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
this->error_message_add(NodeWarningType::Error,
TIP_("No attribute with name \"") + name + "\"");
}
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
const DataTypeConversions &conversions = get_implicit_type_conversions();
if (found_socket->type == SOCK_FLOAT) {
const float value = this->get_input<float>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<float>(), *cpp_type, &value, buffer);
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_INT) {
const int value = this->get_input<int>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<int>(), *cpp_type, &value, buffer);
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_VECTOR) {
const float3 value = this->get_input<float3>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<float3>(), *cpp_type, &value, buffer);
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_RGBA) {
const ColorGeometry4f value = this->get_input<ColorGeometry4f>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(
CPPType::get<ColorGeometry4f>(), *cpp_type, &value, buffer);
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
BLI_assert(false);
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
CustomDataType GeoNodeExecParams::get_input_attribute_data_type(

View File

@@ -24,9 +24,6 @@
namespace blender::nodes {
using fn::GVArrayPtr;
using fn::GVMutableArray;
using fn::GVMutableArrayPtr;
using fn::MFDataType;
template<typename From, typename To, To (*ConversionF)(const From &)>
@@ -242,107 +239,108 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
functions->convert_single_to_uninitialized(from_value, to_value);
}
class GVArray_For_ConvertedGVArray : public GVArray {
class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl {
private:
GVArrayPtr varray_;
fn::GVArray varray_;
const CPPType &from_type_;
ConversionFunctions old_to_new_conversions_;
public:
GVArray_For_ConvertedGVArray(GVArrayPtr varray,
GVArray_For_ConvertedGVArray(fn::GVArray varray,
const CPPType &to_type,
const DataTypeConversions &conversions)
: GVArray(to_type, varray->size()), varray_(std::move(varray)), from_type_(varray_->type())
: fn::GVArrayImpl(to_type, varray.size()),
varray_(std::move(varray)),
from_type_(varray_.type())
{
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
}
private:
void get_impl(const int64_t index, void *r_value) const override
void get(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
varray_->get(index, buffer);
varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
from_type_.destruct(buffer);
}
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
void get_to_uninitialized(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
varray_->get(index, buffer);
varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
from_type_.destruct(buffer);
}
};
class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArray {
class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl {
private:
GVMutableArrayPtr varray_;
fn::GVMutableArray varray_;
const CPPType &from_type_;
ConversionFunctions old_to_new_conversions_;
ConversionFunctions new_to_old_conversions_;
public:
GVMutableArray_For_ConvertedGVMutableArray(GVMutableArrayPtr varray,
GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray,
const CPPType &to_type,
const DataTypeConversions &conversions)
: GVMutableArray(to_type, varray->size()),
: fn::GVMutableArrayImpl(to_type, varray.size()),
varray_(std::move(varray)),
from_type_(varray_->type())
from_type_(varray_.type())
{
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
new_to_old_conversions_ = *conversions.get_conversion_functions(to_type, from_type_);
}
private:
void get_impl(const int64_t index, void *r_value) const override
void get(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
varray_->get(index, buffer);
varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
from_type_.destruct(buffer);
}
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
void get_to_uninitialized(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
varray_->get(index, buffer);
varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
from_type_.destruct(buffer);
}
void set_by_move_impl(const int64_t index, void *value) override
void set_by_move(const int64_t index, void *value) override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
new_to_old_conversions_.convert_single_to_uninitialized(value, buffer);
varray_->set_by_relocate(index, buffer);
varray_.set_by_relocate(index, buffer);
}
};
fn::GVArrayPtr DataTypeConversions::try_convert(fn::GVArrayPtr varray,
const CPPType &to_type) const
fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const
{
const CPPType &from_type = varray->type();
const CPPType &from_type = varray.type();
if (from_type == to_type) {
return varray;
}
if (!this->is_convertible(from_type, to_type)) {
return {};
}
return std::make_unique<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
}
fn::GVMutableArrayPtr DataTypeConversions::try_convert(fn::GVMutableArrayPtr varray,
const CPPType &to_type) const
fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray,
const CPPType &to_type) const
{
const CPPType &from_type = varray->type();
const CPPType &from_type = varray.type();
if (from_type == to_type) {
return varray;
}
if (!this->is_convertible(from_type, to_type)) {
return {};
}
return std::make_unique<GVMutableArray_For_ConvertedGVMutableArray>(
return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>(
std::move(varray), to_type, *this);
}

View File

@@ -199,28 +199,28 @@ class MusgraveFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
auto get_vector = [&](int param_index) -> const VArray<float3> & {
auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
auto get_w = [&](int param_index) -> const VArray<float> & {
auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
auto get_scale = [&](int param_index) -> const VArray<float> & {
auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
auto get_detail = [&](int param_index) -> const VArray<float> & {
auto get_detail = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Detail");
};
auto get_dimension = [&](int param_index) -> const VArray<float> & {
auto get_dimension = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Dimension");
};
auto get_lacunarity = [&](int param_index) -> const VArray<float> & {
auto get_lacunarity = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Lacunarity");
};
auto get_offset = [&](int param_index) -> const VArray<float> & {
auto get_offset = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Offset");
};
auto get_gain = [&](int param_index) -> const VArray<float> & {
auto get_gain = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Gain");
};

View File

@@ -220,22 +220,22 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
auto get_vector = [&](int param_index) -> const VArray<float3> & {
auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
auto get_w = [&](int param_index) -> const VArray<float> & {
auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
auto get_scale = [&](int param_index) -> const VArray<float> & {
auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
auto get_smoothness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Smoothness");
};
auto get_exponent = [&](int param_index) -> const VArray<float> & {
auto get_exponent = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Exponent");
};
auto get_randomness = [&](int param_index) -> const VArray<float> & {
auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
@@ -651,19 +651,19 @@ class VoronoiMetricFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
auto get_vector = [&](int param_index) -> const VArray<float3> & {
auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
auto get_w = [&](int param_index) -> const VArray<float> & {
auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
auto get_scale = [&](int param_index) -> const VArray<float> & {
auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
auto get_smoothness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Smoothness");
};
auto get_randomness = [&](int param_index) -> const VArray<float> & {
auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
@@ -1153,16 +1153,16 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
auto get_vector = [&](int param_index) -> const VArray<float3> & {
auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
auto get_w = [&](int param_index) -> const VArray<float> & {
auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
auto get_scale = [&](int param_index) -> const VArray<float> & {
auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
auto get_randomness = [&](int param_index) -> const VArray<float> & {
auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {