2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2025-01-29 15:13:45 +01:00
|
|
|
#include <optional>
|
|
|
|
|
|
2022-08-10 09:14:22 +02:00
|
|
|
#include "BLI_map.hh"
|
|
|
|
|
|
|
|
|
|
#include "NOD_derived_node_tree.hh"
|
|
|
|
|
|
2025-03-26 13:42:21 +02:00
|
|
|
#include "COM_context.hh"
|
2022-08-10 09:14:22 +02:00
|
|
|
#include "COM_domain.hh"
|
|
|
|
|
#include "COM_node_operation.hh"
|
2024-08-27 14:42:11 +03:00
|
|
|
#include "COM_pixel_operation.hh"
|
2022-08-10 09:14:22 +02:00
|
|
|
#include "COM_scheduler.hh"
|
|
|
|
|
|
2024-12-17 11:39:04 +01:00
|
|
|
namespace blender::compositor {
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
using namespace nodes::derived_node_tree_types;
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
|
* Compile State
|
|
|
|
|
*
|
|
|
|
|
* The compile state is a utility class used to track the state of compilation when compiling the
|
|
|
|
|
* node tree. In particular, it tracks two important pieces of information, each of which is
|
|
|
|
|
* described in one of the following sections.
|
|
|
|
|
*
|
|
|
|
|
* First, it stores a mapping between all nodes and the operations they were compiled into. The
|
|
|
|
|
* mapping are stored independently depending on the type of the operation in the node_operations_
|
2024-08-26 14:38:10 +03:00
|
|
|
* and pixel_operations_ maps. So those two maps are mutually exclusive. The compiler should call
|
|
|
|
|
* the map_node_to_node_operation and map_node_to_pixel_operation methods to populate those maps
|
2022-08-10 09:14:22 +02:00
|
|
|
* as soon as it compiles a node or multiple nodes into an operation. Those maps are used to
|
|
|
|
|
* retrieve the results of outputs linked to the inputs of operations. For more details, see the
|
|
|
|
|
* get_result_from_output_socket method. For the node tree shown below, nodes 1, 2, and 6 are
|
|
|
|
|
* mapped to their compiled operations in the node_operation_ map. While nodes 3 and 4 are both
|
2024-08-26 14:38:10 +03:00
|
|
|
* mapped to the first pixel operation, and node 5 is mapped to the second pixel operation in the
|
|
|
|
|
* pixel_operations_ map.
|
2022-08-10 09:14:22 +02:00
|
|
|
*
|
2024-08-26 14:38:10 +03:00
|
|
|
* Pixel Operation 1 Pixel Operation 2
|
2022-08-10 09:14:22 +02:00
|
|
|
* +-----------------------------------+ +------------------+
|
|
|
|
|
* .------------. | .------------. .------------. | | .------------. | .------------.
|
|
|
|
|
* | Node 1 | | | Node 3 | | Node 4 | | | | Node 5 | | | Node 6 |
|
|
|
|
|
* | |----|--| |--| |---|-----|--| |--|--| |
|
|
|
|
|
* | | .-|--| | | | | .--|--| | | | |
|
|
|
|
|
* '------------' | | '------------' '------------' | | | '------------' | '------------'
|
|
|
|
|
* | +-----------------------------------+ | +------------------+
|
|
|
|
|
* .------------. | |
|
|
|
|
|
* | Node 2 | | |
|
|
|
|
|
* | |--'----------------------------------------'
|
|
|
|
|
* | |
|
|
|
|
|
* '------------'
|
|
|
|
|
*
|
2025-01-29 15:13:45 +01:00
|
|
|
* Second, it stores the pixel compile unit, whether is operates on single values, and its domain
|
|
|
|
|
* if it was not operating on single values. One should first go over the discussion in
|
|
|
|
|
* COM_evaluator.hh for a high level description of the mechanism of the compile unit. The one
|
|
|
|
|
* important detail in this class is the should_compile_pixel_compile_unit method, which implements
|
|
|
|
|
* the criteria of whether the compile unit should be compiled given the node currently being
|
|
|
|
|
* processed as an argument. Those criteria are described as follows. If the compile unit is empty
|
|
|
|
|
* as is the case when processing nodes 1, 2, and 3, then it plainly shouldn't be compiled. If the
|
|
|
|
|
* given node is not a pixel node, then it can't be added to the compile unit and the unit is
|
|
|
|
|
* considered complete and should be compiled, as is the case when processing node 6. If the
|
|
|
|
|
* compile unit operates on single values and the given node operates on non-single values or vice
|
|
|
|
|
* versa, then it can't be added to the compile unit and the unit is considered complete and should
|
|
|
|
|
* be compiled, more on that in the next section. If the computed domain of the given node is not
|
|
|
|
|
* compatible with the domain of the compiled unit, then it can't be added to the unit and the unit
|
|
|
|
|
* is considered complete and should be compiled, as is the case when processing node 5, more on
|
|
|
|
|
* this in the next section. Otherwise, the given node is compatible with the compile unit and can
|
|
|
|
|
* be added to it, so the unit shouldn't be compiled just yet, as is the case when processing
|
|
|
|
|
* node 4.
|
2022-08-10 09:14:22 +02:00
|
|
|
*
|
2025-01-29 15:13:45 +01:00
|
|
|
* Special attention should be given to the aforementioned single value and domain compatibility
|
|
|
|
|
* criterion. One should first go over the discussion in COM_domain.hh for more information on
|
|
|
|
|
* domains. When a compile unit gets eventually compiled to a pixel operation, that operation will
|
|
|
|
|
* have a certain operation domain, and any node that gets added to the compile unit should itself
|
|
|
|
|
* have a computed node domain that is compatible with that operation domain, otherwise, had the
|
|
|
|
|
* node been compiled into its own operation separately, the result would have been be different.
|
|
|
|
|
* For instance, consider the above node tree where node 1 outputs a 100x100 result, node 2 outputs
|
|
|
|
|
* a 50x50 result, the first input in node 3 has the highest domain priority, and the second input
|
|
|
|
|
* in node 5 has the highest domain priority. In this case, pixel operation 1 will output a 100x100
|
2024-08-26 14:38:10 +03:00
|
|
|
* result, and pixel operation 2 will output a 50x50 result, because that's the computed operation
|
2022-08-10 09:14:22 +02:00
|
|
|
* domain for each of them. So node 6 will get a 50x50 result. Now consider the same node tree, but
|
2024-08-26 14:38:10 +03:00
|
|
|
* where all three nodes 3, 4, and 5 were compiled into a single pixel operation as shown the node
|
|
|
|
|
* tree below. In that case, pixel operation 1 will output a 100x100 result, because that's its
|
2022-08-10 09:14:22 +02:00
|
|
|
* computed operation domain. So node 6 will get a 100x100 result. As can be seen, the final result
|
|
|
|
|
* is different even though the node tree is the same. That's why the compiler can decide to
|
|
|
|
|
* compile the compile unit early even though further nodes can still be technically added to it.
|
|
|
|
|
*
|
2024-08-26 14:38:10 +03:00
|
|
|
* Pixel Operation 1
|
2022-08-10 09:14:22 +02:00
|
|
|
* +------------------------------------------------------+
|
|
|
|
|
* .------------. | .------------. .------------. .------------. | .------------.
|
|
|
|
|
* | Node 1 | | | Node 3 | | Node 4 | | Node 5 | | | Node 6 |
|
|
|
|
|
* | |----|--| |--| |------| |--|--| |
|
|
|
|
|
* | | .-|--| | | | .---| | | | |
|
|
|
|
|
* '------------' | | '------------' '------------' | '------------' | '------------'
|
|
|
|
|
* | +----------------------------------|-------------------+
|
|
|
|
|
* .------------. | |
|
|
|
|
|
* | Node 2 | | |
|
|
|
|
|
* | |--'------------------------------------'
|
|
|
|
|
* | |
|
|
|
|
|
* '------------'
|
|
|
|
|
*
|
2025-01-29 15:13:45 +01:00
|
|
|
* Similarly, all nodes in the compile unit should either be operating on single values or not.
|
|
|
|
|
* Otherwise, assuming a node operates on single values and its output is used in 1) a non-single
|
|
|
|
|
* value pixel operation and 2) another node that expects single values, if that node was added to
|
|
|
|
|
* the pixel operation, its output will be non-single value, while it would have been a single
|
|
|
|
|
* value if it was not added to the pixel operation.
|
|
|
|
|
*
|
|
|
|
|
* To check for the single value type and domain compatibility between the compile unit and the
|
|
|
|
|
* node being processed, the single value type and the domain of the compile unit is assumed to be
|
|
|
|
|
* the single value type and the domain of the first node added to the compile unit, noting that
|
|
|
|
|
* the domain is optional, since it is not used if the compile unit is a single value one. The
|
|
|
|
|
* single value type and the domain of the compile unit are computed and set in the
|
|
|
|
|
* add_node_to_pixel_compile_unit method. When processing a node, the computed single value type
|
|
|
|
|
* and the computed domain of node are compared to the compile unit single value type and domain in
|
|
|
|
|
* the should_compile_pixel_compile_unit method. Node single value types and domains are computed
|
|
|
|
|
* in the is_pixel_node_single_value and compute_pixel_node_domain methods respectively, the latter
|
|
|
|
|
* of which is analogous to the Operation::compute_domain method for nodes that are not yet
|
|
|
|
|
* compiled. */
|
2022-08-10 09:14:22 +02:00
|
|
|
class CompileState {
|
|
|
|
|
private:
|
2025-03-26 13:42:21 +02:00
|
|
|
/* A reference to the compositor context. */
|
|
|
|
|
const Context &context_;
|
2022-08-10 09:14:22 +02:00
|
|
|
/* A reference to the node execution schedule that is being compiled. */
|
|
|
|
|
const Schedule &schedule_;
|
|
|
|
|
/* Those two maps associate each node with the operation it was compiled into. Each node is
|
2024-08-26 14:38:10 +03:00
|
|
|
* either compiled into a node operation and added to node_operations, or compiled into a pixel
|
|
|
|
|
* operation and added to pixel_operations. Those maps are used to retrieve the results of
|
2022-08-10 09:14:22 +02:00
|
|
|
* outputs linked to the inputs of operations. See the get_result_from_output_socket method for
|
|
|
|
|
* more information. */
|
|
|
|
|
Map<DNode, NodeOperation *> node_operations_;
|
2024-08-27 14:42:11 +03:00
|
|
|
Map<DNode, PixelOperation *> pixel_operations_;
|
2022-08-10 09:14:22 +02:00
|
|
|
/* A contiguous subset of the node execution schedule that contains the group of nodes that will
|
2024-08-26 14:38:10 +03:00
|
|
|
* be compiled together into a pixel operation. See the discussion in COM_evaluator.hh for more
|
|
|
|
|
* information. */
|
|
|
|
|
PixelCompileUnit pixel_compile_unit_;
|
2025-01-29 15:13:45 +01:00
|
|
|
/* Stores whether the current pixel compile unit operates on single values. Only initialized when
|
|
|
|
|
* the pixel compile unit is not empty. */
|
|
|
|
|
bool is_pixel_compile_unit_single_value_;
|
|
|
|
|
/* The domain of the pixel compile unit if it was not a single value. Only initialized when the
|
|
|
|
|
* pixel compile unit is not empty and is not a single value. */
|
|
|
|
|
std::optional<Domain> pixel_compile_unit_domain_;
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/* Construct a compile state from the node execution schedule being compiled. */
|
2025-03-26 13:42:21 +02:00
|
|
|
CompileState(const Context &context, const Schedule &schedule);
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
/* Get a reference to the node execution schedule being compiled. */
|
|
|
|
|
const Schedule &get_schedule();
|
|
|
|
|
|
|
|
|
|
/* Add an association between the given node and the give node operation that the node was
|
|
|
|
|
* compiled into in the node_operations_ map. */
|
|
|
|
|
void map_node_to_node_operation(DNode node, NodeOperation *operation);
|
|
|
|
|
|
2024-08-26 14:38:10 +03:00
|
|
|
/* Add an association between the given node and the give pixel operation that the node was
|
|
|
|
|
* compiled into in the pixel_operations_ map. */
|
2024-08-27 14:42:11 +03:00
|
|
|
void map_node_to_pixel_operation(DNode node, PixelOperation *operation);
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
/* Returns a reference to the result of the operation corresponding to the given output that the
|
|
|
|
|
* given output's node was compiled to. */
|
|
|
|
|
Result &get_result_from_output_socket(DOutputSocket output);
|
|
|
|
|
|
|
|
|
|
/* Add the given node to the compile unit. And if the domain of the compile unit is not yet
|
|
|
|
|
* determined or was determined to be an identity domain, update it to the computed domain for
|
|
|
|
|
* the give node. */
|
2024-08-26 14:38:10 +03:00
|
|
|
void add_node_to_pixel_compile_unit(DNode node);
|
2022-08-10 09:14:22 +02:00
|
|
|
|
2024-08-26 14:38:10 +03:00
|
|
|
/* Get a reference to the pixel compile unit. */
|
|
|
|
|
PixelCompileUnit &get_pixel_compile_unit();
|
2022-08-10 09:14:22 +02:00
|
|
|
|
2025-01-29 15:13:45 +01:00
|
|
|
/* Returns true if the pixel compile unit operates on single values. */
|
|
|
|
|
bool is_pixel_compile_unit_single_value();
|
|
|
|
|
|
2022-08-10 09:14:22 +02:00
|
|
|
/* Clear the compile unit. This should be called once the compile unit is compiled to ready it to
|
|
|
|
|
* track the next potential compile unit. */
|
2024-08-26 14:38:10 +03:00
|
|
|
void reset_pixel_compile_unit();
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
/* Determines if the compile unit should be compiled based on a number of criteria give the node
|
2025-01-29 15:13:45 +01:00
|
|
|
* currently being processed. See the class description for a description of the method. */
|
2024-08-26 14:38:10 +03:00
|
|
|
bool should_compile_pixel_compile_unit(DNode node);
|
2022-08-10 09:14:22 +02:00
|
|
|
|
2024-08-26 14:38:10 +03:00
|
|
|
/* Computes the number of pixel operation outputs that will be added for this node in the current
|
|
|
|
|
* pixel compile unit. This is essentially the number of outputs that will be added for the node
|
2024-08-27 14:42:11 +03:00
|
|
|
* in PixelOperation::populate_results_for_node. */
|
2024-08-26 14:38:10 +03:00
|
|
|
int compute_pixel_node_operation_outputs_count(DNode node);
|
2024-03-06 07:25:05 +01:00
|
|
|
|
2022-08-10 09:14:22 +02:00
|
|
|
private:
|
2025-01-29 15:13:45 +01:00
|
|
|
/* Determines if the given pixel node operates on single values or not. The node operates on
|
|
|
|
|
* single values if all its inputs are single values, and consequently will also output single
|
|
|
|
|
* values. */
|
|
|
|
|
bool is_pixel_node_single_value(DNode node);
|
|
|
|
|
|
2024-08-26 14:38:10 +03:00
|
|
|
/* Compute the node domain of the given pixel node. This is analogous to the
|
2022-08-10 09:14:22 +02:00
|
|
|
* Operation::compute_domain method, except it is computed from the node itself as opposed to a
|
|
|
|
|
* compiled operation. See the discussion in COM_domain.hh for more information. */
|
2024-08-26 14:38:10 +03:00
|
|
|
Domain compute_pixel_node_domain(DNode node);
|
2022-08-10 09:14:22 +02:00
|
|
|
};
|
|
|
|
|
|
2024-12-17 11:39:04 +01:00
|
|
|
} // namespace blender::compositor
|