Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh43
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc18
-rw-r--r--source/blender/blenkernel/intern/customdata.c4
-rw-r--r--source/blender/functions/FN_field.hh123
-rw-r--r--source/blender/functions/intern/field.cc11
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh1
6 files changed, 139 insertions, 61 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 45e8ab92e41..da758669659 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -35,6 +35,8 @@
#include "BKE_attribute_access.hh"
#include "BKE_geometry_set.h"
+#include "FN_field.hh"
+
struct Collection;
struct Curve;
struct CurveEval;
@@ -581,3 +583,44 @@ class VolumeComponent : public GeometryComponent {
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
};
+
+namespace blender::bke {
+
+class GeometryComponentFieldContext : public fn::FieldContext {
+ private:
+ const GeometryComponent &component_;
+ const AttributeDomain domain_;
+
+ public:
+ GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain)
+ : component_(component), domain_(domain)
+ {
+ }
+
+ const GeometryComponent &geometry_component() const
+ {
+ return component_;
+ }
+
+ AttributeDomain domain() const
+ {
+ return domain_;
+ }
+};
+
+class AttributeContextFieldSource : public fn::ContextFieldSource {
+ private:
+ std::string name_;
+
+ public:
+ AttributeContextFieldSource(std::string name, const CPPType &type)
+ : fn::ContextFieldSource(type, name), name_(std::move(name))
+ {
+ }
+
+ const GVArray *try_get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
+};
+
+} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 941bfebcc60..bf3756b7bcf 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -1300,3 +1300,21 @@ blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_on
{
return create_output_attribute(*this, attribute_id, domain, data_type, true, nullptr);
}
+
+namespace blender::bke {
+
+const GVArray *AttributeContextFieldSource::try_get_varray_for_context(
+ const fn::FieldContext &context, IndexMask UNUSED(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 CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+ GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
+ return scope.add(std::move(attribute), __func__);
+ }
+ return nullptr;
+}
+
+} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index a86d0a608d6..311039bac24 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2848,7 +2848,7 @@ void *CustomData_duplicate_referenced_layer_named(CustomData *data,
}
void *CustomData_duplicate_referenced_layer_anonymous(CustomData *data,
- const int type,
+ const int UNUSED(type),
const AnonymousAttributeID *anonymous_id,
const int totelem)
{
@@ -3564,7 +3564,6 @@ bool CustomData_bmesh_merge(const CustomData *source,
BMesh *bm,
const char htype)
{
-
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
return false;
}
@@ -4813,7 +4812,6 @@ static void copy_bit_flag(void *dst, const void *src, const size_t data_size, co
*((_type *)(_dst)) |= _val; \
} \
(void)0
-
switch (data_size) {
case 1:
COPY_BIT_FLAG(uint8_t, dst, src, flag);
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 76ffb0225ab..744345fd339 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -185,9 +185,15 @@ class OperationFieldSource : public FieldSource {
}
};
+class ContextFieldSource;
+
class FieldContext {
public:
~FieldContext() = default;
+
+ virtual const GVArray *try_get_varray_for_context(const ContextFieldSource &context_source,
+ IndexMask mask,
+ ResourceScope &scope) const;
};
class ContextFieldSource : public FieldSource {
@@ -218,6 +224,7 @@ class ContextFieldSource : public FieldSource {
const CPPType &cpp_type_of_output_index(int output_index) const override
{
BLI_assert(output_index == 0);
+ UNUSED_VARS_NDEBUG(output_index);
return *type_;
}
@@ -255,39 +262,20 @@ template<typename T> Field<T> make_constant_field(T value)
return Field<T>{GField{std::move(operation), 0}};
}
-class FieldEvaluator;
-
-class GFieldOutputHandle {
- protected:
- FieldEvaluator *evaluator_;
- int field_index_;
-
- public:
- GFieldOutputHandle(FieldEvaluator &evaluator, int field_index)
- : evaluator_(&evaluator), field_index_(field_index)
- {
- }
-
- const GVArray &get();
-};
-
-template<typename T> class FieldOutputHandle : GFieldOutputHandle {
- public:
- explicit FieldOutputHandle(const GFieldOutputHandle &other) : GFieldOutputHandle(other)
- {
- }
-
- const VArray<T> &get();
-};
-
class FieldEvaluator : NonMovable, NonCopyable {
private:
+ struct OutputPointerInfo {
+ void *dst = nullptr;
+ void (*set)(void *dst, const GVArray &varray, ResourceScope &scope) = nullptr;
+ };
+
ResourceScope scope_;
const FieldContext &context_;
const IndexMask mask_;
Vector<GField> fields_to_evaluate_;
Vector<GVMutableArray *> dst_hints_;
Vector<const GVArray *> evaluated_varrays_;
+ Vector<OutputPointerInfo> output_pointer_infos_;
bool is_evaluated_ = false;
public:
@@ -297,24 +285,56 @@ class FieldEvaluator : NonMovable, NonCopyable {
{
}
- GFieldOutputHandle add(GField field, GVMutableArray *dst_hint = nullptr)
+ /**
+ * \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)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
- dst_hints_.append(dst_hint);
- return GFieldOutputHandle(*this, field_index);
+ dst_hints_.append(&dst);
+ output_pointer_infos_.append({});
+ return field_index;
}
- template<typename T>
- FieldOutputHandle<T> add(Field<T> field, VMutableArray<T> *dst_hint = nullptr)
+ /** Same as above but typed. */
+ template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
{
- GVMutableArray *generic_dst_hint = nullptr;
- if (dst_hint != nullptr) {
- generic_dst_hint = &scope_.construct<GVMutableArray_For_VMutableArray<T>>(__func__,
- *dst_hint);
- }
- return FieldOutputHandle<T>(this->add(GField(std::move(field)), generic_dst_hint));
+ GVMutableArray &generic_dst_hint = scope_.construct<GVMutableArray_For_VMutableArray<T>>(
+ __func__, dst);
+ return this->add_with_destination(GField(std::move(field)), generic_dst_hint);
}
+ /**
+ * \param field: Field to add to the evaluator.
+ * \param varray_ptr: Once #evaluate is called, the resulting virtual array will be will be
+ * assigned to the given position.
+ */
+ template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
+ {
+ const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
+ dst_hints_.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>>(__func__, varray);
+ }});
+ return field_index;
+ }
+
+ /**
+ * \return Index of the field in the evaluator. Can be used in the #get_evaluated methods.
+ */
+ int add(GField field)
+ {
+ const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
+ dst_hints_.append(nullptr);
+ output_pointer_infos_.append({});
+ return field_index;
+ }
+
+ /**
+ * Evaluate all fields on the evaluator. This can only be called once.
+ */
void evaluate()
{
BLI_assert_msg(!is_evaluated_, "Cannot evaluate twice.");
@@ -323,39 +343,28 @@ class FieldEvaluator : NonMovable, NonCopyable {
fields[i] = &fields_to_evaluate_[i];
}
evaluated_varrays_ = evaluate_fields(scope_, fields, mask_, context_, dst_hints_);
+ BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size());
+ 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_);
+ }
+ }
is_evaluated_ = true;
}
- const GVArray &get(const int field_index) const
+ const GVArray &get_evaluated(const int field_index) const
{
BLI_assert(is_evaluated_);
return *evaluated_varrays_[field_index];
}
- template<typename T> const VArray<T> &get(const int field_index)
+ template<typename T> const VArray<T> &get_evaluated(const int field_index)
{
- const GVArray &varray = this->get(field_index);
+ const GVArray &varray = this->get_evaluated(field_index);
GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(__func__, varray);
return *typed_varray;
}
};
-/* --------------------------------------------------------------------
- * GFieldOutputHandle inline methods.
- */
-
-inline const GVArray &GFieldOutputHandle::get()
-{
- return evaluator_->get(field_index_);
-}
-
-/* --------------------------------------------------------------------
- * FieldOutputHandle inline methods.
- */
-
-template<typename T> inline const VArray<T> &FieldOutputHandle<T>::get()
-{
- return evaluator_->get<T>(field_index_);
-}
-
} // namespace blender::fn
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 4a95bc5ef3f..6d8fce07f5a 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -93,7 +93,7 @@ static Vector<const GVArray *> get_field_context_inputs(ResourceScope &scope,
{
Vector<const GVArray *> field_context_inputs;
for (const ContextFieldSource &context_source : graph_info.deduplicated_context_sources) {
- const GVArray *varray = context_source.try_get_varray_for_context(context, mask, scope);
+ const GVArray *varray = context.try_get_varray_for_context(context_source, mask, scope);
if (varray == nullptr) {
const CPPType &type = context_source.cpp_type();
varray = &scope.construct<GVArray_For_SingleValueRef>(
@@ -420,4 +420,13 @@ void evaluate_fields_to_spans(Span<const GField *> fields_to_evaluate,
evaluate_fields(scope, fields_to_evaluate, mask, context, varrays);
}
+const GVArray *FieldContext::try_get_varray_for_context(const ContextFieldSource &context_source,
+ IndexMask mask,
+ ResourceScope &scope) const
+{
+ /* By default ask the context source to create the varray. Another field context might overwrite
+ * the context here. */
+ return context_source.try_get_varray_for_context(*this, mask, scope);
+}
+
} // namespace blender::fn
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index 7519cc80572..04307019aec 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -35,6 +35,7 @@ namespace blender::nodes {
using bke::AttributeIDRef;
using bke::geometry_set_realize_instances;
+using bke::GeometryComponentFieldContext;
using bke::OutputAttribute;
using bke::OutputAttribute_Typed;
using bke::ReadAttributeLookup;