This patch takes virtual sockets into consideration in the compositor code base. This mostly involves ignoring them as if they were unavailable. This is needed for use with nodes that use Extend sockets. Pull Request: https://projects.blender.org/blender/blender/pulls/139582
144 lines
3.6 KiB
C++
144 lines
3.6 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 "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 (!is_socket_available(output)) {
|
|
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 (!is_socket_available(input)) {
|
|
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 (!is_socket_available(output)) {
|
|
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 (!is_socket_available(input)) {
|
|
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 (!is_socket_available(output)) {
|
|
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
|