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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs