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);
71 const int num_inputs = op->get_number_of_input_sockets();
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;
77 MemoryBuffer *buf = active_buffers_.get_rendered_buffer(input);
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;
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) {
112 const int op_offset_x = output_x - op->get_canvas().xmin;
113 const int op_offset_y = output_y - op->get_canvas().ymin;
114 Vector<rcti> areas = active_buffers_.get_areas_to_render(op, op_offset_x, op_offset_y);
115 op->render(op_buf, areas, input_bufs);
118 for (MemoryBuffer *buf : input_bufs) {
124 active_buffers_.set_rendered_buffer(op, std::unique_ptr<MemoryBuffer>(op_buf));
126 operation_finished(op);
133 context_.get_profiler()->set_node_evaluation_time(node_instance_key, after_time - before_time);
137void FullFrameExecutionModel::render_operations()
139 const bool is_rendering =
context_.is_rendering();
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++) {
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)
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;
209 active_buffers_.is_area_registered(operation, render_area))
214 active_buffers_.register_area(operation, render_area);
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)
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);
241 if (!active_buffers_.has_registered_reads(input_op)) {
244 active_buffers_.register_read(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,...)
struct bNodeInstanceKey bNodeInstanceKey
struct bNodeTree bNodeTree
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void append(const T &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
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="")
struct blender::compositor::ExecutionModel::@366111166121074050370152345304002334322273345111 border_
ExecutionModel(CompositorContext &context, Span< NodeOperation * > operations)
CompositorContext & context_
Span< NodeOperation * > operations_
the ExecutionSystem contains the whole compositor tree.
FullFrameExecutionModel(CompositorContext &context, SharedOperationBuffers &shared_buffers, Span< NodeOperation * > operations)
void execute(ExecutionSystem &exec_system) override
a MemoryBuffer contains access to the data
NodeOperation contains calculation logic.
bool is_operation_rendered(NodeOperation *op)
draw_view in_light_buf[] float
eCompositorPriority
Possible priority settings.
DataType
possible data types for sockets
@ Vector
Vector data type.
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[]
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.