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:
Diffstat (limited to 'source/blender/functions/intern/field.cc')
-rw-r--r--source/blender/functions/intern/field.cc76
1 files changed, 56 insertions, 20 deletions
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index f55b9cd92ff..3274af4a7be 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -540,28 +540,65 @@ FieldOperation::FieldOperation(std::shared_ptr<const MultiFunction> function,
owned_function_ = std::move(function);
}
-static bool any_field_depends_on_input(Span<GField> fields)
+/**
+ * Returns the field inputs used by all the provided fields.
+ * This tries to reuse an existing #FieldInputs whenever possible to avoid copying it.
+ */
+static std::shared_ptr<const FieldInputs> combine_field_inputs(Span<GField> fields)
{
+ /* The #FieldInputs that we try to reuse if possible. */
+ const std::shared_ptr<const FieldInputs> *field_inputs_candidate = nullptr;
for (const GField &field : fields) {
- if (field.node().depends_on_input()) {
- return true;
+ const std::shared_ptr<const FieldInputs> &field_inputs = field.node().field_inputs();
+ /* Only try to reuse non-empty #FieldInputs. */
+ if (field_inputs && !field_inputs->nodes.is_empty()) {
+ if (field_inputs_candidate == nullptr) {
+ field_inputs_candidate = &field_inputs;
+ }
+ else if ((*field_inputs_candidate)->nodes.size() < field_inputs->nodes.size()) {
+ /* Always try to reuse the #FieldInputs that has the most nodes already. */
+ field_inputs_candidate = &field_inputs;
+ }
+ }
+ }
+ if (field_inputs_candidate == nullptr) {
+ /* None of the field depends on an input. */
+ return {};
+ }
+ /* Check if all inputs are in the */
+ Vector<const FieldInput *> inputs_not_in_candidate;
+ for (const GField &field : fields) {
+ const std::shared_ptr<const FieldInputs> &field_inputs = field.node().field_inputs();
+ if (!field_inputs) {
+ continue;
+ }
+ if (&field_inputs == field_inputs_candidate) {
+ continue;
}
+ for (const FieldInput *field_input : field_inputs->nodes) {
+ if (!(*field_inputs_candidate)->nodes.contains(field_input)) {
+ inputs_not_in_candidate.append(field_input);
+ }
+ }
+ }
+ if (inputs_not_in_candidate.is_empty()) {
+ /* The existing #FieldInputs can be reused, because no other field has additional inputs. */
+ return *field_inputs_candidate;
}
- return false;
+ /* Create new #FieldInputs that contains all of the inputs that the fields depend on. */
+ std::shared_ptr<FieldInputs> new_field_inputs = std::make_shared<FieldInputs>(
+ **field_inputs_candidate);
+ for (const FieldInput *field_input : inputs_not_in_candidate) {
+ new_field_inputs->nodes.add(field_input);
+ new_field_inputs->deduplicated_nodes.add(*field_input);
+ }
+ return new_field_inputs;
}
FieldOperation::FieldOperation(const MultiFunction &function, Vector<GField> inputs)
- : FieldNode(false, any_field_depends_on_input(inputs)),
- function_(&function),
- inputs_(std::move(inputs))
+ : FieldNode(false), function_(&function), inputs_(std::move(inputs))
{
-}
-
-void FieldOperation::foreach_field_input(FunctionRef<void(const FieldInput &)> foreach_fn) const
-{
- for (const GField &field : inputs_) {
- field.node().foreach_field_input(foreach_fn);
- }
+ field_inputs_ = combine_field_inputs(inputs);
}
/* --------------------------------------------------------------------
@@ -569,13 +606,12 @@ void FieldOperation::foreach_field_input(FunctionRef<void(const FieldInput &)> f
*/
FieldInput::FieldInput(const CPPType &type, std::string debug_name)
- : FieldNode(true, true), type_(&type), debug_name_(std::move(debug_name))
-{
-}
-
-void FieldInput::foreach_field_input(FunctionRef<void(const FieldInput &)> foreach_fn) const
+ : FieldNode(true), type_(&type), debug_name_(std::move(debug_name))
{
- foreach_fn(*this);
+ std::shared_ptr<FieldInputs> field_inputs = std::make_shared<FieldInputs>();
+ field_inputs->nodes.add_new(this);
+ field_inputs->deduplicated_nodes.add_new(*this);
+ field_inputs_ = std::move(field_inputs);
}
/* --------------------------------------------------------------------