From ce9bf7f143305ab80988478eba2a6ff489e8235a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 4 Jul 2024 23:54:13 +0200 Subject: [PATCH] Invocation: conjectures pertaining an implementation of Node-Graph generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To escape a possible deadlock in analysis, I resort to developing some kind of free-wheeling presupposition how the **Builder** could be implemented — a centrepiece of the Lumiera architecture envisioned thus far — which ''unfortunately'' can only be planned and developed in a more solid way ''after'' the current »Vertical Slice« is completed. Thus I find myself in the uncomfortable situation of having to work towards a core piece, which can not yet be built, since it relies heavily on the very structures to be built... --- ...de-wiring-builder.hpp => node-builder.hpp} | 11 +- tests/core/steam/engine/node-linkage-test.cpp | 2 +- wiki/thinkPad.ichthyo.mm | 642 ++++++++++++++++-- 3 files changed, 611 insertions(+), 44 deletions(-) rename src/steam/engine/{node-wiring-builder.hpp => node-builder.hpp} (92%) diff --git a/src/steam/engine/node-wiring-builder.hpp b/src/steam/engine/node-builder.hpp similarity index 92% rename from src/steam/engine/node-wiring-builder.hpp rename to src/steam/engine/node-builder.hpp index bd47cd649..424e6275b 100644 --- a/src/steam/engine/node-wiring-builder.hpp +++ b/src/steam/engine/node-builder.hpp @@ -1,8 +1,9 @@ /* - NODE-WIRING-BUILDER.hpp - Setup of render nodes connectivity + NODE-BUILDER.hpp - Setup of render nodes connectivity Copyright (C) Lumiera.org 2009, Hermann Vosseler + 2024 , Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -20,7 +21,7 @@ */ -/** @file node-wiring-builder.hpp +/** @file node-builder.hpp ** Helper for defining the desired wiring and operation mode for a render node. ** During the Builder run, the render nodes network is wired up starting from the ** source (generating) nodes up to the exit nodes. As the wiring is implemented through @@ -38,8 +39,8 @@ */ -#ifndef ENGINE_NODE_WIRING_BUILDER_H -#define ENGINE_NODE_WIRING_BUILDER_H +#ifndef ENGINE_NODE_BUILDER_H +#define ENGINE_NODE_BUILDER_H #include "steam/engine/proc-node.hpp" @@ -106,4 +107,4 @@ namespace engine { }} // namespace steam::engine -#endif /*ENGINE_NODE_WIRING_BUILDER_H*/ +#endif /*ENGINE_NODE_BUILDER_H*/ diff --git a/tests/core/steam/engine/node-linkage-test.cpp b/tests/core/steam/engine/node-linkage-test.cpp index 61a920711..8851ef92b 100644 --- a/tests/core/steam/engine/node-linkage-test.cpp +++ b/tests/core/steam/engine/node-linkage-test.cpp @@ -27,7 +27,7 @@ #include "lib/test/run.hpp" #include "steam/engine/proc-node.hpp" -#include "steam/engine/node-wiring-builder.hpp" +#include "steam/engine/node-builder.hpp" #include "steam/engine/test-rand-ontology.hpp" //#include "lib/util.hpp" diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2961b30dc..b03ae2d6f 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -68363,7 +68363,7 @@ - + @@ -68395,7 +68395,11 @@ - + + + + + @@ -71237,6 +71241,153 @@ + + + + + + +

+ «Domain-Ontology-Mapping» +

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

+ Einfach gesagt: jede Media-handling-Library definiert, was für Medien-Dinge es geben kann, wie diese zusammenhängen und klassifiziert werden und wie deren Eigenschaften festgestellt werden können... +

+ + +
+
+ + + + + + +

+ Feststellung: Domain-Ontologies werden über Aufgaben-Callbacks  eingebunden +

+ + +
+ + + + + +

