stubs for some important components of play/engine (JobTicket...)

also touches the question how to represent the job
descriptor datastructure. @Cehteh: I've just pasted
in your preliminary data struct definitinons
from the relevant mailing list discussions.
This commit is contained in:
Fischlurch 2012-02-13 00:37:57 +01:00
parent 23ac29028c
commit e9dbb3bdb1
9 changed files with 275 additions and 9 deletions

View file

@ -34,6 +34,11 @@ namespace engine {
/** */
JobTicket&
Dispatcher::accessJobTicket (FrameCoord const& frameID, mobject::ModelPort const& port)
{
UNIMPLEMENTED ("figure out and create the actual JobTicket, for the current segment and the given port");
}

View file

@ -26,8 +26,10 @@
#include "proc/common.hpp"
//#include "proc/state.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 "lib/time/timevalue.hpp"
#include <boost/noncopyable.hpp>
@ -56,6 +58,7 @@ namespace engine {
virtual FrameCoord locateFrameNext (uint frameCountOffset) =0;
JobTicket& accessJobTicket (FrameCoord const&, mobject::ModelPort const&);
};

View file

@ -0,0 +1,85 @@
/*
JOB-TICKET.hpp - execution plan for render jobs
Copyright (C) Lumiera.org
2012, 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_JOB_TICKET_H
#define PROC_ENGINE_JOB_TICKET_H
#include "proc/common.hpp"
//#include "proc/state.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/time/timequant.hpp"
#include <boost/noncopyable.hpp>
namespace proc {
namespace engine {
//using lib::time::TimeSpan;
//using lib::time::Duration;
//using lib::time::FSecs;
//using lib::time::Time;
//
//class ExitNode;
/**
* execution plan for pulling a specific exit node.
* Usable as blue print for generating actual render jobs.
* Job tickets are created on demand, specialised for each segment
* of the low-level model, and for each individual feed (corresponding
* to a single model port). Once created, they are final for this segment,
* stored together with the other descriptor objects (ProcNode and WiringDescriptor)
* and finally discarded in bulk, in case that segment of the low-level model becomes
* obsolete and is replaced by a newly built new version of.
*
* Job tickets are created by a classical recursive descent call on the exit node,
* which figures out everything to be done for generating data from this node.
* To turn a JobTicket into an actual job, we need the additional information
* regarding the precise frame number (=nominal time) and the channel number
* to calculate (in case the actual feed is multichannel, which is the default).
*
* @todo 1/12 WIP-WIP-WIP defining the invocation sequence and render jobs
*/
class JobTicket
: boost::noncopyable
{
public:
JobTicket()
{
UNIMPLEMENTED ("job representation, planning and scheduling");
}
bool
isValid() const
{
UNIMPLEMENTED ("validity self check");
}
};
}} // namespace proc::engine
#endif

132
src/proc/engine/job.hpp Normal file
View file

@ -0,0 +1,132 @@
/*
JOB.hpp - render job closure
Copyright (C) Lumiera.org
2012, 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_JOB_H
#define PROC_ENGINE_JOB_H
#include <gavl/gavl.h>
typedef void* LList; ////////////////////////////////////TODO
enum JobState
{
DONE, ///< already done, nothing to do
RUNNING, ///< job is currently running
WAITING, ///< waits for some prerequisite resource
REJECTED, ///< sorry, can't do that Dave
EXPIRED, ///< deadline expired
ABORTED ///< got aborted
};
struct lumiera_jobDescriptor_struct
{
gavl_time_t when;
/* == Job prerequisites == */
LList waiting;
LList failed;
LList completed;
JobState jobstate;
void (*jobfn)();
void (*failfn)();
};
typedef struct lumiera_JobDescriptor_struct lumiera_jobDescriptor;
typedef lumiera_jobDescriptor* LumieraJobDescriptor;
#ifdef __cplusplus /* ============== C++ Interface ================= */
#include "proc/common.hpp"
//#include "proc/state.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/time/timequant.hpp"
#include <tr1/functional>
namespace proc {
namespace engine {
//using lib::time::TimeSpan;
//using lib::time::Duration;
//using lib::time::FSecs;
//using lib::time::Time;
//
//class ExitNode;
/**
* Frame rendering task, represented as closure.
* This functor encodes all information necessary actually to
* trigger and invoke the rendering operation. It will be embedded
* into a job descriptor and then enqueued with the scheduler for
* invocation just in time.
*
* @todo 1/12 WIP-WIP-WIP defining the invocation sequence and render jobs
*/
class Job
{
public:
Job()
{
UNIMPLEMENTED ("job representation, planning and scheduling");
}
// using standard copy operations
bool
isValid() const
{
UNIMPLEMENTED ("validity self check");
}
};
}} // namespace proc::engine
extern "C" {
#endif /* =========================== CL Interface ===================== */
////////////////////////////////////TODO define a C binding for use by the scheduler
#ifdef __cplusplus
}
#endif
#endif

