From 08dfe1007ce33409f6382c8d17932a4095537093 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 14 Jun 2023 04:20:50 +0200 Subject: [PATCH] Dispatcher-Pipeline: verify the expansion of prerequisites - fix a bug in the MockDispatcher, when duplicating the ExitNodes. A vector-ctor with curly braces will be interpreted as std::initializer_list - add visualisation of the contents appearing at the end of the pipeline *** something still broken here, increments don't happen as expected --- src/steam/engine/dispatcher.hpp | 47 ++-- src/steam/engine/frame-coord.hpp | 9 + .../steam/engine/job-planning-setup-test.cpp | 52 +++- tests/core/steam/engine/mock-dispatcher.hpp | 6 +- tests/core/steam/engine/mock-support-test.cpp | 12 +- wiki/thinkPad.ichthyo.mm | 224 ++++++++++++++++-- 6 files changed, 285 insertions(+), 65 deletions(-) diff --git a/src/steam/engine/dispatcher.hpp b/src/steam/engine/dispatcher.hpp index 05c40cce0..3809a4955 100644 --- a/src/steam/engine/dispatcher.hpp +++ b/src/steam/engine/dispatcher.hpp @@ -282,15 +282,14 @@ namespace engine { { size_t portIDX = SRC::dispatcher->resolveModelPort(port); return buildPipeline ( - this->transform([portIDX](PipeFrameTick& core) -> TicketDepend - { - FrameCoord frame; ///////////////////////////////////////////OOO need a better ctor for FrameCoord - frame.absoluteNominalTime = core.currPoint; - frame.modelPortIDX = portIDX; - return {nullptr - ,& core.dispatcher->getJobTicketFor(frame) - }; - })); + SRC::transform( + [portIDX](PipeFrameTick& core) -> TicketDepend + { + FrameCoord frame{core.currPoint, portIDX}; + return {nullptr + ,& core.dispatcher->getJobTicketFor(frame) + }; + })); } @@ -303,16 +302,17 @@ namespace engine { expandPrerequisites() { return buildPipeline ( - this->expandAll([](TicketDepend& currentLevel) - { - JobTicket* parent = currentLevel.second; - return lib::transformIterator (parent->getPrerequisites() - ,[&parent](JobTicket& prereqTicket) - { // parent shifted up to first pos - return TicketDepend{parent, &prereqTicket}; - } - ); - })); + SRC::expandAll( + [](TicketDepend& currentLevel) + { + JobTicket* parent = currentLevel.second; + return lib::transformIterator (parent->getPrerequisites() + ,[&parent](JobTicket& prereqTicket) + { // parent shifted up to first pos + return TicketDepend{parent, &prereqTicket}; + } + ); + })); } /** @@ -323,10 +323,11 @@ namespace engine { feedTo (play::DataSink sink) { return terminatePipeline ( - this->transform([sink](TicketDepend& currentLevel) - { - return currentLevel.second; ///////////////////////////////OOO construct a JobPlanning here - })); + SRC::transform( + [sink](TicketDepend& currentLevel) + { + return currentLevel.second; ///////////////////////////////OOO construct a JobPlanning here + })); } diff --git a/src/steam/engine/frame-coord.hpp b/src/steam/engine/frame-coord.hpp index d33d34108..027c6cdbe 100644 --- a/src/steam/engine/frame-coord.hpp +++ b/src/steam/engine/frame-coord.hpp @@ -41,6 +41,7 @@ namespace engine { using mobject::ModelPort; using lib::time::FrameCnt; + using lib::time::TimeValue; using lib::time::TimeVar; using lib::time::Time; @@ -81,6 +82,14 @@ namespace engine { , modelPortIDX{0} { } + explicit + FrameCoord (TimeValue nominalTime, size_t portIDX =0) + : absoluteNominalTime{nominalTime} + , absoluteFrameNumber{std::numeric_limits::max()} + , realTimeDeadline{Time::NEVER} + , modelPortIDX{portIDX} + { } + // using default copy operations /** @remarks sometimes we use NIL frame coordinate records diff --git a/tests/core/steam/engine/job-planning-setup-test.cpp b/tests/core/steam/engine/job-planning-setup-test.cpp index 7765e8bb9..da6274084 100644 --- a/tests/core/steam/engine/job-planning-setup-test.cpp +++ b/tests/core/steam/engine/job-planning-setup-test.cpp @@ -31,6 +31,7 @@ #include "lib/format-cout.hpp"///////////////////////TODO #include "lib/iter-tree-explorer.hpp" +#include "lib/format-string.hpp" #include "lib/format-util.hpp" #include "lib/util.hpp" @@ -41,6 +42,7 @@ using lib::treeExplore; using lib::time::PQuant; using lib::time::FrameRate; using util::isnil; +using util::_Fmt; namespace steam { @@ -75,8 +77,10 @@ namespace test { * - invoke the dispatcher to retrieve the top-level JobTicket * - expander function to explore prerequisite JobTickets * - integration: generate a complete sequence of (dummy)Jobs - * - scaffolding and mocking used for this test - * + * - scaffolding and mocking used for this test + * @remark the »pipeline« is implemented as »Lumiera Forward Iterator« + * and thus forms a chain of on-demand processing. At the output side, + * fully defined render Jobs can be retrieved, ready for scheduling. * @todo WIP-WIP 4/2023 * * @see DispatcherInterface_test @@ -106,6 +110,7 @@ namespace test { Time nominalTime = lib::test::randTime(); int additionalKey = rand() % 5000; + // (1) mocked render Job MockJob mockJob{nominalTime, additionalKey}; mockJob.triggerJob(); CHECK (MockJob::was_invoked (mockJob)); @@ -113,7 +118,7 @@ namespace test { CHECK (nominalTime == MockJob::invocationNominalTime (mockJob) ); CHECK (additionalKey == MockJob::invocationAdditionalKey(mockJob)); - // Build a simple Segment at [10s ... 20s[ + // (2) Build a mocked Segment at [10s ... 20s[ MockSegmentation mockSegs{MakeRec() .attrib ("start", Time{0,10} // start time (inclusive) of the Segment at 10sec ,"after", Time{0,20} // the Segment ends *before* 20sec @@ -140,6 +145,7 @@ namespace test { CHECK (123 == MockJob::invocationAdditionalKey (jobM)); // verify each job was invoked and linked to the correct spec, CHECK (555 == MockJob::invocationAdditionalKey (jobP)); // indicating that in practice it will activate the proper render node + // (3) demonstrate mocked frame dispatcher... coord.modelPortIDX = 1; coord.absoluteNominalTime = Time{0,30}; MockDispatcher dispatcher; // a complete dispatcher backed by a mock Segment for the whole timeline @@ -189,10 +195,10 @@ namespace test { void accessTopLevelJobTicket() { - play::Timings timings (FrameRate::PAL); MockDispatcher dispatcher; - auto [port,sink] = dispatcher.getDummyConnection(0); + play::Timings timings (FrameRate::PAL); + auto [port,sink] = dispatcher.getDummyConnection(0); auto pipeline = dispatcher.forCalcStream (timings) .timeRange(Time{200,0}, Time{300,0}) .pullFrom (port); @@ -201,8 +207,7 @@ namespace test { CHECK (nullptr == pipeline->first); // is a top-level ticket JobTicket const& ticket = *pipeline->second; - FrameCoord dummy; - dummy.absoluteNominalTime = Time::ZERO; // actual time point is irrelevant here + FrameCoord dummy{Time::ZERO}; // actual time point is irrelevant here Job job = ticket.createJobFor(dummy); CHECK (dispatcher.verify(job, port, sink)); } @@ -212,7 +217,38 @@ namespace test { void exploreJobTickets() { - UNIMPLEMENTED ("exploration function"); + MockDispatcher dispatcher{MakeRec() // define a single segment for the complete time axis + .attrib("mark", 11) // the »master job« for each frame has pipeline-ID ≔ 11 + .scope(MakeRec() + .attrib("mark",22) // add a »prerequisite job« with pipeline-ID ≔ 22 + .genNode()) + .genNode()}; + + play::Timings timings (FrameRate::PAL); + auto [port,sink] = dispatcher.getDummyConnection(0); + auto pipeline = dispatcher.forCalcStream (timings) + .timeRange(Time{200,0}, Time{300,0}) + .pullFrom (port) + .expandPrerequisites(); + + // the first element is identical to previous test + CHECK (not isnil (pipeline)); + CHECK (nullptr == pipeline->first); + Job job = pipeline->second->createJobFor(FrameCoord{}); + CHECK (11 == job.parameter.invoKey.part.a); + + auto visualise = [](auto& pipeline) -> string + { + FrameCoord frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time) + Job job = pipeline->second->createJobFor(frame); // looking always at the second element, which is the current JobTicket + TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t) + int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here + return _Fmt{"J(%d|%s)"} % mark % nominalTime; + }; + CHECK (visualise(pipeline) == "J(11|200ms)"_expect); // first job in pipeline is at t=200ms and has mark=11 (it's the master Job for this frame) + + CHECK (materialise (pipeline.transform (visualise)) + == "J(11|200ms)-J(22|200ms)-J(11|240ms)-J(22|240ms)-J(11|280ms)-J(22|280ms)"_expect); } diff --git a/tests/core/steam/engine/mock-dispatcher.hpp b/tests/core/steam/engine/mock-dispatcher.hpp index 18996fcb8..92efbf0a2 100644 --- a/tests/core/steam/engine/mock-dispatcher.hpp +++ b/tests/core/steam/engine/mock-dispatcher.hpp @@ -268,9 +268,9 @@ namespace test { Segmentation::adaptSpecification ([times](Spec const& spec) { - return Spec{ExitNodes{times, spec[0]}}; - }); - } + return Spec{ExitNodes(times, spec[0])}; + }); // vector with copies of spec[0] + } // (Warning: use parens, not braces for this ctor...) /** diff --git a/tests/core/steam/engine/mock-support-test.cpp b/tests/core/steam/engine/mock-support-test.cpp index ae6f21b93..6eb552447 100644 --- a/tests/core/steam/engine/mock-support-test.cpp +++ b/tests/core/steam/engine/mock-support-test.cpp @@ -88,8 +88,7 @@ namespace test { JobTicket const& ticket = seg.jobTicket(0); - FrameCoord coord; - coord.absoluteNominalTime = Time(0,15); + FrameCoord coord{Time(0,15)}; Job job = ticket.createJobFor(coord); CHECK (MockJobTicket::isAssociated (job, ticket)); @@ -128,8 +127,7 @@ namespace test { void verify_MockJobTicket() { - FrameCoord coord; - coord.absoluteNominalTime = lib::test::randTime(); + FrameCoord coord{lib::test::randTime()}; // build a render job to do nothing.... Job nopJob = JobTicket::NOP.createJobFor(coord); @@ -158,9 +156,8 @@ namespace test { void verify_MockSegmentation() { - FrameCoord coord; Time someTime = lib::test::randTime(); - coord.absoluteNominalTime = someTime; + FrameCoord coord{someTime}; // //-----------------------------------------------------------------/// Empty default Segmentation { @@ -392,8 +389,7 @@ namespace test { void verify_MockDispatcherSetup() { - FrameCoord frame; - frame.absoluteNominalTime = Time{0,30}; + FrameCoord frame{Time{0,30}}; { MockDispatcher dispatcher; // automatically generates some fake connection points... diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 8c950d1bb..14c222c1a 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -64554,6 +64554,21 @@ + + + + + + + + + + + + + + + @@ -68800,6 +68815,23 @@ + + + + + + + + + + + + + + + + + @@ -69661,9 +69693,9 @@ - + - + @@ -69724,6 +69756,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +
@@ -69772,10 +69808,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -69783,7 +69819,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
  • - requirement_ als (single)linked-List RLY? + Prerequisites und Channel-Tabelle als (single)linked-List RLY?
  • SubTicketStack wirklich schon gut durchdacht? Funktionsweise? @@ -69792,17 +69828,41 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + +

    + die werden nämlich nur einfach traversiert, und dahinter verbergen sich verschachtelte JobTicket, die allesamt im gleichen Speicherblock (im AllocationCluster) liegen +

    + +
    - + + + + + + + + + + - + - + + + + + @@ -70095,6 +70155,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + + + + + + + + + + @@ -74155,7 +74230,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -74214,7 +74289,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -74560,7 +74635,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -75026,13 +75101,6 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - - - - - @@ -75053,9 +75121,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - + + + +
    @@ -75069,7 +75138,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -75094,7 +75163,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -75162,6 +75231,91 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + also stets das 2.Element im Tupel. Bin nämlich zu faul, hier auch noch das Tupel irgendwie zu rendern. Das mach ich dann im nächsten Testfall... +

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

    + FAIL___expectation___________ +

    +

    + expect:J(11|200ms)-J(22|200ms)-J(11|240ms)-J(22|240ms)-J(11|280ms)-J(22|280ms) +

    +

    + actual:J(11|200ms)-J(22|240ms)-J(11|240ms)-J(22|280ms)-J(11|280ms)-J(22|320ms) +

    + +
    + +
    + + + + + + + + +
    +
    @@ -75208,6 +75362,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + +
    @@ -76109,6 +76270,23 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + + + +

    + geplant: generisches front-End für Custom Allocator +

    + +
    + + +
    +