28 : context_(
context), exec_system_(system), current_node_(nullptr), active_viewer_(nullptr)
42 node->convert_to_operations(converter, *context_);
45 current_node_ =
nullptr;
53 inverse_input_map.
add(item.value, item.key);
63 if (!op_from || op_to_list.
is_empty()) {
85 save_graphviz(
"compositor_prior_folding");
92 save_graphviz(
"compositor_prior_merging");
93 merge_equal_operations();
120 operation->
set_id(operations_.size());
121 operations_.append(operation);
133 unlink_inputs_and_relink_outputs(operation, constant_operation);
137 void NodeOperationBuilder::unlink_inputs_and_relink_outputs(
NodeOperation *unlinked_op,
141 while (i < links_.size()) {
142 Link &link = links_[i];
143 if (&link.to()->get_operation() == unlinked_op) {
144 link.to()->set_link(
nullptr);
149 if (&link.from()->get_operation() == unlinked_op) {
167 input_map_.add_new(operation_socket, node_socket);
176 output_map_.add_new(node_socket, operation_socket);
194 for (
Link &link : links_) {
195 if (link.to() == to) {
199 links_.remove(index);
259 if (active_viewer_) {
264 active_viewer_ = viewer;
270 active_viewer_ = viewer;
283 for (
const Link &link : links_) {
292 if (link.from()->get_data_type() != link.to()->get_data_type()) {
293 convert_links.
append(link);
296 for (
const Link &link : convert_links) {
315 for (
int k = 0; k < op->get_number_of_input_sockets(); ++k) {
317 if (!
input->is_connected()) {
330 switch (
input->get_data_type()) {
382 for (
const Link &link : links_) {
384 if (link.from()->get_operation().get_flags().is_proxy_operation &&
385 !link.to()->get_operation().get_flags().is_proxy_operation) {
390 for (
const Link &link : proxy_links) {
395 from =
from->get_operation().get_input_socket(0)->get_link();
396 }
while (
from &&
from->get_operation().get_flags().is_proxy_operation);
413 if (op->is_output_operation(context_->
is_rendering()) &&
414 !op->get_flags().is_preview_operation) {
416 op->determine_canvas(preferred_area, canvas);
417 op->set_canvas(canvas);
422 if (op->is_output_operation(context_->
is_rendering()) &&
423 op->get_flags().is_preview_operation) {
425 op->determine_canvas(preferred_area, canvas);
426 op->set_canvas(canvas);
433 for (
const Link &link : links_) {
435 const rcti &from_canvas = link.from()->get_operation().get_canvas();
436 const rcti &to_canvas = link.to()->get_operation().get_canvas();
438 bool needs_conversion;
440 needs_conversion = from_canvas.
xmin != to_canvas.
xmin ||
447 if (needs_conversion) {
448 convert_links.
append(link);
452 for (
const Link &link : convert_links) {
462 std::optional<NodeOperationHash>
hash = op->generate_hash();
470 void NodeOperationBuilder::merge_equal_operations()
472 bool check_for_next_merge =
true;
473 while (check_for_next_merge) {
480 bool any_merged =
false;
481 const NodeOperationHash *prev_hash =
nullptr;
482 for (
const NodeOperationHash &
hash : hashes) {
483 if (prev_hash && *prev_hash ==
hash) {
484 merge_equal_operations(prev_hash->get_operation(),
hash.get_operation());
490 check_for_next_merge = any_merged;
494 void NodeOperationBuilder::merge_equal_operations(NodeOperation *
from, NodeOperation *into)
496 unlink_inputs_and_relink_outputs(
from, into);
497 operations_.remove_first_occurrence_and_reorder(
from);
505 for (
const Link &link : links_) {
506 if (link.from() ==
output) {
516 for (
const Link &link : links_) {
517 if (link.from() ==
output) {
530 if (!
input->is_connected()) {
535 if (
output->get_operation().get_flags().is_read_buffer_operation) {
545 if (!writeoperation) {
577 if (target->get_operation().get_flags().is_write_buffer_operation) {
588 if (!write_operation) {
600 if (&target->get_operation() == write_operation) {
622 if (operation->get_flags().complex) {
623 complex_ops.
append(operation);
630 for (
int index = 0; index < op->get_number_of_input_sockets(); index++) {
634 for (
int index = 0; index < op->get_number_of_output_sockets(); index++) {
640 using Tags = std::set<NodeOperation *>;
644 if (reachable.find(op) != reachable.end()) {
647 reachable.insert(op);
651 if (
input->is_connected()) {
669 if (op->is_output_operation(context_->
is_rendering())) {
677 if (reachable.find(op) != reachable.end()) {
685 operations_ = reachable_ops;
700 if (
input->is_connected()) {
711 sorted.
reserve(operations_.size());
718 operations_ = sorted;
735 if (
input->is_connected()) {
744 groups_.append(group);
755 if (op->is_output_operation(context_->
is_rendering())) {
761 if (op->get_flags().is_read_buffer_operation) {
783 os <<
"# Builder start\n";
784 os <<
"digraph G {\n";
785 os <<
" rankdir=LR;\n";
786 os <<
" node [shape=box];\n";
788 os <<
" op" << operation->get_id() <<
" [label=\"" << *operation <<
"\"];\n";
793 os <<
" op" << link.from()->get_operation().get_id() <<
" -> op"
794 << link.to()->get_operation().get_id() <<
";\n";
797 if (operation->get_flags().is_read_buffer_operation) {
802 os <<
" op" << write_operation.
get_id() <<
" -> op" << read_operation.
get_id() <<
";\n";
807 os <<
"# Builder end\n";
MINLINE void zero_v4(float r[4])
MINLINE void zero_v3(float r[3])
bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b)
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
constexpr bool is_empty() const
void append(const T &value)
void reserve(const int64_t min_capacity)
Overall context of the compositor.
bNodeInstanceHash * get_preview_hash() const
get the preview image hash table
Scene * get_scene() const
bool is_rendering() const
get the rendering field of the context
eExecutionModel get_execution_model() const
const bNodeTree * get_bnodetree() const
get the bnodetree of the context
static void node_to_operations(const Node *node)
static void operation_read_write_buffer(const NodeOperation *operation)
static void graphviz(const ExecutionSystem *system, StringRefNull name="")
Class ExecutionGroup is a group of Operations that are executed as one. This grouping is used to comb...
bool add_operation(NodeOperation *operation)
add an operation to this ExecutionGroup
void set_output_execution_group(bool is_output)
set whether this ExecutionGroup is an output
the ExecutionSystem contains the whole compositor tree.
void set_operations(const Vector< NodeOperation * > &operations, const Vector< ExecutionGroup * > &groups)
A MemoryProxy is a unique identifier for a memory buffer. A single MemoryProxy is used among all chun...
void set_executor(ExecutionGroup *executor)
set the ExecutionGroup that can be scheduled to calculate a certain chunk.
ExecutionGroup * get_executor() const
get the ExecutionGroup that can be scheduled to calculate a certain chunk.
WriteBufferOperation * get_write_buffer_operation() const
get the WriteBufferOperation that is responsible for writing to this MemoryProxy
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
const Vector< Node * > & nodes() const
const Vector< Link > & links() const
NodeOperationOutput * from() const
NodeOperationInput * to() const
void map_input_socket(NodeInput *node_socket, NodeOperationInput *operation_socket)
void convert_to_operations(ExecutionSystem *system)
WriteBufferOperation * find_attached_write_buffer_operation(NodeOperationOutput *output) const
void determine_canvases()
void register_viewer(ViewerOperation *viewer)
void add_preview(NodeOperationOutput *output)
void map_output_socket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void add_datatype_conversions()
void remove_input_link(NodeOperationInput *to)
void add_node_input_preview(NodeInput *input)
void replace_operation_with_constant(NodeOperation *operation, ConstantOperation *constant_operation)
void add_input_constant_value(NodeOperationInput *input, const NodeInput *node_input)
void add_output_buffers(NodeOperation *operation, NodeOperationOutput *output)
Vector< NodeOperationInput * > cache_output_links(NodeOperationOutput *output) const
NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree, ExecutionSystem *system)
void add_input_buffers(NodeOperation *operation, NodeOperationInput *input)
const Vector< Link > & get_links() const
void add_operation(NodeOperation *operation)
ExecutionGroup * make_group(NodeOperation *op)
const Vector< NodeOperation * > & get_operations() const
const CompositorContext & context() const
void add_link(NodeOperationOutput *from, NodeOperationInput *to)
void add_operation_input_constants()
void add_complex_operation_buffers()
NodeOperation & get_operation() const
DataType get_data_type() const
NodeOperation contains calculation logic.
void set_bnodetree(const bNodeTree *tree)
void set_name(const std::string name)
void set_id(const int id)
const NodeOperationFlags get_flags() const
unsigned int get_number_of_input_sockets() const
NodeOperationOutput * get_output_socket(unsigned int index=0)
NodeOperationInput * get_input_socket(unsigned int index)
void set_execution_system(ExecutionSystem *system)
void set_execution_model(const eExecutionModel model)
NodeOutput are sockets that can send data/input.
bNodeTree * get_bnodetree() const
get the reference to the SDNA bNodeTree struct
bNodeInstanceKey get_instance_key() const
bNode * get_bnode() const
get the reference to the SDNA bNode struct
bool is_in_active_group() const
Is this node part of the active group the active group is the group that is currently being edited....
void read_resolution_from_write_buffer()
void set_memory_proxy(MemoryProxy *memory_proxy)
MemoryProxy * get_memory_proxy() const
void set_channels(const float value[4])
void set_value(float value)
void set_vector(const float vector[3])
void set_active(bool active)
NodeOperation to write to a tile.
void read_resolution_from_input_socket()
MemoryProxy * get_memory_proxy()
Set< ComponentNode * > visited
@ Vector
Vector data type.
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op)
NodeOperation * COM_convert_data_type(const NodeOperationOutput &from, const NodeOperationInput &to)
This function will add a date-type conversion rule when the to-socket does not support the from-socke...
static constexpr bool COM_EXPORT_GRAPHVIZ
static Vector< NodeOperationHash > generate_hashes(Span< NodeOperation * > operations)
void COM_convert_canvas(NodeOperationBuilder &builder, NodeOperationOutput *from_socket, NodeOperationInput *to_socket)
This function will add a resolution rule based on the settings of the NodeInput.
static void add_group_operations_recursive(Tags &visited, NodeOperation *op, ExecutionGroup *group)
std::set< NodeOperation * > Tags
constexpr rcti COM_AREA_NONE
static void sort_operations_recursive(Vector< NodeOperation * > &sorted, Tags &visited, NodeOperation *op)
std::ostream & operator<<(std::ostream &os, const eCompositorPriority &priority)
static bNodeSocketTemplate inputs[]
ColorManagedViewSettings view_settings
ColorManagedDisplaySettings display_settings
bool is_write_buffer_operation
bool use_datatype_conversion
bool is_read_buffer_operation