+ Dies ist ein Beschluß auf Basis einer induktiven Grundhaltung: Wir haben den bestehenden Umgang mit dem Thema »Media-Processing« betrachtet und auf diesem Hintergrund eine Architektur-Lösung gefunden, die nicht auf einer mutwillig deduktiv gesetzten Ordnung beruht. Es wird ein Rahmen abgesteckt, was man typischerweise „mit Medien machen“ möchte, und aus diesem wird ein Baukasten-System destilliert, auf dessen Basis sich diese üblichen Ziele und Zwecke erreichen lassen. Dieser Rahmen bleibt jedoch offen, insofern er nicht als eine innere Systematik ausgearbeitet wird. Stattdessen gibt es — aus diesem Baukasktensystem heraus — bestimmte Aufgaben, die im Rahmen der jeweiligen Domain-Ontology zu lösen sind. Lumiera stellt dafür den Raum für ein Modell bereit, und einen Ordnungsrahmen, wie mit den Modellbestandteilen umzugehen ist. Es obliegt dann aber dem jeweiligen Domain-Adapter (Façade), diese von Lumiera vorgegebenen Erwartungen in der jeweiligen Domäne zu realisieren. +

+

+ Zur Wirkung der aufgerufenen Aufgaben und zur Semantik müssen gewisse Annahmen gemacht werden, wie z.B. das ein Medium gerendert werden kann. Es wird aber nicht versucht, dies weiter klassifikatorisch zu fassen; die Wirkung dieser Aktionen wird durchgereicht, und der Sinn liegt bei demjenigen, der Lumiera verwendet, um damit etwas zu bauen. +

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

+ Beispiele: +

+
    +
  • + Feststellen, ob eine Verbindung für einen bestimmten Medienstrom realisierbar ist +
  • +
  • + Auswahl eines Codecs für einen »Strom-Prototypen«, dessen Bedeutung anderweitig festgelegt wurde +
  • +
  • + Entscheiden, in welcher Reihenfolge und in welcher Form Voraussetzungen bereitzustellen sind +
  • +
  • + Übersetzen eines Medienstroms in die Repräsentation einer anderen Media-handling-Library +
  • +
  • + Bereitstelleung einer Verschaltung im Detail, damit ein Verarbeitungsschritt im Rahmen der Lumiera Render-Engine als pull-Job ausgeführt werden kann +
  • +
+ + +
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ....gehe aber nicht davon aus, daß dies möglich ist, weil es den Zugriff auf Inhalte aus Plug-ins überall deutlich komplexer macht und auch zu Contention führen könnte +

+ + +
+ +
+ + +
+ + + + + +
+ + + + + + + + + @@ -71440,7 +71591,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -71481,11 +71652,18 @@ - + - + + + + + + + + @@ -72206,6 +72384,33 @@ + + + + + + + + + + + + + +

+ Callback: configureNode(builder) +

+ +
+ + + + + + +
+
+
@@ -81357,7 +81562,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -81747,19 +81952,31 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - - + + + + + + + + + + + - + + + + + @@ -81786,13 +82003,367 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- Problem: wie kommt man von Layer-3 in Layer-2? + diese wird später irgendwo instantiiert

- + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...nach dem Level-3-Build-walk sind sie allesamt nicht mehr erforderlich — und könnten per AllocationCluster auf einen Schlag weggeworfen werden +

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

+ ...d.h. die Planung steigt für einen Port ein, findet für dieses in Proc-Asset in einem bereits vorliegenden Prototypen der Connectivity, und kann für dieses Proc-Asset alle benötigten Inputs identifizieren und jeden von diesen einem anderen, ebenfalls bereits bekannten Vorläufer Proc-Asset zuordnen; diese Zuordnung wäre dann die Belegung eines Port, und das Proc-Asset würde zu einer geplanten Node. Im Besonderen ist durch diese Vorraussetzung festgelegt, daß alle diese Belegungen bereits eindeutig und entscheidbar sind; Zweideutigeiten und Unmöglichkeiten sind in den vorausgehenden Verarbeitungsschritten bereits aussortiert worden... +

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

+ Leads (≙Vorgänger-Nodes) werden nach Bedarf angelegt als Level-3-Builder +

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

+ ...anders als die Konfigurations-Walks auf Level-3 vor dem Triggern des Build-Walk; diese traversieren über Ports und Stream-Verbindungen, folgen also einem bestimmten Berechnungspfad. Dagegen für die Level-2-Builder sind Lead-Nodes vorrausgesetzt, und das bedeutet, ein Build erfolgt für die ganze Nodes, für alle Ports zusammen +

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

+ sodann wird für den Vorgänger ein Level-2-Builder erstellt +

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

+ tatsächlich ist jede Port-Impl ≙ Turnout ein Level-1-Builder +

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

+ nichts davon hängt von Strukturen aus der Domain-Ontology ab +

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

+ ...und hinter dem liegen ebenfalls Strukturen aus der Ontologie; das ist ja sogar gradezu der Kern der Sache: jede Library bestimmt was es für Arten von Medien und Strömen geben kann +

+ + +
+
+ + + + + + +

+ ...das klingt vielleicht nach einer steilen These, beruht aber auf der Beobachtung, daß eine solche Schematisierung (wiewohl denkbar), ihrerseits wieder Teil einer Domain-Ontology wäre — jeder Versuch, dies zu generalisieren liefe auf eine Universal-Ontologie des ganzen Fachbereichs hinaus, und ist daher grundsätzlich zum Scheitern verurteilt, denn so etwas gehört nicht auf die Ebene praktischer Organisation, auf der wir uns hier bewegen, bei der Konstruktion von Systemen der Informationstechnik. +

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

+ Konsequenz ⟹ der Aufruf der Level-2-Parametrisierung muß in einem Callback passieren +

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

+ Das bedeutet: wenn man auf dem default-konstruierten Builder die build()-Metode ausführt, dann entsteht eine Node, die zwar alle erwarteten Ports hat, aber alle diese Ports liefern bei Aufruf ein NULL-Handle des jeweils eingesetzten BufferProviders liefert. (Selbstverständlich wäre es viel schöner, an dieser Stelle einen leeren Frame zu liefern, aber das ist nicht möglich, ohne das Format zu kennen, welches jedoch von der Domain-Façade geleistet werden muß) +

+ + +
+
+ + + + + + +

+ der Callback lautet: configureNode(builder) +

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

+ Hiermit sei nur angezeigt, daß es weitere solche Festlegungen zur Betriebsart geben kann, die typischerweise auf einem höheren Level bereits entschieden wurden, vermutlich ebernfalls unter Zuhilfename der Domain-Façade +

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

+ Alle diese Callbacks werden auf dem Interface DomainFacade gesammelt +

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

+ ...diese muß die Grundzüge des Asset-Systems, die Schnittstellen-Entitägen des Builders, das Stream-Type-Framework (und vmtl.) noch Weiteres enthalten. Außerdem müssen alle die genannten Entitäten von der Implementierungs-Ebene entkoppelt sein +

+ + +
+
+
+ + +
+ + +
@@ -85567,8 +86138,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
dann sind unendlich viele Template-Instanzen die Folge

- - +
@@ -85628,7 +86198,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -85733,7 +86303,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +
@@ -85875,8 +86445,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -85891,7 +86461,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -85962,8 +86532,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
...insofern ist das eindeutig die elegantere Lösung. Auf den ersten Blick mag die komplette Trennung „sauberer“ wirken, jedoch muß dazu eine Meta-Repräsentation geschaffen werden, die für jedwede Art von Medium gilt, und es muß dafür ein Interpreter im Builder bereitstehen. Da auf der anderen Seite ohnehin ein Adapter für jede Library geschrieben werden muß, besteht die Möglichkeit, für jede Library einen eigenständige Weg zu verwenden, um letztlich die Aufrufparameter auszugeben; das bedeutet, man kann in der jeweiligen Fach-Ontologie bleiben, und das Ontology-Mapping beschränkt sich auf eine Übersetzung in das sehr rudimentäre Muster von Node-Aufrufen, wie von der Render-Engine gefordert

- - +
@@ -86011,8 +86580,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
...aber diese Info muß aus dem Library-Adapter bezogen werden können, und zwar schon viel früher, wenn das entspr. Processing-Asset erstellt wird; das kann allerdings auch eine dynamischen Rückruf in die LIbrary implizieren

- - +
@@ -86034,8 +86602,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - +
@@ -86045,8 +86612,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
ein ganz besonders lästiges Thema: in der C-Welt gilt es als Feature, und nicht als Bug, wenn eine Library dem Aufrufer das Memory-Management abnimmt; Libraries sind in der Hinsicht oft unsäglich „kreativ“. Typischerweise bedeutet das, daß man sich dann an ein ganz spezielles Protokoll halten muß; in Lumiera würden wir so etwas als besonderen BufferProvider verkapseln, mit einem speziellen »Inlay-Typ«, der dann lifecycle-Events an die Library weitergibt

- -
+
@@ -86064,8 +86630,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
Das ist ein spezielles Konstrukt, das sich direkt aus dem Setup mit BufferProvider ergibt: man sieht einen speziellen Buffer-»slot« vor, in den ein Adapter-Typ inplantiert wird; dieser Adapter bekommt eine Referenz auf die FeedManifold und wird dann getriggert, was die eigentliche externe Berechnung in der Library bewirkt. Da dieser Typ maßgeschneidert ist, kann er ein zusätzliches Kontroll- und Informations-API bieten

- -
+ @@ -86188,8 +86753,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
...man könnte ein System von nested scopes aufbauen, auf Basis einer persistenten Datenstruktur. Es ist aber noch nicht klar, ob soetwas jemals gebraucht wird (YAGNI); im Besonderen bräuchte man dann auch einen Propagations-Mechanismus für Bindings, und damit wird die Sache komplex und potentiell aufwendig. Als ein anderes Modell könnte man lediglich einen Verweis auf einen Key-Value-Store durchgeben, der dann auf dem Einstiegs-Stackframe liegen würde. Und als minimal-Version würden wir nur einen Koordinaten-Record per Funktionsparameter nach unten durchreichen — bräuchten dann aber einen offband-channel  um Muting und Aktivierungen (z.B. Switchboard) durchzugeben; letztere müssen übrigens auf Ebene der Job-Invocation atomar aufgegriffen werden (wie genau ist noch nicht klar)

- - +
@@ -86338,9 +86902,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ - @@ -86606,8 +87170,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
...und das ist ein besonders lästiger Grenzfall, der höchstwahrscheinlich sehr selten auftritt, dann aber ein knock-out sein könnte; das bedeutet, für diesen seltenen Fall muß die Möglichkeit für freies Mapping vorgesehen werden

- - +
@@ -86629,7 +87192,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -86776,7 +87339,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- Das ist eine Entscheidung. Man könnte ganz im Gegenteil jetzt anfangen, einen generischen Media-Function-Invoker zu schreiben, der von einer Routing-Tabelle gesteuert wird. Das werde ich nicht tun, da dies den  Schein einer Generizität erzeugt, die gar nicht gegeben ist.  Vielmehr gehe ich davon aus, daß die meisten Fälle offensichtlich-einfach sind, und in komplexeren Fällen muß man ohnehin wissen, was die jeweilige Library braucht; es wäre reine Verschwendung, das in ein Meta-Routing-Format zu pressen...  + Das ist eine Entscheidung. Man könnte ganz im Gegenteil jetzt anfangen, einen generischen Media-Function-Invoker zu schreiben, der von einer Routing-Tabelle gesteuert wird. Das werde ich nicht tun, da dies den Schein einer Generizität erzeugt, die gar nicht gegeben ist. Vielmehr gehe ich davon aus, daß die meisten Fälle offensichtlich-einfach sind, und in komplexeren Fällen muß man ohnehin wissen, was die jeweilige Library braucht; es wäre reine Verschwendung, das in ein Meta-Routing-Format zu pressen... 

@@ -86795,7 +87358,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +
@@ -86849,7 +87412,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -127643,8 +128206,11 @@ std::cout << tmpl.render({"what", "World"}) << s
+ + +