/* JobTicket - execution plan for render jobs Copyright (C) 2012, Hermann Vosseler   **Lumiera** 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. See the file COPYING for further details. * *****************************************************************/ /** @file job-ticket.cpp ** Implementation details of preparing and performing job invocations. ** ** @todo WIP-WIP-WIP 3/2012 ** @see Job ** */ #include "steam/engine/job-ticket.hpp" #include "vault/gear/nop-job-functor.hpp" #include "lib/hash-combine.hpp" #include "lib/depend.hpp" #include "lib/util.hpp" namespace steam { namespace engine { using vault::gear::Job; using vault::gear::JobClosure; using lib::HashVal; using lib::unConst; using lib::time::FSecs; namespace { // Details... lib::Depend nopFunctor; /* ======== hard wired =================*/ const FSecs JOB_MINIMUM_RUNTIME{1,1000}; } // (END) Details... /** special »do nothing« JobTicket marker */ JobTicket JobTicket::NOP{}; ////////////////////////////////////////////////////////////////////TICKET #725 : do we actually need that for the final data structure? JobTicket::JobTicket() : provision_{nopFunctor(), ExitNode::NIL} { } /** * Generate a render job to invoke the render network configuration * as defined and backing this JobTicket. The generated job descriptor record * will include a specific InvocationInstanceID, which factors in the nominal * frame time, but also the specific backing render configuration. * The actual implementation of the job functionality will be delegated * to the JobClosure, which was set up for this Segment and JobTiket * after the last Builder run created this part of the render network. */ Job JobTicket::createJobFor (Time nominalTime) { if (this->empty()) { //////////////////////////////////////////////////////////////////////////////////TICKET #1296 : can we get away just with a do-nothing functor? return Job(nopFunctor(), InvocationInstanceID(), nominalTime); } else { REQUIRE (this->isValid(), "Attempt to generate render job for incomplete or unspecified render plan."); JobClosure& functor = static_cast (unConst(provision_.jobFunctor)); ////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs) InvocationInstanceID invoKey{timeHash (nominalTime, provision_.invocationSeed)}; return Job(functor, invoKey, nominalTime); } } /** * Use observed runtime values of past job invocations to guess a sensible bound * for the calculation time to expect for next invocation. * @todo 6/2023 placeholder implementation with hard wired values in ExitNode */ Duration JobTicket::getExpectedRuntime() { if (this->empty()) return Duration{JOB_MINIMUM_RUNTIME}; else { REQUIRE (isValid(), "Attempt to determine timings for incomplete or unspecified render plan."); return provision_.exitNode.getUpperBoundRuntime(); } } /** * Tag the precomputed invocation ID with the nominal frame time */ InvocationInstanceID JobTicket::timeHash (Time nominalTime, InvocationInstanceID const& seed) { InvocationInstanceID res{seed}; HashVal timeMark = res.part.t; lib::hash::combine (timeMark, hash_value (nominalTime)); res.part.t = timeMark; return res; } /** * Helper for tests: verify the given invocation parameters match this JobTicket. */ bool JobTicket::verifyInstance (JobFunctor& functor, InvocationInstanceID const& invoKey, Time nominalTime) const { return util::isSameObject (provision_.jobFunctor, functor) and invoKey == timeHash (nominalTime, provision_.invocationSeed); } }} // namespace steam::engine