diff --git a/src/steam/engine/weaving-pattern.hpp b/src/steam/engine/media-weaving-pattern.hpp similarity index 98% rename from src/steam/engine/weaving-pattern.hpp rename to src/steam/engine/media-weaving-pattern.hpp index 66fd78b94..0bd8cd84f 100644 --- a/src/steam/engine/weaving-pattern.hpp +++ b/src/steam/engine/media-weaving-pattern.hpp @@ -1,5 +1,5 @@ /* - WEAVING-PATTERN.hpp - Base patterns to organise data connections and render processing invocation + MEDIA-WEAVING-PATTERN.hpp - Base patterns to organise data connections and render processing invocation Copyright (C) 2008, Hermann Vosseler @@ -13,7 +13,7 @@ */ -/** @file weaving-pattern.hpp +/** @file media-weaving-pattern.hpp ** Construction set to assemble and operate a data processing scheme within a Render Node. ** Together with turnout.hpp, this header provides the "glue" which holds together the ** typical setup of a Render Node network for processing media data. A MediaWeavingPattern @@ -131,8 +131,8 @@ */ -#ifndef STEAM_ENGINE_WEAVING_PATTERN_H -#define STEAM_ENGINE_WEAVING_PATTERN_H +#ifndef STEAM_ENGINE_MEDIA_WEAVING_PATTERN_H +#define STEAM_ENGINE_MEDIA_WEAVING_PATTERN_H #include "steam/common.hpp" #include "steam/engine/turnout.hpp" @@ -260,4 +260,4 @@ namespace engine { }}// namespace steam::engine -#endif /*STEAM_ENGINE_WEAVING_PATTERN_H*/ +#endif /*STEAM_ENGINE_MEDIA_WEAVING_PATTERN_H*/ diff --git a/src/steam/engine/param-weaving-pattern.hpp b/src/steam/engine/param-weaving-pattern.hpp new file mode 100644 index 000000000..66fc49175 --- /dev/null +++ b/src/steam/engine/param-weaving-pattern.hpp @@ -0,0 +1,263 @@ +/* + PARAM-WEAVING-PATTERN.hpp - Base patterns to organise data connections and render processing invocation + + Copyright (C) + 2008, Hermann Vosseler + 2024, Hermann Vosseler + +  **Lumiera** is free software; you can redistribute it and/or modify it +  under the terms of the GNU General Public License as published by the +  Free Software Foundation; either version 2 of the License, or (at your +  option) any later version. See the file COPYING for further details. + +*/ + + +/** @file param-weaving-pattern.hpp + ** Construction set to assemble and operate a data processing scheme within a Render Node. + ** Together with turnout.hpp, this header provides the "glue" which holds together the + ** typical setup of a Render Node network for processing media data. A MediaWeavingPattern + ** implements the sequence of steps — as driven by the Turnout — to combine the invocation + ** of media processing operations from external Libraries with the buffer- and parameter + ** management provided by the Lumiera Render Engine. Since these operations are conducted + ** concurrently, all invocation state has to be maintained in local storage on the stack. + ** + ** # Integration with media handling Libraries + ** + ** A Render invocation originates from a [Render Job](\ref render-invocation.hpp), which first + ** establishes a TurnoutSystem and then enters into the recursive Render Node activation by + ** invoking Port::weave() for the »Exit Node«, as defined by the job's invocation parameters. + ** The first step in the processing cycle, as established by the Port implementation (\ref Turnout), + ** is to build a »Feed instance«, from the invocation of `mount(TurnoutSystem&)`. + ** + ** Generally speaking, a `Feed` fulfils the role of an _Invocation Adapter_ and a _Manifold_ of + ** data connections. The standard implementation, as given by MediaWeavingPattern, relies on a + ** combination of both into a \ref FeedManifold. This is a flexibly configured data adapter, + ** directly combined with an embedded _adapter functor_ to wrap the invocation of processing + ** operations provided by an external library. + ** + ** Usually some kind of internal systematics is assumed and applied within such a library. + ** Operations can be exposed as plain function to invoke, or through some configuration and + ** builder notion. Function arguments tend to follow a common arrangement and naming scheme, + ** also assuming specific arrangement and data layout for input and output data. This kind of + ** schematism is rooted in something deeper: exposing useful operations as a library collection + ** requires a common ground, an understanding about the _order of things_ to be treated — at least + ** for those kind of things, which fall into a specific _domain,_ when tasks related to such a + ** domain shall be supported by the Library. Such an (implicit or explicit) framework of structuring + ** is usually designated as a **Domain Ontology** (in contrast to the questions pertaining Ontology + ** in general, which are the subject of philosophy proper). Even seemingly practical matters like + ** processing media data do rely on fundamental assumptions and basic premises regarding what is + ** at stake and what shall be subject to treatment, what fundamental entities and relationships + ** to consider within the domain. Incidentally, many of these assumptions are positive in nature + ** and not necessarily a given — which is the root of essential incompatibilities between Libraries + ** targeting a similar domain: due to such fundamental differences, they just can not totally agree + ** upon what kinds of things to expect and where to draw the line of distinction. + ** + ** The Lumiera Render Engine and media handling framework is built in a way _fundamentally agnostic_ + ** to the specific presuppositions of this or that media handling library. By and large, decisions, + ** distinctions and qualifications are redirected back into the scope of the respective library, by + ** means of a media-library adapter plug-in. Assuming that the user _in fact understands_ the meaning + ** of and reasoning behind employing a given library, the _mere handling_ of the related processing + ** can be reduced to a small set of organisational traits. For sake of consistency, you may label + ** these as a »Render Engine Ontology«. In all brevity, + ** - We assume that the library provides distinguishable processing operations + ** that can be structured and classified and managed as _processing assets,_ + ** - we assume that processing is applied to sources or »media« and that + ** the result of processing is again a source that can be processed further; + ** - specific operations can thus be conceptualised as processing-stages or _Nodes,_ + ** interconnected by _media streams,_ which can be tagged with a _stream type._ + ** - At implementation level, such streams can be represented in entirety as data buffers + ** of a specific layout, filled with some »frame« or chunk of data + ** - and the single processing step or operation can be completely encapsulated + ** as a pure function (referentially transparent, without side effects); + ** - all state and parametrisation can be represented either as some further data stream in/out, + ** or as parameters-of-processing, which can be passed as a set of values to the function + ** prior of invocation, thereby completely determining the observable behaviour. + ** + ** # composition of the Invocation State + ** + ** By means of this positing, the attachment point to an external library can be reduced into a small + ** number of connector links. Handling the capabilities of a library within the Session and high-level Model + ** will require some kind of _registration,_ which is beyond the scope of this discussion here. As far as + ** the Render Engine and the low-level-Model is concerned, any usage of the external libraries capabilities + ** can be reduced into... + ** - Preparing an adapter functor, designated as **processing-functor**. This functor takes three kinds of + ** arguments, each packaged as a single function call argument, which may either be a single item, or + ** possibly be structured as a tuple of heterogeneous elements, or an array of homogeneous items. + ** + an output data buffer or several such buffers are always required + ** + (optionally) an input buffer or several such buffers need to be supplied + ** + (optionally) also a parameter value, tuple or array can be specified + ** - Supplying actual parameter values (if necessary); these are drawn from the invocation + ** of a further functor, designated as **parameter-functor**, and provided from within + ** the internal framework of the Lumiera application, either to deliver fixed parameter + ** settings configured by the user in the Session, or by evaluating _Parameter Automation,_ + ** or simply to supply some technically necessary context information, most notably the + ** frame number of a source to retrieve. + ** - Preparing buffers filled with input data, in a suitable format, one for each distinct + ** item expected in the input data section of the processing-functor; filling these + ** input buffers requires the _recursive invocation_ of further Render Nodes... + ** - Allocating buffers for output data, sized and typed accordingly, likewise one for + ** each distinct item detailed in the output data argument of the processing-functor. + ** + ** The FeedManifold template, which (as mentioned above) is used by this standard implementation + ** of media processing in the form of the MediaWeavingPattern, is configured specifically for each + ** distinct signature of a processing-functor to match the implied structural requirements. If a + ** functor is output-only, no input buffer section is present; if it expects processing parameters, + ** storage for an appropriate data tuple is provided and a parameter-functor can be configured. + ** A clone-copy of the processing-functor itself is also stored as clone-copy alongside within + ** the FeedManifold, and thus placed into stack memory, where it is safe even during deeply nested + ** recursive invocation sequences, while rendering in general is performed massively in parallel. + ** + ** In the end, the actual implementation code of the weaving pattern has to perform the connection + ** and integration between the »recursive weaving scheme« and the invocation structure implied by + ** the FeedManifold. It has to set off the recursive pull-invocation of predecessor ports, retrieve + ** the result data buffers from these and configure the FeedManifold with the \ref BuffHandle entries + ** retrieved from these recursive calls. Buffer handling in general is abstracted and codified thorough + ** the [Buffer Provider framework](\ref buffer-provider.hpp), which offers the means to allocate further + ** buffers and configure them into the FeedManifold for the output data. The »buffer handling protocol« + ** also requires to invoke BuffHandle::emit() at the point when result data can be assumed to be placed + ** into the buffer, and to release buffers not further required through a BuffHandle::release() call; + ** Notably this applies to the input buffers are completion of the processing-functor invocation, and + ** is required also for secondary (and in a way, superfluous) result buffers, which are sometimes + ** generated as a by-product of the processing function invocation, but are actually not passed + ** as output up the node invocation chain. + ** + ** @see feed-manifold.hpp + ** @see weaving-pattern-builder.hpp + ** @see \ref proc-node.hpp "Overview of Render Node structures" + ** + ** @warning WIP as of 12/2024 first complete integration round of the Render engine ////////////////////////////TICKET #1367 + ** + */ + + +#ifndef STEAM_ENGINE_PARAM_WEAVING_PATTERN_H +#define STEAM_ENGINE_PARAM_WEAVING_PATTERN_H + +#include "steam/common.hpp" +#include "steam/engine/turnout.hpp" +#include "steam/engine/turnout-system.hpp" +#include "steam/engine/feed-manifold.hpp" +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation +//#include "vault/gear/job.h" +//#include "steam/engine/exit-node.hpp" +//#include "lib/time/timevalue.hpp" +//#include "lib/linked-elements.hpp" +#include "lib/several.hpp" +//#include "lib/util-foreach.hpp" +//#include "lib/iter-adapter.hpp" +//#include "lib/meta/function.hpp" +//#include "lib/itertools.hpp" +//#include "lib/util.hpp" ////////OOO wegen manifoldSiz() + +//#include + + +namespace steam { +namespace engine { + + using lib::Several; + + + /** + * Standard implementation for a _Weaving Pattern_ to connect + * the input and output data feeds (buffers) into a processing function. + * @tparam INVO a configuration / policy base class to _adapt for invocation_ + * @note assumptions made regarding the overall structure + * - `INVO::Feed` defines an _invocation adapter_ for the processing function + * - `INVO::buildFeed()` is a functor to (repeatedly) build `Feed` instances + * - the _invocation adapter_ in turn embeds a `FeedManifold` to hold + * + a setup of output buffer pointers (single, tuple or array) + * + (optionally) a similar setup for input buffer pointers + * + (optionally) a parameter or parameter tuple + * + storage to configure BuffHandle entries for each «slot» + * + storage to hold the actual processing functor + */ + template + struct ParamWeavingPattern + : INVO + { + using Feed = typename INVO::Feed; + + static_assert (_verify_usable_as_InvocationAdapter()); + + Several leadPort; + Several outTypes; + + uint resultSlot{0}; + + /** forwarding-ctor to provide the detailed input/output connections */ + template + ParamWeavingPattern (Several&& pr + ,Several&& dr + ,uint resultIdx + ,ARGS&& ...args) + : INVO{forward(args)...} + , leadPort{move(pr)} + , outTypes{move(dr)} + , resultSlot{resultIdx} + { } + + + Feed + mount (TurnoutSystem& turnoutSys) + { + ENSURE (leadPort.size() <= INVO::FAN_I); + ENSURE (outTypes.size() <= INVO::FAN_O); + return INVO::buildFeed (turnoutSys); + } + + void + pull (Feed& feed, TurnoutSystem& turnoutSys) + { + if constexpr (Feed::hasInput()) + for (uint i=0; i() template function +#include "steam/engine/media-weaving-pattern.hpp" #include "lib/meta/tuple-helper.hpp" //#include "lib/test/test-helper.hpp" ////////////////////////////OOO TODO added for test #include "lib/format-string.hpp" diff --git a/tests/core/steam/engine/node-feed-test.cpp b/tests/core/steam/engine/node-feed-test.cpp index 356d1bdbb..bbbb78dfb 100644 --- a/tests/core/steam/engine/node-feed-test.cpp +++ b/tests/core/steam/engine/node-feed-test.cpp @@ -19,7 +19,7 @@ #include "lib/test/run.hpp" #include "steam/engine/proc-node.hpp" #include "steam/engine/node-builder.hpp" -#include "steam/engine/weaving-pattern.hpp" +#include "steam/engine/media-weaving-pattern.hpp" #include "steam/engine/turnout-system.hpp" #include "steam/engine/turnout.hpp" #include "steam/engine/diagnostic-buffer-provider.hpp" @@ -49,6 +49,7 @@ namespace test { run (Arg) { feedParam(); + feedParamNode(); UNIMPLEMENTED ("render node pulling source data from vault"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 948e6fbdc..d5c3e886f 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -29210,9 +29210,7 @@ - - - +

Verhältnis zum Inteface Renderer klären @@ -29731,9 +29729,7 @@ - - - +

⟹ es muß das strukturell korrekte Maximum explizit berechnet werden; würden wir nur die rechte Spalte summieren, bliebe eine bereits bestehende Spreizung in der linken Spalte unberücksichtigt @@ -29969,9 +29965,7 @@ - - - +

Jeder Track kann 0...N Ruler haben (Ruler = horizontale Scala); @@ -30376,9 +30370,7 @@ - - - +

...im Session-Modell für eine Timeline jeweils ein Property hierfür geben... @@ -31402,9 +31394,7 @@ - - - +

...d.h. dann aus dem InteractionDirector heraus @@ -32043,9 +32033,7 @@ - - - +

falls inset, wird er nur innerhalb der border und über den Hintergrund gezeichnet @@ -79198,7 +79186,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80720,7 +80708,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -82260,8 +82248,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -82275,7 +82263,112 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + +

+ Beachte: es handelt sich um einen Erweiterungspunkt von theoretischer Relevanz... +

+ + +
+ + + +

+ Ich kann derzeit lediglich vorhersagen, daß die strikte Beschränkung allein auf die absolute-nominal-Time im Allgemeinen nicht durchzuhalten ist. Es sind Fälle denkbar, in denen im Besondern aktzeller kontextueller Zustand der Applikation mit einfließt — die Automations-Auswertung mithin keine »pure Function« mehr ist. +

+

+ Ich halte es für ehrlicher, diese Möglichkeit offen aufzuzeigen, und dafür sogar einen Ansatzpunkt im Modell vorzusehen; denn es ist allemal besser, wenn eine solche externe Verbindung sich als eine »AgentNode« im Modell niederschlägt, als wenn sie irgendwo durch eine Hintertür in einem Seiten-Effekt einzelner Parameter-Funktoren versteckt wird... +

+ +
+ +
+ + + + + + + + + +

+ Die ParamAgentNode wird bezüglich des Aufrufs eine darunter liegende Node durchreichen wollen. Aber die Definition dieser darunter liegenden Node und deren Leads wird, typischerweise, auf die »Slots« im ParamAgent bezug nehmen... +

+ +
+
+ + + + +

+ ⟹ folglich braucht es eine vorgelagerte ParamBuildSpec +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -82335,9 +82428,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -82485,6 +82578,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + @@ -83035,6 +83133,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + +
@@ -86590,7 +86696,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -86801,6 +86907,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + +
@@ -88120,11 +88229,79 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + +
+ + + + + + + + + + + + + + + + + + + +

+ der PortBuilder kann einen Adapter für klassische Parameter-Automation bauen; dieser muß intern auf die absolute-nominal-Time  zugreifen können +

+ + +
+
+ + + + +

+ Für den Bau einer Param(Agent)Node wird ein Chain-Block vorbereitet, welcher später dann in einen Invocation-Stack-Frame gelegt werden soll. Die tatsächlichen Dateninhalte für diesen Block stammen aus dem Aufruf eines Funktors, der in diesen Vorgang hinein verdrahtet wird. Der Builder muß selber einen Funktor konstruieren, der später alle diese Aktionen während der Invocation ausführt, als Schritte des speziellen Weaving-Patterns, das hier zum Einsatz kommt. Dafür braucht er Zugang zu Typ-Konstruktoren, die prinzipiell bereits zur compile-Zeit vorliegen,  da das TurnoutSystem eine fest eingestellte Basis-Typisierung als Anker verwendet. Darauf aufbauend erzeugt die konkrete Builder-Instanz den Typ für konkrete Accessoren, und bettet sie in die vorbereitete Invocation ein +

+ +
+ +
+
+ + + + + + + + +

+ die Typisierung über Hetero-Data stellt grundsätzlich sicher, daß es die zuzugreifenden Struktur irgendwann, irgendwie in diesem Executable geben kann, aber nicht wann sie tatsächlich existiert, oder wie lange sie lebt. Auch der Zugang über die interne linked-List stellt nur sicher, daß die Datenstruktur bereits erzeugt wurde, nicht aber daß sie noch lebt +

