Dispatcher-Pipeline: implement the frame-tick core
splitting into a sequence of builder types seems to have done the trick
This commit is contained in:
parent
81ee9a2e67
commit
71ea10bf21
6 changed files with 442 additions and 386 deletions
|
|
@ -48,11 +48,14 @@
|
|||
//#include "lib/nocopy.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace steam {
|
||||
namespace engine {
|
||||
|
||||
using std::move;
|
||||
using std::declval;
|
||||
using std::function;
|
||||
using mobject::ModelPort;
|
||||
using play::Timings;
|
||||
|
|
@ -107,7 +110,13 @@ namespace engine {
|
|||
}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
public: //////////////////////////////////////////////////////////////////OOO TODO not public; need a way to pick up the result type
|
||||
struct PipeFrameTick;
|
||||
struct PipeSelector;
|
||||
struct PipeExpander;
|
||||
struct PipePlanner;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
using FrameNrIter = lib::NumIter<FrameCnt>;
|
||||
|
||||
struct PipelineBuilder
|
||||
|
|
@ -132,6 +141,7 @@ namespace engine {
|
|||
});
|
||||
}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
|
||||
|
||||
public:
|
||||
|
|
@ -139,12 +149,13 @@ namespace engine {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
JobBuilder onCalcStream (ModelPort modelPort, uint channel);
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
|
||||
PipelineBuilder forCalcStream(Timings timings, ModelPort port, DataSink sink)
|
||||
{
|
||||
return PipelineBuilder{FrameNrIter(), this, timings, port, sink};
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
PipeFrameTick forCalcStream (Timings timings);
|
||||
|
||||
|
||||
protected:
|
||||
|
|
@ -180,5 +191,94 @@ namespace engine {
|
|||
|
||||
|
||||
|
||||
|
||||
/* ======== Steps of the Job-planning Pipeline ======== */
|
||||
|
||||
/**
|
||||
* Job-planning Step-1: establish a sequence of frame start times
|
||||
*/
|
||||
struct Dispatcher::PipeFrameTick
|
||||
{
|
||||
Dispatcher * const dispatcher;
|
||||
const Timings timings;
|
||||
|
||||
TimeVar currPoint{Time::NEVER};
|
||||
TimeVar stopPoint{Time::NEVER};
|
||||
FrameCnt frameNr{0};
|
||||
|
||||
|
||||
/* === state protocol API for IterStateWrapper === */
|
||||
bool
|
||||
checkPoint() const
|
||||
{
|
||||
return currPoint < stopPoint;
|
||||
}
|
||||
|
||||
TimeVar const&
|
||||
yield() const
|
||||
{
|
||||
return currPoint;
|
||||
}
|
||||
|
||||
void
|
||||
iterNext()
|
||||
{
|
||||
++frameNr;
|
||||
currPoint = timings.getFrameStartAt (frameNr);
|
||||
}
|
||||
|
||||
|
||||
/** Builder Function: start frame sequence */
|
||||
auto
|
||||
timeRange (Time start, Time after)
|
||||
{
|
||||
stopPoint = after;
|
||||
frameNr = timings.getBreakPointAfter(start);
|
||||
currPoint = timings.getFrameStartAt (frameNr);
|
||||
|
||||
// start iterator pipeline based on this as »state core«
|
||||
return lib::treeExplore (move(*this));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline Dispatcher::PipeFrameTick
|
||||
Dispatcher::forCalcStream(Timings timings)
|
||||
{
|
||||
return PipeFrameTick{this, timings};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////OOO need better solution for type rebinding
|
||||
using Builder = decltype( declval<Dispatcher::PipeFrameTick>().timeRange (declval<Time>(), declval<Time>()));
|
||||
|
||||
/**
|
||||
* Job-planning Step-2: select data feed connection between ModelPort
|
||||
* and DataSink; this entails to select the actually active Node pipeline
|
||||
*/
|
||||
struct Dispatcher::PipeSelector
|
||||
: Builder
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Job-planning Step-3: monadic depth-first exploration of Prerequisites
|
||||
*/
|
||||
struct Dispatcher::PipeExpander
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* Job-planning Step-4: collect the complete planning context and determine time frame
|
||||
*/
|
||||
struct Dispatcher::PipePlanner
|
||||
{};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace steam::engine
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -173,8 +173,8 @@ namespace test {
|
|||
play::Timings timings (FrameRate::PAL);
|
||||
auto [port,sink] = dispatcher.getDummyConnection(0);
|
||||
|
||||
auto pipeline = dispatcher.forCalcStream(timings, port, sink)
|
||||
.timeRange(Time{200,0}, Time{480,0});
|
||||
auto pipeline = dispatcher.forCalcStream(timings)
|
||||
.timeRange(Time{200,0}, Time{FSecs{1,2}});
|
||||
|
||||
CHECK (materialise (pipeline)
|
||||
== "200ms-240ms-280ms-320ms-360ms-400ms-440ms-480ms"_expect);
|
||||
|
|
|
|||
|
|
@ -86,179 +86,109 @@ namespace test {
|
|||
};
|
||||
|
||||
|
||||
using asset::Pipe;
|
||||
using asset::PPipe;
|
||||
using asset::Struct;
|
||||
using asset::Timeline;
|
||||
using asset::PTimeline;
|
||||
using mobject::ModelPort;
|
||||
using mobject::builder::ModelPortRegistry;
|
||||
using util::contains;
|
||||
using lumiera::Query;
|
||||
|
||||
|
||||
using PID = asset::ID<Pipe>;
|
||||
using TID = asset::ID<Struct>;
|
||||
|
||||
using ModelPorts = lib::IterSource<mobject::ModelPort>::iterator;
|
||||
using DummyOutputLink = std::pair<mobject::ModelPort, play::DataSink>;
|
||||
|
||||
|
||||
inline PID
|
||||
getPipe (string id)
|
||||
{
|
||||
return Pipe::query ("id("+id+")");
|
||||
}
|
||||
|
||||
inline TID
|
||||
getTimeline (string id)
|
||||
{
|
||||
return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
|
||||
}
|
||||
|
||||
const uint NUMBER_OF_PORTS = 2;
|
||||
const string namePortA("bus-A");
|
||||
const string namePortB("bus-B");
|
||||
|
||||
/**
|
||||
* helper for dummy render engine:
|
||||
* Simulate the result of a build process,
|
||||
* without actually running the builder.
|
||||
* Produces some mock pipes, model ports etc.
|
||||
*/
|
||||
struct SimulatedBuilderContext
|
||||
{
|
||||
ModelPortRegistry registry_;
|
||||
ModelPortRegistry* existingRegistry_;
|
||||
|
||||
std::vector<ModelPort> modelPorts_;
|
||||
std::vector<DataSink> dataSinks_;
|
||||
|
||||
/** setup */
|
||||
SimulatedBuilderContext()
|
||||
: registry_()
|
||||
, existingRegistry_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
{
|
||||
performMockBuild();
|
||||
}
|
||||
|
||||
/** tear-down */
|
||||
~SimulatedBuilderContext()
|
||||
{
|
||||
if (existingRegistry_)
|
||||
ModelPortRegistry::setActiveInstance (*existingRegistry_);
|
||||
else
|
||||
ModelPortRegistry::shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
performMockBuild()
|
||||
{
|
||||
PID pipeA = getPipe (namePortA);
|
||||
PID pipeB = getPipe (namePortB);
|
||||
TID someTimeline = getTimeline ("dummy_Timeline");
|
||||
|
||||
// start out with defining some new model ports......
|
||||
registry_.definePort (pipeA, someTimeline);
|
||||
registry_.definePort (pipeB, someTimeline);
|
||||
|
||||
registry_.commit();
|
||||
|
||||
// now "bus-A" and "bus-B" are known as model ports
|
||||
modelPorts_.push_back (ModelPort(pipeA));
|
||||
modelPorts_.push_back (ModelPort(pipeB));
|
||||
|
||||
// prepare corresponding placeholder DataSink (a fake active output connection)
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
}
|
||||
|
||||
|
||||
ModelPorts
|
||||
getAllModelPorts()
|
||||
{
|
||||
return lib::iter_source::eachEntry (modelPorts_.begin(), modelPorts_.end());
|
||||
}
|
||||
|
||||
DummyOutputLink
|
||||
getModelPort (uint index)
|
||||
{
|
||||
REQUIRE (index < modelPorts_.size());
|
||||
return {modelPorts_[index]
|
||||
,dataSinks_[index]
|
||||
};
|
||||
}
|
||||
};
|
||||
using asset::Pipe;
|
||||
using asset::PPipe;
|
||||
using asset::Struct;
|
||||
using asset::Timeline;
|
||||
using asset::PTimeline;
|
||||
using mobject::ModelPort;
|
||||
using mobject::builder::ModelPortRegistry;
|
||||
using util::contains;
|
||||
using lumiera::Query;
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
/****************************************************************//**
|
||||
* Framework for dummy playback and rendering.
|
||||
* A DummyPlayConnection provides a coherent set of placeholders,
|
||||
* allowing to start a data producing process while leaving out
|
||||
* various parts of the real engine implementation. The specific
|
||||
* mode of operation, suitable for various test scenarios, may be
|
||||
* fine tuned by the strategy object defined as template parameter.
|
||||
*
|
||||
* @todo not-yet-implemented as of 2016 -- but the design can be considered valid.
|
||||
|
||||
using PID = asset::ID<Pipe>;
|
||||
using TID = asset::ID<Struct>;
|
||||
|
||||
using ModelPorts = lib::IterSource<mobject::ModelPort>::iterator;
|
||||
using DummyOutputLink = std::pair<mobject::ModelPort, play::DataSink>;
|
||||
|
||||
|
||||
inline PID
|
||||
getPipe (string id)
|
||||
{
|
||||
return Pipe::query ("id("+id+")");
|
||||
}
|
||||
|
||||
inline TID
|
||||
getTimeline (string id)
|
||||
{
|
||||
return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
|
||||
}
|
||||
|
||||
const uint NUMBER_OF_PORTS = 2;
|
||||
const string namePortA("bus-A");
|
||||
const string namePortB("bus-B");
|
||||
|
||||
/**
|
||||
* helper for dummy render engine:
|
||||
* Simulate the result of a build process,
|
||||
* without actually running the builder.
|
||||
* Produces some mock pipes, model ports etc.
|
||||
*/
|
||||
template<class DEF>
|
||||
class DummyPlayConnection
|
||||
: util::NonCopyable
|
||||
struct SimulatedBuilderContext
|
||||
{
|
||||
SimulatedBuilderContext mockBuilder_;
|
||||
ModelPortRegistry registry_;
|
||||
ModelPortRegistry* existingRegistry_;
|
||||
|
||||
std::vector<ModelPort> modelPorts_;
|
||||
std::vector<DataSink> dataSinks_;
|
||||
|
||||
/** setup */
|
||||
SimulatedBuilderContext()
|
||||
: registry_()
|
||||
, existingRegistry_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
{
|
||||
performMockBuild();
|
||||
}
|
||||
|
||||
/** tear-down */
|
||||
~SimulatedBuilderContext()
|
||||
{
|
||||
if (existingRegistry_)
|
||||
ModelPortRegistry::setActiveInstance (*existingRegistry_);
|
||||
else
|
||||
ModelPortRegistry::shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
performMockBuild()
|
||||
{
|
||||
PID pipeA = getPipe (namePortA);
|
||||
PID pipeB = getPipe (namePortB);
|
||||
TID someTimeline = getTimeline ("dummy_Timeline");
|
||||
|
||||
// start out with defining some new model ports......
|
||||
registry_.definePort (pipeA, someTimeline);
|
||||
registry_.definePort (pipeB, someTimeline);
|
||||
|
||||
registry_.commit();
|
||||
|
||||
// now "bus-A" and "bus-B" are known as model ports
|
||||
modelPorts_.push_back (ModelPort(pipeA));
|
||||
modelPorts_.push_back (ModelPort(pipeB));
|
||||
|
||||
// prepare corresponding placeholder DataSink (a fake active output connection)
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
ModelPorts
|
||||
getAllModelPorts()
|
||||
{
|
||||
return mockBuilder_.getAllModelPorts();
|
||||
return lib::iter_source::eachEntry (modelPorts_.begin(), modelPorts_.end());
|
||||
}
|
||||
|
||||
DummyOutputLink
|
||||
getModelPort (uint index)
|
||||
{
|
||||
return mockBuilder_.getModelPort (index);
|
||||
}
|
||||
|
||||
POutputManager
|
||||
provide_testOutputSlot()
|
||||
{
|
||||
UNIMPLEMENTED ("provide a suitable output sink simulation");
|
||||
}
|
||||
|
||||
|
||||
/* === Test Support API === */
|
||||
|
||||
bool
|
||||
isWired()
|
||||
{
|
||||
UNIMPLEMENTED ("is this dummy in activated state?");
|
||||
}
|
||||
|
||||
Duration
|
||||
getPlannedTestDuration()
|
||||
{
|
||||
UNIMPLEMENTED ("manage the a planned test duration");
|
||||
}
|
||||
|
||||
/** test helper: blocking wait during an output test.
|
||||
* The waiting time should be in accordance with the
|
||||
* \link #getPlannedTestduration planned value \endlink,
|
||||
*/
|
||||
void
|
||||
waitUntilDue()
|
||||
{
|
||||
UNIMPLEMENTED ("do a blocking wait, while an output test is performed in other threads");
|
||||
}
|
||||
|
||||
bool
|
||||
gotCorrectOutput()
|
||||
{
|
||||
UNIMPLEMENTED ("verify proper operation by inspecting the provided test dummy components");
|
||||
REQUIRE (index < modelPorts_.size());
|
||||
return {modelPorts_[index]
|
||||
,dataSinks_[index]
|
||||
};
|
||||
}
|
||||
};
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
|
||||
|
||||
}}} // namespace steam::play::test
|
||||
|
|
|
|||
|
|
@ -97,138 +97,13 @@ namespace test {
|
|||
using lib::time::Duration;
|
||||
|
||||
|
||||
/*
|
||||
* @todo 5/2023 quick-n-dirty placeholder to be able to fabricate fake DataSink handles (`Handle<Connection>`)
|
||||
* /
|
||||
class UnimplementedConnection
|
||||
: public play::OutputSlot::Connection
|
||||
{
|
||||
BuffHandle claimBufferFor(FrameID) override { UNIMPLEMENTED ("claimBufferFor(FrameID)"); }
|
||||
bool isTimely (FrameID, TimeValue) override { return true; }
|
||||
void transfer (BuffHandle const&) override { UNIMPLEMENTED ("transfer (BuffHandle const&)"); }
|
||||
void pushout (BuffHandle const&) override { UNIMPLEMENTED ("pushout (BuffHandle const&)"); }
|
||||
void discard (BuffHandle const&) override { UNIMPLEMENTED ("discard (BuffHandle const&)"); }
|
||||
void shutDown () override { UNIMPLEMENTED ("shutDown() Connection"); }
|
||||
|
||||
public:
|
||||
~UnimplementedConnection();
|
||||
UnimplementedConnection() = default;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// @todo placeholder as of 6/23
|
||||
struct PlayTestFrames_Strategy
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
namespace { // simulated builder environment
|
||||
|
||||
using asset::Pipe;
|
||||
using asset::PPipe;
|
||||
using asset::Struct;
|
||||
using asset::Timeline;
|
||||
using asset::PTimeline;
|
||||
using mobject::ModelPort;
|
||||
using mobject::builder::ModelPortRegistry;
|
||||
using util::contains;
|
||||
using lumiera::Query;
|
||||
// using lib::ScopedCollection;
|
||||
// using lib::Literal;
|
||||
|
||||
typedef asset::ID<Pipe> PID;
|
||||
typedef asset::ID<Struct> TID;
|
||||
|
||||
// typedef ModelPortRegistry::ModelPortDescriptor const& MPDescriptor;
|
||||
|
||||
|
||||
inline PID
|
||||
getPipe (string id)
|
||||
{
|
||||
return Pipe::query ("id("+id+")");
|
||||
}
|
||||
|
||||
inline TID
|
||||
getTimeline (string id)
|
||||
{
|
||||
return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
|
||||
}
|
||||
|
||||
const uint NUMBER_OF_PORTS = 2;
|
||||
const string namePortA("bus-A");
|
||||
const string namePortB("bus-B");
|
||||
|
||||
/ **
|
||||
* helper for dummy render engine:
|
||||
* Simulate the result of a build process,
|
||||
* without actually running the builder.
|
||||
* Produces some mock pipes, model ports etc.
|
||||
* /
|
||||
struct SimulatedBuilderContext
|
||||
{
|
||||
ModelPortRegistry registry_;
|
||||
ModelPortRegistry* existingRegistry_;
|
||||
|
||||
std::vector<ModelPort> modelPorts_;
|
||||
std::vector<DataSink> dataSinks_;
|
||||
|
||||
SimulatedBuilderContext()
|
||||
: registry_()
|
||||
, existingRegistry_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
{
|
||||
performMockBuild();
|
||||
}
|
||||
|
||||
~SimulatedBuilderContext()
|
||||
{
|
||||
if (existingRegistry_)
|
||||
ModelPortRegistry::setActiveInstance (*existingRegistry_);
|
||||
else
|
||||
ModelPortRegistry::shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
performMockBuild()
|
||||
{
|
||||
PID pipeA = getPipe (namePortA);
|
||||
PID pipeB = getPipe (namePortB);
|
||||
TID someTimeline = getTimeline ("dummy_Timeline");
|
||||
|
||||
// start out with defining some new model ports......
|
||||
registry_.definePort (pipeA, someTimeline);
|
||||
registry_.definePort (pipeB, someTimeline);
|
||||
|
||||
registry_.commit();
|
||||
|
||||
// now "bus-A" and "bus-B" are known as model ports
|
||||
modelPorts_.push_back (ModelPort(pipeA));
|
||||
modelPorts_.push_back (ModelPort(pipeB));
|
||||
|
||||
// prepare corresponding placeholder DataSink (a fake active output connection)
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
}
|
||||
|
||||
|
||||
ModelPorts
|
||||
getAllModelPorts()
|
||||
{
|
||||
return lib::iter_source::eachEntry (modelPorts_.begin(), modelPorts_.end());
|
||||
}
|
||||
|
||||
DummyOutputLink
|
||||
getModelPort (uint index)
|
||||
{
|
||||
REQUIRE (index < modelPorts_.size());
|
||||
return {modelPorts_[index]
|
||||
,dataSinks_[index]
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
/****************************************************************//**
|
||||
* Framework for dummy playback and rendering.
|
||||
|
|
@ -239,6 +114,7 @@ namespace test {
|
|||
* fine tuned by the strategy object defined as template parameter.
|
||||
*
|
||||
* @todo not-yet-implemented as of 2016 -- but the design can be considered valid.
|
||||
* @todo 6/23 still largely unimplemented, but used as generator for mock ModelPort
|
||||
*/
|
||||
template<class DEF>
|
||||
class DummyPlayConnection
|
||||
|
|
|
|||
|
|
@ -2530,7 +2530,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" created="201105222330" modified="202305260210" tags="def Player Rendering" changecount="23">
|
||||
<div title="FrameDispatcher" modifier="Ichthyostega" created="201105222330" modified="202306031535" tags="def Player Rendering" changecount="25">
|
||||
<pre>An entity 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.
|
||||
|
||||
The dispatcher works together with the [[job ticket(s)|JobTicket]] and the scheduler; actually these are the //core abstractions//&nbsp; the process of ''job planning'' relies on. While the actual scheduler implementation lives within the Vault, the job tickets and the dispatcher are located within the [[Segmentation]], which is the backbone of the [[low-level model|LowLevelModel]]. More specifically, the dispatcher interface is //implemented//&nbsp; by a set of &rarr; [[dispatcher tables|DispatcherTables]] within the segmentation.
|
||||
|
|
@ -2551,8 +2551,8 @@ The purpose of this interface is to support the planning of new jobs, for a give
|
|||
*** the relevant [[segment|Segmentation]] responsible for producing this frame
|
||||
*** 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.
|
||||
!!!Planning Chunks
|
||||
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'' and starting point for the next partial evaluation. On the implementation level, each CalcStream maintains a {{{RenderDrive}}} (see below), which acts both as //planning pipeline// and JobFunctor for the next planning chunk to come. Moreover, the associated [[Timings]] record establishes a definitive binding between the abstract logical time of the session timeline, and the real wall-clock time forming the deadline for render evaluation.
|
||||
|
||||
!!!related timelines and the frame grid
|
||||
The frame dispatch step joins and combines multiple time axes. Through the process of //scheduling,// the output generation is linked to real ''wall clock time'' and the dispatch step establishes the deadlines, taking the ''engine latency'' into account. As such, any render or playback process establishes an ''output time grid'', linking frame numbers to nominal output time or timecode, based on the ''output frame rate'' -- and both the framerate and the actual progression (speed) might be changed dynamically. But beyond all of this there is a third, basically independent temporal structure involved: the actual content to render, the ''effective session timeline''. While encoded in nominal, absolute, internal time values not necessarily grid aligned, in practice at least the //breaking points,// the temporal location where the content or structure of the pipeline changes, are aligned //to a grid used while creating the edit.// Yet this session timing structure need not be related in any way to the playback grid, nor is it necessarily the same as the ''source grid'' defined by the media data used to feed the pipeline.
|
||||
|
|
@ -2562,7 +2562,8 @@ These complex relationships are reflected in the invocation structure leading to
|
|||
!!!controlling the planning process
|
||||
[>img[Structure of the Fixture|draw/Play.Dispatch.png]]New render jobs are planned as an ongoing process, proceeding in chunks of evaluation. Typically, to calculate a single frame, several jobs are necessary -- to find out which and how, we'll have to investigate the model structures corresponding to this frame, resulting in a tree of prerequisites. Basically, the planning for each frame is seeded by establishing the nominal time position, in accordance to the current [[mode of playback|NonLinearPlayback]]. Conducted by the [[play controller|PlayController]], there is a strategy to define the precise way of spacing and sequence of frames to be calculated -- yet for the actual process of evaluating the prerequisites and planning the jobs, those details are irrelevant and hidden behind the dispatcher interface, as is most of the model and context information. The planning operation just produces a sequence of job definitions, which can then be associated with real time (wall clock) deadlines for delivery. The relation between the spacing and progression of the nominal frame time (as controlled by the playback mode) and the actual sequence of deadlines (which is more or less dictated by the output device) is rather loose and established anew for each planning chunk, relying on the ''time anchor''. The latter in turn uses the [[timings record|Timings]] of the [[calculation stream|CalcStream]] currently being planned, and these timings act as a strategy to represent the underlying timing grid and playback modalities.
|
||||
|
||||
While the sequence of frame jobs to be planned is possibly infinite, the actual evaluation is confined to the current planning chunk. When done with planning such a chunk of jobs, an additional ''continuation job'' is included to prepare a re-invocation of the planning function for preparation of the next chunk. Terminating playback is equivalent to not including or not invoking this continuation job. Please note that planning proceeds independently for each [[Feed]] -- in Lumiera the //current playback position//&nbsp; is just a conceptual projection of wall clock time to nominal time, yet there is no such thing like a synchronously proceeding "Playhead"
|
||||
While the sequence of frame jobs to be planned is possibly infinite, the actual evaluation is confined to the current planning chunk. When done with planning such a chunk of jobs, an additional ''continuation job'' is included to prepare a re-invocation of the planning function for preparation of the next chunk. Terminating playback is equivalent to not including or not invoking this continuation job. Please note that planning proceeds independently for each [[Feed]] -- in Lumiera the //current playback position//&nbsp; is just a conceptual projection of wall clock time to nominal time, yet there is no such thing like a synchronously proceeding "Playhead"
|
||||
&rarr; [[relation of models|BuildFixture]]
|
||||
|
||||
!!!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. Consequently 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 specific frame coordinates (frame number and time point), the job ticket produces a [[concrete job definition|RenderJob]], which itself is a function to be invoked by the [[scheduler|Scheduler]] to carry out the necessary calculations just in time.
|
||||
|
|
@ -4290,8 +4291,21 @@ Thus an invocation trail represents one specific path leading to the invocation
|
|||
''Note'': {{red{future plans and visions -- no clear and distinct meaning -- as of 4/21}}}
|
||||
</pre>
|
||||
</div>
|
||||
<div title="JobPlanningPipeline" creator="Ichthyostega" modifier="Ichthyostega" created="202305260209" tags="operational Rendering draft" changecount="1">
|
||||
<pre>//Depth-first evaluation pipeline used in the FrameDispatcher to generate the next chunk of [[render jobs|RenderJob]]//</pre>
|
||||
<div title="JobPlanningPipeline" creator="Ichthyostega" modifier="Ichthyostega" created="202305260209" modified="202306031539" tags="operational Rendering draft" changecount="6">
|
||||
<pre>//Depth-first evaluation pipeline used in the FrameDispatcher to generate the next chunk of [[render jobs|RenderJob]]//
|
||||
This is an implementation structure backed and established by the [[Dispatcher|FrameDispatcher]] and operated by the {{{RenderDrive}}} core of each CalcStream, where it is assembled by a //builder notation// -- backed by the {{{TreeExplorer}}} iterator pipeline framework; besides the typical filter and transform operations, the latter offers an »expansion« mechanism to integrate a //monadic exhaustive depth-first search,// allowing to pick up all prerequisites of a given calculation step by step within a local planning context.
|
||||
|
||||
!Stages of the Job-planning pipeline
|
||||
;frame-tick
|
||||
:establish a sequence of frame start times
|
||||
;selector
|
||||
:choose suitable data feed connection between ModelPort and {{{DataSink}}};
|
||||
:this entails to select the actually active ProcNode pipeline
|
||||
;expander
|
||||
:monadic depth-first exploration of calculation prerequisites
|
||||
;job-planning
|
||||
:collect the complete planning context and determine time frame
|
||||
</pre>
|
||||
</div>
|
||||
<div title="JobTicket" modifier="Ichthyostega" created="201202120018" modified="202305111241" tags="spec Rendering draft" changecount="4">
|
||||
<pre>The actual media data is rendered by [[individually scheduled render jobs|RenderJob]]. All these calculations together implement a [[stream of calculations|CalcStream]], as demanded and directed by the PlayProcess. During the preparation of playback, a ''node planning phase'' is performed, to arrange for [[dispatching|FrameDispatcher]] the individual calculations per frame. The goal of these //preparations//&nbsp; is to find out
|
||||
|
|
|
|||
|
|
@ -73413,6 +73413,97 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066463050" ID="ID_1613334312" MODIFIED="1685802330806" TEXT="Mock-Setup schaffen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066492396" ID="ID_1906962794" MODIFIED="1685066501049" TEXT="API für Zugriff klären">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1685676202669" ID="ID_1528500239" MODIFIED="1685676214053" TEXT="analog zu MockSegmentation">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676215324" ID="ID_1375641669" MODIFIED="1685676224971" TEXT="MockDispatcher kann einfach instantiiert werden">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676225634" ID="ID_201099858" MODIFIED="1685676286815" TEXT="er hält intern eine DummyPlayConnection">
|
||||
<arrowlink COLOR="#58b681" DESTINATION="ID_161203143" ENDARROW="Default" ENDINCLINATION="79;-62;" ID="Arrow_ID_502535652" STARTARROW="None" STARTINCLINATION="90;6;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676320949" ID="ID_60016786" MODIFIED="1685802379535" TEXT="ein neuer Builder wird in der Dispatcher-Basisklasse implementiert">
|
||||
<arrowlink COLOR="#a44d82" DESTINATION="ID_1622487483" ENDARROW="Default" ENDINCLINATION="121;-252;" ID="Arrow_ID_1017802335" STARTARROW="None" STARTINCLINATION="231;10;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066474347" ID="ID_122826612" MODIFIED="1685066485373" TEXT="Grid in den Mock-Dispatcher legen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685662239880" ID="ID_1505090088" MODIFIED="1685662250525" TEXT="brauche ModelPort und Sink-Instanzen">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1685662251607" ID="ID_1360980940" MODIFIED="1685662442877" TEXT="tückisches Problem....">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...oder genauer gesagt, ein Design-Mismatch — das ganze ID-System in Lumiera ist <i>magisch</i> und „hintenrum“ mit globalen Tabellen verbunden; <i>damals</i> erschien mir das gradezu natürlich, <i>heute</i> sehe ich leider keine bessere Lösung, die man in C++ realisieren kann (Scala löst dieses Problem mit den Implicits bzw. Givens)
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1685662448009" ID="ID_881674588" MODIFIED="1685662511675" TEXT="andererseits ist Lumiera „bloß“ eine Applikation">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...und nicht das ultimative Medien-Framework!!
|
||||
</p>
|
||||
<p>
|
||||
....also ist es durchaus im Rahmen, wenn es eine fest vereinbarte Hintertür gibt für die Tests
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1685662517358" ID="ID_161203143" MODIFIED="1685676286816">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
es lebe die <b><font face="Monospaced" color="#3d1ca2">DummyPlayConnection</font></b>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#58b681" DESTINATION="ID_161203143" ENDARROW="Default" ENDINCLINATION="79;-62;" ID="Arrow_ID_502535652" SOURCE="ID_201099858" STARTARROW="None" STARTINCLINATION="90;6;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1685676072753" ID="ID_29155074" MODIFIED="1685676082592" TEXT="dort gibt es schon zwei fake-ModelPorts">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676083734" ID="ID_1387602910" MODIFIED="1685676114044" TEXT="nun auch noch zwei korrespondierende DataSink hinzugefügt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676098707" ID="ID_970617797" MODIFIED="1685676172210" TEXT="und als Platzhalter: UnimplementedConnection">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
DataSink ist ein lib::Handle<play::OutputSlot::Connection>
|
||||
</p>
|
||||
<p>
|
||||
Also muß es im einfachsten Fall auf eine Subklasse von Connection zeigen; diese füge ich hinzu mit lauter UNIMPLEMENTED stubs
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685063128431" ID="ID_1958871740" MODIFIED="1685063140918" TEXT="Startpunkt gewinnen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1685231891079" ID="ID_260441580" MODIFIED="1685231911607" TEXT="Rolle des Start-Punktes (TimeAnchor) klären">
|
||||
|
|
@ -73498,6 +73589,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1685406892909" ID="ID_877192337" MODIFIED="1685406903491" TEXT="wir zählen einfach die Frame-Nummer hoch und gut is"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685406904249" ID="ID_1903725712" MODIFIED="1685406939765" TEXT="aus dem TimeAnchor wird eine einfache Variable chunkStart">
|
||||
<arrowlink COLOR="#90417a" DESTINATION="ID_1280247593" ENDARROW="Default" ENDINCLINATION="-241;-172;" ID="Arrow_ID_1703119592" STARTARROW="None" STARTINCLINATION="-212;10;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -73520,7 +73612,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685635478500" ID="ID_1622487483" MODIFIED="1685676386317" TEXT="geeignetes Builder-API ausarbeiten">
|
||||
<linktarget COLOR="#a44d82" DESTINATION="ID_1622487483" ENDARROW="Default" ENDINCLINATION="23;31;" ID="Arrow_ID_1017802335" SOURCE="ID_60016786" STARTARROW="None" STARTINCLINATION="93;-2;"/>
|
||||
<linktarget COLOR="#a44d82" DESTINATION="ID_1622487483" ENDARROW="Default" ENDINCLINATION="121;-252;" ID="Arrow_ID_1017802335" SOURCE="ID_60016786" STARTARROW="None" STARTINCLINATION="231;10;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1685676367077" ID="ID_497119837" MODIFIED="1685676383553" TEXT="Builder-Syntax schaffen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
|
|
@ -73558,10 +73650,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685744020440" ID="ID_189611589" MODIFIED="1685744043568" TEXT="das eigene Builder-API soll aber auf TreeExplorer aufbauen können">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685743991581" ID="ID_865546443" MODIFIED="1685744014683" TEXT="Type-Rebinding einrichten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685744055315" ID="ID_115548313" MODIFIED="1685754522949" TEXT="für Basis-Konstruktion">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685743991581" ID="ID_865546443" MODIFIED="1685809733371" TEXT="Type-Rebinding einrichten">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#5b280f" CREATED="1685744055315" ID="ID_115548313" MODIFIED="1685809647945" TEXT="für Basis-Konstruktion">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685754130097" ID="ID_286369938" MODIFIED="1685754149459" TEXT="schwierig">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
|
|
@ -73590,9 +73682,67 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0bbaa" COLOR="#da1b25" CREATED="1685756935681" ID="ID_1637410723" MODIFIED="1685756972905" TEXT="führt zu gefährlichen self-captures (SEGFAULT)">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685809658922" ID="ID_1957536311" MODIFIED="1685809719591" TEXT="Basis-Fall besser ohne Type-Rebinding">
|
||||
<arrowlink COLOR="#32c808" DESTINATION="ID_1438204358" ENDARROW="Default" ENDINCLINATION="283;12;" ID="Arrow_ID_1706669462" STARTARROW="None" STARTINCLINATION="280;20;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685744060666" ID="ID_676050987" MODIFIED="1685744074319" TEXT="für Anwendung von TreeExplorer-Builder-Funktionen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685809751146" ID="ID_1263839813" MODIFIED="1685809769709" TEXT="über Sequenz von dedizierten Builder-Typen lösen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685809771167" ID="ID_998998083" MODIFIED="1685809780626" TEXT="Problem: Definitions-Sequenz">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1685809782637" ID="ID_1994330949" MODIFIED="1685809800179" TEXT="(inline)-Funktionen sind erst nach dem Typ definiert"/>
|
||||
<node CREATED="1685809800830" ID="ID_835161833" MODIFIED="1685809812910" TEXT="decltype kann erst auf vollständigen Typ angewendet werden"/>
|
||||
<node CREATED="1685809816376" ID="ID_1605798061" MODIFIED="1685809838809" TEXT="brauche aber den decltype zu Beginn des nächsten Binder-Typs"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685809839549" ID="ID_97735774" MODIFIED="1685809855277" TEXT="wo kann ich diesen Schlonz sauber unterbringen?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685757095009" ID="ID_707524538" MODIFIED="1685809878137" TEXT="Sequenz von Builder-Typen verwenden">
|
||||
<icon BUILTIN="idea"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1685757114222" ID="ID_1148981272" MODIFIED="1685757140497" TEXT="weil ohnehin die Builder-Funktionen in einer fixen Reihenfolge aufgerufen werden müssen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685757512876" ID="ID_1438204358" MODIFIED="1685809712356" TEXT="den Tick-Generator besser explizit als StateCore ausimplementieren">
|
||||
<linktarget COLOR="#32c808" DESTINATION="ID_1438204358" ENDARROW="Default" ENDINCLINATION="283;12;" ID="Arrow_ID_1706669462" SOURCE="ID_1957536311" STARTARROW="None" STARTINCLINATION="280;20;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685802397240" ID="ID_958561473" MODIFIED="1685809511387" TEXT="direkt einen Zeitpunkt als Haltepunkt verwenden">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685809519544" ID="ID_619200654" MODIFIED="1685809529263" TEXT="Haltepunkt-Semantik im Test verifiziert">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1685804222909" ID="ID_882875787" MODIFIED="1685804227895" TEXT="Gliederung">
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1685804229424" ID="ID_1243885994" MODIFIED="1685804229424" TEXT="struct PipeFrameTick;">
|
||||
<node CREATED="1685804263831" ID="ID_1326960664" MODIFIED="1685804267603" TEXT="Zeitpunkte"/>
|
||||
<node CREATED="1685804268663" ID="ID_1765378616" MODIFIED="1685804275894" TEXT="Stop am Ende"/>
|
||||
</node>
|
||||
<node CREATED="1685804229425" ID="ID_1068361872" MODIFIED="1685804229425" TEXT="struct PipeSelector;">
|
||||
<node CREATED="1685804280614" ID="ID_636246298" MODIFIED="1685804307946" TEXT="wählt Verbindung zum low-level-Model"/>
|
||||
<node CREATED="1685804312326" ID="ID_1049622554" MODIFIED="1685804385924" TEXT="neue Idee: »FrameDropper« bereitstellen">
|
||||
<linktarget COLOR="#fdfed9" DESTINATION="ID_1049622554" ENDARROW="Default" ENDINCLINATION="-118;8;" ID="Arrow_ID_109489850" SOURCE="ID_9551953" STARTARROW="None" STARTINCLINATION="124;-21;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1685804229425" ID="ID_1660231509" MODIFIED="1685804229425" TEXT="struct PipeExpander;">
|
||||
<node CREATED="1685804397958" ID="ID_897391572" MODIFIED="1685804414527" TEXT="die rekursive monadische Tiefensuche"/>
|
||||
<node CREATED="1685804425069" ID="ID_703856821" MODIFIED="1685804474914" TEXT="(Dependent, Dependency)"/>
|
||||
</node>
|
||||
<node CREATED="1685804229425" ID="ID_1653285546" MODIFIED="1685804229425" TEXT="struct PipePlanner;">
|
||||
<node CREATED="1685804493985" ID="ID_1670773237" MODIFIED="1685804500860" TEXT="Aggregat aller Planungsdaten"/>
|
||||
<node CREATED="1685804506903" ID="ID_1557824404" MODIFIED="1685804516211" TEXT="JobPlanning legt die Zeitfenster fest"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -73610,105 +73760,57 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066463050" ID="ID_1613334312" MODIFIED="1685066472930" TEXT="Mock-Setup schaffen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066492396" ID="ID_1906962794" MODIFIED="1685066501049" TEXT="API für Zugriff klären">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1685676202669" ID="ID_1528500239" MODIFIED="1685676214053" TEXT="analog zu MockSegmentation">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676215324" ID="ID_1375641669" MODIFIED="1685676224971" TEXT="MockDispatcher kann einfach instantiiert werden">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676225634" ID="ID_201099858" MODIFIED="1685676286815" TEXT="er hält intern eine DummyPlayConnection">
|
||||
<arrowlink COLOR="#58b681" DESTINATION="ID_161203143" ENDARROW="Default" ENDINCLINATION="79;-62;" ID="Arrow_ID_502535652" STARTARROW="None" STARTINCLINATION="90;6;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676320949" ID="ID_60016786" MODIFIED="1685676362183" TEXT="ein neuer Builder wird in der Dispatcher-Basisklasse implementiert">
|
||||
<arrowlink COLOR="#a44d82" DESTINATION="ID_1622487483" ENDARROW="Default" ENDINCLINATION="23;31;" ID="Arrow_ID_1017802335" STARTARROW="None" STARTINCLINATION="93;-2;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685066474347" ID="ID_122826612" MODIFIED="1685066485373" TEXT="Grid in den Mock-Dispatcher legen">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685809903965" ID="ID_1280247593" MODIFIED="1685809942333" TEXT="nächsten chunkStart auslesen">
|
||||
<linktarget COLOR="#90417a" DESTINATION="ID_1280247593" ENDARROW="Default" ENDINCLINATION="-241;-172;" ID="Arrow_ID_1703119592" SOURCE="ID_1903725712" STARTARROW="None" STARTINCLINATION="-212;10;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685662239880" ID="ID_1505090088" MODIFIED="1685662250525" TEXT="brauche ModelPort und Sink-Instanzen">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1685662251607" ID="ID_1360980940" MODIFIED="1685662442877" TEXT="tückisches Problem....">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...oder genauer gesagt, ein Design-Mismatch — das ganze ID-System in Lumiera ist <i>magisch</i> und „hintenrum“ mit globalen Tabellen verbunden; <i>damals</i> erschien mir das gradezu natürlich, <i>heute</i> sehe ich leider keine bessere Lösung, die man in C++ realisieren kann (Scala löst dieses Problem mit den Implicits bzw. Givens)
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1685662448009" ID="ID_881674588" MODIFIED="1685662511675" TEXT="andererseits ist Lumiera „bloß“ eine Applikation">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...und nicht das ultimative Medien-Framework!!
|
||||
</p>
|
||||
<p>
|
||||
....also ist es durchaus im Rahmen, wenn es eine fest vereinbarte Hintertür gibt für die Tests
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1685662517358" ID="ID_161203143" MODIFIED="1685676286816">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
es lebe die <b><font face="Monospaced" color="#3d1ca2">DummyPlayConnection</font></b>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#58b681" DESTINATION="ID_161203143" ENDARROW="Default" ENDINCLINATION="79;-62;" ID="Arrow_ID_502535652" SOURCE="ID_201099858" STARTARROW="None" STARTINCLINATION="90;6;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1685676072753" ID="ID_29155074" MODIFIED="1685676082592" TEXT="dort gibt es schon zwei fake-ModelPorts">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676083734" ID="ID_1387602910" MODIFIED="1685676114044" TEXT="nun auch noch zwei korrespondierende DataSink hinzugefügt">
|
||||
<node COLOR="#338800" CREATED="1685809977795" HGAP="-6" ID="ID_479052957" MODIFIED="1685809989039" TEXT="einfacher Test: funktioniert" VSHIFT="21">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1685676098707" ID="ID_970617797" MODIFIED="1685676172210" TEXT="und als Platzhalter: UnimplementedConnection">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
DataSink ist ein lib::Handle<play::OutputSlot::Connection>
|
||||
</p>
|
||||
<p>
|
||||
Also muß es im einfachsten Fall auf eine Subklasse von Connection zeigen; diese füge ich hinzu mit lauter UNIMPLEMENTED stubs
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1790705283" MODIFIED="1684878198471" TEXT="invoke the dispatcher to retrieve the top-level JobTicket">
|
||||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1224963303" MODIFIED="1684878201314" TEXT="expander function to explore prerequisite JobTickets">
|
||||
<icon BUILTIN="full-4"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803059992" ID="ID_1436607523" MODIFIED="1685803066369" TEXT="expander-Funktor(einfach)">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803068234" ID="ID_1458286668" MODIFIED="1685803183999" TEXT="Gruppierung mit Dependent">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803252313" ID="ID_981519455" MODIFIED="1685803288229" TEXT="Problem: Ende des Kind-Levels erkennen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803392203" ID="ID_1347930311" MODIFIED="1685803426832" TEXT="Idee: Level-Shift als positional shift in Expander selber einbauen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1685803432791" ID="ID_612766289" MODIFIED="1685803491700" TEXT="das heißt: die Verklammerung macht der Expander selber">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...denn dieser hat natürlicherweise beide Elemente in der Hand...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1685803493398" ID="ID_312364874" MODIFIED="1685803517871" TEXT="⟹ Folge schrittweise verschobener Paare"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803519291" ID="ID_1625457703" MODIFIED="1685803542875" TEXT="⟹ neue Idee: künstlichen Root einführen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803556486" ID="ID_9551953" MODIFIED="1685804392492" TEXT="der muß vom Basis-Iterator-Level künstlich eingeführt werden">
|
||||
<arrowlink COLOR="#fdfed9" DESTINATION="ID_1049622554" ENDARROW="Default" ENDINCLINATION="-118;8;" ID="Arrow_ID_109489850" STARTARROW="None" STARTINCLINATION="124;-21;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803612926" ID="ID_755957373" MODIFIED="1685803714187" TEXT="damit könnte man nebenbei das Problem der Output-Sink-Steuerung lösen">
|
||||
<arrowlink COLOR="#5f3daf" DESTINATION="ID_87044302" ENDARROW="Default" ENDINCLINATION="265;-32;" ID="Arrow_ID_1548054846" STARTARROW="None" STARTINCLINATION="-44;200;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1332543018" MODIFIED="1684878204163" TEXT="integration: generate a complete sequence of (dummy)Jobs">
|
||||
<arrowlink COLOR="#4d3a6e" DESTINATION="ID_92268538" ENDARROW="Default" ENDINCLINATION="184;0;" ID="Arrow_ID_1841184971" STARTARROW="None" STARTINCLINATION="146;7;"/>
|
||||
|
|
@ -73818,12 +73920,46 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685034304654" ID="ID_187208942" MODIFIED="1685052153799" TEXT="JobPlanning">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685052155282" ID="ID_1374932582" MODIFIED="1685052157494" TEXT="fügt die FrameCoord hinzu">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685052158905" ID="ID_298268641" MODIFIED="1685802456361" TEXT="ist eine State-Facade für den aktuellen Planungs-Stand">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802434530" ID="ID_84580124" MODIFIED="1685802448802" TEXT="fügt die DataSink(Handle) hinzu">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685052158905" ID="ID_298268641" MODIFIED="1685052192794" TEXT="ist eine State-Facade für den aktuellen Planungs-Stand">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685052155282" ID="ID_1374932582" MODIFIED="1685802461544" TEXT="fügt die FrameCoord hinzu">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802570984" ID="ID_1417369009" MODIFIED="1685802579931" TEXT="Daten-Anordnung für Jobs vorbereiten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1685802581055" ID="ID_1626475025" MODIFIED="1685802602595" TEXT="Umbau der Job-Struktur noch nicht gleich">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802605380" ID="ID_1316148159" MODIFIED="1685802617500" TEXT="aber schon mal die benötigten Daten analysieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802625130" ID="ID_148642807" MODIFIED="1685802642496" TEXT="Kernproblem: welche Daten für den Einzelfall">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802655901" ID="ID_554344836" MODIFIED="1685802665981" TEXT="nomineller Zeitpunkt">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802711785" ID="ID_296909810" MODIFIED="1685802724498" TEXT="JobFunctor">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802725228" ID="ID_848236204" MODIFIED="1685802740418" TEXT="Parameter-Paket">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802741818" ID="ID_87044302" MODIFIED="1685803707711" TEXT="DataSink(Handle)">
|
||||
<linktarget COLOR="#5f3daf" DESTINATION="ID_87044302" ENDARROW="Default" ENDINCLINATION="265;-32;" ID="Arrow_ID_1548054846" SOURCE="ID_755957373" STARTARROW="None" STARTINCLINATION="-44;200;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802759365" ID="ID_377618445" MODIFIED="1685802764857" TEXT="InstanceID">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685802968612" ID="ID_733865950" MODIFIED="1685802988724" TEXT="Problem: Variabilität ermöglichen und steuern">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue