Compositor: Add GPU per-node execution time report

This patch adds support for timing GPU compositor executions. This was
previously not possible since there was no mechanism to measure GPU
calls, which is still the case. However, since 2cf8b5c4e1, we now flush
GPU calls immediately for interactive editing, so we can now measure the
GPU evaluation on the host, which is not a very accurate method, but it
is better than having no timing information. Therefore, timing is only
implemented for interactive editing.

This is different from the CPU implementation in that it measures the
total evaluation time, including any preprocessing of the inputs like
implicit type conversion as well as things like previews.

The profiling implementation was moved to the realtime compositor since
the compositor module is optional.

Pull Request: https://projects.blender.org/blender/blender/pulls/122230
This commit is contained in:
Omar Emara
2024-05-28 08:13:46 +02:00
committed by Omar Emara
parent aea2ac4c78
commit 0dca908191
29 changed files with 269 additions and 214 deletions

View File

@@ -34,7 +34,6 @@ if(WITH_COMPOSITOR_CPU)
set(SRC
COM_compositor.hh
COM_defines.h
COM_profile.hh
intern/COM_BufferArea.h
intern/COM_BufferRange.h
@@ -83,7 +82,6 @@ if(WITH_COMPOSITOR_CPU)
intern/COM_WorkScheduler.cc
intern/COM_WorkScheduler.h
intern/COM_compositor.cc
intern/COM_profile.cc
# Internal nodes
nodes/COM_SocketProxyNode.cc

View File

@@ -9,10 +9,8 @@
namespace blender::realtime_compositor {
class RenderContext;
}
namespace blender::compositor {
class ProfilerData;
}
class Profiler;
} // namespace blender::realtime_compositor
struct Render;
@@ -104,7 +102,7 @@ void COM_execute(Render *render,
bNodeTree *node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context,
blender::compositor::ProfilerData &profiler_data);
blender::realtime_compositor::Profiler *profiler);
/**
* \brief Deinitialize the compositor caches and allocated memory.

View File

@@ -1,58 +0,0 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_map.hh"
#include "BLI_timeit.hh"
#include "DNA_node_types.h"
#include "BKE_node.hh"
struct bNodeTree;
namespace blender::compositor {
class NodeOperation;
/* Profiling data gathered during execution of a compositing node tree. */
class ProfilerData {
public:
/* Per-node accumulated execution time. Includes execution time of all operations the node was
* broken down into. */
Map<bNodeInstanceKey, timeit::Nanoseconds> per_node_execution_time;
};
/* Profiler implementation which is used by the node execution system. */
class Profiler {
/* Local copy of the profiling data, which is known to not cause threading conflicts with the
* interface thread while the compositing tree is evaluated in the background. */
ProfilerData data_;
public:
void add_operation_execution_time(const NodeOperation &operation,
const timeit::TimePoint &start,
const timeit::TimePoint &end);
void finalize(const bNodeTree &node_tree);
const ProfilerData &get_data() const
{
return data_;
}
private:
/* Add execution time to the node denoted by its key. */
void add_execution_time(const bNodeInstanceKey parent_key,
const timeit::Nanoseconds &execution_time);
/* Accumulate execution time of the group node instances, and store their execution time in the
* per_node_execution_time_.
* Returns total execution time of the given node tree. */
timeit::Nanoseconds accumulate_node_group_times(
const bNodeTree &node_tree, const bNodeInstanceKey parent_key = bke::NODE_INSTANCE_KEY_BASE);
};
} // namespace blender::compositor

View File

