Commit: 94b98d3f882517076b652fd16734c673fb03a3a4
Author: Jacques Lucke
Date: Fri Sep 3 12:54:28 2021 +0200
Branches: temp-geometry-nodes-fields
https://developer.blender.org/rB94b98d3f882517076b652fd16734c673fb03a3a4
fix bug when the same field is evaluated twice
===================================================================
M source/blender/functions/FN_multi_function_builder.hh
M source/blender/functions/intern/field.cc
M source/blender/functions/intern/multi_function_builder.cc
M source/blender/functions/tests/FN_field_test.cc
===================================================================
diff --git a/source/blender/functions/FN_multi_function_builder.hh
b/source/blender/functions/FN_multi_function_builder.hh
index 7a526bb640b..d13615ced07 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -417,4 +417,13 @@ class CustomMF_DefaultOutput : public MultiFunction {
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
+class CustomMF_GenericCopy : public MultiFunction {
+ private:
+ MFSignature signature_;
+
+ public:
+ CustomMF_GenericCopy(StringRef name, MFDataType data_type);
+ void call(IndexMask mask, MFParams params, MFContext context) const override;
+};
+
} // namespace blender::fn
diff --git a/source/blender/functions/intern/field.cc
b/source/blender/functions/intern/field.cc
index 6d8fce07f5a..073908e6c1d 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -136,6 +136,7 @@ static Set<const GField *> find_varying_fields(const
FieldGraphInfo &graph_info,
}
static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
+ ResourceScope &scope,
const FieldGraphInfo
&graph_info,
Span<const GField *>
output_fields)
{
@@ -187,9 +188,15 @@ static void
build_multi_function_procedure_for_fields(MFProcedure &procedure,
}
}
- /* TODO: Handle case when there are duplicates in #output_fields. */
+ Set<MFVariable *> already_output_variables;
for (const GField *field : output_fields) {
MFVariable *variable = variable_by_field.lookup(*field);
+ if (!already_output_variables.add(variable)) {
+ /* The same variable is output twice. Create a copy to make it work. */
+ const MultiFunction ©_fn = scope.construct<CustomMF_GenericCopy>(
+ __func__, "copy", variable->data_type());
+ variable = builder.add_call<1>(copy_fn, {variable})[0];
+ }
builder.add_output_parameter(*variable);
}
@@ -293,7 +300,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope
&scope,
const int array_size = mask.min_array_size();
if (!varying_fields_to_evaluate.is_empty()) {
MFProcedure procedure;
- build_multi_function_procedure_for_fields(procedure, graph_info,
varying_fields_to_evaluate);
+ build_multi_function_procedure_for_fields(
+ procedure, scope, graph_info, varying_fields_to_evaluate);
MFProcedureExecutor procedure_executor{"Procedure", procedure};
MFParamsBuilder mf_params{procedure_executor, mask.min_array_size()};
MFContextBuilder mf_context;
@@ -335,7 +343,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope
&scope,
}
if (!constant_fields_to_evaluate.is_empty()) {
MFProcedure procedure;
- build_multi_function_procedure_for_fields(procedure, graph_info,
constant_fields_to_evaluate);
+ build_multi_function_procedure_for_fields(
+ procedure, scope, graph_info, constant_fields_to_evaluate);
MFProcedureExecutor procedure_executor{"Procedure", procedure};
MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context;
diff --git a/source/blender/functions/intern/multi_function_builder.cc
b/source/blender/functions/intern/multi_function_builder.cc
index c6b3b808130..180d1f17a54 100644
--- a/source/blender/functions/intern/multi_function_builder.cc
+++ b/source/blender/functions/intern/multi_function_builder.cc
@@ -123,4 +123,32 @@ void CustomMF_DefaultOutput::call(IndexMask mask, MFParams
params, MFContext UNU
}
}
+CustomMF_GenericCopy::CustomMF_GenericCopy(StringRef name, MFDataType
data_type)
+{
+ MFSignatureBuilder signature{name};
+ signature.input("Input", data_type);
+ signature.output("Output", data_type);
+ signature_ = signature.build();
+ this->set_signature(&signature_);
+}
+
+void CustomMF_GenericCopy::call(IndexMask mask, MFParams params, MFContext
UNUSED(context)) const
+{
+ const MFDataType data_type = this->param_type(0).data_type();
+ switch (data_type.category()) {
+ case MFDataType::Single: {
+ const GVArray &inputs = params.readonly_single_input(0, "Input");
+ GMutableSpan outputs = params.uninitialized_single_output(1, "Output");
+ inputs.materialize_to_uninitialized(mask, outputs.data());
+ break;
+ }
+ case MFDataType::Vector: {
+ const GVVectorArray &inputs = params.readonly_vector_input(0, "Input");
+ GVectorArray &outputs = params.vector_output(1, "Output");
+ outputs.extend(mask, inputs);
+ break;
+ }
+ }
+}
+
} // namespace blender::fn
diff --git a/source/blender/functions/tests/FN_field_test.cc
b/source/blender/functions/tests/FN_field_test.cc
index 67fda512c92..b02e14559b5 100644
--- a/source/blender/functions/tests/FN_field_test.cc
+++ b/source/blender/functions/tests/FN_field_test.cc
@@ -237,4 +237,24 @@ TEST(field, TwoFunctionsTwoOutputs)
EXPECT_EQ(result_2->get(8), 36);
}
+TEST(field, SameFieldTwice)
+{
+ GField constant_field{
+
std::make_shared<OperationFieldSource>(std::make_unique<CustomMF_Constant<int>>(10)),
0};
+
+ FieldContext field_context;
+ IndexMask mask{IndexRange(2)};
+ ResourceScope scope;
+ Vector<const GVArray *> results = evaluate_fields(
+ scope, {&constant_field, &constant_field}, mask, field_context);
+
+ GVArray_Typed<int> varray1{*results[0]};
+ GVArray_Typed<int> varray2{*results[1]};
+
+ EXPECT_EQ(varray1->get(0), 10);
+ EXPECT_EQ(varray1->get(1), 10);
+ EXPECT_EQ(varray2->get(0), 10);
+ EXPECT_EQ(varray2->get(1), 10);
+}
+
} // namespace blender::fn::tests
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs