Changeset View
Changeset View
Standalone View
Standalone View
source/blender/compositor/intern/COM_NodeOperationBuilder.cc
| Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | void NodeOperationBuilder::convertToOperations(ExecutionSystem *system) | ||||
| add_operation_input_constants(); | add_operation_input_constants(); | ||||
| resolve_proxies(); | resolve_proxies(); | ||||
| add_datatype_conversions(); | add_datatype_conversions(); | ||||
| if (m_context->get_execution_model() == eExecutionModel::FullFrame) { | if (m_context->get_execution_model() == eExecutionModel::FullFrame) { | ||||
| /* Copy operations to system. Needed for graphviz. */ | save_graphviz("compositor_prior_folding"); | ||||
| system->set_operations(m_operations, {}); | |||||
| DebugInfo::graphviz(system, "compositor_prior_folding"); | |||||
| ConstantFolder folder(*this); | ConstantFolder folder(*this); | ||||
| folder.fold_operations(); | folder.fold_operations(); | ||||
| } | } | ||||
| determineResolutions(); | determineResolutions(); | ||||
| save_graphviz("compositor_prior_merging"); | |||||
| merge_equal_operations(); | |||||
| if (m_context->get_execution_model() == eExecutionModel::Tiled) { | if (m_context->get_execution_model() == eExecutionModel::Tiled) { | ||||
| /* surround complex ops with read/write buffer */ | /* surround complex ops with read/write buffer */ | ||||
| add_complex_operation_buffers(); | add_complex_operation_buffers(); | ||||
| } | } | ||||
| /* links not available from here on */ | /* links not available from here on */ | ||||
| /* XXX make m_links a local variable to avoid confusion! */ | /* XXX make m_links a local variable to avoid confusion! */ | ||||
| m_links.clear(); | m_links.clear(); | ||||
| Show All 22 Lines | void NodeOperationBuilder::addOperation(NodeOperation *operation) | ||||
| operation->set_execution_model(m_context->get_execution_model()); | operation->set_execution_model(m_context->get_execution_model()); | ||||
| operation->set_execution_system(exec_system_); | operation->set_execution_system(exec_system_); | ||||
| } | } | ||||
| void NodeOperationBuilder::replace_operation_with_constant(NodeOperation *operation, | void NodeOperationBuilder::replace_operation_with_constant(NodeOperation *operation, | ||||
| ConstantOperation *constant_operation) | ConstantOperation *constant_operation) | ||||
| { | { | ||||
| BLI_assert(constant_operation->getNumberOfInputSockets() == 0); | BLI_assert(constant_operation->getNumberOfInputSockets() == 0); | ||||
| unlink_inputs_and_relink_outputs(operation, constant_operation); | |||||
| addOperation(constant_operation); | |||||
| } | |||||
| /** Returns relinked output operations. */ | |||||
| void NodeOperationBuilder::unlink_inputs_and_relink_outputs(NodeOperation *unlinked_op, | |||||
| NodeOperation *to_op) | |||||
| { | |||||
| int i = 0; | int i = 0; | ||||
| while (i < m_links.size()) { | while (i < m_links.size()) { | ||||
| Link &link = m_links[i]; | Link &link = m_links[i]; | ||||
| if (&link.to()->getOperation() == operation) { | if (&link.to()->getOperation() == unlinked_op) { | ||||
| link.to()->setLink(nullptr); | link.to()->setLink(nullptr); | ||||
| m_links.remove(i); | m_links.remove(i); | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (&link.from()->getOperation() == operation) { | if (&link.from()->getOperation() == unlinked_op) { | ||||
| link.to()->setLink(constant_operation->getOutputSocket()); | link.to()->setLink(to_op->getOutputSocket()); | ||||
| m_links[i] = Link(constant_operation->getOutputSocket(), link.to()); | m_links[i] = Link(to_op->getOutputSocket(), link.to()); | ||||
| } | } | ||||
| i++; | i++; | ||||
| } | } | ||||
| addOperation(constant_operation); | |||||
| } | } | ||||
| void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, | void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, | ||||
| NodeOperationInput *operation_socket) | NodeOperationInput *operation_socket) | ||||
| { | { | ||||
| BLI_assert(m_current_node); | BLI_assert(m_current_node); | ||||
| BLI_assert(node_socket->getNode() == m_current_node); | BLI_assert(node_socket->getNode() == m_current_node); | ||||
| ▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | for (const Link &link : m_links) { | ||||
| } | } | ||||
| } | } | ||||
| for (const Link &link : convert_links) { | for (const Link &link : convert_links) { | ||||
| COM_convert_resolution(*this, link.from(), link.to()); | COM_convert_resolution(*this, link.from(), link.to()); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static Vector<NodeOperationHash> generate_hashes(Span<NodeOperation *> operations) | |||||
| { | |||||
| Vector<NodeOperationHash> hashes; | |||||
| for (NodeOperation *op : operations) { | |||||
| std::optional<NodeOperationHash> hash = op->generate_hash(); | |||||
| if (hash) { | |||||
| hashes.append(std::move(*hash)); | |||||
| } | |||||
| } | |||||
| return hashes; | |||||
| } | |||||
| /** Merge operations with same type, inputs and parameters that produce the same result. */ | |||||
| void NodeOperationBuilder::merge_equal_operations() | |||||
| { | |||||
| bool any_merged = true; | |||||
jbakker: Bit of naming confusion.
```
bool check_for_next_merge = true
while (check_for_next_merge) {… | |||||
| while (any_merged) { | |||||
| /* Re-generate hashes with any change. */ | |||||
| Vector<NodeOperationHash> hashes = generate_hashes(m_operations); | |||||
| /* Make hashes be consecutive when they are equal. */ | |||||
| std::sort(hashes.begin(), hashes.end()); | |||||
| any_merged = false; | |||||
| const NodeOperationHash *prev_hash = nullptr; | |||||
| for (const NodeOperationHash &hash : hashes) { | |||||
| if (prev_hash && *prev_hash == hash) { | |||||
| merge_equal_operations(prev_hash->get_operation(), hash.get_operation()); | |||||
| any_merged = true; | |||||
| } | |||||
| prev_hash = &hash; | |||||
| } | |||||
| } | |||||
| } | |||||
| void NodeOperationBuilder::merge_equal_operations(NodeOperation *from, NodeOperation *into) | |||||
| { | |||||
| unlink_inputs_and_relink_outputs(from, into); | |||||
| m_operations.remove_first_occurrence_and_reorder(from); | |||||
| delete from; | |||||
| } | |||||
| Vector<NodeOperationInput *> NodeOperationBuilder::cache_output_links( | Vector<NodeOperationInput *> NodeOperationBuilder::cache_output_links( | ||||
| NodeOperationOutput *output) const | NodeOperationOutput *output) const | ||||
| { | { | ||||
| Vector<NodeOperationInput *> inputs; | Vector<NodeOperationInput *> inputs; | ||||
| for (const Link &link : m_links) { | for (const Link &link : m_links) { | ||||
| if (link.from() == output) { | if (link.from() == output) { | ||||
| inputs.append(link.to()); | inputs.append(link.to()); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 256 Lines • ▼ Show 20 Lines | if (op->get_flags().is_read_buffer_operation) { | ||||
| if (memproxy->getExecutor() == nullptr) { | if (memproxy->getExecutor() == nullptr) { | ||||
| ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation()); | ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation()); | ||||
| memproxy->setExecutor(group); | memproxy->setExecutor(group); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void NodeOperationBuilder::save_graphviz(StringRefNull name) | |||||
| { | |||||
| if (COM_EXPORT_GRAPHVIZ) { | |||||
| exec_system_->set_operations(m_operations, m_groups); | |||||
| DebugInfo::graphviz(exec_system_, name); | |||||
| } | |||||
| } | |||||
| /** Create a graphviz representation of the NodeOperationBuilder. */ | /** Create a graphviz representation of the NodeOperationBuilder. */ | ||||
| std::ostream &operator<<(std::ostream &os, const NodeOperationBuilder &builder) | std::ostream &operator<<(std::ostream &os, const NodeOperationBuilder &builder) | ||||
| { | { | ||||
| os << "# Builder start\n"; | os << "# Builder start\n"; | ||||
| os << "digraph G {\n"; | os << "digraph G {\n"; | ||||
| os << " rankdir=LR;\n"; | os << " rankdir=LR;\n"; | ||||
| os << " node [shape=box];\n"; | os << " node [shape=box];\n"; | ||||
| for (const NodeOperation *operation : builder.get_operations()) { | for (const NodeOperation *operation : builder.get_operations()) { | ||||
| Show All 30 Lines | |||||
Bit of naming confusion.
bool check_for_next_merge = true while (check_for_next_merge) { ... bool any_merged = false; ... check_for_next_merge = any_merged; }