From f6fbc15e5f5e7f8f69a7f4c9bedaa6dd78db40c2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 1 May 2023 01:48:36 +0200 Subject: [PATCH] Job-Planning: provide stub implementation for NOP job (see #1296) - can now create a Job from JobTicket::NIL - on invocation this Job will to nothing Only when the first real output backend is implemented, we can decide if this simplistic implementation is enough, or if an empty output must be explicitly generated... --- src/lib/luid.c | 6 +- src/lib/luid.h | 6 +- src/steam/engine/job-ticket.cpp | 35 ++++-- src/steam/engine/job-ticket.hpp | 2 +- src/vault/engine/job.cpp | 2 + src/vault/engine/job.h | 14 ++- src/vault/engine/nop-job-functor.hpp | 107 ++++++++++++++++++ tests/core/steam/engine/mock-support-test.cpp | 12 +- wiki/thinkPad.ichthyo.mm | 82 +++++++++++++- 9 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 src/vault/engine/nop-job-functor.hpp diff --git a/src/lib/luid.c b/src/lib/luid.c index 86b965dcf..25a50ead7 100644 --- a/src/lib/luid.c +++ b/src/lib/luid.c @@ -47,7 +47,7 @@ lumiera_uid_set_ptr (lumiera_uid* luid, void* ptr) void* -lumiera_uid_ptr_get (lumiera_uid* luid) +lumiera_uid_ptr_get (const lumiera_uid* luid) { return *(void**)luid; } @@ -103,13 +103,13 @@ lumiera_uid_copy (lumiera_uid* dest, lumiera_uid* src) int -lumiera_uid_eq (lumiera_uid* luida, lumiera_uid* luidb) +lumiera_uid_eq (const lumiera_uid* luida, const lumiera_uid* luidb) { return !memcmp (luida, luidb, 16); } size_t -lumiera_uid_hash (lumiera_uid* luid) +lumiera_uid_hash (const lumiera_uid* luid) { return *(size_t*)luid; } diff --git a/src/lib/luid.h b/src/lib/luid.h index 020d0883e..ffcd105dc 100644 --- a/src/lib/luid.h +++ b/src/lib/luid.h @@ -100,7 +100,7 @@ * Retrieve a generic pointer stored in a luid */ void* -lumiera_uid_ptr_get (lumiera_uid* luid); +lumiera_uid_ptr_get (const lumiera_uid* luid); /** * Generate a new luid @@ -126,13 +126,13 @@ lumiera_uid_copy (lumiera_uid* dest, lumiera_uid* src); * Test 2 luid's for equality */ int -lumiera_uid_eq (lumiera_uid* luida, lumiera_uid* luidb); +lumiera_uid_eq (const lumiera_uid* luida, const lumiera_uid* luidb); /** * Generate a hash sum over an luid */ size_t -lumiera_uid_hash (lumiera_uid* luid); +lumiera_uid_hash (const lumiera_uid* luid); #endif /*LIB_LUID_H*/ diff --git a/src/steam/engine/job-ticket.cpp b/src/steam/engine/job-ticket.cpp index 65783b028..3ed1e9552 100644 --- a/src/steam/engine/job-ticket.cpp +++ b/src/steam/engine/job-ticket.cpp @@ -31,22 +31,27 @@ #include "steam/engine/job-ticket.hpp" +#include "vault/engine/nop-job-functor.hpp" +#include "lib/depend.hpp" +#include "lib/util.hpp" namespace steam { namespace engine { namespace { // Details... - + lib::Depend nopFunctor; } // (END) Details... // using mobject::Placement; // using mobject::session::Effect; -using vault::engine::JobParameter; -using vault::engine::JobClosure; + using vault::engine::JobParameter; + using vault::engine::JobClosure; -using lib::HashVal; + using lib::HashVal; + + using lib::unConst; class FrameJobClosure @@ -104,21 +109,29 @@ using lib::HashVal; const JobTicket JobTicket::NOP{}; //////////////////////////////////////////////////////////////TICKET #725 : do we actually need that for the final data structure? - /** */ + /** + * Generate a render job to invoke the render network configuration + * as defined and backing this JobTicket. The generated job descriptor record + * will include a specific InvocationInstanceID, which factors in the nominal + * frame time, but also the specific backing render configuration. + * The actual implementation of the job functionality will be delegated + * to the JobClosure, which was set up for this Segment and JobTiket + * after the last Builder run created this part of the render network. + */ Job - JobTicket::createJobFor (FrameCoord coordinates) + JobTicket::createJobFor (FrameCoord coordinates) const { + Time nominalTime = coordinates.absoluteNominalTime; if (isnil (provision_)) - { - + { //////////////////////////////////////////////////////////////////////////////////TICKET #1296 : can we get away just with a do-nothing functor? + return Job(nopFunctor(), InvocationInstanceID(), nominalTime); } else { REQUIRE (this->isValid(), "Attempt to generate render job for incomplete or unspecified render plan."); REQUIRE (coordinates.channelNr < provision_.size(), "Inconsistent Job planning; channel beyond provision"); - Provision& provision = provision_[coordinates.channelNr]; - JobClosure& functor = static_cast (provision.jobFunctor); /////////////////////////TICKET #1295 : fix actual interface down to JobFunctor (after removing C structs) - Time nominalTime = coordinates.absoluteNominalTime; + Provision const& provision = provision_[coordinates.channelNr]; + JobClosure& functor = static_cast (unConst(provision.jobFunctor)); ////////////////TICKET #1295 : fix actual interface down to JobFunctor (after removing C structs) InvocationInstanceID invoKey{timeHash (nominalTime, provision.invocationSeed)}; return Job(functor, invoKey, nominalTime); diff --git a/src/steam/engine/job-ticket.hpp b/src/steam/engine/job-ticket.hpp index 11057f149..92f8b2520 100644 --- a/src/steam/engine/job-ticket.hpp +++ b/src/steam/engine/job-ticket.hpp @@ -147,7 +147,7 @@ using lib::LUID; ExplorationState startExploration() const; ExplorationState discoverPrerequisites (uint channelNr =0) const; - Job createJobFor (FrameCoord coordinates); + Job createJobFor (FrameCoord coordinates) const; bool diff --git a/src/vault/engine/job.cpp b/src/vault/engine/job.cpp index 5fafe6790..6ca7fba97 100644 --- a/src/vault/engine/job.cpp +++ b/src/vault/engine/job.cpp @@ -34,6 +34,7 @@ #include "vault/engine/job.h" +#include "vault/engine/nop-job-functor.hpp" #include "lib/util.hpp" #include @@ -69,6 +70,7 @@ namespace engine { JobFunctor::~JobFunctor() { } JobClosure::~JobClosure() { } ///< @deprecated 4/23 refactoring to retract C-structs from the Scheduler interface + NopJobFunctor::NopJobFunctor() { } diff --git a/src/vault/engine/job.h b/src/vault/engine/job.h index 61137a989..0fddb35f3 100644 --- a/src/vault/engine/job.h +++ b/src/vault/engine/job.h @@ -53,7 +53,7 @@ #include "lib/llist.h" -#include "lib/hash-value.h" +#include "lib/luid.h" #include "lib/time.h" @@ -126,6 +126,18 @@ union InvocationInstanceID struct { int32_t a,b; int64_t t; } part; + + friend bool + operator== (InvocationInstanceID const& l, InvocationInstanceID const& r) + { + return lumiera_uid_eq (&l.luid, &r.luid); + } + + friend bool + operator!= (InvocationInstanceID const& l, InvocationInstanceID const& r) + { + return not (l == r); + } }; diff --git a/src/vault/engine/nop-job-functor.hpp b/src/vault/engine/nop-job-functor.hpp new file mode 100644 index 000000000..ea6602dee --- /dev/null +++ b/src/vault/engine/nop-job-functor.hpp @@ -0,0 +1,107 @@ +/* + NOP-JOB-FUNCTOR.hpp - a render job to do nothing + + Copyright (C) Lumiera.org + 2023, 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 + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file nop-job-functor.hpp + ** Generic implementation of a JobFunctor to perform no calculations. + ** Shall be used whenever playback or rendering must be implemented + ** over a part of the effective timeline with no model at all. + ** @todo WIP draft for the »Playback Vertical Slice« 4/2023 + ** @warning not clear if this solution is feasible ///////////////////////////////////////////////////////TICKET #1296 : do we need to produce "empty output" explicitly? + ** + */ + + +#ifndef VAULT_ENGINE_NOP_JOB_FUNCTOR_H +#define VAULT_ENGINE_NOP_JOB_FUNCTOR_H + + + +#include "lib/hash-standard.hpp" +#include "vault/engine/job.h" +#include "lib/time/timevalue.hpp" + + +namespace vault { +namespace engine{ + + using lib::time::Time; + using lib::HashVal; + + + /** + * Stub implementation of the JobFunctor interface + * for a render job _to do nothing at all_ + * @todo WIP as of 4/2023 + */ + class NopJobFunctor + : public JobClosure + { + + /* === JobFunctor Interface === */ + + JobKind + getJobKind() const + { + return META_JOB; + } + + bool + verify (Time, InvocationInstanceID) const + { + return true; // always happy + } + + InvocationInstanceID + buildInstanceID (HashVal) const override + { + return InvocationInstanceID(); + } + + size_t + hashOfInstance (InvocationInstanceID invoKey) const override + { + std::hash hashr; + HashVal res = hashr (invoKey.frameNumber); + lib::hash::combine (res, hashr (invoKey.part.t)); + return res; + } + + void + invokeJobOperation (JobParameter) override + { + /* NOP */ + } + + void + signalFailure (JobParameter, JobFailureReason) override + { + ///////////TODO do we ever need to notify anyone? can this even happen? + } + + public: + NopJobFunctor(); + }; + + +}} // namespace vault::engine +#endif /*VAULT_ENGINE_NOP_JOB_FUNCTOR_H*/ diff --git a/tests/core/steam/engine/mock-support-test.cpp b/tests/core/steam/engine/mock-support-test.cpp index dad38eb9f..2efb20c4c 100644 --- a/tests/core/steam/engine/mock-support-test.cpp +++ b/tests/core/steam/engine/mock-support-test.cpp @@ -30,6 +30,7 @@ #include "steam/engine/mock-dispatcher.hpp" #include "vault/engine/dummy-job.hpp" #include "lib/util.hpp" +#include "vault/engine/nop-job-functor.hpp" #include "lib/format-cout.hpp"///////////////////////TODO @@ -115,9 +116,18 @@ namespace test { void verify_MockJobTicket() { + FrameCoord coord; + coord.absoluteNominalTime = lib::test::randTime(); + + // build a render job to do nothing.... + Job nopJob = JobTicket::NOP.createJobFor(coord); + CHECK (INSTANCEOF (vault::engine::NopJobFunctor, static_cast (nopJob.jobClosure))); //////////TICKET #1295 : fix actual interface down to JobFunctor (after removing C structs) + CHECK (nopJob.parameter.nominalTime == coord.absoluteNominalTime); + CHECK (nopJob.parameter.invoKey == InvocationInstanceID()); + MockJobTicket mockTicket; CHECK (mockTicket.discoverPrerequisites().empty()); - Job mockJob = mockTicket.createJobFor (FrameCoord{}); + Job mockJob = mockTicket.createJobFor (coord); CHECK (mockTicket.verify_associated (mockJob)); TODO ("cover details of MockJobTicket"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 38291bfe4..b52483778 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -69824,8 +69824,8 @@ - - + + @@ -69859,6 +69859,17 @@ + + + + + + + + + + + @@ -70357,6 +70368,19 @@ + + + + + + + + + + + + + @@ -70791,6 +70815,59 @@ + + + + + + + + +

+ welcher Teil muß wirklich flexibel sein? +

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

+ ...denn von den grundsätzlichen Abhängigkeiten her weiß nicht einmal ein JobTicket, in welchem Segment es hängt; auch ProcNodes könnten theoretisch sogar in mehreren Segmenten hängen ⟹ es schreint mehr als fragwürdig, ob ein JobFunktor überhaupt im Stande ist, eine inhaltlich sinnvolle verifikation zu machen (über das Prüfen auf null-Pointer hinaus) +

+ +
+ +
+
+ + + + + +
+ + + + + + + + + + + + + +
@@ -70801,6 +70878,7 @@ +