This PR adds debug groups to improve using GPU tools like debuggers and profilers. It will try to use the node type as debug group name when available. Pull Request: https://projects.blender.org/blender/blender/pulls/138768
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 (!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
|