Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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)
5 2023, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
19#include "lib/test/run.hpp"
23#include "lib/format-cout.hpp"
24#include "lib/util.hpp"
25
26#include <utility>
27
28using test::Test;
29using std::move;
31
32
33namespace steam {
34namespace engine{
35namespace test {
36
39 using lib::time::Time;
40 using play::Timings;
41
42
43
44
45
46 /***************************************************************/
50 class JobPlanning_test : public Test
51 {
52
53 virtual void
54 run (Arg)
55 {
56 seedRand();
57
61 }
62
63
66 void
68 {
69 MockDispatcher dispatcher;
71 auto [port,sink] = dispatcher.getDummyConnection(1);
72
73 FrameCnt frameNr{5};
74 TimeVar nominalTime{Time{200,0}};
75 size_t portIDX = dispatcher.resolveModelPort (port);
76 JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
77
78 JobPlanning plan{ticket,nominalTime,frameNr};
79 Job job = plan.buildJob();
80
81 CHECK (dispatcher.verify (job, port, sink));
82 }
83
84
85
89 void
91 {
92 MockDispatcher dispatcher;
93 play::Timings timings (FrameRate::PAL, Time{0,0,5});
94 auto [port,sink] = dispatcher.getDummyConnection(1);
95
96 FrameCnt frameNr{5};
97 Time nominalTime{200,0};
98 size_t portIDX = dispatcher.resolveModelPort (port);
99 JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
100
101 JobPlanning plan{ticket,nominalTime,frameNr};
102
103 // the following calculations are expected to happen....
104 Duration latency = ticket.getExpectedRuntime()
105 + timings.engineLatency
106 + timings.outputLatency;
107
108 Offset nominalOffset (timings.getFrameStartAt(0), timings.getFrameStartAt(frameNr));
109 Time expectedDeadline{timings.scheduledDelivery + nominalOffset - latency};
110
111 cout << util::_Fmt{"Frame #%d @ %s\n"
112 "real-time-origin : %s\n"
113 "total latency : %s\n"
114 "deadline : %s"}
115 % frameNr % nominalOffset
116 % timings.scheduledDelivery
117 % latency
118 % plan.determineDeadline(timings)
119 << endl;
120 CHECK (plan.determineDeadline(timings) == expectedDeadline);
121 CHECK (timings.scheduledDelivery == Time(0,0,5) );
122 CHECK (timings.playbackUrgency == play::TIMEBOUND);
123
124 // But when switching form "timebound" to "best effort"...
125 timings.playbackUrgency = play::ASAP;
126 CHECK (Time::ANYTIME == plan.determineDeadline (timings));
127 // ... no deadline is calculated at all
128 }
129
130
131
135 void
137 {
138 MockDispatcher dispatcher{MakeRec() // »master job« for each frame
139 .attrib("runtime", Duration{Time{30,0}})
140 .scope(MakeRec() // a »prerequisite job« on which the »master job« depends
141 .attrib("runtime", Duration{Time{50,0}})
142 .genNode())
143 .genNode()};
144
145 play::Timings timings (FrameRate::PAL, Time{0,0,5});
146 auto [port,sink] = dispatcher.getDummyConnection(1);
147
148 FrameCnt frameNr{5};
149 Time nominalTime{200,0};
150 size_t portIDX = dispatcher.resolveModelPort (port);
151 JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
152 JobTicket& prereq = *(ticket.getPrerequisites()); // pick up the (only) prerequisite
153
154 JobPlanning masterPlan{ticket,nominalTime,frameNr}; // the job plan for the master frame calculation
155 JobPlanning prereqPlan{move(*(masterPlan.buildDependencyPlanning() ))}; // build a plan for calculating the prerequisite
156
157 CHECK (isSameObject(ticket, masterPlan.ticket()));
158 CHECK (isSameObject(prereq, prereqPlan.ticket()));
159 CHECK ( masterPlan.isTopLevel());
160 CHECK (not prereqPlan.isTopLevel());
161
162 Time masterDeadline = masterPlan.determineDeadline (timings);
163 Time prereqDeadline = prereqPlan.determineDeadline (timings);
164
165 // the following relations are expected to hold for the prerequisite....
166 Duration latency = prereq.getExpectedRuntime()
167 + timings.engineLatency; // Note: here only the engine, not the output latency
168
169 Time expectedDeadline{masterDeadline - latency};
170
171 cout << util::_Fmt{"Prerequisite......\n"
172 "master deadline : %s\n"
173 "latency : %s\n"
174 "prereq deadline : %s"}
175 % masterDeadline
176 % latency
177 % prereqDeadline
178 << endl;
179 CHECK (prereqDeadline == expectedDeadline);
180
181 // However, no deadline established for "best effort" rendering...
182 timings.playbackUrgency = play::ASAP;
183 CHECK (Time::ANYTIME == masterPlan.determineDeadline (timings));
184 CHECK (Time::ANYTIME == prereqPlan.determineDeadline (timings));
185 }
186 };
187
188
190 LAUNCHER (JobPlanning_test, "unit engine");
191
192
193
194}}} // namespace steam::engine::test
Mutator && attrib(string const &key, X &&initialiser, ARGS &&...args)
Definition record.hpp:569
Duration is the internal Lumiera time metric.
Framerate specified as frames per second.
static const FrameRate PAL
predefined constant for PAL framerate
Offset measures a distance in time.
a mutable time value, behaving like a plain number, allowing copy and re-accessing
Lumiera's internal time value datatype.
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
View on the execution planning for a single calculation step.
execution plan for pulling a specific exit node.
Duration getExpectedRuntime()
Core operation: guess expected runtime for rendering.
auto getPrerequisites()
Core operation: iterate over the prerequisites, required to carry out a render operation based on thi...
A mocked frame Dispatcher setup without any backing model.
bool verify(Job const &job, ModelPort const &port, play::DataSink const &sink)
Test support: verify the given Job is consistent with this Dispatcher.
size_t resolveModelPort(ModelPort modelPort) override
translate a generic ModelPort spec into the specific index number applicable at the Timeline referred...
play::test::DummyOutputLink getDummyConnection(uint index)
The faked builder/playback setup provides some preconfigured ModelPort and corresponding DataSink han...
JobTicket & getJobTicketFor(size_t portIDX, TimeValue nominalTime) override
Core Dispatcher operation: locate the appropriate Segment and retrieve/derive a »blueprint« for rende...
Generic frame timing specification.
Definition timings.hpp:87
Abstract Base Class for all testcases.
Definition run.hpp:54
void seedRand()
draw a new random seed from a common nucleus, and re-seed the default-Gen.
Definition suite.cpp:211
A front-end for using printf-style formatting.
Individual frame rendering task, forwarding to a closure.
Definition job.h:276
Automatically use custom string conversion in C++ stream output.
Mock data structures to support implementation testing of render job planning and frame dispatch.
Steam-Layer implementation namespace root.
Test runner and basic definitions for tests.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
a family of time value like entities and their relationships.
How to define a timing specification or constraint.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...