@@ -16,7 +16,8 @@ struct bNodeInstanceHash;
namespace blender::realtime_compositor {
class RenderContext;
}
class Profiler;
} // namespace blender::realtime_compositor
namespace blender::compositor {
@@ -65,6 +66,12 @@ class CompositorContext {
*/
realtime_compositor::RenderContext *render_context_;
/**
* \brief Profiler that stores timing information about compositor execution. Can be null if the
* compositor context does not support profiling.
*/
realtime_compositor::Profiler *profiler_;
public:
/**
* \brief constructor initializes the context with default values.
@@ -171,6 +178,22 @@ class CompositorContext {
render_context_ = render_context;
}
/**
* \brief get the profiler
*/
realtime_compositor::Profiler *get_profiler() const
{
return profiler_;
}
/**
* \brief set the profiler
*/
void set_profiler(realtime_compositor::Profiler *profiler)
{
profiler_ = profiler;
}
/**
* \brief get the active rendering view
*/

View File

@@ -12,8 +12,6 @@
# include "MEM_guardedalloc.h"
#endif
#include "COM_profile.hh"
namespace blender::compositor {
class CompositorContext;
@@ -46,8 +44,6 @@ class ExecutionModel {
*/
Span<NodeOperation *> operations_;
Profiler profiler_;
public:
ExecutionModel(CompositorContext &context, Span<NodeOperation *> operations);
@@ -55,11 +51,6 @@ class ExecutionModel {
virtual void execute(ExecutionSystem &exec_system) = 0;
const ProfilerData &get_profiler_data() const
{
return profiler_.get_data();
}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:BaseExecutionModel")
#endif

View File

@@ -11,6 +11,8 @@
#include "COM_WorkPackage.h"
#include "COM_WorkScheduler.h"
#include "COM_profiler.hh"
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
@@ -23,11 +25,11 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
bool rendering,
const char *view_name,
realtime_compositor::RenderContext *render_context,
ProfilerData &profiler_data)
: profiler_data_(profiler_data)
realtime_compositor::Profiler *profiler)
{
num_work_threads_ = WorkScheduler::get_num_cpu_threads();
context_.set_render_context(render_context);
context_.set_profiler(profiler);
context_.set_view_name(view_name);
context_.set_scene(scene);
context_.set_bnodetree(editingtree);
@@ -72,8 +74,9 @@ void ExecutionSystem::execute()
op->init_data();
}
execution_model_->execute(*this);
profiler_data_ = execution_model_->get_profiler_data();
if (context_.get_profiler()) {
context_.get_profiler()->finalize(*context_.get_bnodetree());
}
}
void ExecutionSystem::execute_work(const rcti &work_rect,

View File

@@ -22,12 +22,11 @@
namespace blender::realtime_compositor {
class RenderContext;
}
class Profiler;
} // namespace blender::realtime_compositor
namespace blender::compositor {
class ProfilerData;
/**
* \page execution Execution model
* In order to get to an efficient model for execution, several steps are being done. these steps
@@ -122,8 +121,6 @@ class ExecutionSystem {
ThreadMutex work_mutex_;
ThreadCondition work_finished_cond_;
ProfilerData &profiler_data_;
public:
/**
* \brief Create a new ExecutionSystem and initialize it with the
@@ -138,7 +135,7 @@ class ExecutionSystem {
bool rendering,
const char *view_name,
realtime_compositor::RenderContext *render_context,
ProfilerData &profiler_data);
realtime_compositor::Profiler *profiler);
/**
* Destructor

View File

@@ -12,6 +12,8 @@
#include "COM_ViewerOperation.h"
#include "COM_WorkScheduler.h"
#include "COM_profiler.hh"
#include "BLI_timeit.hh"
#ifdef WITH_CXX_GUARDEDALLOC
@@ -42,8 +44,6 @@ void FullFrameExecutionModel::execute(ExecutionSystem &exec_system)
determine_areas_to_render_and_reads();
render_operations();
profiler_.finalize(*node_tree);
}
void FullFrameExecutionModel::determine_areas_to_render_and_reads()
@@ -103,7 +103,7 @@ void FullFrameExecutionModel::render_operation(NodeOperation *op)
constexpr int output_x = 0;
constexpr int output_y = 0;
const timeit::TimePoint time_start = timeit::Clock::now();
const timeit::TimePoint before_time = timeit::Clock::now();
const bool has_outputs = op->get_number_of_output_sockets() > 0;
MemoryBuffer *op_buf = has_outputs ? create_operation_buffer(op, output_x, output_y) : nullptr;
@@ -125,7 +125,13 @@ void FullFrameExecutionModel::render_operation(NodeOperation *op)
operation_finished(op);
profiler_.add_operation_execution_time(*op, time_start, timeit::Clock::now());
/* The operation may not come from any node. For example, it may have been added to convert data
* type. Do not accumulate time from its execution. */
const timeit::TimePoint after_time = timeit::Clock::now();
const bNodeInstanceKey node_instance_key = op->get_node_instance_key();
if (context_.get_profiler() && node_instance_key != bke::NODE_INSTANCE_KEY_NONE) {
context_.get_profiler()->set_node_evaluation_time(node_instance_key, after_time - before_time);
}
}
void FullFrameExecutionModel::render_operations()

View File

@@ -55,7 +55,7 @@ void COM_execute(Render *render,
bNodeTree *node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context,
blender::compositor::ProfilerData &profiler_data)
blender::realtime_compositor::Profiler *profiler)
{
/* Initialize mutex, TODO: this mutex init is actually not thread safe and
* should be done somewhere as part of blender startup, all the other
@@ -79,7 +79,8 @@ void COM_execute(Render *render,
if (scene->r.compositor_device == SCE_COMPOSITOR_DEVICE_GPU) {
/* GPU compositor. */
RE_compositor_execute(*render, *scene, *render_data, *node_tree, view_name, render_context);
RE_compositor_execute(
*render, *scene, *render_data, *node_tree, view_name, render_context, profiler);
}
else {
/* CPU compositor. */
@@ -90,7 +91,7 @@ void COM_execute(Render *render,
/* Execute. */
const bool is_rendering = render_context != nullptr;
blender::compositor::ExecutionSystem system(
render_data, scene, node_tree, is_rendering, view_name, render_context, profiler_data);
render_data, scene, node_tree, is_rendering, view_name, render_context, profiler);
system.execute();
}

View File

@@ -1,76 +0,0 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_profile.hh"
#include "BKE_node_runtime.hh"
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
namespace blender::compositor {
void Profiler::add_operation_execution_time(const NodeOperation &operation,
const timeit::TimePoint &start,
const timeit::TimePoint &end)
{
const timeit::Nanoseconds execution_time = end - start;
const bNodeInstanceKey key = operation.get_node_instance_key();
if (key.value == bke::NODE_INSTANCE_KEY_NONE.value) {
/* The operation does not come from any node. It was, for example, added to convert data type.
* Do not accumulate time from its execution. */
return;
}
this->add_execution_time(key, execution_time);
}
void Profiler::add_execution_time(const bNodeInstanceKey key,
const timeit::Nanoseconds &execution_time)
{
data_.per_node_execution_time.lookup_or_add(key, timeit::Nanoseconds(0)) += execution_time;
}
void Profiler::finalize(const bNodeTree &node_tree)
{
this->accumulate_node_group_times(node_tree);
}
timeit::Nanoseconds Profiler::accumulate_node_group_times(const bNodeTree &node_tree,
const bNodeInstanceKey parent_key)
{
timeit::Nanoseconds tree_execution_time(0);
for (const bNode *node : node_tree.all_nodes()) {
const bNodeInstanceKey key = bke::BKE_node_instance_key(parent_key, &node_tree, node);
if (node->type != NODE_GROUP) {
/* Non-group node, no need to recurse into. Simply accumulate the node's execution time to
* the current tree's execution time. */
tree_execution_time += data_.per_node_execution_time.lookup_default(key,
timeit::Nanoseconds(0));
continue;
}
if (node->id == nullptr) {
/* Node group has lost link to its node tree. For example, due to missing linked file. */
continue;
}
const timeit::Nanoseconds group_execution_time = this->accumulate_node_group_times(
*reinterpret_cast<const bNodeTree *>(node->id), key);
/* Store execution time of the group node. */
this->add_execution_time(key, group_execution_time);
/* Add group execution time to the overall tree execution time. */
tree_execution_time += group_execution_time;
}
return tree_execution_time;
}
} // namespace blender::compositor

View File

@@ -30,6 +30,7 @@ set(SRC
intern/input_single_value_operation.cc
intern/node_operation.cc
intern/operation.cc
intern/profiler.cc
intern/realize_on_domain_operation.cc
intern/reduce_to_single_value_operation.cc
intern/render_context.cc
@@ -51,6 +52,7 @@ set(SRC
COM_input_single_value_operation.hh
COM_node_operation.hh
COM_operation.hh
COM_profiler.hh
COM_realize_on_domain_operation.hh
COM_reduce_to_single_value_operation.hh
COM_render_context.hh

View File

@@ -15,6 +15,7 @@
#include "GPU_texture.hh"
#include "COM_domain.hh"
#include "COM_profiler.hh"
#include "COM_render_context.hh"
#include "COM_result.hh"
#include "COM_static_cache_manager.hh"
@@ -112,6 +113,10 @@ class Context {
* render pipeline. */
virtual RenderContext *render_context() const;
/* Get a pointer to the profiler of this context. It might be null if the compositor context does
* not support profiling. */
virtual Profiler *profiler() const;
/* Gets called after the evaluation of each compositor operation. See overrides for possible
* uses. */
virtual void evaluate_operation_post() const;
@@ -120,6 +125,10 @@ class Context {
* executing as soon as possible. */
virtual bool is_canceled() const;
/* Resets the context's internal structures like texture pool and cache manager. This should be
* called before every evaluation. */
void reset();
/* Get the size of the compositing region. See get_compositing_region(). The output size is
* sanitized such that it is at least 1 in both dimensions. However, the developer is expected to
* gracefully handled zero sizes regions by checking the is_valid_compositing_region method. */

View File

@@ -38,6 +38,10 @@ class NodeOperation : public Operation {
* on the node inputs. */
NodeOperation(Context &context, DNode node);
/* Calls the evaluate method of the operation, but also measures the execution time and stores it
* in the context's profile data. */
void evaluate() override;
/* Compute and set the initial reference counts of all the results of the operation. The
* reference counts of the results are the number of operations that use those results, which is
* computed as the number of inputs whose node is part of the schedule and is linked to the

View File

@@ -94,7 +94,7 @@ class Operation {
* 2. Resetting the results of the operation.
* 3. Calling the execute method of the operation.
* 4. Releasing the results mapped to the inputs. */
void evaluate();
virtual void evaluate();
/* Get a reference to the output result identified by the given identifier. */
Result &get_result(StringRef identifier);

View File

@@ -0,0 +1,49 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_map.hh"
#include "BLI_timeit.hh"
#include "DNA_node_types.h"
#include "NOD_derived_node_tree.hh"
namespace blender::realtime_compositor {
class Context;
/* -------------------------------------------------------------------------------------------------
* Profiler
*
* A class that profiles the evaluation of the compositor and tracks information like the
* evaluation time of every node. */
class Profiler {
private:
/* Stores the evaluation time of each node instance keyed by its instance key. Note that
* pixel-wise nodes like Math nodes will not be measured, that's because they are compiled
* together with other pixel-wise operations in a single operation, so we can't measure the
* evaluation time of each individual node. */
Map<bNodeInstanceKey, timeit::Nanoseconds> nodes_evaluation_times_;
public:
/* Returns a reference to the nodes evaluation times. */
Map<bNodeInstanceKey, timeit::Nanoseconds> &get_nodes_evaluation_times();
/* Set the evaluation time of the node identified by the given node instance key. */
void set_node_evaluation_time(bNodeInstanceKey node_instance_key, timeit::Nanoseconds time);
/* Finalize profiling by computing node group times. This should be called after evaluation. */
void finalize(const bNodeTree &node_tree);
private:
/* Computes the evaluation time of every group node inside the given tree recursively by
* accumulating the evaluation time of its nodes, setting the computed time to the group nodes.
* The time is returned since the method is called recursively. */
timeit::Nanoseconds accumulate_node_group_times(const bNodeTree &node_tree,
bNodeInstanceKey instance_key);
};
} // namespace blender::realtime_compositor

View File

@@ -13,6 +13,7 @@
#include "BKE_node_runtime.hh"
#include "COM_context.hh"
#include "COM_profiler.hh"
#include "COM_render_context.hh"
#include "COM_static_cache_manager.hh"
#include "COM_texture_pool.hh"
@@ -26,6 +27,11 @@ RenderContext *Context::render_context() const
return nullptr;
}
Profiler *Context::profiler() const
{
return nullptr;
}
void Context::evaluate_operation_post() const {}
bool Context::is_canceled() const
@@ -36,6 +42,12 @@ bool Context::is_canceled() const
return this->get_node_tree().runtime->test_break(get_node_tree().runtime->tbh);
}
void Context::reset()
{
texture_pool_.reset();
cache_manager_.reset();
}
int2 Context::get_compositing_region_size() const
{
const rcti compositing_region = get_compositing_region();

View File

@@ -27,19 +27,22 @@ Evaluator::Evaluator(Context &context) : context_(context) {}
void Evaluator::evaluate()
{
context_.cache_manager().reset();
context_.texture_pool().reset();
context_.reset();
if (!is_compiled_) {
compile_and_evaluate();
return;
}
else {
for (const std::unique_ptr<Operation> &operation : operations_stream_) {
if (context_.is_canceled()) {
break;
}
operation->evaluate();
}
}
for (const std::unique_ptr<Operation> &operation : operations_stream_) {
if (context_.is_canceled()) {
return;
}
operation->evaluate();
if (context_.profiler()) {
context_.profiler()->finalize(context_.get_node_tree());
}
}

View File

@@ -10,6 +10,7 @@
#include "BLI_math_base.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string_ref.hh"
#include "BLI_timeit.hh"
#include "BLI_vector.hh"
#include "GPU_shader.hh"
@@ -47,6 +48,16 @@ NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context),
}
}
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 (is_node_preview_needed(node())) {

View File

@@ -0,0 +1,72 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_timeit.hh"
#include "DNA_node_types.h"
#include "BKE_node.hh"
#include "NOD_derived_node_tree.hh"
#include "COM_context.hh"
#include "COM_profiler.hh"
namespace blender::realtime_compositor {
Map<bNodeInstanceKey, timeit::Nanoseconds> &Profiler::get_nodes_evaluation_times()
{
return nodes_evaluation_times_;
}
void Profiler::set_node_evaluation_time(bNodeInstanceKey node_instance_key,
timeit::Nanoseconds time)
{
nodes_evaluation_times_.lookup_or_add(node_instance_key, timeit::Nanoseconds::zero()) += time;
}
timeit::Nanoseconds Profiler::accumulate_node_group_times(const bNodeTree &node_tree,
bNodeInstanceKey instance_key)
{
timeit::Nanoseconds tree_evaluation_time = timeit::Nanoseconds::zero();
for (const bNode *node : node_tree.all_nodes()) {
const bNodeInstanceKey node_instance_key = bke::BKE_node_instance_key(
instance_key, &node_tree, node);
if (!node->is_group()) {
/* Non-group node, no need to recurse into. Simply accumulate the node's evaluation time to
* the current tree's evaluation time. Note that not everey node might have an evaluation
* time stored, so default to zero. See the documentation on nodes_evaluation_times_ for more
* information. */
tree_evaluation_time += nodes_evaluation_times_.lookup_default(node_instance_key,
timeit::Nanoseconds::zero());
continue;
}
const bNodeTree *child_tree = reinterpret_cast<bNodeTree *>(node->id);
if (child_tree == nullptr) {
/* Node group has lost link to its node tree. For example, due to missing linked file. */
continue;
}
const timeit::Nanoseconds group_execution_time = this->accumulate_node_group_times(
*child_tree, node_instance_key);
/* Set evaluation time of the group node. */
this->set_node_evaluation_time(node_instance_key, group_execution_time);
/* Add group evaluation time to the overall tree execution time. */
tree_evaluation_time += group_execution_time;
}
return tree_evaluation_time;
}
void Profiler::finalize(const bNodeTree &node_tree)
{
/* Compute the evaluation time of all node groups starting from the root tree. */
this->accumulate_node_group_times(node_tree, bke::NODE_INSTANCE_KEY_BASE);
}
} // namespace blender::realtime_compositor

View File

@@ -10,6 +10,7 @@ set(INC
../../blenloader
../../blentranslation
../../compositor
../../compositor/realtime_compositor
../../draw
../../functions
../../geometry
@@ -58,6 +59,7 @@ set(LIB
PRIVATE bf::dna
bf_editor_screen
PRIVATE bf::intern::guardedalloc
bf_realtime_compositor
PRIVATE bf::extern::fmtlib
)

View File

@@ -94,8 +94,6 @@
#include "GEO_fillet_curves.hh"
#include "COM_profile.hh"
#include "node_intern.hh" /* own include */
#include <fmt/format.h>

View File

@@ -69,7 +69,7 @@
#include "NOD_texture.h"
#include "node_intern.hh" /* own include */
#include "COM_profile.hh"
#include "COM_profiler.hh"
namespace blender::ed::space_node {
@@ -102,7 +102,7 @@ struct CompoJob {
float *progress;
bool cancelled;
blender::compositor::ProfilerData profiler_data;
realtime_compositor::Profiler profiler;
};
float node_socket_calculate_height(const bNodeSocket &socket)
@@ -296,7 +296,7 @@ static void compo_startjob(void *cjv, wmJobWorkerStatus *worker_status)
BKE_callback_exec_id(cj->bmain, &scene->id, BKE_CB_EVT_COMPOSITE_PRE);
if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
ntreeCompositExecTree(cj->re, cj->scene, ntree, &cj->scene->r, "", nullptr, cj->profiler_data);
ntreeCompositExecTree(cj->re, cj->scene, ntree, &cj->scene->r, "", nullptr, &cj->profiler);
}
else {
LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) {
@@ -304,7 +304,7 @@ static void compo_startjob(void *cjv, wmJobWorkerStatus *worker_status)
continue;
}
ntreeCompositExecTree(
cj->re, cj->scene, ntree, &cj->scene->r, srv->name, nullptr, cj->profiler_data);
cj->re, cj->scene, ntree, &cj->scene->r, srv->name, nullptr, &cj->profiler);
}
}
@@ -321,7 +321,7 @@ static void compo_canceljob(void *cjv)
BKE_callback_exec_id(bmain, &scene->id, BKE_CB_EVT_COMPOSITE_CANCEL);
cj->cancelled = true;
scene->runtime->compositor.per_node_execution_time = cj->profiler_data.per_node_execution_time;
scene->runtime->compositor.per_node_execution_time = cj->profiler.get_nodes_evaluation_times();
}
static void compo_completejob(void *cjv)
@@ -331,7 +331,7 @@ static void compo_completejob(void *cjv)
Scene *scene = cj->scene;
BKE_callback_exec_id(bmain, &scene->id, BKE_CB_EVT_COMPOSITE_POST);
scene->runtime->compositor.per_node_execution_time = cj->profiler_data.per_node_execution_time;
scene->runtime->compositor.per_node_execution_time = cj->profiler.get_nodes_evaluation_times();
}
/** \} */

