[Bf-blender-cvs] [7cb4665beeb] temp-geometry-nodes-fields: new FieldEvaluator utility class
Jacques Lucke
noreply at git.blender.org
Wed Sep 1 18:01:56 CEST 2021
Commit: 7cb4665beeb72b83999950dad3978a3be8994795
Author: Jacques Lucke
Date: Wed Sep 1 18:01:48 2021 +0200
Branches: temp-geometry-nodes-fields
https://developer.blender.org/rB7cb4665beeb72b83999950dad3978a3be8994795
new FieldEvaluator utility class
===================================================================
M source/blender/functions/FN_field.hh
M source/blender/functions/intern/field.cc
M source/blender/functions/tests/FN_field_test.cc
===================================================================
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 0cf83e25d0b..76ffb0225ab 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -128,6 +128,11 @@ template<typename T> class Field : public GField {
{
BLI_assert(this->cpp_type().template is<T>());
}
+
+ Field(std::shared_ptr<FieldSource> source, const int source_output_index = 0)
+ : Field(GField(std::move(source), source_output_index))
+ {
+ }
};
class OperationFieldSource : public FieldSource {
@@ -225,14 +230,14 @@ class ContextFieldSource : public FieldSource {
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Span<const GField *> fields_to_evaluate,
IndexMask mask,
- FieldContext &context,
+ const FieldContext &context,
Span<GVMutableArray *> dst_hints = {});
void evaluate_constant_field(const GField &field, void *r_value);
void evaluate_fields_to_spans(Span<const GField *> fields_to_evaluate,
IndexMask mask,
- FieldContext &context,
+ const FieldContext &context,
Span<GMutableSpan> out_spans);
template<typename T> T evaluate_constant_field(const Field<T> &field)
@@ -250,4 +255,107 @@ 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:
+ ResourceScope scope_;
+ const FieldContext &context_;
+ const IndexMask mask_;
+ Vector<GField> fields_to_evaluate_;
+ Vector<GVMutableArray *> dst_hints_;
+ Vector<const GVArray *> evaluated_varrays_;
+ bool is_evaluated_ = false;
+
+ public:
+ /** Takes #mask by pointer because the mask has to live longer than the evaluator. */
+ FieldEvaluator(const FieldContext &context, const IndexMask *mask)
+ : context_(context), mask_(*mask)
+ {
+ }
+
+ GFieldOutputHandle add(GField field, GVMutableArray *dst_hint = nullptr)
+ {
+ const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
+ dst_hints_.append(dst_hint);
+ return GFieldOutputHandle(*this, field_index);
+ }
+
+ template<typename T>
+ FieldOutputHandle<T> add(Field<T> field, VMutableArray<T> *dst_hint = nullptr)
+ {
+ 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));
+ }
+
+ void evaluate()
+ {
+ BLI_assert_msg(!is_evaluated_, "Cannot evaluate twice.");
+ Array<const GField *> fields(fields_to_evaluate_.size());
+ for (const int i : fields_to_evaluate_.index_range()) {
+ fields[i] = &fields_to_evaluate_[i];
+ }
+ evaluated_varrays_ = evaluate_fields(scope_, fields, mask_, context_, dst_hints_);
+ is_evaluated_ = true;
+ }
+
+ const GVArray &get(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)
+ {
+ const GVArray &varray = this->get(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 24d6ab0477f..24a5bc907a8 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -88,7 +88,7 @@ static FieldGraphInfo preprocess_field_graph(Span<const GField *> entry_fields)
static Vector<const GVArray *> get_field_context_inputs(ResourceScope &scope,
const IndexMask mask,
- FieldContext &context,
+ const FieldContext &context,
const FieldGraphInfo &graph_info)
{
Vector<const GVArray *> field_context_inputs;
@@ -238,7 +238,7 @@ struct PartiallyInitializedArray : NonCopyable, NonMovable {
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Span<const GField *> fields_to_evaluate,
IndexMask mask,
- FieldContext &context,
+ const FieldContext &context,
Span<GVMutableArray *> dst_hints)
{
Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr);
@@ -408,7 +408,7 @@ void evaluate_constant_field(const GField &field, void *r_value)
void evaluate_fields_to_spans(Span<const GField *> fields_to_evaluate,
IndexMask mask,
- FieldContext &context,
+ const FieldContext &context,
Span<GMutableSpan> out_spans)
{
ResourceScope scope;
diff --git a/source/blender/functions/tests/FN_field_test.cc b/source/blender/functions/tests/FN_field_test.cc
index 67708331c6d..0eb9e9e1351 100644
--- a/source/blender/functions/tests/FN_field_test.cc
+++ b/source/blender/functions/tests/FN_field_test.cc
@@ -207,24 +207,26 @@ TEST(field, TwoFunctionsTwoOutputs)
OperationFieldSource(std::make_unique<TwoOutputFunction>("SI_SI_SO_SO"),
{index_field, index_field}));
- GField result_field_1{fn, 0};
- GField intermediate_field{fn, 1};
+ Vector<int64_t> mask_indices = {2, 4, 6, 8};
+ IndexMask mask = mask_indices.as_span();
+
+ Field<int> result_field_1{fn, 0};
+ Field<int> intermediate_field{fn, 1};
std::unique_ptr<MultiFunction> add_10_fn = std::make_unique<CustomMF_SI_SO<int, int>>(
"add_10", [](int a) { return a + 10; });
- GField result_field_2{std::make_shared<OperationFieldSource>(
- OperationFieldSource(std::move(add_10_fn), {intermediate_field})),
- 0};
+ Field<int> result_field_2{std::make_shared<OperationFieldSource>(
+ OperationFieldSource(std::move(add_10_fn), {intermediate_field})),
+ 0};
- Array<int> result_1(10);
- Array<int> result_2(10);
- GMutableSpan result_generic_1(result_1.as_mutable_span());
- GMutableSpan result_generic_2(result_2.as_mutable_span());
FieldContext field_context;
- evaluate_fields_to_spans({&result_field_1, &result_field_2},
- {2, 4, 6, 8},
- field_context,
- {result_generic_1, result_generic_2});
+ FieldEvaluator field_evaluator{field_context, &mask};
+ FieldOutputHandle<int> handle_1 = field_evaluator.add(result_field_1);
+ FieldOutputHandle<int> handle_2 = field_evaluator.add(result_field_2);
+ field_evaluator.evaluate();
+ const VArray<int> &result_1 = handle_1.get();
+ const VArray<int> &result_2 = handle_2.get();
+
EXPECT_EQ(result_1[2], 4);
EXPECT_EQ(result_1[4], 8);
EXPECT_EQ(result_1[6], 12);
More information about the Bf-blender-cvs
mailing list