Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/intern/geometry_nodes_lazy_function.cc
| Show First 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | void execute_impl(lf::Params ¶ms, const lf::Context &context) const override | ||||
| geo_eval_log::TimePoint start_time = geo_eval_log::Clock::now(); | geo_eval_log::TimePoint start_time = geo_eval_log::Clock::now(); | ||||
| node_.typeinfo->geometry_node_execute(geo_params); | node_.typeinfo->geometry_node_execute(geo_params); | ||||
| geo_eval_log::TimePoint end_time = geo_eval_log::Clock::now(); | geo_eval_log::TimePoint end_time = geo_eval_log::Clock::now(); | ||||
| if (geo_eval_log::GeoModifierLog *modifier_log = user_data->modifier_data->eval_log) { | if (geo_eval_log::GeoModifierLog *modifier_log = user_data->modifier_data->eval_log) { | ||||
| geo_eval_log::GeoTreeLogger &tree_logger = modifier_log->get_local_tree_logger( | geo_eval_log::GeoTreeLogger &tree_logger = modifier_log->get_local_tree_logger( | ||||
| *user_data->compute_context); | *user_data->compute_context); | ||||
| tree_logger.node_execution_times.append({node_.name, start_time, end_time}); | tree_logger.node_execution_times.append( | ||||
| {tree_logger.allocator->copy_string(node_.name), start_time, end_time}); | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| /** | /** | ||||
| * Used to gather all inputs of a multi-input socket. A separate node is necessary, because | * Used to gather all inputs of a multi-input socket. A separate node is necessary, because | ||||
| * multi-inputs are not supported in lazy-function graphs. | * multi-inputs are not supported in lazy-function graphs. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | void execute_impl(lf::Params ¶ms, const lf::Context &UNUSED(context)) const override | ||||
| BLI_assert(output_value != nullptr); | BLI_assert(output_value != nullptr); | ||||
| const CPPType &type = *inputs_[0].type; | const CPPType &type = *inputs_[0].type; | ||||
| type.move_construct(input_value, output_value); | type.move_construct(input_value, output_value); | ||||
| params.output_set(0); | params.output_set(0); | ||||
| } | } | ||||
| }; | }; | ||||
| /** | /** | ||||
| * Lazy functions for nodes whose type cannot be found. An undefined function just outputs default | |||||
| * values. It's useful to have so other parts of the conversion don't have to care about undefined | |||||
| * nodes. | |||||
| */ | |||||
| class LazyFunctionForUndefinedNode : public LazyFunction { | |||||
| public: | |||||
| LazyFunctionForUndefinedNode(const bNode &node, Vector<const bNodeSocket *> &r_used_outputs) | |||||
| { | |||||
| debug_name_ = "Undefined"; | |||||
| Vector<const bNodeSocket *> dummy_used_inputs; | |||||
| Vector<lf::Input> dummy_inputs; | |||||
| lazy_function_interface_from_node( | |||||
| node, dummy_used_inputs, r_used_outputs, dummy_inputs, outputs_); | |||||
| } | |||||
| void execute_impl(lf::Params ¶ms, const lf::Context &UNUSED(context)) const override | |||||
| { | |||||
| params.set_default_remaining_outputs(); | |||||
| } | |||||
| }; | |||||
| /** | |||||
| * Executes a multi-function. If all inputs are single values, the results will also be single | * Executes a multi-function. If all inputs are single values, the results will also be single | ||||
| * values. If any input is a field, the outputs will also be fields. | * values. If any input is a field, the outputs will also be fields. | ||||
| */ | */ | ||||
| static void execute_multi_function_on_value_or_field( | static void execute_multi_function_on_value_or_field( | ||||
| const MultiFunction &fn, | const MultiFunction &fn, | ||||
| const std::shared_ptr<MultiFunction> &owned_fn, | const std::shared_ptr<MultiFunction> &owned_fn, | ||||
| const Span<const ValueOrFieldCPPType *> input_types, | const Span<const ValueOrFieldCPPType *> input_types, | ||||
| const Span<const ValueOrFieldCPPType *> output_types, | const Span<const ValueOrFieldCPPType *> output_types, | ||||
| ▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * This lazy-function wraps nodes that are implemented as multi-function (mostly math nodes). | * This lazy-function wraps nodes that are implemented as multi-function (mostly math nodes). | ||||
| */ | */ | ||||
| class LazyFunctionForMultiFunctionNode : public LazyFunction { | class LazyFunctionForMultiFunctionNode : public LazyFunction { | ||||
| private: | private: | ||||
| const NodeMultiFunctions::Item fn_item_; | const NodeMultiFunctions::Item fn_item_; | ||||
| Vector<const ValueOrFieldCPPType *> input_types_; | Vector<const ValueOrFieldCPPType *> input_types_; | ||||
| Vector<const ValueOrFieldCPPType *> output_types_; | Vector<const ValueOrFieldCPPType *> output_types_; | ||||
| Vector<const bNodeSocket *> output_sockets_; | |||||
| public: | public: | ||||
| LazyFunctionForMultiFunctionNode(const bNode &node, | LazyFunctionForMultiFunctionNode(const bNode &node, | ||||
| NodeMultiFunctions::Item fn_item, | NodeMultiFunctions::Item fn_item, | ||||
| Vector<const bNodeSocket *> &r_used_inputs, | Vector<const bNodeSocket *> &r_used_inputs, | ||||
| Vector<const bNodeSocket *> &r_used_outputs) | Vector<const bNodeSocket *> &r_used_outputs) | ||||
| : fn_item_(std::move(fn_item)) | : fn_item_(std::move(fn_item)) | ||||
| { | { | ||||
| BLI_assert(fn_item_.fn != nullptr); | BLI_assert(fn_item_.fn != nullptr); | ||||
| debug_name_ = node.name; | debug_name_ = node.name; | ||||
| lazy_function_interface_from_node(node, r_used_inputs, r_used_outputs, inputs_, outputs_); | lazy_function_interface_from_node(node, r_used_inputs, r_used_outputs, inputs_, outputs_); | ||||
| for (const lf::Input &fn_input : inputs_) { | for (const lf::Input &fn_input : inputs_) { | ||||
| input_types_.append(dynamic_cast<const ValueOrFieldCPPType *>(fn_input.type)); | input_types_.append(dynamic_cast<const ValueOrFieldCPPType *>(fn_input.type)); | ||||
| } | } | ||||
| for (const lf::Output &fn_output : outputs_) { | for (const lf::Output &fn_output : outputs_) { | ||||
| output_types_.append(dynamic_cast<const ValueOrFieldCPPType *>(fn_output.type)); | output_types_.append(dynamic_cast<const ValueOrFieldCPPType *>(fn_output.type)); | ||||
| } | } | ||||
| output_sockets_ = r_used_outputs; | |||||
| } | } | ||||
| void execute_impl(lf::Params ¶ms, const lf::Context &UNUSED(context)) const override | void execute_impl(lf::Params ¶ms, const lf::Context &UNUSED(context)) const override | ||||
| { | { | ||||
| Vector<const void *> input_values(inputs_.size()); | Vector<const void *> input_values(inputs_.size()); | ||||
| Vector<void *> output_values(outputs_.size()); | Vector<void *> output_values(outputs_.size()); | ||||
| for (const int i : inputs_.index_range()) { | for (const int i : inputs_.index_range()) { | ||||
| input_values[i] = params.try_get_input_data_ptr(i); | input_values[i] = params.try_get_input_data_ptr(i); | ||||
| ▲ Show 20 Lines • Show All 321 Lines • ▼ Show 20 Lines | for (const bNode *bnode : btree_.all_nodes()) { | ||||
| if (node_type->geometry_node_execute) { | if (node_type->geometry_node_execute) { | ||||
| this->handle_geometry_node(*bnode); | this->handle_geometry_node(*bnode); | ||||
| break; | break; | ||||
| } | } | ||||
| const NodeMultiFunctions::Item &fn_item = lf_graph_info_->node_multi_functions->try_get( | const NodeMultiFunctions::Item &fn_item = lf_graph_info_->node_multi_functions->try_get( | ||||
| *bnode); | *bnode); | ||||
| if (fn_item.fn != nullptr) { | if (fn_item.fn != nullptr) { | ||||
| this->handle_multi_function_node(*bnode, fn_item); | this->handle_multi_function_node(*bnode, fn_item); | ||||
| break; | |||||
| } | |||||
| if (node_type == &NodeTypeUndefined) { | |||||
| this->handle_undefined_node(*bnode); | |||||
| break; | |||||
| } | } | ||||
| /* Nodes that don't match any of the criteria above are just ignored. */ | /* Nodes that don't match any of the criteria above are just ignored. */ | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | for (const int i : used_inputs.index_range()) { | ||||
| lf::InputSocket &lf_socket = lf_node.input(i); | lf::InputSocket &lf_socket = lf_node.input(i); | ||||
| input_socket_map_.add(&bsocket, &lf_socket); | input_socket_map_.add(&bsocket, &lf_socket); | ||||
| mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket); | mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket); | ||||
| } | } | ||||
| mapping_->viewer_node_map.add(&bnode, &lf_node); | mapping_->viewer_node_map.add(&bnode, &lf_node); | ||||
| } | } | ||||
| void handle_undefined_node(const bNode &bnode) | |||||
| { | |||||
| Vector<const bNodeSocket *> used_outputs; | |||||
| auto lazy_function = std::make_unique<LazyFunctionForUndefinedNode>(bnode, used_outputs); | |||||
| lf::FunctionNode &lf_node = lf_graph_->add_function(*lazy_function); | |||||
| lf_graph_info_->functions.append(std::move(lazy_function)); | |||||
| for (const int i : used_outputs.index_range()) { | |||||
| const bNodeSocket &bsocket = *used_outputs[i]; | |||||
| lf::OutputSocket &lf_socket = lf_node.output(i); | |||||
| output_socket_map_.add(&bsocket, &lf_socket); | |||||
| mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket); | |||||
| } | |||||
| } | |||||
| void handle_links() | void handle_links() | ||||
| { | { | ||||
| for (const auto item : output_socket_map_.items()) { | for (const auto item : output_socket_map_.items()) { | ||||
| this->insert_links_from_socket(*item.key, *item.value); | this->insert_links_from_socket(*item.key, *item.value); | ||||
| } | } | ||||
| } | } | ||||
| void insert_links_from_socket(const bNodeSocket &from_bsocket, lf::OutputSocket &from_lf_socket) | void insert_links_from_socket(const bNodeSocket &from_bsocket, lf::OutputSocket &from_lf_socket) | ||||
| ▲ Show 20 Lines • Show All 342 Lines • Show Last 20 Lines | |||||