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/multi_function_network_evaluation.cc')
-rw-r--r--source/blender/functions/intern/multi_function_network_evaluation.cc1083
1 files changed, 0 insertions, 1083 deletions
diff --git a/source/blender/functions/intern/multi_function_network_evaluation.cc b/source/blender/functions/intern/multi_function_network_evaluation.cc
deleted file mode 100644
index 9a0cb0c35ce..00000000000
--- a/source/blender/functions/intern/multi_function_network_evaluation.cc
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/** \file
- * \ingroup fn
- *
- * The `MFNetworkEvaluator` class is a multi-function that consists of potentially many smaller
- * multi-functions. When called, it traverses the underlying MFNetwork and executes the required
- * function nodes.
- *
- * There are many possible approaches to evaluate a function network. The approach implemented
- * below has the following features:
- * - It does not use recursion. Those could become problematic with long node chains.
- * - It can handle all existing parameter types (including mutable parameters).
- * - Avoids data copies in many cases.
- * - Every node is executed at most once.
- * - Can compute sub-functions on a single element, when the result is the same for all elements.
- *
- * Possible improvements:
- * - Cache and reuse buffers.
- * - Use "deepest depth first" heuristic to decide which order the inputs of a node should be
- * computed. This reduces the number of required temporary buffers when they are reused.
- */
-
-#include "FN_multi_function_network_evaluation.hh"
-
-#include "BLI_resource_scope.hh"
-#include "BLI_stack.hh"
-
-namespace blender::fn {
-
-struct Value;
-
-/**
- * This keeps track of all the values that flow through the multi-function network. Therefore it
- * maintains a mapping between output sockets and their corresponding values. Every `value`
- * references some memory, that is owned either by the caller or this storage.
- *
- * A value can be owned by different sockets over time to avoid unnecessary copies.
- */
-class MFNetworkEvaluationStorage {
- private:
- LinearAllocator<> allocator_;
- IndexMask mask_;
- Array<Value *> value_per_output_id_;
- int64_t min_array_size_;
-
- public:
- MFNetworkEvaluationStorage(IndexMask mask, int socket_id_amount);
- ~MFNetworkEvaluationStorage();
-
- /* Add the values that have been provided by the caller of the multi-function network. */
- void add_single_input_from_caller(const MFOutputSocket &socket, const GVArray &virtual_array);
- void add_vector_input_from_caller(const MFOutputSocket &socket,
- const GVVectorArray &virtual_vector_array);
- void add_single_output_from_caller(const MFOutputSocket &socket, GMutableSpan span);
- void add_vector_output_from_caller(const MFOutputSocket &socket, GVectorArray &vector_array);
-
- /* Get input buffers for function node evaluations. */
- const GVArray &get_single_input__full(const MFInputSocket &socket, ResourceScope &scope);
- const GVArray &get_single_input__single(const MFInputSocket &socket, ResourceScope &scope);
- const GVVectorArray &get_vector_input__full(const MFInputSocket &socket, ResourceScope &scope);
- const GVVectorArray &get_vector_input__single(const MFInputSocket &socket, ResourceScope &scope);
-
- /* Get output buffers for function node evaluations. */
- GMutableSpan get_single_output__full(const MFOutputSocket &socket);
- GMutableSpan get_single_output__single(const MFOutputSocket &socket);
- GVectorArray &get_vector_output__full(const MFOutputSocket &socket);
- GVectorArray &get_vector_output__single(const MFOutputSocket &socket);
-
- /* Get mutable buffers for function node evaluations. */
- GMutableSpan get_mutable_single__full(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope);
- GMutableSpan get_mutable_single__single(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope);
- GVectorArray &get_mutable_vector__full(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope);
- GVectorArray &get_mutable_vector__single(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope);
-
- /* Mark a node as being done with evaluation. This might free temporary buffers that are no
- * longer needed. */
- void finish_node(const MFFunctionNode &node);
- void finish_output_socket(const MFOutputSocket &socket);
- void finish_input_socket(const MFInputSocket &socket);
-
- IndexMask mask() const;
- bool socket_is_computed(const MFOutputSocket &socket);
- bool is_same_value_for_every_index(const MFOutputSocket &socket);
- bool socket_has_buffer_for_output(const MFOutputSocket &socket);
-};
-
-MFNetworkEvaluator::MFNetworkEvaluator(Vector<const MFOutputSocket *> inputs,
- Vector<const MFInputSocket *> outputs)
- : inputs_(std::move(inputs)), outputs_(std::move(outputs))
-{
- BLI_assert(outputs_.size() > 0);
- MFSignatureBuilder signature{"Function Tree"};
-
- for (const MFOutputSocket *socket : inputs_) {
- BLI_assert(socket->node().is_dummy());
-
- MFDataType type = socket->data_type();
- switch (type.category()) {
- case MFDataType::Single:
- signature.single_input(socket->name(), type.single_type());
- break;
- case MFDataType::Vector:
- signature.vector_input(socket->name(), type.vector_base_type());
- break;
- }
- }
-
- for (const MFInputSocket *socket : outputs_) {
- BLI_assert(socket->node().is_dummy());
-
- MFDataType type = socket->data_type();
- switch (type.category()) {
- case MFDataType::Single:
- signature.single_output(socket->name(), type.single_type());
- break;
- case MFDataType::Vector:
- signature.vector_output(socket->name(), type.vector_base_type());
- break;
- }
- }
-
- signature_ = signature.build();
- this->set_signature(&signature_);
-}
-
-void MFNetworkEvaluator::call(IndexMask mask, MFParams params, MFContext context) const
-{
- if (mask.size() == 0) {
- return;
- }
-
- const MFNetwork &network = outputs_[0]->node().network();
- Storage storage(mask, network.socket_id_amount());
-
- Vector<const MFInputSocket *> outputs_to_initialize_in_the_end;
-
- this->copy_inputs_to_storage(params, storage);
- this->copy_outputs_to_storage(params, storage, outputs_to_initialize_in_the_end);
- this->evaluate_network_to_compute_outputs(context, storage);
- this->initialize_remaining_outputs(params, storage, outputs_to_initialize_in_the_end);
-}
-
-BLI_NOINLINE void MFNetworkEvaluator::copy_inputs_to_storage(MFParams params,
- Storage &storage) const
-{
- for (int input_index : inputs_.index_range()) {
- int param_index = input_index + 0;
- const MFOutputSocket &socket = *inputs_[input_index];
- switch (socket.data_type().category()) {
- case MFDataType::Single: {
- const GVArray &input_list = params.readonly_single_input(param_index);
- storage.add_single_input_from_caller(socket, input_list);
- break;
- }
- case MFDataType::Vector: {
- const GVVectorArray &input_list_list = params.readonly_vector_input(param_index);
- storage.add_vector_input_from_caller(socket, input_list_list);
- break;
- }
- }
- }
-}
-
-BLI_NOINLINE void MFNetworkEvaluator::copy_outputs_to_storage(
- MFParams params,
- Storage &storage,
- Vector<const MFInputSocket *> &outputs_to_initialize_in_the_end) const
-{
- for (int output_index : outputs_.index_range()) {
- int param_index = output_index + inputs_.size();
- const MFInputSocket &socket = *outputs_[output_index];
- const MFOutputSocket &origin = *socket.origin();
-
- if (origin.node().is_dummy()) {
- BLI_assert(inputs_.contains(&origin));
- /* Don't overwrite input buffers. */
- outputs_to_initialize_in_the_end.append(&socket);
- continue;
- }
-
- if (storage.socket_has_buffer_for_output(origin)) {
- /* When two outputs will be initialized to the same values. */
- outputs_to_initialize_in_the_end.append(&socket);
- continue;
- }
-
- switch (socket.data_type().category()) {
- case MFDataType::Single: {
- GMutableSpan span = params.uninitialized_single_output(param_index);
- storage.add_single_output_from_caller(origin, span);
- break;
- }
- case MFDataType::Vector: {
- GVectorArray &vector_array = params.vector_output(param_index);
- storage.add_vector_output_from_caller(origin, vector_array);
- break;
- }
- }
- }
-}
-
-BLI_NOINLINE void MFNetworkEvaluator::evaluate_network_to_compute_outputs(
- MFContext &global_context, Storage &storage) const
-{
- Stack<const MFOutputSocket *, 32> sockets_to_compute;
- for (const MFInputSocket *socket : outputs_) {
- sockets_to_compute.push(socket->origin());
- }
-
- /* This is the main loop that traverses the MFNetwork. */
- while (!sockets_to_compute.is_empty()) {
- const MFOutputSocket &socket = *sockets_to_compute.peek();
- const MFNode &node = socket.node();
-
- if (storage.socket_is_computed(socket)) {
- sockets_to_compute.pop();
- continue;
- }
-
- BLI_assert(node.is_function());
- BLI_assert(!node.has_unlinked_inputs());
- const MFFunctionNode &function_node = node.as_function();
-
- bool all_origins_are_computed = true;
- for (const MFInputSocket *input_socket : function_node.inputs()) {
- const MFOutputSocket *origin = input_socket->origin();
- if (origin != nullptr) {
- if (!storage.socket_is_computed(*origin)) {
- sockets_to_compute.push(origin);
- all_origins_are_computed = false;
- }
- }
- }
-
- if (all_origins_are_computed) {
- this->evaluate_function(global_context, function_node, storage);
- sockets_to_compute.pop();
- }
- }
-}
-
-BLI_NOINLINE void MFNetworkEvaluator::evaluate_function(MFContext &global_context,
- const MFFunctionNode &function_node,
- Storage &storage) const
-{
-
- const MultiFunction &function = function_node.function();
- // std::cout << "Function: " << function.name() << "\n";
-
- if (this->can_do_single_value_evaluation(function_node, storage)) {
- /* The function output would be the same for all elements. Therefore, it is enough to call the
- * function only on a single element. This can avoid many duplicate computations. */
- MFParamsBuilder params{function, 1};
- ResourceScope &scope = params.resource_scope();
-
- for (int param_index : function.param_indices()) {
- MFParamType param_type = function.param_type(param_index);
- switch (param_type.category()) {
- case MFParamType::SingleInput: {
- const MFInputSocket &socket = function_node.input_for_param(param_index);
- const GVArray &values = storage.get_single_input__single(socket, scope);
- params.add_readonly_single_input(values);
- break;
- }
- case MFParamType::VectorInput: {
- const MFInputSocket &socket = function_node.input_for_param(param_index);
- const GVVectorArray &values = storage.get_vector_input__single(socket, scope);
- params.add_readonly_vector_input(values);
- break;
- }
- case MFParamType::SingleOutput: {
- const MFOutputSocket &socket = function_node.output_for_param(param_index);
- GMutableSpan values = storage.get_single_output__single(socket);
- params.add_uninitialized_single_output(values);
- break;
- }
- case MFParamType::VectorOutput: {
- const MFOutputSocket &socket = function_node.output_for_param(param_index);
- GVectorArray &values = storage.get_vector_output__single(socket);
- params.add_vector_output(values);
- break;
- }
- case MFParamType::SingleMutable: {
- const MFInputSocket &input = function_node.input_for_param(param_index);
- const MFOutputSocket &output = function_node.output_for_param(param_index);
- GMutableSpan values = storage.get_mutable_single__single(input, output, scope);
- params.add_single_mutable(values);
- break;
- }
- case MFParamType::VectorMutable: {
- const MFInputSocket &input = function_node.input_for_param(param_index);
- const MFOutputSocket &output = function_node.output_for_param(param_index);
- GVectorArray &values = storage.get_mutable_vector__single(input, output, scope);
- params.add_vector_mutable(values);
- break;
- }
- }
- }
-
- function.call(IndexRange(1), params, global_context);
- }
- else {
- MFParamsBuilder params{function, storage.mask().min_array_size()};
- ResourceScope &scope = params.resource_scope();
-
- for (int param_index : function.param_indices()) {
- MFParamType param_type = function.param_type(param_index);
- switch (param_type.category()) {
- case MFParamType::SingleInput: {
- const MFInputSocket &socket = function_node.input_for_param(param_index);
- const GVArray &values = storage.get_single_input__full(socket, scope);
- params.add_readonly_single_input(values);
- break;
- }
- case MFParamType::VectorInput: {
- const MFInputSocket &socket = function_node.input_for_param(param_index);
- const GVVectorArray &values = storage.get_vector_input__full(socket, scope);
- params.add_readonly_vector_input(values);
- break;
- }
- case MFParamType::SingleOutput: {
- const MFOutputSocket &socket = function_node.output_for_param(param_index);
- GMutableSpan values = storage.get_single_output__full(socket);
- params.add_uninitialized_single_output(values);
- break;
- }
- case MFParamType::VectorOutput: {
- const MFOutputSocket &socket = function_node.output_for_param(param_index);
- GVectorArray &values = storage.get_vector_output__full(socket);
- params.add_vector_output(values);
- break;
- }
- case MFParamType::SingleMutable: {
- const MFInputSocket &input = function_node.input_for_param(param_index);
- const MFOutputSocket &output = function_node.output_for_param(param_index);
- GMutableSpan values = storage.get_mutable_single__full(input, output, scope);
- params.add_single_mutable(values);
- break;
- }
- case MFParamType::VectorMutable: {
- const MFInputSocket &input = function_node.input_for_param(param_index);
- const MFOutputSocket &output = function_node.output_for_param(param_index);
- GVectorArray &values = storage.get_mutable_vector__full(input, output, scope);
- params.add_vector_mutable(values);
- break;
- }
- }
- }
-
- function.call(storage.mask(), params, global_context);
- }
-
- storage.finish_node(function_node);
-}
-
-bool MFNetworkEvaluator::can_do_single_value_evaluation(const MFFunctionNode &function_node,
- Storage &storage) const
-{
- for (const MFInputSocket *socket : function_node.inputs()) {
- if (!storage.is_same_value_for_every_index(*socket->origin())) {
- return false;
- }
- }
- if (storage.mask().min_array_size() >= 1) {
- for (const MFOutputSocket *socket : function_node.outputs()) {
- if (storage.socket_has_buffer_for_output(*socket)) {
- return false;
- }
- }
- }
- return true;
-}
-
-BLI_NOINLINE void MFNetworkEvaluator::initialize_remaining_outputs(
- MFParams params, Storage &storage, Span<const MFInputSocket *> remaining_outputs) const
-{
- ResourceScope scope;
- for (const MFInputSocket *socket : remaining_outputs) {
- int param_index = inputs_.size() + outputs_.first_index_of(socket);
-
- switch (socket->data_type().category()) {
- case MFDataType::Single: {
- const GVArray &values = storage.get_single_input__full(*socket, scope);
- GMutableSpan output_values = params.uninitialized_single_output(param_index);
- values.materialize_to_uninitialized(storage.mask(), output_values.data());
- break;
- }
- case MFDataType::Vector: {
- const GVVectorArray &values = storage.get_vector_input__full(*socket, scope);
- GVectorArray &output_values = params.vector_output(param_index);
- output_values.extend(storage.mask(), values);
- break;
- }
- }
- }
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Value Types
- * \{ */
-
-enum class ValueType {
- InputSingle,
- InputVector,
- OutputSingle,
- OutputVector,
- OwnSingle,
- OwnVector,
-};
-
-struct Value {
- ValueType type;
-
- Value(ValueType type) : type(type)
- {
- }
-};
-
-struct InputSingleValue : public Value {
- /** This virtual array has been provided by the code that called the multi-function network. */
- const GVArray &virtual_array;
-
- InputSingleValue(const GVArray &virtual_array)
- : Value(ValueType::InputSingle), virtual_array(virtual_array)
- {
- }
-};
-
-struct InputVectorValue : public Value {
- /** This virtual vector has been provided by the code that called the multi-function network. */
- const GVVectorArray &virtual_vector_array;
-
- InputVectorValue(const GVVectorArray &virtual_vector_array)
- : Value(ValueType::InputVector), virtual_vector_array(virtual_vector_array)
- {
- }
-};
-
-struct OutputValue : public Value {
- bool is_computed = false;
-
- OutputValue(ValueType type) : Value(type)
- {
- }
-};
-
-struct OutputSingleValue : public OutputValue {
- /** This span has been provided by the code that called the multi-function network. */
- GMutableSpan span;
-
- OutputSingleValue(GMutableSpan span) : OutputValue(ValueType::OutputSingle), span(span)
- {
- }
-};
-
-struct OutputVectorValue : public OutputValue {
- /** This vector array has been provided by the code that called the multi-function network. */
- GVectorArray *vector_array;
-
- OutputVectorValue(GVectorArray &vector_array)
- : OutputValue(ValueType::OutputVector), vector_array(&vector_array)
- {
- }
-};
-
-struct OwnSingleValue : public Value {
- /** This span has been allocated during the evaluation of the multi-function network and contains
- * intermediate data. It has to be freed once the network evaluation is finished. */
- GMutableSpan span;
- int max_remaining_users;
- bool is_single_allocated;
-
- OwnSingleValue(GMutableSpan span, int max_remaining_users, bool is_single_allocated)
- : Value(ValueType::OwnSingle),
- span(span),
- max_remaining_users(max_remaining_users),
- is_single_allocated(is_single_allocated)
- {
- }
-};
-
-struct OwnVectorValue : public Value {
- /** This vector array has been allocated during the evaluation of the multi-function network and
- * contains intermediate data. It has to be freed once the network evaluation is finished. */
- GVectorArray *vector_array;
- int max_remaining_users;
-
- OwnVectorValue(GVectorArray &vector_array, int max_remaining_users)
- : Value(ValueType::OwnVector),
- vector_array(&vector_array),
- max_remaining_users(max_remaining_users)
- {
- }
-};
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Storage methods
- * \{ */
-
-MFNetworkEvaluationStorage::MFNetworkEvaluationStorage(IndexMask mask, int socket_id_amount)
- : mask_(mask),
- value_per_output_id_(socket_id_amount, nullptr),
- min_array_size_(mask.min_array_size())
-{
-}
-
-MFNetworkEvaluationStorage::~MFNetworkEvaluationStorage()
-{
- for (Value *any_value : value_per_output_id_) {
- if (any_value == nullptr) {
- continue;
- }
- if (any_value->type == ValueType::OwnSingle) {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(any_value);
- GMutableSpan span = value->span;
- const CPPType &type = span.type();
- if (value->is_single_allocated) {
- type.destruct(span.data());
- }
- else {
- type.destruct_indices(span.data(), mask_);
- MEM_freeN(span.data());
- }
- }
- else if (any_value->type == ValueType::OwnVector) {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(any_value);
- delete value->vector_array;
- }
- }
-}
-
-IndexMask MFNetworkEvaluationStorage::mask() const
-{
- return mask_;
-}
-
-bool MFNetworkEvaluationStorage::socket_is_computed(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- return false;
- }
- if (ELEM(any_value->type, ValueType::OutputSingle, ValueType::OutputVector)) {
- return static_cast<OutputValue *>(any_value)->is_computed;
- }
- return true;
-}
-
-bool MFNetworkEvaluationStorage::is_same_value_for_every_index(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- switch (any_value->type) {
- case ValueType::OwnSingle:
- return static_cast<OwnSingleValue *>(any_value)->span.size() == 1;
- case ValueType::OwnVector:
- return static_cast<OwnVectorValue *>(any_value)->vector_array->size() == 1;
- case ValueType::InputSingle:
- return static_cast<InputSingleValue *>(any_value)->virtual_array.is_single();
- case ValueType::InputVector:
- return static_cast<InputVectorValue *>(any_value)->virtual_vector_array.is_single_vector();
- case ValueType::OutputSingle:
- return static_cast<OutputSingleValue *>(any_value)->span.size() == 1;
- case ValueType::OutputVector:
- return static_cast<OutputVectorValue *>(any_value)->vector_array->size() == 1;
- }
- BLI_assert(false);
- return false;
-}
-
-bool MFNetworkEvaluationStorage::socket_has_buffer_for_output(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- return false;
- }
-
- BLI_assert(ELEM(any_value->type, ValueType::OutputSingle, ValueType::OutputVector));
- return true;
-}
-
-void MFNetworkEvaluationStorage::finish_node(const MFFunctionNode &node)
-{
- for (const MFInputSocket *socket : node.inputs()) {
- this->finish_input_socket(*socket);
- }
- for (const MFOutputSocket *socket : node.outputs()) {
- this->finish_output_socket(*socket);
- }
-}
-
-void MFNetworkEvaluationStorage::finish_output_socket(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- return;
- }
-
- if (ELEM(any_value->type, ValueType::OutputSingle, ValueType::OutputVector)) {
- static_cast<OutputValue *>(any_value)->is_computed = true;
- }
-}
-
-void MFNetworkEvaluationStorage::finish_input_socket(const MFInputSocket &socket)
-{
- const MFOutputSocket &origin = *socket.origin();
-
- Value *any_value = value_per_output_id_[origin.id()];
- if (any_value == nullptr) {
- /* Can happen when a value has been forward to the next node. */
- return;
- }
-
- switch (any_value->type) {
- case ValueType::InputSingle:
- case ValueType::OutputSingle:
- case ValueType::InputVector:
- case ValueType::OutputVector: {
- break;
- }
- case ValueType::OwnSingle: {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(any_value);
- BLI_assert(value->max_remaining_users >= 1);
- value->max_remaining_users--;
- if (value->max_remaining_users == 0) {
- GMutableSpan span = value->span;
- const CPPType &type = span.type();
- if (value->is_single_allocated) {
- type.destruct(span.data());
- }
- else {
- type.destruct_indices(span.data(), mask_);
- MEM_freeN(span.data());
- }
- value_per_output_id_[origin.id()] = nullptr;
- }
- break;
- }
- case ValueType::OwnVector: {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(any_value);
- BLI_assert(value->max_remaining_users >= 1);
- value->max_remaining_users--;
- if (value->max_remaining_users == 0) {
- delete value->vector_array;
- value_per_output_id_[origin.id()] = nullptr;
- }
- break;
- }
- }
-}
-
-void MFNetworkEvaluationStorage::add_single_input_from_caller(const MFOutputSocket &socket,
- const GVArray &virtual_array)
-{
- BLI_assert(value_per_output_id_[socket.id()] == nullptr);
- BLI_assert(virtual_array.size() >= min_array_size_);
-
- auto *value = allocator_.construct<InputSingleValue>(virtual_array).release();
- value_per_output_id_[socket.id()] = value;
-}
-
-void MFNetworkEvaluationStorage::add_vector_input_from_caller(
- const MFOutputSocket &socket, const GVVectorArray &virtual_vector_array)
-{
- BLI_assert(value_per_output_id_[socket.id()] == nullptr);
- BLI_assert(virtual_vector_array.size() >= min_array_size_);
-
- auto *value = allocator_.construct<InputVectorValue>(virtual_vector_array).release();
- value_per_output_id_[socket.id()] = value;
-}
-
-void MFNetworkEvaluationStorage::add_single_output_from_caller(const MFOutputSocket &socket,
- GMutableSpan span)
-{
- BLI_assert(value_per_output_id_[socket.id()] == nullptr);
- BLI_assert(span.size() >= min_array_size_);
-
- auto *value = allocator_.construct<OutputSingleValue>(span).release();
- value_per_output_id_[socket.id()] = value;
-}
-
-void MFNetworkEvaluationStorage::add_vector_output_from_caller(const MFOutputSocket &socket,
- GVectorArray &vector_array)
-{
- BLI_assert(value_per_output_id_[socket.id()] == nullptr);
- BLI_assert(vector_array.size() >= min_array_size_);
-
- auto *value = allocator_.construct<OutputVectorValue>(vector_array).release();
- value_per_output_id_[socket.id()] = value;
-}
-
-GMutableSpan MFNetworkEvaluationStorage::get_single_output__full(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- const CPPType &type = socket.data_type().single_type();
- void *buffer = MEM_mallocN_aligned(min_array_size_ * type.size(), type.alignment(), AT);
- GMutableSpan span(type, buffer, min_array_size_);
-
- auto *value =
- allocator_.construct<OwnSingleValue>(span, socket.targets().size(), false).release();
- value_per_output_id_[socket.id()] = value;
-
- return span;
- }
-
- BLI_assert(any_value->type == ValueType::OutputSingle);
- return static_cast<OutputSingleValue *>(any_value)->span;
-}
-
-GMutableSpan MFNetworkEvaluationStorage::get_single_output__single(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- const CPPType &type = socket.data_type().single_type();
- void *buffer = allocator_.allocate(type.size(), type.alignment());
- GMutableSpan span(type, buffer, 1);
-
- auto *value =
- allocator_.construct<OwnSingleValue>(span, socket.targets().size(), true).release();
- value_per_output_id_[socket.id()] = value;
-
- return value->span;
- }
-
- BLI_assert(any_value->type == ValueType::OutputSingle);
- GMutableSpan span = static_cast<OutputSingleValue *>(any_value)->span;
- BLI_assert(span.size() == 1);
- return span;
-}
-
-GVectorArray &MFNetworkEvaluationStorage::get_vector_output__full(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- const CPPType &type = socket.data_type().vector_base_type();
- GVectorArray *vector_array = new GVectorArray(type, min_array_size_);
-
- auto *value =
- allocator_.construct<OwnVectorValue>(*vector_array, socket.targets().size()).release();
- value_per_output_id_[socket.id()] = value;
-
- return *value->vector_array;
- }
-
- BLI_assert(any_value->type == ValueType::OutputVector);
- return *static_cast<OutputVectorValue *>(any_value)->vector_array;
-}
-
-GVectorArray &MFNetworkEvaluationStorage::get_vector_output__single(const MFOutputSocket &socket)
-{
- Value *any_value = value_per_output_id_[socket.id()];
- if (any_value == nullptr) {
- const CPPType &type = socket.data_type().vector_base_type();
- GVectorArray *vector_array = new GVectorArray(type, 1);
-
- auto *value =
- allocator_.construct<OwnVectorValue>(*vector_array, socket.targets().size()).release();
- value_per_output_id_[socket.id()] = value;
-
- return *value->vector_array;
- }
-
- BLI_assert(any_value->type == ValueType::OutputVector);
- GVectorArray &vector_array = *static_cast<OutputVectorValue *>(any_value)->vector_array;
- BLI_assert(vector_array.size() == 1);
- return vector_array;
-}
-
-GMutableSpan MFNetworkEvaluationStorage::get_mutable_single__full(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope)
-{
- const MFOutputSocket &from = *input.origin();
- const MFOutputSocket &to = output;
- const CPPType &type = from.data_type().single_type();
-
- Value *from_any_value = value_per_output_id_[from.id()];
- Value *to_any_value = value_per_output_id_[to.id()];
- BLI_assert(from_any_value != nullptr);
- BLI_assert(type == to.data_type().single_type());
-
- if (to_any_value != nullptr) {
- BLI_assert(to_any_value->type == ValueType::OutputSingle);
- GMutableSpan span = static_cast<OutputSingleValue *>(to_any_value)->span;
- const GVArray &virtual_array = this->get_single_input__full(input, scope);
- virtual_array.materialize_to_uninitialized(mask_, span.data());
- return span;
- }
-
- if (from_any_value->type == ValueType::OwnSingle) {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(from_any_value);
- if (value->max_remaining_users == 1 && !value->is_single_allocated) {
- value_per_output_id_[to.id()] = value;
- value_per_output_id_[from.id()] = nullptr;
- value->max_remaining_users = to.targets().size();
- return value->span;
- }
- }
-
- const GVArray &virtual_array = this->get_single_input__full(input, scope);
- void *new_buffer = MEM_mallocN_aligned(min_array_size_ * type.size(), type.alignment(), AT);
- GMutableSpan new_array_ref(type, new_buffer, min_array_size_);
- virtual_array.materialize_to_uninitialized(mask_, new_array_ref.data());
-
- OwnSingleValue *new_value =
- allocator_.construct<OwnSingleValue>(new_array_ref, to.targets().size(), false).release();
- value_per_output_id_[to.id()] = new_value;
- return new_array_ref;
-}
-
-GMutableSpan MFNetworkEvaluationStorage::get_mutable_single__single(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope)
-{
- const MFOutputSocket &from = *input.origin();
- const MFOutputSocket &to = output;
- const CPPType &type = from.data_type().single_type();
-
- Value *from_any_value = value_per_output_id_[from.id()];
- Value *to_any_value = value_per_output_id_[to.id()];
- BLI_assert(from_any_value != nullptr);
- BLI_assert(type == to.data_type().single_type());
-
- if (to_any_value != nullptr) {
- BLI_assert(to_any_value->type == ValueType::OutputSingle);
- GMutableSpan span = static_cast<OutputSingleValue *>(to_any_value)->span;
- BLI_assert(span.size() == 1);
- const GVArray &virtual_array = this->get_single_input__single(input, scope);
- virtual_array.get_single_to_uninitialized(span[0]);
- return span;
- }
-
- if (from_any_value->type == ValueType::OwnSingle) {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(from_any_value);
- if (value->max_remaining_users == 1) {
- value_per_output_id_[to.id()] = value;
- value_per_output_id_[from.id()] = nullptr;
- value->max_remaining_users = to.targets().size();
- BLI_assert(value->span.size() == 1);
- return value->span;
- }
- }
-
- const GVArray &virtual_array = this->get_single_input__single(input, scope);
-
- void *new_buffer = allocator_.allocate(type.size(), type.alignment());
- virtual_array.get_single_to_uninitialized(new_buffer);
- GMutableSpan new_array_ref(type, new_buffer, 1);
-
- OwnSingleValue *new_value =
- allocator_.construct<OwnSingleValue>(new_array_ref, to.targets().size(), true).release();
- value_per_output_id_[to.id()] = new_value;
- return new_array_ref;
-}
-
-GVectorArray &MFNetworkEvaluationStorage::get_mutable_vector__full(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope)
-{
- const MFOutputSocket &from = *input.origin();
- const MFOutputSocket &to = output;
- const CPPType &base_type = from.data_type().vector_base_type();
-
- Value *from_any_value = value_per_output_id_[from.id()];
- Value *to_any_value = value_per_output_id_[to.id()];
- BLI_assert(from_any_value != nullptr);
- BLI_assert(base_type == to.data_type().vector_base_type());
-
- if (to_any_value != nullptr) {
- BLI_assert(to_any_value->type == ValueType::OutputVector);
- GVectorArray &vector_array = *static_cast<OutputVectorValue *>(to_any_value)->vector_array;
- const GVVectorArray &virtual_vector_array = this->get_vector_input__full(input, scope);
- vector_array.extend(mask_, virtual_vector_array);
- return vector_array;
- }
-
- if (from_any_value->type == ValueType::OwnVector) {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(from_any_value);
- if (value->max_remaining_users == 1) {
- value_per_output_id_[to.id()] = value;
- value_per_output_id_[from.id()] = nullptr;
- value->max_remaining_users = to.targets().size();
- return *value->vector_array;
- }
- }
-
- const GVVectorArray &virtual_vector_array = this->get_vector_input__full(input, scope);
-
- GVectorArray *new_vector_array = new GVectorArray(base_type, min_array_size_);
- new_vector_array->extend(mask_, virtual_vector_array);
-
- OwnVectorValue *new_value =
- allocator_.construct<OwnVectorValue>(*new_vector_array, to.targets().size()).release();
- value_per_output_id_[to.id()] = new_value;
-
- return *new_vector_array;
-}
-
-GVectorArray &MFNetworkEvaluationStorage::get_mutable_vector__single(const MFInputSocket &input,
- const MFOutputSocket &output,
- ResourceScope &scope)
-{
- const MFOutputSocket &from = *input.origin();
- const MFOutputSocket &to = output;
- const CPPType &base_type = from.data_type().vector_base_type();
-
- Value *from_any_value = value_per_output_id_[from.id()];
- Value *to_any_value = value_per_output_id_[to.id()];
- BLI_assert(from_any_value != nullptr);
- BLI_assert(base_type == to.data_type().vector_base_type());
-
- if (to_any_value != nullptr) {
- BLI_assert(to_any_value->type == ValueType::OutputVector);
- GVectorArray &vector_array = *static_cast<OutputVectorValue *>(to_any_value)->vector_array;
- BLI_assert(vector_array.size() == 1);
- const GVVectorArray &virtual_vector_array = this->get_vector_input__single(input, scope);
- vector_array.extend({0}, virtual_vector_array);
- return vector_array;
- }
-
- if (from_any_value->type == ValueType::OwnVector) {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(from_any_value);
- if (value->max_remaining_users == 1) {
- value_per_output_id_[to.id()] = value;
- value_per_output_id_[from.id()] = nullptr;
- value->max_remaining_users = to.targets().size();
- return *value->vector_array;
- }
- }
-
- const GVVectorArray &virtual_vector_array = this->get_vector_input__single(input, scope);
-
- GVectorArray *new_vector_array = new GVectorArray(base_type, 1);
- new_vector_array->extend({0}, virtual_vector_array);
-
- OwnVectorValue *new_value =
- allocator_.construct<OwnVectorValue>(*new_vector_array, to.targets().size()).release();
- value_per_output_id_[to.id()] = new_value;
- return *new_vector_array;
-}
-
-const GVArray &MFNetworkEvaluationStorage::get_single_input__full(const MFInputSocket &socket,
- ResourceScope &scope)
-{
- const MFOutputSocket &origin = *socket.origin();
- Value *any_value = value_per_output_id_[origin.id()];
- BLI_assert(any_value != nullptr);
-
- if (any_value->type == ValueType::OwnSingle) {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(any_value);
- if (value->is_single_allocated) {
- return scope.construct<GVArray_For_SingleValueRef>(
- __func__, value->span.type(), min_array_size_, value->span.data());
- }
-
- return scope.construct<GVArray_For_GSpan>(__func__, value->span);
- }
- if (any_value->type == ValueType::InputSingle) {
- InputSingleValue *value = static_cast<InputSingleValue *>(any_value);
- return value->virtual_array;
- }
- if (any_value->type == ValueType::OutputSingle) {
- OutputSingleValue *value = static_cast<OutputSingleValue *>(any_value);
- BLI_assert(value->is_computed);
- return scope.construct<GVArray_For_GSpan>(__func__, value->span);
- }
-
- BLI_assert(false);
- return scope.construct<GVArray_For_Empty>(__func__, CPPType::get<float>());
-}
-
-const GVArray &MFNetworkEvaluationStorage::get_single_input__single(const MFInputSocket &socket,
- ResourceScope &scope)
-{
- const MFOutputSocket &origin = *socket.origin();
- Value *any_value = value_per_output_id_[origin.id()];
- BLI_assert(any_value != nullptr);
-
- if (any_value->type == ValueType::OwnSingle) {
- OwnSingleValue *value = static_cast<OwnSingleValue *>(any_value);
- BLI_assert(value->span.size() == 1);
- return scope.construct<GVArray_For_GSpan>(__func__, value->span);
- }
- if (any_value->type == ValueType::InputSingle) {
- InputSingleValue *value = static_cast<InputSingleValue *>(any_value);
- BLI_assert(value->virtual_array.is_single());
- return value->virtual_array;
- }
- if (any_value->type == ValueType::OutputSingle) {
- OutputSingleValue *value = static_cast<OutputSingleValue *>(any_value);
- BLI_assert(value->is_computed);
- BLI_assert(value->span.size() == 1);
- return scope.construct<GVArray_For_GSpan>(__func__, value->span);
- }
-
- BLI_assert(false);
- return scope.construct<GVArray_For_Empty>(__func__, CPPType::get<float>());
-}
-
-const GVVectorArray &MFNetworkEvaluationStorage::get_vector_input__full(
- const MFInputSocket &socket, ResourceScope &scope)
-{
- const MFOutputSocket &origin = *socket.origin();
- Value *any_value = value_per_output_id_[origin.id()];
- BLI_assert(any_value != nullptr);
-
- if (any_value->type == ValueType::OwnVector) {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(any_value);
- if (value->vector_array->size() == 1) {
- GSpan span = (*value->vector_array)[0];
- return scope.construct<GVVectorArray_For_SingleGSpan>(__func__, span, min_array_size_);
- }
-
- return scope.construct<GVVectorArray_For_GVectorArray>(__func__, *value->vector_array);
- }
- if (any_value->type == ValueType::InputVector) {
- InputVectorValue *value = static_cast<InputVectorValue *>(any_value);
- return value->virtual_vector_array;
- }
- if (any_value->type == ValueType::OutputVector) {
- OutputVectorValue *value = static_cast<OutputVectorValue *>(any_value);
- return scope.construct<GVVectorArray_For_GVectorArray>(__func__, *value->vector_array);
- }
-
- BLI_assert(false);
- return scope.construct<GVVectorArray_For_SingleGSpan>(__func__, GSpan(CPPType::get<float>()), 0);
-}
-
-const GVVectorArray &MFNetworkEvaluationStorage::get_vector_input__single(
- const MFInputSocket &socket, ResourceScope &scope)
-{
- const MFOutputSocket &origin = *socket.origin();
- Value *any_value = value_per_output_id_[origin.id()];
- BLI_assert(any_value != nullptr);
-
- if (any_value->type == ValueType::OwnVector) {
- OwnVectorValue *value = static_cast<OwnVectorValue *>(any_value);
- BLI_assert(value->vector_array->size() == 1);
- return scope.construct<GVVectorArray_For_GVectorArray>(__func__, *value->vector_array);
- }
- if (any_value->type == ValueType::InputVector) {
- InputVectorValue *value = static_cast<InputVectorValue *>(any_value);
- BLI_assert(value->virtual_vector_array.is_single_vector());
- return value->virtual_vector_array;
- }
- if (any_value->type == ValueType::OutputVector) {
- OutputVectorValue *value = static_cast<OutputVectorValue *>(any_value);
- BLI_assert(value->vector_array->size() == 1);
- return scope.construct<GVVectorArray_For_GVectorArray>(__func__, *value->vector_array);
- }
-
- BLI_assert(false);
- return scope.construct<GVVectorArray_For_SingleGSpan>(__func__, GSpan(CPPType::get<float>()), 0);
-}
-
-/** \} */
-
-} // namespace blender::fn