From 44b3dbe68297379d71a96a4d76f5b9d2a2c40b9b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 12 Apr 2026 23:53:07 +0200 Subject: [PATCH] BufferProvider: investigate and fix broken NodeDevel_test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The actual mystery, that could ''not'' be clarified, is why that test did pass previously. Because it was always broken, insofar it pretended that the output buffer does hold a valid test frame, while in fact the buffer is just newly allocated. The deeper reason behind this mismatch lies in the concept of ''in-place processing'' — which is a very obvious, nullary optimisation, and thus we want our engine to be ''in-place capable'' in the long run. Which explains why I did write the dummy-test operations with in-place processing in mind. Yet the actual version of the render engine leaves out a lot of future improvements, amongst others the in-place processing. This implies that — at least at the moment — it is clearly the responsibility of the processing function to prepare the output buffer, in cases where such preparation is necessary (and this applies in the case of `TestFrame`, which needs to be primed with a valid header mark) This change touches on another unsolved problem in the `TestDomainOntology`: we need a mechanism to allow the generic builder front-end to set specific configuration for some kind of processing. Generally speaking, such things are possible in C++, yet somewhat tricky — and thus I postponed that aspect and just included a configuration variant, hard-coded for the moment. --- src/test/test-rand-ontology.cpp | 13 +- src/test/test-rand-ontology.hpp | 37 +++++- tests/steam/engine/node-devel-test.cpp | 8 +- wiki/thinkPad.ichthyo.mm | 170 ++++++++++++++++++++++--- 4 files changed, 198 insertions(+), 30 deletions(-) diff --git a/src/test/test-rand-ontology.cpp b/src/test/test-rand-ontology.cpp index 7c05dfe97..1d399ce61 100644 --- a/src/test/test-rand-ontology.cpp +++ b/src/test/test-rand-ontology.cpp @@ -35,11 +35,6 @@ using lib::zip; namespace test { namespace ont { -// namespace err = lumiera::error; - - namespace { // hidden local support facilities.... - - } // (End) hidden impl details /** @remark will be returned from dummyOp() */ int dummyNum{-1}; @@ -120,11 +115,14 @@ namespace ont { } /** - * @param out existing allocation to place the generated TestFrame into + * @param out existing allocation with a TestFrame to receive manipulated data * @param in allocation holding the input TestFrame data * @param param parameter to control or »mark« the data manipulation (hash-combining) * @remark this function emulates „media data processing“: data is processed in 64-bit words, * by hash-chaining with \a param. The generated result is marked with a valid checksum. + * @note this function is _in-place capable_; `*out` must point to a valid TestFrame + * that will never be read and only receive the result word by word, which + * implies that this can be the same location as the input TestFrame. */ void manipulateFrame (TestFrame* out, TestFrame const* in, Param param) @@ -138,12 +136,13 @@ namespace ont { } /** - * @param out existing allocation to receive the calculated result TestFrame + * @param out existing allocation with a TestFrame to receive the combined data * @param srcA a buffer holding the input data for feed-A * @param srcB a buffer holding the input data for feed-B * @param mix degree of mixing (by integer arithmetics): 100 means 100% feed-B * @remark this function emulates a mixing or overlaying operation: * each result byte is the linear interpolation between the corresponding inputs. + * @note similar to \ref manipulateFrame, this function is _in-place capable_. */ void combineFrames (TestFrame* out, TestFrame const* srcA, TestFrame const* srcB, Factr mix) diff --git a/src/test/test-rand-ontology.hpp b/src/test/test-rand-ontology.hpp index b24262c52..eb0e6e09a 100644 --- a/src/test/test-rand-ontology.hpp +++ b/src/test/test-rand-ontology.hpp @@ -76,6 +76,20 @@ namespace test { const Literal DUMMY_PROC_ID{"op(int)"}; + /** prime a working buffer so that it holds some valid TestFrame. + * @param src a source buffer to copy, when given + * @warning contents of the target buffer will be overwritten. + */ + inline void + initBuff (TestFrame* buff, TestFrame const* src = nullptr) + { + REQUIRE (buff); + if (not src) + src = & testData(0,0); + new(buff) TestFrame{*src}; + } + + /** produce sequences of frames with (reproducible) random data */ void generateFrame (TestFrame* buff, FraNo frameNr =0, Flavr flavour =0); @@ -128,7 +142,9 @@ namespace test { - + /** _common core_ of the configuration. + * to be extended for each special form of processing. + */ struct TestRandOntology::Spec : util::Cloneable { @@ -145,6 +161,18 @@ namespace test { { } }; + + /** + * Generic front-End for the client to setup some processing, + * and to qualify and configure possible flavours and variations. + * Invoke the _terminal operations_ to get a processing function + * or similar config artifacts that can be passed to a NodeBuilder. + * @tparam CONF specialised config for some form of processing. + * @todo 4/2026 unsolved problem: how can the Builder expose + * setters to adapt special aspects of some processing, + * as opposed to control elements that are present in + * any kind of config / spec...? + */ template class TestRandOntology::Builder : public Spec @@ -205,6 +233,7 @@ namespace test { Param filter = 0; string streamType; + bool procInplace{false}; ConfMan(Spec const& spec) : streamType{spec.BASE_TYPE} @@ -213,9 +242,12 @@ namespace test { auto binding() { - return [offset = filter] + return [offset = filter + ,inplace = procInplace] (Param par, TestFrame const* in, TestFrame* out) { + if (not inplace) + initBuff (out, in); manipulateFrame (out, in, par); }; } @@ -246,6 +278,7 @@ namespace test { return [] (Factr mix, InFeed inChan, TestFrame* out) { + initBuff (out); combineFrames (out, inChan[0],inChan[1], mix); }; } diff --git a/tests/steam/engine/node-devel-test.cpp b/tests/steam/engine/node-devel-test.cpp index c694215fd..b9278d675 100644 --- a/tests/steam/engine/node-devel-test.cpp +++ b/tests/steam/engine/node-devel-test.cpp @@ -326,7 +326,7 @@ namespace test { BuffHandle buffHandle = provider.lockBuffer (provider.getDescriptorFor(sizeof(TestFrame))); uint port{0}; - CHECK (not buffHandle.accessAs().isSane()); + CHECK (not buffHandle.accessAs().isSane()); // no valid data yet in the buffer... // Trigger Node invocation... buffHandle = node.pull (port, buffHandle, Time::ZERO, ProcessKey{0}); @@ -375,7 +375,7 @@ namespace test { // generate a binding as processing-functor auto procFun = spec.makeFun(); using Sig = lib::meta::_Fun::Sig; - CHECK (showType() == "void (ulong, engine::TestFrame const*, engine::TestFrame*)"_expect); + CHECK (showType() == "void (ulong, TestFrame const*, TestFrame*)"_expect); // Results can be verified by ont::manipulateFrame() — see above size_t frameNr = defaultGen.u64(); @@ -449,8 +449,8 @@ namespace test { // generate a binding as processing-functor auto procFun = spec.makeFun(); using Sig = lib::meta::_Fun::Sig; - CHECK (showType() == "void (double, array, " - "engine::TestFrame*)"_expect); //^^/////////////////TICKET #1391 needlessly rendered as `long` + CHECK (showType() == "void (double, array, " + "TestFrame*)"_expect); //^^///////////////////////////////TICKET #1391 needlessly rendered as `long` size_t frameNr = defaultGen.u64(); uint flavour = defaultGen.u64(); double mix = defaultGen.uni(); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a3c33dc9a..166c932f4 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -111338,6 +111338,25 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + +

+ ...da die Conf bewußt nicht uniform ist, sondern mehr sowas wie ein Concept +

+ +
+
+
+
@@ -117719,9 +117738,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -119369,8 +119388,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -119715,10 +119734,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + + @@ -119745,8 +119765,34 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + +

+ Vermutung: da es der Output-Buffer ist, +

+

+ könnte es direkt mit dem Umbau zusammenhängen +

+ +
+ + + + + +

+ ...der Umbau hat vermutlich nur ein latentes Problem aufgedeckt, insofern der Test auch bisher schon auf uninitialisiertem Speicher lief +

+ +
+ +
+
+
+ + @@ -119761,10 +119807,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -119909,8 +119955,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -119924,22 +119971,111 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + +

+ das entspricht mehr der Weise, in der die Test-Rand-Ontology die Struktur einer Medien-Verarbeitungs-Library nachbildet +

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

+ Vor einem Jahr, als ich den »umgepolten« Entwurf zur Renderengine zustande gebracht habe, hat es mir genügt, irgendwie brauchbare Processing-Funktionen zu bekommen. +

+ +
+ + +
+ + + + +

+ ...er hat nur die generischen Terminal-Funktionen +

+
    +
  • + makeFun() +
  • +
  • + procID() +
  • +
  • + nodeID() +
  • +
+ +
+
+
+ + + + + + + + + + - - + + + + + + +

+ diese bekommt einen Zielpuffer und optional einen Quellpuffer und kopiert einfach den TestFrame aus dem Quellpuffer — was uns ganz banal einen validen Header liefert, und doch etwas effizienter sein dürfte, als nochmal die Daten zu generieren. Geht wohl nicht anders, denn ich habe TestFrame ziemlich »zugedengelt« und opaque gemacht. +

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

+ also nur halb engageiert ... und das Design-Problem vertagt +

+ +
+ +
+ + + +
@@ -144072,9 +144208,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+ -