diff --git a/tests/46node.tests b/tests/46node.tests index d87391b24..d025f04b3 100644 --- a/tests/46node.tests +++ b/tests/46node.tests @@ -14,15 +14,15 @@ TEST "Proc Node test setup" NodeDevel_test < @@ -43,15 +42,25 @@ namespace test { using lib::time::FrameNr; using lib::time::FrameCnt; + namespace { + ont::Flavr SRC_A = 10; ///< »chain-A« arbitrary source frame marker + ont::Flavr SRC_B = 20; ///< similar for »chain-B« + Symbol SECONDS_GRID = "grid_sec"; ///< 1-seconds grid for translation Time -> Frame-# + + const uint NUM_INVOCATIONS = 100; + } + /***************************************************************//** * @test demonstrate and document how [render nodes](\ref proc-node.hpp) * are connected into a processing network, allowing to _invoke_ * a \ref Port on a node to pull-generate a render result. - * - the foundation layer is formed by the nodes as linked into a network - * - starting from any Port, a TurnoutSystem can be established - * - which in turn allows _turn out_ a render result from this port. + * - Nodes can be built and ID metadata can be inspected + * - several Nodes can be linked into a render graph + * - connectivity can be verified to match definition + * - TestFrame data can be computed in a complex processing network + * - parameters can be derived from time and fed into the nodes. */ class NodeLink_test : public Test { @@ -321,8 +330,19 @@ namespace test { - /** @test TODO Invoke some render nodes as linked together - * @todo WIP 2/25 🔁 define ⟶ ✔ implement + /** @test Invoke some render nodes as linked together. + * - use exactly the same topology as in the preceding test + * - but this time use TestFrame (random data) and configure + * hash-chaining operations provided by »Test Random« + * - setup various automation functions, based on the frame-# + * - use a pre-computation step to _quantise_ time into frame-# + * - install this pre-computation as »Param Agent Node« + * - configure individual parameters to consume precomputed frame-# + * - use _partial closure_ to supply the source-»flavour« parameter + * - also rebuild the expected computations by direct invocation + * - sample various test runs with randomly chosen time and port-# + * - verify computed data checksums match with expected computation. + * @todo 2/25 ✔ define ⟶ ✔ implement */ void trigger_node_port_invocation() @@ -331,24 +351,22 @@ namespace test { auto testMan = testRand().setupManipulator(); auto testMix = testRand().setupCombinator(); - ont::Flavr SRC_A = 10; - ont::Flavr SRC_B = 20; // Prepare for Time-Quantisation --> Frame-# or Offset parameter - Symbol SECONDS_GRID = "grid_sec"; steam::asset::meta::TimeGrid::build (SECONDS_GRID, 1); + auto quantSecs = [&](Time time){ return FrameNr::quant (time, SECONDS_GRID); }; // Prepare a precomputed parameter for the complete tree - auto selectFrameNo = [&](TurnoutSystem& tuSys){ return FrameNr::quant (tuSys.getNomTime(), SECONDS_GRID); }; + auto selectFrameNo = [&](TurnoutSystem& tuSys){ return quantSecs(tuSys.getNomTime()); }; auto paramSpec = buildParamSpec() .addSlot (selectFrameNo); auto accFrameNo = paramSpec.makeAccessor<0>(); // Prepare mapping- and automation-functions - auto stepFilter = [] (FrameCnt id)-> ont::Param { return util::limited (10, -10 + id, 20); }; - auto stepMixer = [] (FrameCnt id)-> double { return util::limited (0, + id, 50) / 50.0; }; + auto stepFilter = [] (FrameCnt id)-> ont::Param { return util::limited (10, -10 + id, 50); }; + auto stepMixer = [] (FrameCnt id)-> ont::Factr { return util::limited (0, + id, 50) / 50.0; }; // note: binds the accessor for the precomputed FrameNo-parameter auto autoFilter = [=](TurnoutSystem& tuSys){ return stepFilter (tuSys.get (accFrameNo)); }; @@ -445,20 +463,51 @@ namespace test { .build()}; + // Effectively, the following computation is expected to happen... + auto verify = [&](Time nomTime, uint port) + { + ont::FraNo fraNo = quantSecs(nomTime); + ont::Flavr fla_A = SRC_A + util::min (port, 1u); + ont::Flavr fla_B = SRC_B + util::min (port, 2u); + ont::Param param = stepFilter(fraNo); + ont::Factr mix = stepMixer (fraNo); + + TestFrame f1{uint(fraNo),fla_A}; + TestFrame f2{uint(fraNo),fla_B}; + + ont::manipulateFrame (&f1, &f1, param); + ont::combineFrames (&f1, &f1, &f2, mix); + CHECK (not f1.isPristine()); + CHECK ( f2.isPristine()); + return f1.getChecksum(); + }; + BufferProvider& provider = DiagnosticBufferProvider::build(); - const BuffDescr buffDescr = provider.getDescriptorFor(sizeof(TestFrame)); + const BuffDescr buffDescr = provider.getDescriptor(); auto invoke = [&](Time nomTime, uint port) { // Sequence to invoke a Node... BuffHandle buff = provider.lockBuffer(buffDescr); - CHECK (not buff.accessAs().isValid()); + TestFrame& result = buff.accessAs(); + CHECK ( result.isPristine()); buff = parNode.pull (port, buff, nomTime, ProcessKey{}); - HashVal checksum = buff.accessAs().getChecksum(); + CHECK ( result.isValid()); + CHECK (not result.isPristine()); + HashVal checksum = result.getChecksum(); buff.release(); return checksum; }; -SHOW_EXPR(invoke(Time::ZERO, 1)); + // Computations should be pure (not depending on order) + // Thus sample various random times and ports + for (uint i=0; i < NUM_INVOCATIONS; ++i) + { + uint port = rani(3); + Time nomTime{rani(60'000),0}; // drive test with a random »nominal Time« <60s with ms granularity + + // Invoke -- and compare checksum with direct computation + CHECK (invoke (nomTime,port) == verify (nomTime,port)); + } } }; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 13bb0bc6d..0fa59cd16 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -6174,7 +6174,7 @@ This is the core service provided by the player subsystem. The purpose is to cre :any details of this processing remain opaque for the clients; even the player subsystem just accesses the EngineFaçade -
+
//Integration effort to promote the development of rendering, playback and video display in the GUI//
 This IntegrationSlice was started in {{red{2023}}} as [[Ticket #1221|https://issues.lumiera.org/ticket/1221]] to coordinate the completion and integration of various implementation facilities, planned, drafted and built during the last years; this effort marks the return of development focus to the lower layers (after years of focussed UI development) and will implement the asynchronous and time-bound rendering coordinated by the [[Scheduler]] in the [[Vault|Vault-Layer]]
 
@@ -6212,11 +6212,12 @@ __December.23__: building the Scheduler required time and dedication, including
 __April.24__: after completing an extended round of performance tests for the new Scheduler, development focus is shifted now shifted upwards to the [[Render Node Network|ProcNode]], where Engine activity is carried out. This part was addressed at the very start of the project, and later again -- yet could never be completed, due to a lack of clear reference points and technical requirements. Hope to achieve a breakthrough rests on this integration effort now.
 __June.24__: assessment of the existing code indicated some parts not well suited to the expected usage. Notably the {{{AllocationCluster}}}, which is the custom allocator used by the render nodes network, was reworked and simplified. Moreover, a new custom container was developed, to serve as //link to connect the nodes.// Beyond that, in-depth review validated the existing design for the render nodes, while also indicating a clear need to rearrange and re-orient the internal structure within an node invocation to be better aligned with the structure of the Application developed thus far...
 __December.24__: after an extended break of several months (due to family-related obligations), a re-oriented concept for the Render Node invocation was developed in a prototyping setup. Assessment of results and further analysis leads to the conclusion that a more flexible invocation scheme -- and especially structured invocation parameters -- must be retro-fitted into the code developed thus far. Features of this kind can not be added later by decoration and extension -- rather, the data structures used directly within the invocation required considerable elaboration. This could be accomplished in the end, through a bold move to abandon array-style storage and switch over to strictly typed data tuples and a functor-based binding to the implementation library.
+__February.25__: built extended verification mechanisms, including some Node metadata handling; after some further retro-fitting and modernisation of function-support libraries (partial closure), a **complex Render Node graph could be built and invoked**, using {{{TestData}}} frames with reproducible hash-chaining computations. This is a milestone — the re-oriented Render Node structure feels much more adequate, and connection to [[Scheduler]] and [[Job-Planning|JobPlanningPipeline]] seems to be within reach now
 * ✔ establish a test setup for developing render node functionality
 * ✔ build and connect some dummy render nodes directly in a test setup
-* 🗘 invoke render nodes stand-alone, without framework
+* ✔ invoke render nodes stand-alone, without framework
 * ⌛ introduce a //placeholder link// to connect JobTicket to the actual invocation (without actual [[Fixture]])
-* ⌛ rework and complete the existing node invocation code
+* ✔ rework and complete the existing node invocation code
 
 !Decisions
 ;Scheduler
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 92fa5a66a..64e980c33 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -90069,7 +90069,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -91733,9 +91733,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + @@ -91748,18 +91752,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - - - - + + + + + - - - + + + @@ -92407,9 +92411,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Alle Parameter einer processing-function sind in ein einziges Tupel zusammengefaßt, aber typischerweise sind einige technisch, während andere die gestalterischen Steuermöglichkeiten der Operation repräsentieren. Beide Aspekte müssen auf dem gleichen NodeBuilder konfiguriert werden, aber aus verschiedenen Quellen (und vermutlich auch in verschiedenen Schritten) @@ -92420,9 +92422,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

implementiert auf Basis der partial-function-closure @@ -92472,11 +92472,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + - + @@ -92498,21 +92500,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + - + - + - + @@ -92520,19 +92522,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + - + - + @@ -92578,6 +92580,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + +
@@ -92611,7 +92616,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -92630,15 +92635,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + + + + - + + - + @@ -92650,8 +92661,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -92659,14 +92670,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + - + @@ -102821,10 +102832,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - - + + @@ -103473,8 +103484,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -104618,10 +104629,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -104868,9 +104879,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - + + + @@ -105549,8 +105560,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -105558,7 +105569,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105699,11 +105710,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - - - + + + + + @@ -105729,11 +105740,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + - + @@ -105741,7 +105752,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105765,7 +105776,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -105781,7 +105792,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -106415,33 +106426,39 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - - - - + + + + + + + - - + + + + + + + - - + + - - - - - - + + + + + + @@ -106449,19 +106466,169 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + + + + + + + + + + + + + + + + +

+ in combineFrames() : out->markChecksum(); +

+ +
- + + + + +

+ zunächst formal, aber habe das per Debugger bestätigt +

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

+ aber — +

+

+ warum funktioniert das dann +

+

+ für Arbeit-Buffer in der Engine? +

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

+ d.h. die source-Node alloziert hier einen Buffer vom generischen Provider +

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

+ in einem Einzelfall von Hand nachgezählt... +

+ + +
+ + +
+ + + + + + + + + +
@@ -108607,12 +108774,12 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + - + - + @@ -108787,8 +108954,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -108828,36 +108995,35 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - - + - + - + - - - - + + + + - + - - - - + + + + - - + + - - + + - - + + @@ -108919,11 +109085,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - - + +