define setup and chaining of render planning chunks (#920)

This commit is contained in:
Fischlurch 2013-08-17 03:37:36 +02:00
parent d192c42faa
commit 86e76bf7fe
7 changed files with 97 additions and 74 deletions

View file

@ -1,5 +1,5 @@
/*
HASH-UTIL.hpp - collection of tools and definitions for working with hashes
HASH-VALUE.hpp - collection of tools and definitions for working with hashes
Copyright (C) Lumiera.org
2012, Hermann Vosseler <Ichthyostega@web.de>
@ -21,7 +21,7 @@
*/
/** @file hash-util.h
/** @file hash-value.h
** Hash value types and utilities.
** This header defines the basic hash value types and provides some simple
** utilities to support working with hash values.

View file

@ -63,8 +63,8 @@ namespace engine {
, boost::noncopyable
{
Dispatcher* dispatcher_;
TimeAnchor refPoint_;
play::Timings const& timings_;
Dispatcher& dispatcher_;
const ModelPort modelPort_;
const uint channel_;
@ -87,7 +87,9 @@ namespace engine {
void
invokeJobOperation (JobParameter parameter)
{
UNIMPLEMENTED ("representation of the job functor, especially the invocation instance ID for this planning chunk");
ASSERT (parameter.nominalTime == timings_.getFrameStartAt (parameter.invoKey.frameNumber));
this->performJobPlanningChunk (parameter.invoKey.frameNumber);
}
@ -97,7 +99,7 @@ namespace engine {
UNIMPLEMENTED ("what needs to be done when a planning continuation cant be invoked?");
}
public:
/**
@ -106,39 +108,52 @@ namespace engine {
CalcPlanContinuation(play::Timings const& timings
,Dispatcher& dispatcher
,ModelPort modelPort
,int64_t startFrame
,uint channel)
: dispatcher_(&dispatcher)
, refPoint_(TODO)
: timings_(timings)
, dispatcher_(dispatcher)
, modelPort_(modelPort)
, channel_(channel)
{
UNIMPLEMENTED ("how to set up the initial playback start point");
}
{ }
/** create the "start trigger job"
* Scheduling this job will effectively get a calculation stream
* into active processing, since it causes the first chunk of job planning
* plus the automated scheduling of follow-up planning jobs. The relation
* to real (wall clock) time will be established when the returned job
* is actually invoked
* @param startFrame where to begin rendering, relative to the nominal
* time grid implicitly related to the ModelPort to be pulled
*/
Job
initiateRenderPlanning ()
prepareRenderPlanningFrom (int64_t startFrame)
{
UNIMPLEMENTED ("setup of the initial planning job");
InvocationInstanceID invoKey;
invoKey.frameNumber = startFrame;
Time nominalPlanningStartTime = timings_.getFrameStartAt (startFrame);
return Job(this, invoKey, nominalPlanningStartTime);
}
private:
void
performJobPlanningChunk()
performJobPlanningChunk(int64_t nextStartFrame)
{
JobPlanningSequence jobs = dispatcher_->onCalcStream(modelPort_, channel_)
.establishNextJobs(refPoint_);
TimeAnchor refPoint(timings_, nextStartFrame);
JobPlanningSequence jobs = dispatcher_.onCalcStream(modelPort_, channel_)
.establishNextJobs(refPoint);
Job nextChunkOfPlanning = buildFollowUpJobFrom (refPoint);
UNIMPLEMENTED ("the actual meat: access the scheduler and fed those jobs");
}
Job
buildFollowUpJobFromThis()
buildFollowUpJobFrom (TimeAnchor const& refPoint)
{
refPoint_.setNextAnchorPoint();
UNIMPLEMENTED ("create the follow-up job, wired with this closure");
return this->prepareRenderPlanningFrom(
refPoint.getNextAnchorPoint());
}
};

View file

