This patch allows the compositor context to specify exactly which outputs it needs, selecting from: Composite, Viewer, File Output, and Previews. Previously, the compositor fully executed if any of those were needed, without granular control on which outputs are needed exactly. For the viewport compositor engine, it requests Composite and Viewer, with no Previews or File Outputs. For the render pipeline, it requests Composite and File Output, with node Viewer or Previews. For the interactive compositor, it requests Viewer if the backdrop is visible or an image editor with the viewer image is visible, it requests Compositor if an image editor with the render result is visible, it requests Previews if a node editor has previews overlay enabled. File outputs are never requested. Pull Request: https://projects.blender.org/blender/blender/pulls/133960
108 lines
2.9 KiB
C++
108 lines
2.9 KiB
C++
/* 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 "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()) {
|
|
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()) {
|
|
const InputDescriptor input_descriptor = input_descriptor_from_input_socket(input);
|
|
declare_input_descriptor(input->identifier, input_descriptor);
|
|
}
|
|
}
|
|
|
|
void NodeOperation::evaluate()
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
void NodeOperation::compute_preview()
|
|
{
|
|
if (bool(context().needed_outputs() & OutputTypes::Previews) && is_node_preview_needed(node())) {
|
|
compositor::compute_preview(context(), node(), *get_preview_result());
|
|
}
|
|
}
|
|
|
|
Result *NodeOperation::get_preview_result()
|
|
{
|
|
/* Find the first linked output. */
|
|
for (const bNodeSocket *output : node()->output_sockets()) {
|
|
Result &output_result = get_result(output->identifier);
|
|
if (output_result.should_compute()) {
|
|
return &output_result;
|
|
}
|
|
}
|
|
|
|
/* No linked outputs, find the first allocated input. */
|
|
for (const bNodeSocket *input : node()->input_sockets()) {
|
|
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()) {
|
|
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_initial_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
|