Files
test/source/blender/nodes/NOD_multi_function.hh
Omar Emara fbdb803750 Compositor: Implement Multi-Function Procedure Operation
This patch implements the multi-function procedure operation for the new
CPU compositor, which is a concrete implementation of the PixelOperation
abstraction, much like ShaderOperation, but uses the FN system to more
efficiently evaluate a group of pixel-wise operations.

A few changes were done to FN to support development. The multi-function
builder now allows retrieving the built function. A new builder method
construct_and_set_matching_fn_cb was added to allow using the SI_SO
builders with non static functions. A few other SI_SO were added to. And
a CPP type for float4 was added.

Additionally, the Gamma, Math, Brightness, and Normal nodes were
implemented as an example. The Math node implementation reused the
existing GN math node implementation, so the code was moved to a common
file.

Reference #125968.

Pull Request: https://projects.blender.org/blender/blender/pulls/126988
2024-10-15 06:51:42 +02:00

144 lines
3.6 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "FN_multi_function.hh"
#include "DNA_node_types.h"
namespace blender::nodes {
class NodeMultiFunctions;
/**
* Utility class to help nodes build a multi-function for themselves.
*/
class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
private:
const bNode &node_;
const bNodeTree &tree_;
std::shared_ptr<mf::MultiFunction> owned_built_fn_;
const mf::MultiFunction *built_fn_ = nullptr;
friend NodeMultiFunctions;
public:
NodeMultiFunctionBuilder(const bNode &node, const bNodeTree &tree);
/**
* Assign a multi-function for the current node. The input and output parameters of the function
* have to match the available sockets in the node.
*/
void set_matching_fn(const mf::MultiFunction *fn);
void set_matching_fn(const mf::MultiFunction &fn);
/**
* Utility method for creating and assigning a multi-function when it can't have a static
* lifetime.
*/
template<typename T, typename... Args> void construct_and_set_matching_fn(Args &&...args);
/**
* Similar to #construct_and_set_matching_fn, but can be used when the type name of the
* multi-function is not known (e.g. when using `mf::build::SI1_SO`).
*
* \param create_multi_function: A function that returns the multi-function by value.
*/
template<typename Fn> void construct_and_set_matching_fn_cb(Fn &&create_multi_function);
const bNode &node();
const bNodeTree &tree();
const mf::MultiFunction &function();
};
/**
* Gives access to multi-functions for all nodes in a node tree that support them.
*/
class NodeMultiFunctions {
public:
struct Item {
const mf::MultiFunction *fn = nullptr;
std::shared_ptr<mf::MultiFunction> owned_fn;
};
private:
Map<const bNode *, Item> map_;
public:
NodeMultiFunctions(const bNodeTree &tree);
const Item &try_get(const bNode &node) const;
};
/* -------------------------------------------------------------------- */
/** \name #NodeMultiFunctionBuilder Inline Methods
* \{ */
inline NodeMultiFunctionBuilder::NodeMultiFunctionBuilder(const bNode &node, const bNodeTree &tree)
: node_(node), tree_(tree)
{
}
inline const bNode &NodeMultiFunctionBuilder::node()
{
return node_;
}
inline const bNodeTree &NodeMultiFunctionBuilder::tree()
{
return tree_;
}
inline const mf::MultiFunction &NodeMultiFunctionBuilder::function()
{
return *built_fn_;
}
inline void NodeMultiFunctionBuilder::set_matching_fn(const mf::MultiFunction *fn)
{
built_fn_ = fn;
}
inline void NodeMultiFunctionBuilder::set_matching_fn(const mf::MultiFunction &fn)
{
built_fn_ = &fn;
}
template<typename T, typename... Args>
inline void NodeMultiFunctionBuilder::construct_and_set_matching_fn(Args &&...args)
{
owned_built_fn_ = std::make_shared<T>(std::forward<Args>(args)...);
built_fn_ = &*owned_built_fn_;
}
template<typename Fn>
inline void NodeMultiFunctionBuilder::construct_and_set_matching_fn_cb(Fn &&create_multi_function)
{
using T = decltype(create_multi_function());
T *allocated_function = new T(create_multi_function());
owned_built_fn_ = std::shared_ptr<T>(allocated_function);
built_fn_ = &*owned_built_fn_;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #NodeMultiFunctions Inline Methods
* \{ */
inline const NodeMultiFunctions::Item &NodeMultiFunctions::try_get(const bNode &node) const
{
static Item empty_item;
const Item *item = map_.lookup_ptr(&node);
if (item == nullptr) {
return empty_item;
}
return *item;
}
/** \} */
} // namespace blender::nodes