[Bf-blender-cvs] [70eaba3cb1d] temp-geometry-nodes-fields--fields: Basic constant input test passes
Hans Goudey
noreply at git.blender.org
Wed Aug 25 23:23:54 CEST 2021
Commit: 70eaba3cb1d74d5fb9ae12a7997ba1e8c5622a9a
Author: Hans Goudey
Date: Wed Aug 25 16:23:46 2021 -0500
Branches: temp-geometry-nodes-fields--fields
https://developer.blender.org/rB70eaba3cb1d74d5fb9ae12a7997ba1e8c5622a9a
Basic constant input test passes
===================================================================
M source/blender/functions/CMakeLists.txt
M source/blender/functions/FN_field.hh
A source/blender/functions/intern/field.cc
M source/blender/functions/tests/FN_field_test.cc
===================================================================
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index a4ba9a61a85..5941034de78 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC_SYS
set(SRC
intern/cpp_types.cc
+ intern/field.cc
intern/generic_vector_array.cc
intern/generic_virtual_array.cc
intern/generic_virtual_vector_array.cc
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 208f3ce2d76..daff025d0d6 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -24,7 +24,6 @@
#include "BLI_map.hh"
#include "BLI_vector.hh"
-#include "FN_generic_array.hh"
#include "FN_generic_virtual_array.hh"
#include "FN_multi_function_procedure.hh"
#include "FN_multi_function_procedure_builder.hh"
@@ -33,152 +32,103 @@
namespace blender::fn {
class Field;
+using FieldPtr = std::unique_ptr<Field>;
class Field {
- fn::CPPType *type_;
+ const fn::CPPType *type_;
+ std::string debug_name_ = "";
public:
- fn::CPPType &type()
+ virtual ~Field() = default;
+ Field(const fn::CPPType &type, std::string &&debug_name = "")
+ : type_(&type), debug_name_(std::move(debug_name))
{
+ }
+
+ const fn::CPPType &type() const
+ {
+ BLI_assert(type_ != nullptr);
return *type_;
}
- virtual void foreach_input_recursive(blender::FunctionRef<void(const InputField &input)> fn) = 0;
- virtual void foreach_input(blender::FunctionRef<void(const InputField &input)> fn) = 0;
+ 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;
};
+/**
+ * A field that doesn't have any dependencies on other fields.
+ *
+ * TODO: It might be an elegant simplification if every single field was a multi-function 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:
- virtual GVArrayPtr get_data(IndexMask mask) const = 0;
- void foreach_input_recursive(blender::FunctionRef<void(const InputField &input)> fn) final
+ InputField(const CPPType &type) : Field(type)
{
}
- void foreach_input(blender::FunctionRef<void(const InputField &input)> fn) final
+
+ void foreach_input(blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
{
}
-};
-
-class MultiFunctionField final : public Field {
- blender::Vector<std::shared_ptr<Field>> input_fields_;
- MultiFunction &function_;
-
- public:
- void foreach_input_recursive(blender::FunctionRef<void(const InputField &input)> fn) final
+ void foreach_input_recursive(
+ blender::FunctionRef<void(const Field &input)> UNUSED(fn)) const final
{
- for (const std::shared_ptr<Field> &field : input_fields_) {
- if (const InputField *input_field = dynamic_cast<const InputField *>(field.get())) {
- fn(*input_field);
- }
- else {
- field->foreach_input(fn);
- }
- }
}
- void foreach_input(blender::FunctionRef<void(const InputField &input)> fn) 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))
{
- for (const std::shared_ptr<Field> &field : input_fields_) {
- if (const InputField *input_field = dynamic_cast<const InputField *>(field.get())) {
- fn(*input_field);
- }
- }
+ return false;
}
};
-void add_procedure_inputs_recursive(const Field &field, MFProcedureBuilder &builder)
-{
- field.foreach_input()
-}
-
/**
- * Evaluate more than one prodecure at a time
+ * A field that takes inputs
*/
-void evaluate_fields(const Span<std::shared_ptr<Field>> fields,
- const MutableSpan<GMutableSpan> outputs,
- const IndexMask mask)
-{
- blender::Map<const InputField *, GVArrayPtr> computed_inputs;
- for (const std::shared_ptr<Field> &field : fields) {
- field->foreach_input_recursive([&](const InputField &input_field) {
- if (!computed_inputs.contains(&input_field)) {
- computed_inputs.add_new(&input_field, input_field.get_data(mask));
- }
- });
- }
-
- /* Build procedure. */
- MFProcedure procedure;
- MFProcedureBuilder builder{procedure};
-
- Map<const Field *, MFVariable *> fields_to_variables;
- Map<const GMutableSpan, MFVariable *> outputs_to_variables;
-
- /* Add the unique inputs. */
- for (blender::Map<const InputField *, GVArrayPtr>::Item item : computed_inputs.items()) {
- fields_to_variables.add_new(
- item.key, &builder.add_parameter(MFParamType::ForSingleInput(item.value->type())));
- }
+class MultiFunctionField final : public Field {
+ blender::Vector<FieldPtr> input_fields_;
+ const MultiFunction *function_;
- /* Add the inputs recursively for the entire group of nodes. */
- builder.add_return();
- for (const int i : outputs.index_range()) {
- BLI_assert(fields_to_variables.contains(fields[i].get()));
- builder.add_output_parameter(*fields_to_variables.lookup(fields[i].get()));
+ public:
+ void foreach_input(blender::FunctionRef<void(const Field &input)> fn) const final
+ {
+ for (const FieldPtr &field : input_fields_) {
+ fn(*field);
+ }
}
- // builder.add_output_parameter(*var4);
-
- BLI_assert(procedure.validate());
-
- /* Evaluate procedure. */
- MFProcedureExecutor executor{"Evaluate Field", procedure};
- MFParamsBuilder params{executor, mask.min_array_size()};
- MFContextBuilder context;
-
- /* Add the input data. */
- for (blender::Map<const InputField *, GVArrayPtr>::Item item : computed_inputs.items()) {
- params.add_readonly_single_input(*item.value);
+ 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);
+ }
}
- /* Add the output arrays. */
- for (const int i : fields.index_range()) {
- BLI_assert(outputs[i].type() == fields[i]->type());
- params.add_uninitialized_single_output(outputs[i]);
+ const MultiFunction &function() const
+ {
+ BLI_assert(function_ != nullptr);
+ return *function_;
}
+};
- executor.call(mask, params, context);
-
- // int input_index = 0;
- // for (const int param_index : fn_->param_indices()) {
- // fn::MFParamType param_type = fn_->param_type(param_index);
- // switch (param_type.category()) {
- // case fn::MFParamType::SingleInput: {
- // const Field &field = *input_fields_[input_index];
- // FieldOutput &output = scope.add_value(field.evaluate(mask, inputs), __func__);
- // params.add_readonly_single_input(output.varray_ref());
- // input_index++;
- // break;
- // }
- // case fn::MFParamType::SingleOutput: {
- // const CPPType &type = param_type.data_type().single_type();
- // void *buffer = MEM_mallocN_aligned(
- // mask.min_array_size() * type.size(), type.alignment(), __func__);
- // GMutableSpan span{type, buffer, mask.min_array_size()};
- // outputs.append(span);
- // params.add_uninitialized_single_output(span);
- // if (param_index == output_param_index_) {
- // output_span_index = outputs.size() - 1;
- // }
- // break;
- // }
- // case fn::MFParamType::SingleMutable:
- // case fn::MFParamType::VectorInput:
- // case fn::MFParamType::VectorMutable:
- // case fn::MFParamType::VectorOutput:
- // BLI_assert_unreachable();
- // break;
- // }
- // }
-}
+/**
+ * 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,
+ const blender::MutableSpan<GMutableSpan> outputs,
+ const blender::IndexMask mask);
} // namespace blender::fn
\ No newline at end of file
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
new file mode 100644
index 00000000000..e2c25ac1ad7
--- /dev/null
+++ b/source/blender/functions/intern/field.cc
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#include "FN_field.hh"
+
+namespace blender::fn {
+
+static void add_field_parameters(const Field &field,
+ MFProcedureBuilder &builder,
+ Map<const Field *, MFVariable *> &variable_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);
+ });
+
+ /* 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)); });
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list