Blender V4.3
operation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <limits>
6#include <memory>
7
8#include "BLI_map.hh"
9#include "BLI_string_ref.hh"
10#include "BLI_vector.hh"
11
12#include "COM_context.hh"
14#include "COM_domain.hh"
16#include "COM_operation.hh"
19#include "COM_result.hh"
21#include "COM_texture_pool.hh"
22
24
25Operation::Operation(Context &context) : context_(context) {}
26
27Operation::~Operation() = default;
28
30{
31 evaluate_input_processors();
32
33 reset_results();
34
35 execute();
36
38
39 release_inputs();
40
41 release_unneeded_results();
42
44}
45
47{
48 return results_.lookup(identifier);
49}
50
52{
53 results_mapped_to_inputs_.add_new(identifier, result);
54}
55
57{
58 /* Default to an identity domain in case no domain input was found, most likely because all
59 * inputs are single values. */
60 Domain operation_domain = Domain::identity();
61 int current_domain_priority = std::numeric_limits<int>::max();
62
63 /* Go over the inputs and find the domain of the non single value input with the highest domain
64 * priority. */
65 for (StringRef identifier : input_descriptors_.keys()) {
66 const Result &result = get_input(identifier);
68
69 /* A single value input can't be a domain input. */
70 if (result.is_single_value() || descriptor.expects_single_value) {
71 continue;
72 }
73
74 /* An input that skips operation domain realization can't be a domain input. */
75 if (!descriptor.realization_options.realize_on_operation_domain) {
76 continue;
77 }
78
79 /* Notice that the lower the domain priority value is, the higher the priority is, hence the
80 * less than comparison. */
81 if (descriptor.domain_priority < current_domain_priority) {
82 operation_domain = result.domain();
83 current_domain_priority = descriptor.domain_priority;
84 }
85 }
86
87 return operation_domain;
89
91{
92 /* Each input processor type is added to all inputs entirely before the next type. This is done
93 * because the construction of the input processors may depend on the result of previous input
94 * processors for all inputs. For instance, the realize on domain input processor considers the
95 * value of all inputs, so previous input processors for all inputs needs to be added and
96 * evaluated first. */
97
98 for (const StringRef &identifier : results_mapped_to_inputs_.keys()) {
100 context(), get_input(identifier));
101 add_and_evaluate_input_processor(identifier, single_value);
102 }
103
104 for (const StringRef &identifier : results_mapped_to_inputs_.keys()) {
106 context(), get_input(identifier), get_input_descriptor(identifier));
107 add_and_evaluate_input_processor(identifier, conversion);
108 }
109
110 for (const StringRef &identifier : results_mapped_to_inputs_.keys()) {
112 context(), get_input(identifier), get_input_descriptor(identifier), compute_domain());
114 }
115}
116
118{
119 /* Allow null inputs to facilitate construct_if_needed pattern of addition. For instance, see the
120 * implementation of the add_and_evaluate_input_processors method. */
121 if (!processor) {
122 return;
123 }
124
125 ProcessorsVector &processors = input_processors_.lookup_or_add_default(identifier);
126
127 /* Get the result that should serve as the input for the processor. This is either the result
128 * mapped to the input or the result of the last processor depending on whether this is the first
129 * processor or not. */
130 Result &result = processors.is_empty() ? get_input(identifier) : processors.last()->get_result();
131
132 /* Map the input result of the processor and add it to the processors vector. */
133 processor->map_input_to_result(&result);
134 processors.append(std::unique_ptr<SimpleOperation>(processor));
135
136 /* Switch the result mapped to the input to be the output result of the processor. */
137 switch_result_mapped_to_input(identifier, &processor->get_result());
138
139 processor->evaluate();
140}
141
143
145{
146 return *results_mapped_to_inputs_.lookup(identifier);
147}
148
150{
151 results_mapped_to_inputs_.lookup(identifier) = result;
152}
153
155{
156 results_.add_new(identifier, result);
157}
158
160{
161 input_descriptors_.add_new(identifier, descriptor);
162}
163
165{
166 return input_descriptors_.lookup(identifier);
167}
168
170{
171 return context_;
172}
173
175{
176 return context_.texture_pool();
177}
178
179void Operation::evaluate_input_processors()
180{
181 if (!input_processors_added_) {
183 input_processors_added_ = true;
184 return;
185 }
186
187 for (const ProcessorsVector &processors : input_processors_.values()) {
188 for (const std::unique_ptr<SimpleOperation> &processor : processors) {
189 processor->evaluate();
190 }
191 }
192}
193
194void Operation::reset_results()
195{
196 for (Result &result : results_.values()) {
197 result.reset();
198 }
199}
200
201void Operation::release_inputs()
202{
203 for (Result *result : results_mapped_to_inputs_.values()) {
204 result->release();
205 }
206}
207
208void Operation::release_unneeded_results()
209{
210 for (Result &result : results_.values()) {
211 if (!result.should_compute() && result.is_allocated()) {
212 result.release();
213 }
214 }
215}
216
217} // namespace blender::realtime_compositor
void append(const T &value)
const T & last(const int64_t n=0) const
bool is_empty() const
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor)
Result & get_input(StringRef identifier) const
Definition operation.cc:144
void switch_result_mapped_to_input(StringRef identifier, Result *result)
Definition operation.cc:149
Result & get_result(StringRef identifier)
Definition operation.cc:46
InputDescriptor & get_input_descriptor(StringRef identifier)
Definition operation.cc:164
void populate_result(StringRef identifier, Result result)
Definition operation.cc:154
void add_and_evaluate_input_processor(StringRef identifier, SimpleOperation *processor)
Definition operation.cc:117
void map_input_to_result(StringRef identifier, Result *result)
Definition operation.cc:51
void declare_input_descriptor(StringRef identifier, InputDescriptor descriptor)
Definition operation.cc:159
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor, const Domain &operation_domain)
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result)
descriptor
Vector< std::unique_ptr< SimpleOperation > > ProcessorsVector
void realize_on_domain(Context &context, Result &input, Result &output, const Domain &domain, const float3x3 &input_transformation, const RealizationOptions &realization_options)