Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
proc-node.hpp File Reference

Interface to the processing nodes and the Render Nodes network. More...

Go to the source code of this file.

Description

Interface to the processing nodes and the Render Nodes network.

The Lumiera Render Engine is based on a graph of interconnected Render Nodes. This »Low-level-Model« is pre-arranged by a Builder as result of compiling and interpreting the arrangement created by the user in the Session, known as »High-level-Model«. All ways to possibly perform (play, render) the current arrangement are thus encoded into the configuration and connectivity of ProcNode elements.

Usage

Regarding access, there are three different interfaces to consider

  • the ProcNode::pull is the invocation interface. It is function-call style
  • the builder interface, comprising the NodeBuilder (TODO 2024 what else actually?).
  • the control of playback and rendering processes is accomplished by the Player. For actual processing, Lumiera relies on functionality provided by dedicated domain libraries (e.g. FFmpeg for video processing). A binding implemented as a Lumiera Plug-in will expose such a Library's resources as Assets and will set up function bindings to be embedded into Render Nodes.

By using the NodeBuilder interface, concrete ProcNode and Port instances are created, interconnected and attached below the Fixture, which is the »backbone« of the low-level-Model. The coordination and the act of invoking this NodeBuilder is conducted by structures in the Builder subsystem of Lumiera, which works similar to a compiler for programming languages — with the difference that within this application an edit and media arrangement is compiled into „executable“ form, ready for rendering and performance. In this context performance implies to »play« (render) part of a »Timeline«, which is accomplished through a PlayProcess, which in turn breaks down the work into individual »Render Jobs« organised through the Scheduler. Through such a sequence of translations, the processing of a frame ends up as a job to invoke some entrance point into the Render Node network.

Arrangement of Render Nodes

The arrangement of ProcNode elements in the render graph exhibits a DAG topology. Each node knows only its direct predecessors, designated as »Lead Nodes« or »Leads«. Conceptually, each Node represents a specific processing capability, delegating internally to some actual Library implementation of the desired processing algorithm. Yet in reality, several flavours of this processing capability are typically required. For example, maybe sound processing will be expected in stereo format (channel interleaved blocks of audio samples), but in addition also the two individual mono channels will be required independently. Or a video processing pipeline might be required in full resolution, but also sampled down for display in a GUI viewer window or for thumbnail images. The existence of several flavours of computation might seem obvious or irrelevant — yet touches on a fundamental decision: in Lumiera, no media processing happens beyond the Render Nodes. Even for the down-sampled tiny preview images, a render pipeline is specifically preconfigured, and then exposed through a Port on the Render Node.

The actual rendering thus proceeds through the successive activation of Ports. Internally, each Port is connected to predecessor ports, which can be »pulled« to generate the input data for the current processing step. Conducting the invocation of a single processing step in a Port thus requires the interplay of several, intricately interwoven activities — forming a »Weaving Pattern«: Establishing a frame, pulling from predecessors, spawning out further memory buffers to hold computed result data and finally triggering the actual »weft«. The Port on a Node is thus an interface, actually implemented by a Turnout, which comprises a Weaving Pattern Template. The most common scheme for media processing is embodied by the MediaWeavingPattern template, yet other Weaving Patterns may be configured to adapt to different processing needs (e.g. hardware accelerated computation).

Templates in C++ must be instantiated, with arguments specific to the usage. Which would be the signature of the processing function, the types and number of input- and output buffers and an additional tuple of specific parameters to pass, like e.g. the frame number or the (possibly automated) parameter settings for an effect. The invocation of a Port thus calls through a (classical, function-virtual) interface into specific code instantiated within the Library-adapter Plug-in. At compile time, consistency of involved buffer types and function signatures and memory allocation schemes can be ensured, so that no further checks and dynamic adaptation and transformation is necessary at runtime. The engine implementation works on data tuples, typed buffer pointers and helpers checked for memory safety — and not on plain arrays and void pointers.

Remarks
A future extension to this scheme is conceivable, where common processing pipelines are pre-compiled in entirety, possibly combined with hardware acceleration.
Todo:
WIP 2/2025 Node-Invocation is reworked from ground up for the »Playback Vertical Slice«
See also
turnout.hpp
turnout-system.hpp
node-builder.hpp
node-link.test.cpp

Definition in file proc-node.hpp.

#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/hash-value.h"
#include "steam/engine/buffhandle.hpp"
#include "steam/engine/turnout-system.hpp"
#include "lib/format-string.hpp"
#include "lib/several.hpp"
#include <string>
#include <optional>

Namespaces

namespace  steam
 Steam-Layer implementation namespace root.
 
namespace  steam::engine
 Lumiera's render engine core and operational control.
 

Typedefs

using ProcNodeRef = std::reference_wrapper< ProcNode >
 
using OptionalBuff = std::optional< BuffHandle >
 
using PortRef = std::reference_wrapper< Port >
 

Classes

class  Port
 
class  Connectivity
 Interface: Description of the input and output ports, processing function and predecessor nodes for a given ProcNode. More...
 
class  ProcNode
 Key abstraction of the Render Engine: A Data processing Node. More...
 
class  ProcNodeDiagnostic
 
class  PortDiagnostic
 
class  _ConCheck
 Helper for connectivity-checks in tests. More...
 

Functions

ProcNodeDiagnostic watch (ProcNode &theNode)
 
PortDiagnostic watch (Port &thePort)
 
_ConCheck is_linked (ProcNode &n)
 start a DSL expression to verify node connectivity.
 

Variables

const size_t MAX_NODE_ARG = LUMIERA_MAX_ORDINAL_NUMBER / 2
 arbitrary safety limit on fain-in / fan-out