Page MenuHome
Paste P2904

(An Untitled Masterwork)
ActivePublic

Authored by Jacques Lucke (JacquesLucke) on Apr 21 2022, 1:27 PM.
diff --git a/source/blender/functions/intern/multi_function_procedure_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc
index 7a0b74d8039..4146f1d5ead 100644
--- a/source/blender/functions/intern/multi_function_procedure_executor.cc
+++ b/source/blender/functions/intern/multi_function_procedure_executor.cc
@@ -681,14 +681,9 @@ class VariableState : NonCopyable, NonMovable {
/* Sanity check to make sure that enough indices can be destructed. */
BLI_assert(new_tot_initialized >= 0);
- bool do_destruct_self = false;
-
switch (value_->type) {
case ValueType::GVArray: {
- if (mask.size() == full_mask.size()) {
- do_destruct_self = true;
- }
- else {
+ if (mask.size() < full_mask.size()) {
/* Not all elements are destructed. Since we can't work on the original array, we have to
* create a copy first. */
this->ensure_is_mutable(full_mask, data_type, value_allocator);
@@ -701,16 +696,10 @@ class VariableState : NonCopyable, NonMovable {
case ValueType::Span: {
const CPPType &type = data_type.single_type();
type.destruct_indices(this->value_as<VariableValue_Span>()->data, mask);
- if (new_tot_initialized == 0) {
- do_destruct_self = true;
- }
break;
}
case ValueType::GVVectorArray: {
- if (mask.size() == full_mask.size()) {
- do_destruct_self = true;
- }
- else {
+ if (mask.size() < full_mask.size()) {
/* Not all elements are cleared. Since we can't work on the original vector array, we
* have to create a copy first. A possible future optimization is to create the partial
* copy directly. */
@@ -728,23 +717,18 @@ class VariableState : NonCopyable, NonMovable {
auto *value_typed = this->value_as<VariableValue_OneSingle>();
BLI_assert(value_typed->is_initialized);
UNUSED_VARS_NDEBUG(value_typed);
- if (mask.size() == tot_initialized_) {
- do_destruct_self = true;
- }
break;
}
case ValueType::OneVector: {
- auto *value_typed = this->value_as<VariableValue_OneVector>();
- UNUSED_VARS(value_typed);
- if (mask.size() == tot_initialized_) {
- do_destruct_self = true;
- }
break;
}
}
tot_initialized_ = new_tot_initialized;
- return do_destruct_self;
+
+ const bool should_self_destruct = new_tot_initialized == 0 &&
+ caller_provided_storage_ == nullptr;
+ return should_self_destruct;
}
void indices_split(IndexMask mask, IndicesSplitVectors &r_indices)
diff --git a/source/blender/functions/tests/FN_multi_function_procedure_test.cc b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
index a196d0396ec..aa3f91f5ef4 100644
--- a/source/blender/functions/tests/FN_multi_function_procedure_test.cc
+++ b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
@@ -378,4 +378,48 @@ TEST(multi_function_procedure, BufferReuse)
EXPECT_EQ(results[4], 53);
}
+TEST(multi_function_procedure, OutputBufferReplaced)
+{
+ MFProcedure procedure;
+ MFProcedureBuilder builder{procedure};
+
+ const bool default_output = false;
+ CustomMF_GenericConstant constant_fn(CPPType::get<bool>(), &default_output, false);
+ CustomMF_SI_SI_SO<int, int, bool> equal_fn{"Equal", [](int a, int b) { return a == b; }};
+ CustomMF_GenericCopy copy_fn(MFDataType::ForSingle<bool>());
+ MFVariable &var_o = procedure.new_variable(MFDataType::ForSingle<bool>());
+ builder.add_output_parameter(var_o);
+ MFVariable *var_a = &builder.add_single_input_parameter<int>();
+ MFVariable *var_b = &builder.add_single_input_parameter<int>();
+ builder.add_call_with_all_variables(constant_fn, {&var_o});
+ auto [temp_out] = builder.add_call<1>(equal_fn, {var_a, var_b});
+ builder.add_destruct(var_o);
+ builder.add_call_with_all_variables(copy_fn, {temp_out, &var_o});
+ builder.add_destruct(*temp_out);
+ builder.add_destruct(*var_a);
+ builder.add_destruct(*var_b);
+ builder.add_return();
+
+ EXPECT_TRUE(procedure.validate());
+
+ MFProcedureExecutor procedure_fn{procedure};
+
+ Array<int> input1 = {30, 5, 0};
+ Array<int> input2 = {-4, 5, -0};
+ Array<bool> output(input1.size());
+
+ fn::MFParamsBuilder params(procedure_fn, input1.size());
+
+ params.add_uninitialized_single_output(output.as_mutable_span());
+ params.add_readonly_single_input(input1.as_span());
+ params.add_readonly_single_input(input2.as_span());
+
+ fn::MFContextBuilder context;
+ procedure_fn.call(IndexMask(input1.size()), params, context);
+
+ EXPECT_FALSE(output[0]);
+ EXPECT_TRUE(output[1]);
+ EXPECT_TRUE(output[2]);
+}
+
} // namespace blender::fn::tests

Event Timeline