/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_assert.h" #include "BLI_string_ref.hh" #include "BLI_timeit.hh" #include "DNA_node_types.h" #include "NOD_derived_node_tree.hh" #include "BKE_node.hh" #include "GPU_debug.hh" #include "COM_algorithm_compute_preview.hh" #include "COM_context.hh" #include "COM_input_descriptor.hh" #include "COM_node_operation.hh" #include "COM_operation.hh" #include "COM_result.hh" #include "COM_scheduler.hh" #include "COM_utilities.hh" namespace blender::compositor { using namespace nodes::derived_node_tree_types; NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context), node_(node) { for (const bNodeSocket *output : node->output_sockets()) { if (!output->is_available()) { continue; } const ResultType result_type = get_node_socket_result_type(output); populate_result(output->identifier, context.create_result(result_type)); } for (const bNodeSocket *input : node->input_sockets()) { if (!input->is_available()) { continue; } const InputDescriptor input_descriptor = input_descriptor_from_input_socket(input); declare_input_descriptor(input->identifier, input_descriptor); } } void NodeOperation::evaluate() { if (context().use_gpu()) { GPU_debug_group_begin(node().bnode()->typeinfo->idname.c_str()); } const timeit::TimePoint before_time = timeit::Clock::now(); Operation::evaluate(); const timeit::TimePoint after_time = timeit::Clock::now(); if (context().profiler()) { context().profiler()->set_node_evaluation_time(node_.instance_key(), after_time - before_time); } if (context().use_gpu()) { GPU_debug_group_end(); } } void NodeOperation::compute_preview() { if (bool(context().needed_outputs() & OutputTypes::Previews) && is_node_preview_needed(node())) { const Result *result = get_preview_result(); if (result) { compositor::compute_preview(context(), node(), *result); } } } Result *NodeOperation::get_preview_result() { /* Find the first linked output. */ for (const bNodeSocket *output : node()->output_sockets()) { if (!output->is_available()) { continue; } Result &output_result = get_result(output->identifier); if (output_result.should_compute()) { return &output_result; } } /* No linked outputs, but no inputs either, so nothing to preview. */ if (node()->input_sockets().is_empty()) { return nullptr; } /* Find the first allocated input. */ for (const bNodeSocket *input : node()->input_sockets()) { if (!input->is_available()) { continue; } Result &input_result = get_input(input->identifier); if (input_result.is_allocated()) { return &input_result; } } BLI_assert_unreachable(); return nullptr; } void NodeOperation::compute_results_reference_counts(const Schedule &schedule) { for (const bNodeSocket *output : this->node()->output_sockets()) { if (!output->is_available()) { continue; } const DOutputSocket doutput{node().context(), output}; const int reference_count = number_of_inputs_linked_to_output_conditioned( doutput, [&](DInputSocket input) { return schedule.contains(input.node()); }); get_result(doutput->identifier).set_reference_count(reference_count); } } const DNode &NodeOperation::node() const { return node_; } const bNode &NodeOperation::bnode() const { return *node_; } bool NodeOperation::should_compute_output(StringRef identifier) { return get_result(identifier).should_compute(); } } // namespace blender::compositor