View File

@@ -12,10 +12,8 @@
namespace blender::realtime_compositor {
class RenderContext;
}
namespace blender::compositor {
class ProfilerData;
}
class Profiler;
} // namespace blender::realtime_compositor
namespace blender::bke {
struct bNodeTreeType;
} // namespace blender::bke
@@ -45,7 +43,7 @@ void ntreeCompositExecTree(Render *render,
RenderData *rd,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context,
blender::compositor::ProfilerData &profiler_data);
blender::realtime_compositor::Profiler *profiler);
/**
* Called from render pipeline, to tag render input and output.

View File

@@ -181,12 +181,12 @@ void ntreeCompositExecTree(Render *render,
RenderData *rd,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context,
blender::compositor::ProfilerData &profiler_data)
blender::realtime_compositor::Profiler *profiler)
{
#ifdef WITH_COMPOSITOR_CPU
COM_execute(render, rd, scene, ntree, view_name, render_context, profiler_data);
COM_execute(render, rd, scene, ntree, view_name, render_context, profiler);
#else
UNUSED_VARS(render, scene, ntree, rd, view_name, render_context, profiler_data);
UNUSED_VARS(render, scene, ntree, rd, view_name, render_context, profiler);
#endif
}

View File

@@ -8,7 +8,6 @@ set(INC
intern
../blenkernel
../blentranslation
../compositor
../compositor/realtime_compositor
../compositor/realtime_compositor/cached_resources
../draw

View File

@@ -8,7 +8,8 @@
namespace blender::realtime_compositor {
class RenderContext;
}
class Profiler;
} // namespace blender::realtime_compositor
struct bNodeTree;
struct Depsgraph;
@@ -33,7 +34,8 @@ void RE_compositor_execute(Render &render,
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context);
blender::realtime_compositor::RenderContext *render_context,
blender::realtime_compositor::Profiler *profiler);
/* Free compositor caches. */
void RE_compositor_free(Render &render);

