BatchMicroNode is the base class for custom micro nodes which shall receive a batch of input values in their Process method and compute the corresponding output values. You should prefer this over a BasicMicroNode when the Process method consists of just a few simple operations: Then the calling overhead of nodes is significant, and it can be reduced when a single call to Process handles a whole batch of values. Of course this only holds when there is a proper batch of values, for example in the context of shading there's usually just one set of values.
To implement a BatchMicroNode, you have to derive a new class from BatchMicroNode and add a function template
{Result<void> Process(Batch<...>&)} (no const in front of Batch) to that class with a list of those ports between the angular brackets which shall be accessed by the node. Within the Process method you have to write a for loop over the batch as in the example shown below. The ports have to be defined by MAXON_PORT macros in a micro node group class. Usually the BatchMicroNode class is a member of that micro node group class:
// This class defines a micro node group which adds batches of two Int values by a BatchMicroNode.
class MyBatchAddNode
{
public:
// Declaration of the input and output ports of the micro node group.
MAXON_PORT_INPUT(Int, in1);
MAXON_PORT_INPUT(Int, in2);
MAXON_PORT_OUTPUT(Int, out);
// Implementation of the single custom micro node.
class Impl : public BatchMicroNode
{
public:
// The Process method needs to specify which ports of the group the micro node accesses, in this case all ports.
// If the group contains more than one micro node, each micro node usually needs only a subset of the ports.
//
// The PORTMODE template parameter allows to instantiate the Process method with different port modes, see PortMode.
//
// Note that there's no const in front of Batch!
Result<void> Process(Batch<in1, in2, out>& batch) const
{
// Iterate over the batch. Again there's no const in front of auto.
for (auto& ports : batch)
{
// Do the computation for a single set of values.
ports.out.Update(ports.in1() + ports.in2());
}
return OK;
}
};
// The Init function will be called to set up the micro node group
// when you call CreateNode<MyBatchAddNode>() or as part of the MAXON_CORENODE_REGISTER macro.
static Result<void> Init(const MicroNodeGroupRef& group)
{
iferr_scope;
group.AddChild<Impl>() iferr_return;
return OK;
}
};
There is the helper class OperatorNode to simplify the implementation of a core node class consisting of a single BatchMicroNode. If you want to implement a core node class consisting of a single BatchMicroNode which just invokes an existing C++ function or operator (as in the example with the + operator) you can also use one of the macros MAXON_CORENODE_FUNCTION, MAXON_CORENODE_OPERATOR_UNARY and MAXON_CORENODE_OPERATOR_BINARY.
|
using | MicroNodeClass = BatchMicroNode |
|
template<typename... PORTS> |
using | Batch = PortsAccess< PORTSACCESS_FLAGS::BATCH, PORTS... > |
|
using | ProcessFn = Result< void >(*)(const MicroNode *, const void *,) |
|
enum | TYPE {
INVALID,
BASIC,
BATCH,
SPLIT_MERGE,
ITERATION,
SEQUENCING,
RECURSION_STEP,
CURRENT_ITERATION_VALUE,
CURRENT_ITERATION_VALUE_WITH_INIT,
COPY,
SET_TRUE,
NOP,
SUBTRACTIVE_DOMAIN,
VARIABLE_MASK,
VALUE_PORT_MASK,
INPUT_PORT_MASK,
EXPORTED_PORT,
VIRTUAL_INPUT_PORT,
OUTPUT_PORT_MASK,
VARIABLE,
PORT_MASK,
FACTOR_MASK,
ROOT,
WHILE_CONDITION,
INDEFINITE_LOOP,
TOP_LEVEL_FACTOR_MASK,
FRAME_MASK,
TOP_LEVEL_FRAME,
FRAME,
EVENT_MASK,
EVENT,
FACTOR_HEAD_MASK,
DEFINITE_FACTOR_HEAD_MASK,
CONTAINER_LOOP_HEAD_MASK,
CONTAINER_OUTPUT_HEAD_MASK,
DEFINITE_FACTOR_MASK,
CONTAINER_OUTPUT_ELEMENT_MASK,
INDEXABLE_FACTOR_MASK,
DIMENSIONAL_FACTOR_TEST,
CONTAINER_LOOP_MASK,
INDEFINITE_LOOP_HEAD,
RECURSION_HEAD,
DEFINITE_LOOP_HEAD,
CONTAINER_LOOP_HEAD,
ARRAY_LOOP_HEAD,
CONTAINER_LOOP,
ARRAY_LOOP,
CONTAINER_OUTPUT_HEAD,
CONTAINER_OUTPUT_ELEMENT,
ARRAY_OUTPUT_ELEMENT,
DEFINITE_LOOP,
GENERIC_DEFINITE_LOOP,
RECURSION,
INPUT_ELEMENT_MASK,
ARRAY_INPUT_ELEMENT,
CONTAINER_INPUT_ELEMENT,
INPUT_MASK,
OUTPUT_MASK,
CONTAINER_MASK,
CONTAINER,
ARRAY_CONTAINER,
ARRAY,
CONTAINER_OUTPUT_MASK,
CONTAINER_OUTPUT,
CONTAINER_INPUT_GROUP_MASK,
CONTAINER_INPUT_GROUP,
ALL
} |
|
enum | FLAGS {
NONE,
STATE,
STATE_MODIFIER,
LOCAL,
PERMANENT,
CACHED,
DONT_WRAP,
CURRENT_ITV,
NEXT_ITV,
CONTAINER_MEMBER,
COMMUTATIVE,
STATE_MAPPER,
PARAMETER,
INPUT_WITHOUT_VALUE,
OUTER_DOMAIN,
NO_FACTORS,
SUSPEND,
KEEP_LETTER_CASE,
INDEPENDENT,
INCLUDE_IN_PREDECESSORS,
FACTOR_REFERENCE,
OPTIONAL_INPUT,
CURRENT_ITV_GROUP,
NEXT_ITV_GROUP,
HIDDEN,
ITV_MASK,
ITV_GROUP_MASK,
PORT_MODIFIERS,
MODIFIERS,
ALL
} |
|
enum | PORTSACCESS_FLAGS {
NONE,
ITERATION,
CONTAINER_MASK,
CONST_MASK,
BATCH,
BATCH_ACCESS,
CONTAINER,
CONST_CONTAINER,
DIRECT_ACCESS_TEST
} |
|
template<typename PORT > |
using | Input = typename PORT::PrivateInput |
|
template<typename... PORTS> |
using | Ports = typename PortsAccess< PORTSACCESS_FLAGS::NONE, PORTS... >::Members |
|