+ +
+
+ + + + +

+ die konkreten Accessoren werden als spezielle Typisierung in einen privaten Kontext in ein invocation-λ eingebettet, so daß sie nur aus dem Scope der tatsächlichen Invocation heraus sichtbar sind; solange dieser Scope lebt, ist per Definitionem auch zumindest dieser Chain-Block valide und zugreifbar. +

+ + +
+
+
+
+
+
@@ -91129,8 +91306,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -91573,8 +91751,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -93992,6 +94170,25 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + @@ -97366,12 +97563,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + - + + @@ -97399,7 +97598,36 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + + + + + + + + + + + + + + + + +

+ getrieben durch elaborierten Testfall +

+

+ NodeFeed_test::feedParamNode() +

+ + +
+ +
@@ -97467,9 +97695,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- - - +

Über das Prototyping hat eine Art Normierung stattgefunden; ich bin jetzt sicher, daß die allermeisten Aufgaben zur Medien-Berechnung in dieses Standard-Pattern abgebildet werden können, vor allem durch die stark erweiterte Flexibilität des Buffer- und Parameter-Bindings @@ -97555,8 +97781,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -98399,9 +98625,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -98465,6 +98692,16 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + @@ -99751,7 +99988,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -99762,6 +99999,23 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + +

+ Denn das Konzept der »AgentNode« ist ja generisch, und nicht aus der Welt zu schaffen — hängt es doch an der Wurzel zusammen mit dem Ansatz einer vereinfachenden Abstraktion in einen Node-Graphen, die dann das Einlassen komplexerer Zusammenhänge in die lokale Struktur innerhalb dieses Graphen impliziert, in Form von Bau- und Verschaltungsmustern... +

+

+ Für die Parameter-Behandlung sind komplexe Spezialfälle vorhersehbar, welche die Pasis-Parameter, den Kontext-Zugriff über einen Prozeß-Key, sowie weitere, kontextuell zugängliche Zustandsdaten in einen erweiterten Satz konkreter Steuerparameter synthetisieren, um diese dann an anderer Stelle, rekursiv tiefer im Invocation-Tree, zur Parametrisierung der Medien-Berechnung heranzuziehen. Ein solches Muster ist in der Tat „speziell“ und ohne im Moment für mich erkennbaren konkreten Bezug; ich leite diese Möglichkeit lediglich aus allgemeinen Überlegungen zur Struktur her, und ziehe den Schluß, zumindest die Ansatzpunkte hierfür schaffen zu müssen.... +

+ + +
+ + + +
@@ -100831,7 +101085,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + @@ -100843,6 +101097,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + @@ -102039,13 +102297,21 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+ + + + + + + + - +