[Bf-blender-cvs] [81a0c384dae] temp-geometry-nodes-fields--fields: Experimental simplification: non-virtual multi-function-only fields
Hans Goudey
noreply at git.blender.org
Thu Aug 26 00:39:27 CEST 2021
Commit: 81a0c384daefdb370c83b257078f59c7dfda7711
Author: Hans Goudey
Date: Wed Aug 25 17:39:19 2021 -0500
Branches: temp-geometry-nodes-fields--fields
https://developer.blender.org/rB81a0c384daefdb370c83b257078f59c7dfda7711
Experimental simplification: non-virtual multi-function-only fields
The stupidly simple test doesn't pass anymore.
===================================================================
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 daff025d0d6..9ccdca4238c 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -32,16 +32,20 @@
namespace blender::fn {
class Field;
-using FieldPtr = std::unique_ptr<Field>;
class Field {
const fn::CPPType *type_;
+ // std::unique_ptr<MultiFunction> function_;
+ const MultiFunction *function_;
+
+ blender::Vector<std::shared_ptr<Field>> input_fields_;
+
std::string debug_name_ = "";
public:
- virtual ~Field() = default;
- Field(const fn::CPPType &type, std::string &&debug_name = "")
- : type_(&type), debug_name_(std::move(debug_name))
+ ~Field() = default;
+ Field(const fn::CPPType &type, const MultiFunction &function)
+ : type_(&type), function_(&function)
{
}
@@ -51,14 +55,30 @@ class Field {
return *type_;
}
+ const MultiFunction &function() const
+ {
+ BLI_assert(function_ != nullptr);
+ return *function_;
+ }
+
blender::StringRef debug_name() const
{
return debug_name_;
}
- virtual void foreach_input(blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const = 0;
- virtual void foreach_input_recursive(
- blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const = 0;
+ void foreach_input(blender::FunctionRef<void(const Field &input)> fn) const
+ {
+ for (const std::shared_ptr<Field> &field : input_fields_) {
+ fn(*field);
+ }
+ }
+ void foreach_input_recursive(blender::FunctionRef<void(const Field &input)> fn) const
+ {
+ for (const std::shared_ptr<Field> &field : input_fields_) {
+ fn(*field);
+ field->foreach_input(fn);
+ }
+ }
};
/**
@@ -68,66 +88,66 @@ class Field {
* and input fields just happened to have no inputs. Then it might not need to be a virtual class,
* since the dynamic behavior would be contained in the multifunction, which would be very nice.
*/
-class InputField : public Field {
- public:
- InputField(const CPPType &type) : Field(type)
- {
- }
-
- void foreach_input(blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
- {
- }
- void foreach_input_recursive(
- blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
- {
- }
-
- virtual GVArrayPtr get_data(IndexMask mask) const = 0;
-
- /**
- * Return true when the field input is the same as another field, used as an
- * optimization to avoid creating multiple virtual arrays for the same input node.
- */
- virtual bool equals(const InputField &UNUSED(other))
- {
- return false;
- }
-};
+// class InputField : public Field {
+// public:
+// InputField(const CPPType &type) : Field(type)
+// {
+// }
+
+// void foreach_input(blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
+// {
+// }
+// void foreach_input_recursive(
+// blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
+// {
+// }
+
+// virtual GVArrayPtr get_data(IndexMask mask) const = 0;
+
+// /**
+// * Return true when the field input is the same as another field, used as an
+// * optimization to avoid creating multiple virtual arrays for the same input node.
+// */
+// virtual bool equals(const InputField &UNUSED(other))
+// {
+// return false;
+// }
+// };
/**
* A field that takes inputs
*/
-class MultiFunctionField final : public Field {
- blender::Vector<FieldPtr> input_fields_;
- const MultiFunction *function_;
-
- public:
- void foreach_input(blender::FunctionRef<void(const Field &input)> fn) const final
- {
- for (const FieldPtr &field : input_fields_) {
- fn(*field);
- }
- }
- void foreach_input_recursive(blender::FunctionRef<void(const Field &input)> fn) const final
- {
- for (const FieldPtr &field : input_fields_) {
- fn(*field);
- field->foreach_input(fn);
- }
- }
-
- const MultiFunction &function() const
- {
- BLI_assert(function_ != nullptr);
- return *function_;
- }
-};
+// class MultiFunctionField final : public Field {
+// blender::Vector<FieldPtr> input_fields_;
+// const MultiFunction *function_;
+
+// public:
+// void foreach_input(blender::FunctionRef<void(const Field &input)> fn) const final
+// {
+// for (const FieldPtr &field : input_fields_) {
+// fn(*field);
+// }
+// }
+// void foreach_input_recursive(blender::FunctionRef<void(const Field &input)> fn) const final
+// {
+// for (const FieldPtr &field : input_fields_) {
+// fn(*field);
+// field->foreach_input(fn);
+// }
+// }
+
+// const MultiFunction &function() const
+// {
+// BLI_assert(function_ != nullptr);
+// return *function_;
+// }
+// };
/**
* Evaluate more than one field at a time, as an optimization
* in case they share inputs or various intermediate values.
*/
-void evaluate_fields(const blender::Span<FieldPtr> fields,
+void evaluate_fields(const blender::Span<Field> fields,
const blender::MutableSpan<GMutableSpan> outputs,
const blender::IndexMask mask);
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index e2c25ac1ad7..acecbfd79ec 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -20,64 +20,51 @@ namespace blender::fn {
static void add_field_parameters(const Field &field,
MFProcedureBuilder &builder,
- Map<const Field *, MFVariable *> &variable_map)
+ Map<const Field *, MFVariable *> &output_map)
{
- if (const MultiFunctionField *mf_field = dynamic_cast<const MultiFunctionField *>(&field)) {
- /* Recursively make sure all of the inputs have entries in the parameter map. */
- mf_field->foreach_input_recursive([&](const Field &input_field) {
- add_field_parameters(input_field, builder, variable_map);
- });
+ /* Recursively make sure all of the inputs have entries in the variable map. */
+ field.foreach_input_recursive(
+ [&](const Field &input_field) { add_field_parameters(input_field, builder, output_map); });
- /* Gather the immediate inputs to this field. */
- Vector<MFVariable *> inputs;
- mf_field->foreach_input(
- [&](const Field &input_field) { inputs.append(variable_map.lookup(&input_field)); });
+ /* Add the immediate inputs to this field. */
+ field.foreach_input([&](const Field &input_field) {
+ builder.add_input_parameter(output_map.lookup(&input_field)->data_type());
+ });
- for (const int i : inputs.index_range()) {
- builder.add_input_parameter(inputs[i]->data_type());
- }
+ Vector<MFVariable *> outputs = builder.add_call(field.function());
- Vector<MFVariable *> outputs = builder.add_call(mf_field->function());
+ // builder.add_destruct(inputs);
- // builder.add_destruct(inputs);
-
- /* TODO: How to support multiple outputs?! */
- BLI_assert(outputs.size() == 1);
- variable_map.add_new(mf_field, outputs.first());
- }
- else if (const InputField *input_field = dynamic_cast<const InputField *>(&field)) {
- variable_map.add_new(input_field,
- &builder.add_input_parameter(MFDataType::ForSingle(field.type()),
- std::string(field.debug_name())));
- }
+ /* TODO: How to support multiple outputs?! */
+ BLI_assert(outputs.size() == 1);
+ output_map.add_new(&field, outputs.first());
}
-static void build_procedure(const Span<FieldPtr> fields, MFProcedure &procedure)
+static void build_procedure(const Span<Field> fields, MFProcedure &procedure)
{
MFProcedureBuilder builder{procedure};
- Map<const Field *, MFVariable *> variable_map;
-
- for (const FieldPtr &field : fields) {
- if (dynamic_cast<const InputField *>(field.get())) {
- continue;
- }
+ Map<const Field *, MFVariable *> output_map;
- add_field_parameters(*field, builder, variable_map);
+ for (const Field &field : fields) {
+ add_field_parameters(field, builder, output_map);
}
/* TODO: Move this to the proper place. */
- for (MFVariable *variable : variable_map.values()) {
+ for (MFVariable *variable : output_map.values()) {
builder.add_destruct(*variable);
}
builder.add_return();
+ for (const Field &field : fields) {
+ builder.add_output_parameter(*output_map.lookup(&field));
+ }
+
BLI_assert(procedure.validate());
}
static void evaluate_procedure(MFProcedure &procedure,
- const Span<FieldPtr> fields,
const IndexMask mask,
const MutableSpan<GMutableSpan> outputs)
{
@@ -85,34 +72,9 @@ static void evaluate_procedure(MFProcedure &procedure,
MFParamsBuilder params{executor, mask.min_array_size()};
MFContextBuilder context;
- /* Add the input data from the input fields. */
- Map<const InputField *, GVArrayPtr> computed_inputs;
- for (const FieldPtr &field : fields) {
- if (const InputField *input_field = dynamic_cast<const InputField *>(field.get())) {
- if (!computed_inputs.contains(input_field)) {
- computed_inputs.add_new(input_field, input_field->get_data(mask));
- }
- continue;
- }
- field->foreach_input_recursive([&](const Field &field) {
- if (const InputField *input_field = dynamic_cast<const InputField *>(&field)) {
- /* TODO: Optimize, too many lookups. */
- if (!computed_inputs.contains(input_field)) {
- computed_inputs.add_new(input_field, input_field->get_data(mask));
- }
- params.add_readonly_single_input(*computed_inputs.lookup(input_field));
- }
- });
- }
-
/* Add the output arrays. */
for (const int i : outputs.index_range()) {
- if (const InputField *input_field = dynamic_cast<const InputField *>(fields[i].get())) {
- computed_inputs.lookup(input_field)->materialize(mask, outputs[i].data());
- }
- else {
- params.add_uninitialized_single_output(outputs[i]);
- }
+ params.add_uninitialized_single_output(outputs[i]);
}
ex
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list