Lumiera  0.pre.03
»edit your freedom«
job-planning-test.cpp
Go to the documentation of this file.
1 /*
2  JobPlanning(Test) - data evaluation for frame job creation
3 
4  Copyright (C) Lumiera.org
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
30 #include "steam/play/timings.hpp"
31 #include "lib/time/timevalue.hpp"
32 #include "lib/format-cout.hpp"
33 #include "lib/util.hpp"
34 
35 #include <utility>
36 
37 using test::Test;
38 using std::move;
39 using util::isSameObject;
40 
41 
42 namespace steam {
43 namespace engine{
44 namespace test {
45 
47  using lib::time::Offset;
48  using lib::time::Time;
49  using play::Timings;
50 
51 
52 
53 
54 
55  /***************************************************************/
59  class JobPlanning_test : public Test
60  {
61 
62  virtual void
63  run (Arg)
64  {
65  simpleUsage();
68  }
69 
70 
73  void
75  {
76  MockDispatcher dispatcher;
77  play::Timings timings (FrameRate::PAL);
78  auto [port,sink] = dispatcher.getDummyConnection(1);
79 
80  FrameCnt frameNr{5};
81  TimeVar nominalTime{Time{200,0}};
82  size_t portIDX = dispatcher.resolveModelPort (port);
83  JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
84 
85  JobPlanning plan{ticket,nominalTime,frameNr};
86  Job job = plan.buildJob();
87 
88  CHECK (dispatcher.verify (job, port, sink));
89  }
90 
91 
92 
96  void
98  {
99  MockDispatcher dispatcher;
100  play::Timings timings (FrameRate::PAL, Time{0,0,5});
101  auto [port,sink] = dispatcher.getDummyConnection(1);
102 
103  FrameCnt frameNr{5};
104  Time nominalTime{200,0};
105  size_t portIDX = dispatcher.resolveModelPort (port);
106  JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
107 
108  JobPlanning plan{ticket,nominalTime,frameNr};
109 
110  // the following calculations are expected to happen....
111  Duration latency = ticket.getExpectedRuntime()
112  + timings.engineLatency
113  + timings.outputLatency;
114 
115  Offset nominalOffset (timings.getFrameStartAt(0), timings.getFrameStartAt(frameNr));
116  Time expectedDeadline{timings.scheduledDelivery + nominalOffset - latency};
117 
118  cout << util::_Fmt{"Frame #%d @ %s\n"
119  "real-time-origin : %s\n"
120  "total latency : %s\n"
121  "deadline : %s"}
122  % frameNr % nominalOffset
123  % timings.scheduledDelivery
124  % latency
125  % plan.determineDeadline(timings)
126  << endl;
127  CHECK (plan.determineDeadline(timings) == expectedDeadline);
128  CHECK (timings.scheduledDelivery == Time(0,0,5) );
129  CHECK (timings.playbackUrgency == play::TIMEBOUND);
130 
131  // But when switching form "timebound" to "best effort"...
132  timings.playbackUrgency = play::ASAP;
133  CHECK (Time::ANYTIME == plan.determineDeadline (timings));
134  // ... no deadline is calculated at all
135  }
136 
137 
138 
142  void
144  {
145  MockDispatcher dispatcher{MakeRec() // »master job« for each frame
146  .attrib("runtime", Duration{Time{30,0}})
147  .scope(MakeRec() // a »prerequisite job« on which the »master job« depends
148  .attrib("runtime", Duration{Time{50,0}})
149  .genNode())
150  .genNode()};
151 
152  play::Timings timings (FrameRate::PAL, Time{0,0,5});
153  auto [port,sink] = dispatcher.getDummyConnection(1);
154 
155  FrameCnt frameNr{5};
156  Time nominalTime{200,0};
157  size_t portIDX = dispatcher.resolveModelPort (port);
158  JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
159  JobTicket& prereq = *(ticket.getPrerequisites()); // pick up the (only) prerequisite
160 
161  JobPlanning masterPlan{ticket,nominalTime,frameNr}; // the job plan for the master frame calculation
162  JobPlanning prereqPlan{move(*(masterPlan.buildDependencyPlanning() ))}; // build a plan for calculating the prerequisite
163 
164  CHECK (isSameObject(ticket, masterPlan.ticket()));
165  CHECK (isSameObject(prereq, prereqPlan.ticket()));
166  CHECK ( masterPlan.isTopLevel());
167  CHECK (not prereqPlan.isTopLevel());
168 
169  Time masterDeadline = masterPlan.determineDeadline (timings);
170  Time prereqDeadline = prereqPlan.determineDeadline (timings);
171 
172  // the following relations are expected to hold for the prerequisite....
173  Duration latency = prereq.getExpectedRuntime()
174  + timings.engineLatency; // Note: here only the engine, not the output latency
175 
176  Time expectedDeadline{masterDeadline - latency};
177 
178  cout << util::_Fmt{"Prerequisite......\n"
179  "master deadline : %s\n"
180  "latency : %s\n"
181  "prereq deadline : %s"}
182  % masterDeadline
183  % latency
184  % prereqDeadline
185  << endl;
186  CHECK (prereqDeadline == expectedDeadline);
187 
188  // However, no deadline established for "best effort" rendering...
189  timings.playbackUrgency = play::ASAP;
190  CHECK (Time::ANYTIME == masterPlan.determineDeadline (timings));
191  CHECK (Time::ANYTIME == prereqPlan.determineDeadline (timings));
192  }
193  };
194 
195 
197  LAUNCHER (JobPlanning_test, "unit engine");
198 
199 
200 
201 }}} // namespace steam::engine::test
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:322
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:241
size_t resolveModelPort(ModelPort modelPort) override
translate a generic ModelPort spec into the specific index number applicable at the Timeline referred...
Mock data structures to support implementation testing of render job planning and frame dispatch...
Automatically use custom string conversion in C++ stream output.
JobTicket & getJobTicketFor(size_t portIDX, TimeValue nominalTime) override
Core Dispatcher operation: locate the appropriate Segment and retrieve/derive a »blueprint« for rende...
Definition: run.hpp:49
Framerate specified as frames per second.
Definition: timevalue.hpp:664
Generic frame timing specification.
Definition: timings.hpp:95
A mocked frame Dispatcher setup without any backing model.
play::test::DummyOutputLink getDummyConnection(uint index)
The faked builder/playback setup provides some preconfigured ModelPort and corresponding DataSink han...
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:308
Abstract Base Class for all testcases.
Definition: run.hpp:62
bool verify(Job const &job, ModelPort const &port, play::DataSink const &sink)
Test support: verify the given Job is consistent with this Dispatcher.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Offset measures a distance in time.
Definition: timevalue.hpp:367
How to define a timing specification or constraint.
View on the execution planning for a single calculation step.
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:477
Individual frame rendering task, forwarding to a closure.
Definition: job.h:277
a family of time value like entities and their relationships.
auto getPrerequisites()
Core operation: iterate over the prerequisites, required to carry out a render operation based on thi...
Definition: job-ticket.hpp:164
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:680
execution plan for pulling a specific exit node.
Definition: job-ticket.hpp:87
Duration getExpectedRuntime()
Core operation: guess expected runtime for rendering.
Definition: job-ticket.cpp:102
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372