diff --git a/src/proc/engine/dispatcher.hpp b/src/proc/engine/dispatcher.hpp index 806f49cd4..b084f6c83 100644 --- a/src/proc/engine/dispatcher.hpp +++ b/src/proc/engine/dispatcher.hpp @@ -60,6 +60,8 @@ namespace engine { ModelPort modelPort_; uint channel_; + /////TODO need storage for the continuation + FrameCoord relativeFrameLocation (TimeAnchor refPoint, uint frameCountOffset); JobBuilder& establishNextJobs (TimeAnchor refPoint); @@ -70,8 +72,9 @@ namespace engine { { UNIMPLEMENTED ("how to represent the closure for defining and scheduling jobs"); - ////////TODO: use a closure based on the JobTicket (which can be accessed through the dispatcher backlink) - //////////// Because this closure is what backs the IterSource, it needs to have a reliable storage though. + ////////TODO: use a closure based on FrameCoord plus a back-reference to the Dispatcher. + //////////// Thus actually we need a *generator* for a sequence of FrameCoord + //////////// This generator is then wrapped up into an evaluation-Monad (IterExplorer) } }; @@ -83,8 +86,9 @@ namespace engine { JobTicket& accessJobTicket (FrameCoord const&); - protected: - virtual FrameCoord locateFrameNext (uint frameCountOffset, TimeAnchor refPoint) =0; + protected: + virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0; + virtual FrameCoord locateRelative (TimeAnchor, uint frameCountOffset) =0; }; diff --git a/src/proc/engine/frame-coord.hpp b/src/proc/engine/frame-coord.hpp index c211b1193..a73be8d96 100644 --- a/src/proc/engine/frame-coord.hpp +++ b/src/proc/engine/frame-coord.hpp @@ -90,5 +90,33 @@ namespace engine { + /** + * Facility for producing a sequence of FrameCoord. + * This interface describes the essence of generating + * a series of frame locations, which is necessary for + * planning render jobs. To implement it, actually some + * kind of \link lib::time::Quantiser frame grid \endlink + * is necessary -- in practice we use a Dispatcher, which is + * backed by the Segmentation (i.e. the render nodes network). + */ + class FrameSequencer + : boost::noncopyable + { + + public: + virtual ~FrameSequencer(); ///< this is an interface + + FrameCoord + getNextFrame (FrameCoord refPoint) + { + return locateRelative (refPoint, +1 ); + } + + protected: + virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0; + }; + + + }} // namespace proc::engine #endif diff --git a/src/proc/engine/job-planning.hpp b/src/proc/engine/job-planning.hpp index abe77c9d8..f0268b289 100644 --- a/src/proc/engine/job-planning.hpp +++ b/src/proc/engine/job-planning.hpp @@ -240,7 +240,8 @@ namespace engine { */ class PlanningStepGenerator { - engine::TimeAnchor anchor_; + engine::FrameSequencer* locationGenerator_; + engine::FrameCoord current_; public: typedef JobPlanning value_type; @@ -252,6 +253,12 @@ namespace engine { PlanningStepGenerator(engine::TimeAnchor startPoint) : anchor_(startPoint) { } + //////////////////////////////////////////////////////////////TODO actually we need two distinct services + //////////////////////////////////////////////////////////////TODO - getting the next FrameCoord + //////////////////////////////////////////////////////////////TODO - getting the JobTicket for this location + //////////////////////////////////////////////////////////////TODO Actually, the Dispatcher would provide exactly those services, + //////////////////////////////////////////////////////////////TODO but depending on the Dispatcher constitutes a cyclic dependency. + //////////////////////////////////////////////////////////////TODO There seems to be a problem hidden somewhere in this design. /* === Iteration control API for IterStateWrapper== */ @@ -287,6 +294,28 @@ namespace engine { /** + * This iterator represents a pipeline to pull planned jobs from. + * For dispatching individual frame jobs for rendering, this pipeline is + * generated and internally wired such as to interpret the render node definitions. + * + * \par Explanation of the structure + * + * The JobPlanningSequence is constructed from several nested layers of functionality + * - for the client, it is an iterator, exposing a sequence of JobPlanning elements + * - a JobPlanning element allows to add a frame render job to the scheduler + * - actually such an element can even be \em converted directly into a Job (descriptor) + * - the sequence of such JobPlanning elements (that is, the iterator) is called a PlanningState, + * since evaluating this iterator effectively drives the process of job planning ahead + * - this planning process is \em implemented as a recursive evaluation and exploration of + * a tree of prerequisites; these prerequisites are defined in the JobTicket datastructure + * - there is an underlying grid of evaluation starting points, each corresponding to a + * single frame. Typically, each frame generates at least two jobs, one for fetching + * data, and one for the actual calculations. Depending on the actual render network, + * a lot of additional jobs might be necessary + * - this basic frame grid is generated by the PlanningStepGenerator, which is + * effectively backed by the Dispatcher and thus the render node model. + * + * * @todo 6/12 WIP-WIP-WIP how to prepare jobs for scheduling */ class JobPlanningSequence diff --git a/src/proc/engine/job-ticket.hpp b/src/proc/engine/job-ticket.hpp index b38df691c..45ff53b47 100644 --- a/src/proc/engine/job-ticket.hpp +++ b/src/proc/engine/job-ticket.hpp @@ -242,6 +242,9 @@ using util::isnil; /////////////////////TODO problem is: we need an JobTicket::Prerequisite instance, where the descriptor points to "self" (this JobTicket) /////////////////////TODO : but this instance needs to reside somewhere at a safe location, since we want to embed an LinkedElements-iterator /////////////////////TODO : into the ExplorationState. And obviously we do not want that instance in each JobTicket, only in the top level ones + + /////////////////////TODO : on second thought -- better have a top-level entry point to the evaluation of a frame + /////////////////////TODO basically this inherits from Prerequisite and lives somehow in the dispatcher-table or segment } diff --git a/src/proc/engine/time-anchor.hpp b/src/proc/engine/time-anchor.hpp index f944a5f86..7d2b5cc63 100644 --- a/src/proc/engine/time-anchor.hpp +++ b/src/proc/engine/time-anchor.hpp @@ -46,17 +46,14 @@ namespace engine { // class ExitNode; /** - * The process of playback or rendering is a continued series of - * exploration and evaluation. The outline of what needs to be calculated - * is determined continuously, proceeding in chunks of evaluation. - * Each of these continued partial evaluations establishes a distinct - * anchor or breaking point in time: everything before this point - * is settled and planned thus far. Effectively, this time point - * acts as a evaluation closure, to be picked up on the - * next partial evaluation. More specifically, the TimeAnchor - * closure is the definitive binding between the abstract - * logical time of the session timeline, and the real - * wall-clock time forming the deadline for rendering. + * The process of playback or rendering is a continued series of exploration and evaluation. + * The outline of what needs to be calculated is determined continuously, proceeding in + * chunks of evaluation. Each of these continued partial evaluations establishes a distinct + * anchor or breaking point in time: everything before this point can be considered settled + * and planned thus far. Effectively, this time point acts as a evaluation closure, + * to be picked up on the next partial evaluation. More specifically, the TimeAnchor closure + * is the definitive binding between the abstract logical time of the session timeline, and + * the real wall-clock time forming the deadline for rendering. * * \par internals * The time anchor associates a nominal time, defined on the implicit time grid