View file

@ -67,7 +67,7 @@ namespace engine {
// using default copy operations
static TimeAnchor
build (play::Timings timings, uint64_t startFrame)
build (play::Timings timings, uint64_t startFrame, uint channel)
{
UNIMPLEMENTED ("representation of the Time Anchor closure");
}

View file

@ -97,7 +97,7 @@ namespace play {
// using lumiera::DummyPlayer;
using lib::time::Duration;
typedef lib::IterSource<proc::mobject::ModelPort>::iterator ModelPorts;
typedef lib::IterSource<proc::mobject::ModelPort>::iterator ModelPorts;
struct PlayTestFrames_Strategy

View file

@ -25,6 +25,8 @@
#include "lib/error.hpp"
//#include "proc/engine/procnode.hpp"
#include "proc/play/dummy-play-connection.hpp"
#include "proc/mobject/model-port.hpp"
#include "proc/engine/dispatcher.hpp"
#include "proc/play/timings.hpp"
#include "lib/time/timevalue.hpp"
@ -46,15 +48,26 @@ namespace test {
using lib::time::QuTime;
using lib::time::FrameRate;
using lib::time::Duration;
using proc::play::Timings;
using mobject::ModelPort;
using play::Timings;
namespace { // used internally
using play::PlayTestFrames_Strategy;
using play::ModelPorts;
typedef play::DummyPlayConnection<play::PlayTestFrames_Strategy> DummyPlaybackSetup;
class MockDispatcherTable
: public Dispatcher
{
DummyPlaybackSetup dummySetup_;
/* == mock Dispatcher implementation == */
FrameCoord
locateFrameNext (uint frameCountOffset)
{
@ -62,13 +75,26 @@ namespace test {
}
public:
ModelPort
provideMockModelPort()
{
ModelPorts mockModelPorts = dummySetup_.provide_testModelPorts();
return *mockModelPorts; // using just the first dummy port
}
};
lib::Singleton<MockDispatcherTable> mockDispatcher;
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #890
ModelPort
getTestPort()
{
return mockDispatcher().provideMockModelPort();
}
} // (End) internal defs
@ -100,15 +126,20 @@ namespace test {
{
Dispatcher& dispatcher = mockDispatcher();
Timings timings (FrameRate::PAL);
ModelPort modelPort (getTestPort());
uint startFrame(10);
uint channel(0);
TimeAnchor refPoint = TimeAnchor::build (timings, startFrame);
TimeAnchor refPoint = TimeAnchor::build (timings, startFrame, channel);
CHECK (refPoint == Time::ZERO + Duration(10, FrameRate::PAL));
FrameCoord coordinates = dispatcher.locateFrameNext (15);
CHECK (coordinates.absoluteNominalTime == Time(0,1));
CHECK (coordinates.absoluteFrameNumber == 25);
CHECK (coordinates.remainingRealTime() >= Time(FSecs(24,25)));
JobTicket& executionPlan = dispatcher.accessJobTicket (coordinates, modelPort);
CHECK (executionPlan.isValid());
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
}

View file

@ -258,7 +258,7 @@ namespace test {
CHECK (pwc);
registry.rollback();
CHECK ( registry.contains (pipeA)); // no effect to the officialy visible state
CHECK ( registry.contains (pipeA)); // no effect to the officially visible state
CHECK (!registry.contains (pipeB));
CHECK ( registry.contains (pipeWC));

View file

@ -1969,6 +1969,12 @@ Some further details
* a special case of this factory use is the [[Singleton]] factory, which is used a lot within the Proy-Layer code
</pre>
</div>
<div title="Feed" modifier="Ichthyostega" modified="201202122123" created="201202122115" tags="def Rendering" changecount="2">
<pre>A grouping device within an ongoing [[playback or render process|PlayProcess]].
Any feed corresponds to a specific ModelPort, which in turn typically corresponds to a given GlobalPipe.
When starting playback or render, a play process (with a PlayController front-end for client code) is established to coordinate the processing. This ongoing data production might encompass multiple media streams, i.e. multiple feeds pulled from several model ports and delivered into several [[output slots|OutputSlot]]. Each feed in turn might carry structured MultichannelMedia, and is thus further structured into individual [[streams of calculation|CalcStream]]. Since the latter are //stateless descriptors,// while the player and play process obviously is stateful, it's the feed's role to mediate between a state-based (procedural) and a stateless (functional and parallelised) organisation model -- ensuring a seamless data feed even during modification of the playback parameters.
</pre>
</div>
<div title="Fixture" modifier="Ichthyostega" modified="201201281945" created="200706220324" tags="def spec Builder Model" changecount="53">
<pre>a specially configured view -- joining together high-level and low-level model.
The Fixture acts as //isolation layer// between the two models, and as //backbone to attach the render nodes.//
@ -2125,7 +2131,7 @@ Additionally, they may be used for resource management purposes by embedding a r
#* one OpenGL Dataframe could contain raw texture data (but I am lacking expertise for this topic)
</pre>
</div>
<div title="FrameDispatcher" modifier="Ichthyostega" modified="201202032340" created="201105222330" tags="def Rendering" changecount="13">
<div title="FrameDispatcher" modifier="Ichthyostega" modified="201202122109" created="201105222330" tags="def Rendering" changecount="14">
<pre>An implementation facility within the RenderEngine, responsible for translating a logical [[calculation stream|CalcStream]] (corresponding to a PlayProcess) into a sequence of individual RenderJob entries, which can then be handed over to the [[Scheduler]]. Performing this operation involves a special application of [[time quantisation|TimeQuant]]: after establishing a suitable starting point, a typically contiguous series of frame numbers need to be generated, together with the time coordinates for each of those frames.
!defining the dispatcher interface
@ -2143,7 +2149,11 @@ The purpose of this interface is to support the planning of new jobs, for a give
*** the corresponding JobTicket to use at this point
!!!the ~TimeAnchor
In fact, the whole 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. The evaluation structure of the render engine is quite similar to the //fork-join//-pattern, just with the addition of timing constraints. This leads to an invocation pattern, where a partial evaluation happens from time to time. Each of those evaluations establishes a breaking point in time: everything //before// this point is settled and planned thus far. So, this point is an ''anchor'' or closure to root the next partial evaluation. More specifically, this ~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 render evaluation.</pre>
In fact, the whole 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. The evaluation structure of the render engine is quite similar to the //fork-join//-pattern, just with the addition of timing constraints. This leads to an invocation pattern, where a partial evaluation happens from time to time. Each of those evaluations establishes a breaking point in time: everything //before// this point is settled and planned thus far. So, this point is an ''anchor'' or closure to root the next partial evaluation. More specifically, this ~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 render evaluation.
!!!producing actual jobs
The JobTicket is created on demand, specialised for a single [[segment|Segmentation]] of the timeline and a single [[feed|Feed]] of data frames to be pulled from a ModelPort. Thus, in turn, this means that all frames and all channels within that realm will rely on the same job ticket -- which is a //higher order function,// a function producing another function: when provided with the actual channel number and the specific frame coordinates, the job ticket produces a [[concrete job definition|RenderJob]], which itself is a function to be invoked by the [[scheduler|Scheduler]] just in time.
</pre>
</div>
<div title="FullScreenPlugin" modifier="CehTeh" modified="200706110313" created="200607241016" tags="systemConfig lewcidExtension" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200706110313">
<pre>/***
@ -4493,7 +4503,7 @@ We need a way of addressing existing [[pipes|Pipe]]. Besides, as the Pipes and T
&lt;&lt;tasksum end&gt;&gt;
</pre>
</div>
<div title="PlayProcess" modifier="Ichthyostega" modified="201202112352" created="201012181714" tags="def spec Player img" changecount="18">
<div title="PlayProcess" modifier="Ichthyostega" modified="201202122111" created="201012181714" tags="def spec Player img" changecount="19">
<pre>With //play process//&amp;nbsp; we denote an ongoing effort to calculate a stream of frames for playback or rendering.
The play process is an conceptual entity linking together several activities in the [[Backend]] and the RenderEngine. Creating a play process is the central service provided by the [[player subsystem|Player]]: it maintains a registration entry for the process to keep track of associated entities, resources allocated and calls [[dispatched|FrameDispatcher]] as a consequence, and it wires and exposes a PlayController to serve as an interface and information hub.
@ -4504,7 +4514,7 @@ The play process is an conceptual entity linking together several activities in
[&gt;img[Anatomy of a Play Process|uml/fig144005.png]]
!Anatomy of a Play Process
The Controller is exposed to the client and acts as frontend handle, while the play process body groups and manages all the various parts cooperating to generate output. For each of the participating global pipes we get a feed to drive that pipeline to deliver media of a specific kind.
The Controller is exposed to the client and acts as frontend handle, while the play process body groups and manages all the various parts cooperating to generate output. For each of the participating global pipes we get a [[feed|Feed]] to drive that pipeline to deliver media of a specific kind.
Right within the play process, there is a separation into two realms, relying on different programming paradigms. Obviously the play controller is a state machine, and similarily the body object (play process) has a distinct operation state. Moreover, the current collection of individual objects hooked up at any given instance is a stateful variable. To the contrary, when we enter the realm of actual processing, operations are carried out in parallel, relying on stateless descriptor objects, wired into individual calculation jobs, to be scheduled as non-blocking units of operation. For each series of consecutive frames to be calculated, there is a descriptor object, the CalcStream, which also links to a specificaly tailored dispatcher table, allowing to schedule the individual frame jobs. Whenever the controller determines a change in the playback plan (speed change, skip, scrubbing, looping, ...), a new CalcStream is created, while the existing one is just used to mark any not-yet processed job as superseded.
</pre>