View File

@@ -128,17 +128,20 @@ class ContextInputData {
const bNodeTree *node_tree;
std::string view_name;
realtime_compositor::RenderContext *render_context;
realtime_compositor::Profiler *profiler;
ContextInputData(const Scene &scene,
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
realtime_compositor::RenderContext *render_context)
realtime_compositor::RenderContext *render_context,
realtime_compositor::Profiler *profiler)
: scene(&scene),
render_data(&render_data),
node_tree(&node_tree),
view_name(view_name),
render_context(render_context)
render_context(render_context),
profiler(profiler)
{
}
};
@@ -458,6 +461,11 @@ class Context : public realtime_compositor::Context {
return input_data_.render_context;
}
realtime_compositor::Profiler *profiler() const override
{
return input_data_.profiler;
}
void evaluate_operation_post() const override
{
/* If no render context exist, that means this is an interactive compositor evaluation due to
@@ -561,12 +569,13 @@ void Render::compositor_execute(const Scene &scene,
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context)
blender::realtime_compositor::RenderContext *render_context,
blender::realtime_compositor::Profiler *profiler)
{
std::unique_lock lock(gpu_compositor_mutex);
blender::render::ContextInputData input_data(
scene, render_data, node_tree, view_name, render_context);
scene, render_data, node_tree, view_name, render_context, profiler);
if (gpu_compositor == nullptr) {
gpu_compositor = new blender::render::RealtimeCompositor(*this, input_data);
@@ -590,9 +599,10 @@ void RE_compositor_execute(Render &render,
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context)
blender::realtime_compositor::RenderContext *render_context,
blender::realtime_compositor::Profiler *profiler)
{
render.compositor_execute(scene, render_data, node_tree, view_name, render_context);
render.compositor_execute(scene, render_data, node_tree, view_name, render_context, profiler);
}
void RE_compositor_free(Render &render)

View File

@@ -63,7 +63,6 @@
#include "NOD_composite.hh"
#include "COM_profile.hh"
#include "COM_render_context.hh"
#include "DEG_depsgraph.hh"
@@ -1306,7 +1305,6 @@ static void do_render_compositor(Render *re)
}
blender::realtime_compositor::RenderContext compositor_render_context;
blender::compositor::ProfilerData profiler_data;
LISTBASE_FOREACH (RenderView *, rv, &re->result->views) {
ntreeCompositExecTree(re,
re->pipeline_scene_eval,
@@ -1314,7 +1312,7 @@ static void do_render_compositor(Render *re)
&re->r,
rv->name,
&compositor_render_context,
profiler_data);
nullptr);
}
compositor_render_context.save_file_outputs(re->pipeline_scene_eval);

View File

@@ -25,7 +25,8 @@
namespace blender::realtime_compositor {
class RenderContext;
}
class Profiler;
} // namespace blender::realtime_compositor
struct bNodeTree;
struct Depsgraph;
@@ -50,7 +51,8 @@ struct BaseRender {
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context) = 0;
blender::realtime_compositor::RenderContext *render_context,
blender::realtime_compositor::Profiler *profiler) = 0;
virtual void compositor_free() = 0;
virtual void display_init(RenderResult *render_result) = 0;
@@ -97,12 +99,12 @@ struct ViewRender : public BaseRender {
return nullptr;
}
void compositor_execute(
const Scene & /*scene*/,
const RenderData & /*render_data*/,
const bNodeTree & /*node_tree*/,
const char * /*view_name*/,
blender::realtime_compositor::RenderContext * /*render_context*/) override
void compositor_execute(const Scene & /*scene*/,
const RenderData & /*render_data*/,
const bNodeTree & /*node_tree*/,
const char * /*view_name*/,
blender::realtime_compositor::RenderContext * /*render_context*/,
blender::realtime_compositor::Profiler * /*profiler*/) override
{
}
void compositor_free() override {}
@@ -146,7 +148,8 @@ struct Render : public BaseRender {
const RenderData &render_data,
const bNodeTree &node_tree,
const char *view_name,
blender::realtime_compositor::RenderContext *render_context) override;
blender::realtime_compositor::RenderContext *render_context,
blender::realtime_compositor::Profiler *profiler) override;
void compositor_free() override;
void display_init(RenderResult *render_result) override;