@ -101,6 +101,14 @@ namespace engine{
friend class EngineService;
CalcStream
sendToOutput (play::DataSink)
{
UNIMPLEMENTED ("set up dispatcher to start calculating and feeding to the given output sink");
return *this;
}
public:
CalcStream()
@ -109,25 +117,19 @@ namespace engine{
{ }
~CalcStream() { }
// using standard copy operations
// using standard copy operations
CalcStream
sendToOutput (play::DataSink)
{
UNIMPLEMENTED ("set up dispatcher to start calculating and feeding to the given output sink");
return *this;
}
play::Timings const&
getTimings()
{
if (!eng_)
throw error::State ("attempt to get the playback timings "
"of an unconfigured, disabled or halted calculation stream"
,error::LUMIERA_ERROR_LIFECYCLE);
return eng_->effectiveTimings();
}
play::Timings const&
getTimings()
{
if (!eng_)
throw error::State ("attempt to get the playback timings "
"of an unconfigured, disabled or halted calculation stream"
,error::LUMIERA_ERROR_LIFECYCLE);
return eng_->effectiveTimings();
}
};

View file

@ -90,7 +90,7 @@ namespace engine{
return runningCalculations;
/////////////////////////////////////////////////////////////////////////////////////////////TICKET #874 : use a pipeline builder to write it as follows:
// treat_all(output.getOpenedSinks())
// .apply (activateCalculation, renderConfig, _1)
// .apply (activateCalculation, _1, renderConfig)
// .buildVector();
}
@ -123,13 +123,20 @@ namespace engine{
/** @internal extension point
* Install and activate a single, ongoing calculation effort.
* Configure and prepare all the internal components, pre-allocate
* resources and add entries to the registration tables to get this
* render activity into running state
* @return CalcStream representing this newly started rendering activity
* Create the environment for rendering a connected and related set of output streams.
* Configure and prepare all the internal components, pre-allocate resources and add
* entries to the registration tables necessary to get the related render activities
* into "running" state. The created setup will typically be used to generate all
* the individual channel streams linked together for playback or rendering;
* they all share the same media type and quality settings.
* @return an abstracted representation of the specific setup for this render;
* from this point on, this RenderEnvironmentClosure will be the only way
* for client code to talk to "the engine". The actual instance of this
* closure is just a handle and can be copied; any CalcStream created
* off this closure will be linked to the same "environment" and be
* tracked and managed for resource usage automatically.
* @note variations and especially mock implementations of the render engine
* might choose to configure internal differently. As long as the
* might choose to configure internals differently. As long as the
* CalcStream and the embedded RenderEnvironmentClosure are consistent,
* such a specific configuration remains opaque for the user of the
* created render activity

View file

@ -72,16 +72,16 @@ namespace engine {
/** @todo WIP-WIP 2/12
*/
void
Job::triggerJob () const
Job::triggerJob() const
{
myClosure(this).invokeJobOperation (parameter);
myClosure(this).invokeJobOperation (parameter, currentTime);
}
void
Job::signalFailure () const
Job::signalFailure() const
{
UNIMPLEMENTED ("how to organise job failure and abortion");
myClosure(this).signalFailure (parameter, now);
}

View file

@ -26,18 +26,28 @@
#include "lib/llist.h"
#include "lib/hash-value.h"
#include <gavl/gavl.h>
typedef uint64_t InvocationInstanceID; /////////////////TODO
/** opaque ID attached to each individual job invocation.
* Used by the implementation of the Jobs (i.e. the JobClosure)
* for internal organisation; will be fed back on job activation.
*/
union InvocationInstanceID
{
int64_t frameNumber;
lumiera_uid luid;
};
enum JobState
{
DONE, ///< already done, nothing to do
DONE, ///< mission accomplished
RUNNING, ///< job is currently running
WAITING, ///< waits for some prerequisite resource
WAITING, ///< waiting for some prerequisite
REJECTED, ///< sorry, can't do that Dave
EXPIRED, ///< deadline expired
ABORTED ///< got aborted
@ -51,6 +61,7 @@ enum JobKind
};
/**
* closure representing the execution context of a job.
* The information reachable through this closure is specific

View file

@ -109,44 +109,32 @@ namespace engine {
}
public:
TimeAnchor (play::Timings timings, int64_t startFrame, Offset startDelay =Offset::ZERO)
: timings_(timings)
, anchorPoint_(startFrame)
, relatedRealTime_(expectedTimeofArival(timings,startFrame,startDelay))
{ }
public:
// using default copy operations
/** create a TimeAnchor for playback/rendering start at the given startFrame.
* For latency calculations, the EngineConfig will be queried behind the scenes.
* regarding the reaction latency required to get the engine
* @note this builder function adds an additional, hard wired start margin
* of one frame duration, to compensate for first time effects.
*/
static TimeAnchor
build (play::Timings timings, int64_t startFrame)
{
Offset startDelay(timings.getFrameDurationAt(startFrame));
return TimeAnchor (timings,startFrame,startDelay);
}
/** set a follow-up TimeAnchor point.
* After planning a chunk of jobs, the dispatcher uses
* this function to set up a new breaking point (TimeAnchor)
* and places a continuation job to resume the planning activity.
* @note precisely satisfies the <i>planning chunk duration</i>:
* afterwards the start point will be anchored at the grid point
* following the end of the previous planning chunk, resulting
* in a seamless coverage of the timeline
* @note precisely satisfies the <i>planning chunk duration</i>
* @return a frame number suitable to build the next TimeAnchor
* based on the current play::Timings. This new start point
* will be anchored at the grid point following the end of
* the previous planning chunk, resulting in a seamless
* coverage of the timeline
*/
void
setNextAnchorPoint()
int64_t
getNextAnchorPoint() const
{
this->anchorPoint_ = timings_.establishNextPlanningChunkStart (this->anchorPoint_);
this->relatedRealTime_ = expectedTimeofArival(this->timings_,this->anchorPoint_, Offset::ZERO);
return timings_.establishNextPlanningChunkStart (this->anchorPoint_);
}