forked from bartvdbraak/blender
Functions: fix procedure executor not writing output in correct buffer
The issue was that the executor would forget about the caller provided storage if the variable is destructed.
This commit is contained in:
parent
0178e694b7
commit
c196ca3740
@ -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. */
|
||||
@ -729,22 +718,26 @@ class VariableState : NonCopyable, NonMovable {
|
||||
BLI_assert(value_typed->is_initialized);
|
||||
UNUSED_VARS_NDEBUG(value_typed);
|
||||
if (mask.size() == tot_initialized_) {
|
||||
do_destruct_self = true;
|
||||
const CPPType &type = data_type.single_type();
|
||||
type.destruct(value_typed->data);
|
||||
value_typed->is_initialized = false;
|
||||
}
|
||||
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;
|
||||
value_typed->data.clear(IndexRange(1));
|
||||
}
|
||||
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)
|
||||
|
@ -378,4 +378,34 @@ TEST(multi_function_procedure, BufferReuse)
|
||||
EXPECT_EQ(results[4], 53);
|
||||
}
|
||||
|
||||
TEST(multi_function_procedure, OutputBufferReplaced)
|
||||
{
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
|
||||
const int output_value = 42;
|
||||
CustomMF_GenericConstant constant_fn(CPPType::get<int>(), &output_value, false);
|
||||
MFVariable &var_o = procedure.new_variable(MFDataType::ForSingle<int>());
|
||||
builder.add_output_parameter(var_o);
|
||||
builder.add_call_with_all_variables(constant_fn, {&var_o});
|
||||
builder.add_destruct(var_o);
|
||||
builder.add_call_with_all_variables(constant_fn, {&var_o});
|
||||
builder.add_return();
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
|
||||
Array<int> output(3, 0);
|
||||
fn::MFParamsBuilder params(procedure_fn, output.size());
|
||||
params.add_uninitialized_single_output(output.as_mutable_span());
|
||||
|
||||
fn::MFContextBuilder context;
|
||||
procedure_fn.call(IndexMask(output.size()), params, context);
|
||||
|
||||
EXPECT_EQ(output[0], output_value);
|
||||
EXPECT_EQ(output[1], output_value);
|
||||
EXPECT_EQ(output[2], output_value);
|
||||
}
|
||||
|
||||
} // namespace blender::fn::tests
|
||||
|
Loading…
Reference in New Issue
Block a user