46using namespace nodes::derived_node_tree_types;
53 this->build_procedure();
54 procedure_executor_ = std::make_unique<mf::ProcedureExecutor>(procedure_);
62 mf::ParamsBuilder parameter_builder{*procedure_executor_, &
mask};
64 const bool is_single_value = this->is_single_value_operation();
68 for (
int i = 0;
i < procedure_.params().
size();
i++) {
69 if (procedure_.params()[
i].type == mf::ParamType::InterfaceType::Input) {
71 if (
input.is_single_value()) {
72 parameter_builder.add_readonly_single_input(
input.single_value());
75 parameter_builder.add_readonly_single_input(
input.cpu_data());
80 if (is_single_value) {
81 output.allocate_single_value();
82 parameter_builder.add_uninitialized_single_output(
86 output.allocate_texture(domain);
87 parameter_builder.add_uninitialized_single_output(
output.cpu_data());
92 mf::ContextBuilder context_builder;
93 procedure_executor_->call_auto(
mask, parameter_builder, context_builder);
96 if (is_single_value) {
97 for (
int i = 0;
i < procedure_.params().
size();
i++) {
98 if (procedure_.params()[
i].type == mf::ParamType::InterfaceType::Output) {
100 output.update_single_value_data();
106void MultiFunctionProcedureOperation::build_procedure()
110 auto &multi_function_builder = *node_multi_functions_.lookup_or_add_cb(node, [&]() {
111 return std::make_unique<nodes::NodeMultiFunctionBuilder>(*node.bnode(),
112 node.context()->btree());
114 node->typeinfo->build_multi_function(multi_function_builder);
115 const mf::MultiFunction &multi_function = multi_function_builder.function();
127 this->assign_output_variables(node, output_variables);
131 for (
const auto &item : output_to_variable_map_.
items()) {
133 if (!output_variables_.
contains(item.value)) {
134 procedure_builder_.add_destruct(*item.value);
137 for (mf::Variable *variable : implicit_variables_) {
139 if (!output_variables_.contains(variable)) {
140 procedure_builder_.add_destruct(*variable);
143 for (mf::Variable *variable : implicit_input_to_variable_map_.values()) {
144 procedure_builder_.add_destruct(*variable);
147 mf::ReturnInstruction &return_instruction = procedure_builder_.add_return();
148 mf::procedure_optimization::move_destructs_up(procedure_, return_instruction);
152Vector<mf::Variable *> MultiFunctionProcedureOperation::get_input_variables(
153 DNode node,
const mf::MultiFunction &multi_function)
155 int available_inputs_index = 0;
156 Vector<mf::Variable *> input_variables;
157 for (
int i = 0;
i < node->input_sockets().
size();
i++) {
158 const DInputSocket
input{node.context(), node->input_sockets()[
i]};
166 if (origin->is_input()) {
172 input_variables.
append(this->get_constant_input_variable(DInputSocket(origin)));
175 input_variables.
append(this->get_implicit_input_variable(
input, DInputSocket(origin)));
180 const DOutputSocket
output = DOutputSocket(origin);
185 input_variables.
append(output_to_variable_map_.lookup(
output));
203 const mf::DataType expected_type = mf::DataType::ForSingle(
204 CPPType::get<ColorSceneLinear4f<eAlpha::Premultiplied>>());
205 input_variables.
last() = this->convert_variable(input_variables.
last(), expected_type);
209 const mf::ParamType parameter_type = multi_function.param_type(available_inputs_index);
210 input_variables.
last() = this->convert_variable(input_variables.
last(),
211 parameter_type.data_type());
213 available_inputs_index++;
216 return input_variables;
219mf::Variable *MultiFunctionProcedureOperation::get_constant_input_variable(
DInputSocket input)
221 const mf::MultiFunction *constant_function =
nullptr;
222 switch (
input->type) {
225 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<float>>(value);
230 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<int32_t>>(value);
235 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<bool>>(value);
242 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<float2>>(value);
247 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<float3>>(value);
252 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<float4>>(value);
263 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<float4>>(value);
268 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<nodes::MenuValue>>(
274 constant_function = &procedure_.construct_function<mf::CustomMF_Constant<std::string>>(
283 mf::Variable *constant_variable = procedure_builder_.add_call<1>(*constant_function)[0];
284 implicit_variables_.
append(constant_variable);
285 return constant_variable;
288mf::Variable *MultiFunctionProcedureOperation::get_implicit_input_variable(
292 const ImplicitInput implicit_input = origin_descriptor.implicit_input;
297 input_descriptor.type = origin_descriptor.type;
298 input_descriptor.implicit_input = implicit_input;
302 if (implicit_input_to_variable_map_.contains(implicit_input)) {
309 existing_input_descriptor.domain_priority =
math::min(
310 existing_input_descriptor.domain_priority, input_descriptor.domain_priority);
312 return implicit_input_to_variable_map_.lookup(implicit_input);
316 const std::string input_identifier =
"implicit_input" + std::to_string(implicit_input_index);
322 mf::Variable &variable = procedure_builder_.add_input_parameter(
323 mf::DataType::ForSingle(
Result::cpp_type(input_descriptor.type)), input_identifier);
324 parameter_identifiers_.append(input_identifier);
327 implicit_input_to_variable_map_.add(implicit_input, &variable);
332mf::Variable *MultiFunctionProcedureOperation::get_multi_function_input_variable(
337 if (output_to_variable_map_.contains(output_socket)) {
344 input_descriptor.domain_priority =
math::min(
345 input_descriptor.domain_priority,
351 return output_to_variable_map_.lookup(output_socket);
355 const std::string input_identifier =
"input" + std::to_string(input_index);
364 mf::Variable &variable = procedure_builder_.add_input_parameter(
365 mf::DataType::ForSingle(
Result::cpp_type(input_descriptor.type)), input_identifier);
366 parameter_identifiers_.append(input_identifier);
369 output_to_variable_map_.add(output_socket, &variable);
384void MultiFunctionProcedureOperation::assign_output_variables(
DNode node,
385 Vector<mf::Variable *> &variables)
389 int available_outputs_index = 0;
390 for (
int i = 0;
i < node->output_sockets().
size();
i++) {
391 const DOutputSocket
output{node.context(), node->output_sockets()[
i]};
397 mf::Variable *output_variable = variables[available_outputs_index];
398 output_to_variable_map_.add_new(
output, output_variable);
409 const bool is_preview_output =
output == preview_output;
410 if (is_preview_output) {
414 if (is_operation_output || is_preview_output) {
415 this->populate_operation_result(
output, output_variable);
418 available_outputs_index++;
422void MultiFunctionProcedureOperation::populate_operation_result(
DOutputSocket output_socket,
423 mf::Variable *variable)
426 const std::string output_identifier =
"output" + std::to_string(output_id);
436 const mf::DataType expected_type = mf::DataType::ForSingle(
result.get_cpp_type());
437 mf::Variable *converted_variable = this->convert_variable(variable, expected_type);
439 procedure_builder_.add_output_parameter(*converted_variable);
440 output_variables_.add_new(converted_variable);
441 parameter_identifiers_.append(output_identifier);
444mf::Variable *MultiFunctionProcedureOperation::convert_variable(mf::Variable *variable,
445 const mf::DataType expected_type)
448 const mf::DataType variable_type = variable->data_type();
449 if (variable_type == expected_type) {
454 const mf::MultiFunction *function = conversion_table.get_conversion_multi_function(
455 variable_type, expected_type);
459 const mf::MultiFunction &constant_function =
460 procedure_.construct_function<mf::CustomMF_GenericConstant>(
461 expected_type.single_type(), expected_type.single_type().default_value(),
false);
462 mf::Variable *constant_variable = procedure_builder_.add_call<1>(constant_function)[0];
463 implicit_variables_.append(constant_variable);
464 return constant_variable;
467 mf::Variable *converted_variable = procedure_builder_.add_call<1>(*function, {variable})[0];
468 implicit_variables_.append(converted_variable);
469 return converted_variable;
472bool MultiFunctionProcedureOperation::is_single_value_operation()
475 for (
int i = 0;
i < procedure_.params().
size();
i++) {
476 if (procedure_.params()[
i].type == mf::ParamType::InterfaceType::Input) {
478 if (!
input.is_single_value()) {
#define BLI_assert_unreachable()
struct bNodeSocketValueFloat bNodeSocketValueFloat
struct bNodeSocketValueMenu bNodeSocketValueMenu
struct bNodeSocketValueInt bNodeSocketValueInt
struct bNodeSocketValueRGBA bNodeSocketValueRGBA
struct bNodeSocketValueVector bNodeSocketValueVector
struct bNodeSocketValueString bNodeSocketValueString
struct bNodeSocketValueBoolean bNodeSocketValueBoolean
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
ItemIterator items() const &
bool contains(const Key &key) const
void append(const T &value)
const T & last(const int64_t n=0) const
static const CPPType & get()
Result create_result(ResultType type, ResultPrecision precision)
MultiFunctionProcedureOperation(Context &context, PixelCompileUnit &compile_unit, const Schedule &schedule)
Result & get_result(StringRef identifier)
void populate_result(StringRef identifier, Result result)
Context & context() const
Result & get_input(StringRef identifier) const
virtual Domain compute_domain()
InputDescriptor & get_input_descriptor(StringRef identifier)
void declare_input_descriptor(StringRef identifier, InputDescriptor descriptor)
Map< DOutputSocket, std::string > outputs_to_declared_inputs_map_
Map< std::string, DOutputSocket > inputs_to_linked_outputs_map_
Map< std::string, int > inputs_to_reference_counts_map_
const Schedule & schedule_
VectorSet< DOutputSocket > preview_outputs_
Map< DOutputSocket, std::string > output_sockets_to_output_identifiers_map_
PixelOperation(Context &context, PixelCompileUnit &compile_unit, const Schedule &schedule)
PixelCompileUnit compile_unit_
Map< ImplicitInput, std::string > implicit_inputs_to_input_identifiers_map_
static const CPPType & cpp_type(const ResultType type)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
const DataTypeConversions & get_implicit_type_conversions()
bool is_output_linked_to_node_conditioned(DOutputSocket output, FunctionRef< bool(DNode)> condition)
DSocket get_input_origin_socket(DInputSocket input)
VectorSet< DNode > Schedule
VectorSet< DNode > PixelCompileUnit
DOutputSocket find_preview_output_socket(const DNode &node)
ResultType get_node_socket_result_type(const bNodeSocket *socket)
InputDescriptor input_descriptor_from_input_socket(const bNodeSocket *socket)
bool is_socket_available(const bNodeSocket *socket)
T min(const T &a, const T &b)
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3