134 lines
5.5 KiB
C++
134 lines
5.5 KiB
C++
/*
|
|
DISPATCHER.hpp - translating calculation streams into frame jobs
|
|
|
|
Copyright (C) Lumiera.org
|
|
2011, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
#ifndef PROC_ENGINE_DISPATCHER_H
|
|
#define PROC_ENGINE_DISPATCHER_H
|
|
|
|
#include "proc/common.hpp"
|
|
#include "proc/mobject/model-port.hpp"
|
|
#include "proc/engine/time-anchor.hpp"
|
|
#include "proc/engine/frame-coord.hpp"
|
|
#include "proc/engine/job-ticket.hpp"
|
|
#include "proc/engine/job-planning.hpp"
|
|
#include "lib/time/timevalue.hpp"
|
|
|
|
#include <boost/noncopyable.hpp>
|
|
#include <functional>
|
|
|
|
|
|
namespace proc {
|
|
namespace engine {
|
|
|
|
using std::function;
|
|
using mobject::ModelPort;
|
|
using lib::time::FrameCnt;
|
|
using lib::time::TimeSpan;
|
|
using lib::time::FSecs;
|
|
using lib::time::Time;
|
|
|
|
|
|
/**
|
|
* Internal abstraction: a service within the engine
|
|
* for translating a logical calculation stream (corresponding to a PlayProcess)
|
|
* into a sequence of individual RenderJob entries for calculations and data access.
|
|
* The actual implementation of this service is tied to the low-level-model, i.e.
|
|
* the render nodes network. The Dispatcher service is used to implement the CalcStreams
|
|
* during playback and rendering; there will be a continuous, chunk-wise proceeding
|
|
* evaluation and planning of new jobs, which can then be handed over to the Scheduler
|
|
* for time-bound activation.
|
|
*
|
|
* \par usage considerations
|
|
* the asynchronous and ongoing nature of the render process mandates to avoid a central
|
|
* instance for operating this planning process. Instead, together with each chunk of
|
|
* planned jobs we generate a continuation job, which -- on activation -- will pick up
|
|
* the planning of the next chunk. The Dispatcher interface was shaped especially to
|
|
* support this process, with a local JobBuilder for use within the continuation job,
|
|
* and a TimeAnchor to represent the continuation point. All the complexities of
|
|
* actually planning the jobs are hidden within the JobPlanningSequence,
|
|
* which, for the purpose of dispatching a series of jobs just looks
|
|
* like a sequence of job descriptors
|
|
*
|
|
* @todo 10/12 still WIP, but conceptually settled by now
|
|
*/
|
|
class Dispatcher
|
|
: public FrameLocator
|
|
{
|
|
struct JobBuilder
|
|
{
|
|
Dispatcher* dispatcher_;
|
|
ModelPort modelPort_;
|
|
uint channel_;
|
|
|
|
FrameCoord relativeFrameLocation (TimeAnchor& refPoint, FrameCnt frameCountOffset =0);
|
|
|
|
JobPlanningSequence
|
|
establishNextJobs (TimeAnchor& refPoint)
|
|
{
|
|
return JobPlanningSequence(
|
|
relativeFrameLocation(refPoint),
|
|
*dispatcher_);
|
|
}
|
|
};
|
|
|
|
|
|
public:
|
|
virtual ~Dispatcher(); ///< this is an interface
|
|
|
|
JobBuilder onCalcStream (ModelPort modelPort, uint channel);
|
|
|
|
|
|
protected:
|
|
/** core dispatcher operation: based on the coordinates of a reference point,
|
|
* establish binding frame number, nominal time and real (wall clock) deadline.
|
|
* @return new FrameCoord record (copy), with the nominal time, frame number
|
|
* and deadline adjusted in accordance to the given frame offset.
|
|
*/
|
|
virtual FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) =0;
|
|
|
|
virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0;
|
|
|
|
////////TODO: API-1 = just get next frame, without limitations .... CHECK
|
|
////////TODO: API-2 = query limitation of planning chunk .... CHECK
|
|
////////TODO: API-3 = establish next chunk .... still WIP
|
|
|
|
////////TODO: Question: why not embedding the time anchor directly within the location generator??
|
|
//////// Answer: no this would lead to a huge blob called "the dispatcher"
|
|
|
|
////////TODO: immediate point to consider: the time anchor is responsible for the real timing calculations. But how to introduce the play strategy *here* ?
|
|
|
|
////////////TODO: the solution is simple: get rid of the additional job placed magically into the chunk
|
|
//////////// instead, provide a dedicated API function to create exactly that job
|
|
//////////// and *enclosed* into a specialised JobClosure subclass, embody the code for the follow-up
|
|
//////////// As a corollary: the scheduling deadline should be defined right *within* the job!
|
|
|
|
////////////TODO: remaining issues
|
|
//////////// - the TimeAnchor needs to be created directly from the JobParameter. No mutable state!
|
|
//////////// - but this leads to a lot of duplicated Timings records, unless we rewrite the TimeAnchor to be noncopyable and use a Timings const&
|
|
|
|
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
|
|
};
|
|
|
|
|
|
|
|
}} // namespace proc::engine
|
|
#endif
|