![]() |
Lumiera 0.pre.04
»edit your freedom«
|
Interface to the processing nodes and the Render Nodes network. More...
Go to the source code of this file.
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.
Regarding access, there are three different interfaces to consider
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.
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.
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 | |