19#ifdef WITH_CXX_GUARDEDALLOC
29 active_buffers_(shared_buffers),
30 num_operations_finished_(0)
41 RPT_(
"Compositing | Initializing execution"));
45 determine_areas_to_render_and_reads();
49void FullFrameExecutionModel::determine_areas_to_render_and_reads()
58 if (op->is_output_operation(is_rendering) && op->get_render_priority() == priority) {
59 get_output_render_area(op, area);
60 determine_areas_to_render(op, area);
67Vector<MemoryBuffer *> FullFrameExecutionModel::get_input_buffers(NodeOperation *op,
71 const int num_inputs = op->get_number_of_input_sockets();
72 Vector<MemoryBuffer *> inputs_buffers(num_inputs);
73 for (
int i = 0; i < num_inputs; i++) {
74 NodeOperation *input = op->get_input_operation(i);
75 const int offset_x = (input->get_canvas().xmin - op->get_canvas().xmin) + output_x;
76 const int offset_y = (input->get_canvas().ymin - op->get_canvas().ymin) + output_y;
79 rcti rect = buf->get_rect();
81 inputs_buffers[i] =
new MemoryBuffer(
82 buf->get_buffer(), buf->get_num_channels(), rect, buf->is_a_single_elem());
84 return inputs_buffers;
87MemoryBuffer *FullFrameExecutionModel::create_operation_buffer(NodeOperation *op,
93 &rect, output_x, output_x + op->get_width(), output_y, output_y + op->get_height());
95 const DataType data_type = op->get_output_socket(0)->get_data_type();
96 const bool is_a_single_elem = op->get_flags().is_constant_operation;
97 return new MemoryBuffer(data_type, rect, is_a_single_elem);
100void FullFrameExecutionModel::render_operation(NodeOperation *op)
103 constexpr int output_x = 0;
104 constexpr int output_y = 0;
108 const bool has_outputs = op->get_number_of_output_sockets() > 0;
109 MemoryBuffer *op_buf = has_outputs ? create_operation_buffer(op, output_x, output_y) : nullptr;
110 if (op->get_width() > 0 && op->get_height() > 0) {
111 Vector<MemoryBuffer *> input_bufs = get_input_buffers(op, output_x, output_y);
112 const int op_offset_x = output_x - op->get_canvas().xmin;
113 const int op_offset_y = output_y - op->get_canvas().ymin;
115 op->render(op_buf, areas, input_bufs);
118 for (MemoryBuffer *buf : input_bufs) {
126 operation_finished(op);
137void FullFrameExecutionModel::render_operations()
144 const bool has_size = op->get_width() > 0 && op->get_height() > 0;
145 const bool is_priority_output = op->is_output_operation(is_rendering) &&
146 op->get_render_priority() == priority;
147 if (is_priority_output && has_size) {
148 render_output_dependencies(op);
149 render_operation(op);
151 else if (is_priority_output && !has_size && op->is_active_viewer_output()) {
152 static_cast<ViewerOperation *
>(op)->clear_display_buffer();
168 next_outputs.
append(operation);
169 while (next_outputs.
size() > 0) {
171 next_outputs.
clear();
173 for (
int i = 0; i < output->get_number_of_input_sockets(); i++) {
174 next_outputs.
append(output->get_input_operation(i));
177 dependencies.
extend(next_outputs);
181 std::reverse(dependencies.
begin(), dependencies.
end());
186void FullFrameExecutionModel::render_output_dependencies(NodeOperation *output_op)
190 for (NodeOperation *op : dependencies) {
192 render_operation(op);
197void FullFrameExecutionModel::determine_areas_to_render(NodeOperation *output_op,
198 const rcti &output_area)
202 Vector<std::pair<NodeOperation *, const rcti>> stack;
203 stack.append({output_op, output_area});
204 while (stack.size() > 0) {
205 std::pair<NodeOperation *, rcti> pair = stack.pop_last();
206 NodeOperation *operation = pair.first;
207 const rcti &render_area = pair.second;
216 const int num_inputs = operation->get_number_of_input_sockets();
217 for (
int i = 0; i < num_inputs; i++) {
218 NodeOperation *input_op = operation->get_input_operation(i);
220 operation->get_area_of_interest(input_op, render_area, input_area);
223 BLI_rcti_isect(&input_area, &input_op->get_canvas(), &input_area);
225 stack.append({input_op, input_area});
230void FullFrameExecutionModel::determine_reads(NodeOperation *output_op)
234 Vector<NodeOperation *> stack;
235 stack.append(output_op);
236 while (stack.size() > 0) {
237 NodeOperation *operation = stack.pop_last();
238 const int num_inputs = operation->get_number_of_input_sockets();
239 for (
int i = 0; i < num_inputs; i++) {
240 NodeOperation *input_op = operation->get_input_operation(i);
242 stack.append(input_op);
249void FullFrameExecutionModel::get_output_render_area(NodeOperation *output_op,
rcti &r_area)
254 rcti canvas = output_op->get_canvas();
257 const bool has_viewer_border =
border_.use_viewer_border &&
258 (output_op->get_flags().is_viewer_operation ||
259 output_op->get_flags().is_preview_operation);
260 const bool has_render_border =
border_.use_render_border &&
261 output_op->get_flags().use_render_border;
262 if (has_viewer_border || has_render_border) {
264 const rctf *norm_border = has_viewer_border ?
border_.viewer_border :
border_.render_border;
267 const int w = output_op->get_width();
268 const int h = output_op->get_height();
276void FullFrameExecutionModel::operation_finished(NodeOperation *operation)
279 const int num_inputs = operation->get_number_of_input_sockets();
280 for (
int i = 0; i < num_inputs; i++) {
281 active_buffers_.
read_finished(operation->get_input_operation(i));
284 num_operations_finished_++;
285 update_progress_bar();
288void FullFrameExecutionModel::update_progress_bar()
292 const float progress = num_operations_finished_ /
float(
operations_.size());
293 tree->runtime->progress(
tree->runtime->prh, progress);
297 RPT_(
"Compositing | Operation %i-%li"),
298 num_operations_finished_ + 1,
300 tree->runtime->stats_draw(
tree->runtime->sdh, buf);
void BLI_rcti_translate(struct rcti *rect, int x, int y)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
bool BLI_rcti_is_empty(const struct rcti *rect)
#define SNPRINTF(dst, format,...)
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void append(const T &value)
void extend(Span< T > array)
Overall context of the compositor.
const bNodeTree * get_bnodetree() const
get the bnodetree of the context
realtime_compositor::Profiler * get_profiler() const
get the profiler
bool is_rendering() const
get the rendering field of the context
static void operation_rendered(const NodeOperation *op, MemoryBuffer *render)
static void graphviz(const ExecutionSystem *system, StringRefNull name="")
CompositorContext & context_
Span< NodeOperation * > operations_
struct blender::compositor::ExecutionModel::@171 border_
the ExecutionSystem contains the whole compositor tree.
FullFrameExecutionModel(CompositorContext &context, SharedOperationBuffers &shared_buffers, Span< NodeOperation * > operations)
void execute(ExecutionSystem &exec_system) override
NodeOperation contains calculation logic.
bool has_registered_reads(NodeOperation *op)
void set_rendered_buffer(NodeOperation *op, std::unique_ptr< MemoryBuffer > buffer)
Vector< rcti > get_areas_to_render(NodeOperation *op, int offset_x, int offset_y)
bool is_area_registered(NodeOperation *op, const rcti &area_to_render)
bool is_operation_rendered(NodeOperation *op)
void register_read(NodeOperation *read_op)
MemoryBuffer * get_rendered_buffer(NodeOperation *op)
void register_area(NodeOperation *op, const rcti &area_to_render)
void read_finished(NodeOperation *read_op)
void set_node_evaluation_time(bNodeInstanceKey node_instance_key, timeit::Nanoseconds time)
draw_view in_light_buf[] float
eCompositorPriority
Possible priority settings.
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
static Vector< NodeOperation * > get_operation_dependencies(NodeOperation *operation)
Clock::time_point TimePoint
static blender::bke::bNodeSocketTemplate outputs[]
bNodeTreeRuntimeHandle * runtime
static void start()
Start the execution this methods will start the WorkScheduler. Inside this method all threads are ini...
static void stop()
stop the execution All created thread by the start method are destroyed.