diff --git a/src/proc/engine/buffhandle.hpp b/src/proc/engine/buffhandle.hpp index 40a5d1996..c2602cc96 100644 --- a/src/proc/engine/buffhandle.hpp +++ b/src/proc/engine/buffhandle.hpp @@ -41,6 +41,7 @@ #include "lib/error.hpp" #include "lib/streamtype.hpp" +#include "lib/bool-checkable.hpp" namespace engine { @@ -52,22 +53,36 @@ namespace engine { * The real buffer pointer can be retrieved by dereferencing this smart-handle class. */ struct BuffHandle + : lib::BoolCheckable { typedef lumiera::StreamType::ImplFacade::DataBuffer Buff; typedef Buff* PBuff; PBuff - operator->() const + operator->() const { return pBuffer_; } Buff& - operator* () const + operator* () const { ENSURE (pBuffer_); return *pBuffer_; } + bool + isValid() const + { + return pBuffer_; + } + + + //////////////////////TODO: the whole logic how to create a BuffHandle needs to be solved in a more clever way. --> Ticket 249 + BuffHandle() + : pBuffer_(0), + sourceID_(0) + { } + private: PBuff pBuffer_; long sourceID_; diff --git a/src/proc/engine/nodeoperation.hpp b/src/proc/engine/nodeoperation.hpp index d3a36067d..838b9a31f 100644 --- a/src/proc/engine/nodeoperation.hpp +++ b/src/proc/engine/nodeoperation.hpp @@ -203,6 +203,7 @@ namespace config { } }; + template struct FeedCache : NEXT { @@ -219,6 +220,7 @@ namespace config { } }; + template struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor?? { ///////////////// this would require BuffHandle to be a smart ref.... diff --git a/src/proc/engine/nodewiring.cpp b/src/proc/engine/nodewiring.cpp index 84e52c4be..41b212af5 100644 --- a/src/proc/engine/nodewiring.cpp +++ b/src/proc/engine/nodewiring.cpp @@ -133,7 +133,7 @@ namespace engine { /** create and configure a concrete wiring descriptor to tie * a ProcNode to its predecessor nodes. This includes selecting - * the actual StateProxy type, configuring it out of some operation + * the actual StateAdapter type, configuring it out of some operation * control templates (policy classes). Compiling this operator function * actually drives the necessary template instantiations for all cases * encountered while building the node network. diff --git a/src/proc/engine/nodewiring.hpp b/src/proc/engine/nodewiring.hpp index 160625205..354b5d0fa 100644 --- a/src/proc/engine/nodewiring.hpp +++ b/src/proc/engine/nodewiring.hpp @@ -83,10 +83,7 @@ namespace engine { setup.makeInDescriptor(), setup.resolveProcessingFunction(), setup.createNodeID()) - { - nrO = out.size(); - nrI = in.size(); - } + { } friend class WiringFactory; diff --git a/src/proc/engine/procnode.hpp b/src/proc/engine/procnode.hpp index 2d95bd7cb..000666d96 100644 --- a/src/proc/engine/procnode.hpp +++ b/src/proc/engine/procnode.hpp @@ -90,7 +90,10 @@ namespace engine { : out(o), in(i), procFunction(pFunc), nodeID(nID) - { } + { + nrO = out.size(); + nrI = in.size(); + } /** the wiring-dependent part of the node operation. * Includes the creation of a one-way state object on the stack @@ -129,6 +132,9 @@ namespace engine { public: + /** output channel count */ + uint nrO() { return wiringConfig_.nrO; } + /** Engine Core operation: render and pull output from this node. * On return, currentProcess will hold onto output buffer(s) * containing the calculated result frames. In case this node diff --git a/src/proc/engine/render-invocation.cpp b/src/proc/engine/render-invocation.cpp index 0fae10cfe..abd0ce338 100644 --- a/src/proc/engine/render-invocation.cpp +++ b/src/proc/engine/render-invocation.cpp @@ -22,6 +22,8 @@ #include "proc/engine/render-invocation.hpp" +#include "proc/engine/stateproxy.hpp" + namespace engine { @@ -35,51 +37,21 @@ namespace engine { // using mobject::session::Effect; - /** @internal */ + /** @note this builds a one-way off invocation state context + * and then forwards the call; this may or may not cause + * actual calculations, depending on the cache. + * @todo for real use within the engine, the pull()-call should be + * dispatched through the scheduler; of course then the call semantics + * would be completely different. Maybe this invocation will be test only? + */ BuffHandle - RenderInvocation::allocateBuffer (BufferDescriptor const&) + RenderInvocation::operator[] (size_t channel) { - UNIMPLEMENTED ("allocate a suitable buffer to hold a frame of the denoted type"); - } - - - - void - RenderInvocation::releaseBuffer (BuffHandle& bh) - { - UNIMPLEMENTED ("free a buffer"); - } - - - - BuffHandle - RenderInvocation::fetch (FrameID const& fID) - { - UNIMPLEMENTED ("fetch a buffer with input data"); - } - - - - void - RenderInvocation::is_calculated (BuffHandle const& bh) - { - UNIMPLEMENTED ("declare a buffer as fully calculated and done"); - } - - - - FrameID const& - RenderInvocation::genFrameID (NodeID const&, uint chanNo) - { - UNIMPLEMENTED ("derive/generate an ID to denote this specific fame+Node position in the graph"); - } - - - - BuffTableStorage& - RenderInvocation::getBuffTableStorage() /////////////TODO need somehow to denote the specific storage requirements - { - UNIMPLEMENTED ("allocate a chunk of storage suitable for holding the buffer pointer tables"); + REQUIRE (theNode_); + REQUIRE (channel < size()); + + StateProxy invocationState; + return theNode_->pull(invocationState, channel); } diff --git a/src/proc/engine/render-invocation.hpp b/src/proc/engine/render-invocation.hpp index d26d87c4f..2138169cf 100644 --- a/src/proc/engine/render-invocation.hpp +++ b/src/proc/engine/render-invocation.hpp @@ -34,9 +34,9 @@ #define ENGINE_RENDER_INVOCATION_H -#include "proc/state.hpp" -//#include "proc/engine/procnode.hpp" -//#include "proc/engine/buffhandle.hpp" +//#include "proc/state.hpp" +#include "proc/engine/procnode.hpp" +#include "proc/engine/buffhandle.hpp" //#include "proc/engine/bufftable.hpp" @@ -49,34 +49,23 @@ namespace engine { * TODO: type comment */ class RenderInvocation - : public State { - protected: -// State& parent_; -// State& current_; + ProcNode* theNode_; - RenderInvocation() - { } + public: + RenderInvocation (ProcNode* exitNode) + : theNode_(exitNode) + { + REQUIRE (theNode_); + } + + size_t size() { return theNode_->nrO(); } + + /** pull calculated data from the N-th node output channel */ + BuffHandle operator[] (size_t channel); - private: /* === top-level implementation of the State interface === */ - - BuffHandle allocateBuffer (BufferDescriptor const&); - - void releaseBuffer (BuffHandle& bh); - - BuffHandle fetch (FrameID const& fID); - - void is_calculated (BuffHandle const& bh); - - FrameID const& genFrameID (NodeID const&, uint chanNo); - - BuffTableStorage& getBuffTableStorage(); - - virtual State& getCurrentImplementation () { return *this; } - - }; ///////////////////////////////////TODO: currently just fleshing out the API diff --git a/src/proc/engine/stateproxy.cpp b/src/proc/engine/stateproxy.cpp index 6e2566d3e..c8a07a429 100644 --- a/src/proc/engine/stateproxy.cpp +++ b/src/proc/engine/stateproxy.cpp @@ -25,8 +25,63 @@ namespace engine { - /** */ + namespace { // Details... + + + } // (END) Details... + + +// using mobject::Placement; +// using mobject::session::Effect; + + + /** @internal */ + BuffHandle + StateProxy::allocateBuffer (BufferDescriptor const&) + { + UNIMPLEMENTED ("allocate a suitable buffer to hold a frame of the denoted type"); + } + + + + void + StateProxy::releaseBuffer (BuffHandle& bh) + { + UNIMPLEMENTED ("free a buffer"); + } + + + + BuffHandle + StateProxy::fetch (FrameID const& fID) + { + UNIMPLEMENTED ("fetch a buffer with input data"); + } + + + + void + StateProxy::is_calculated (BuffHandle const& bh) + { + UNIMPLEMENTED ("declare a buffer as fully calculated and done"); + } + + + + FrameID const& + StateProxy::genFrameID (NodeID const&, uint chanNo) + { + UNIMPLEMENTED ("derive/generate an ID to denote this specific fame+Node position in the graph"); + } + + + + BuffTableStorage& + StateProxy::getBuffTableStorage() /////////////TODO need somehow to denote the specific storage requirements + { + UNIMPLEMENTED ("allocate a chunk of storage suitable for holding the buffer pointer tables"); + } } // namespace engine diff --git a/src/proc/engine/stateproxy.hpp b/src/proc/engine/stateproxy.hpp index ff7d107d3..50e961ca1 100644 --- a/src/proc/engine/stateproxy.hpp +++ b/src/proc/engine/stateproxy.hpp @@ -35,7 +35,21 @@ namespace engine { class StateProxy : public proc_interface::State { - protected: + + private: /* === top-level implementation of the State interface === */ + + BuffHandle allocateBuffer (BufferDescriptor const&); + + void releaseBuffer (BuffHandle& bh); + + BuffHandle fetch (FrameID const& fID); + + void is_calculated (BuffHandle const& bh); + + FrameID const& genFrameID (NodeID const&, uint chanNo); + + BuffTableStorage& getBuffTableStorage(); + virtual State& getCurrentImplementation () { return *this; } }; diff --git a/tests/components/proc/engine/node-basic-test.cpp b/tests/components/proc/engine/node-basic-test.cpp index bf36e3bf6..3c1aee4d7 100644 --- a/tests/components/proc/engine/node-basic-test.cpp +++ b/tests/components/proc/engine/node-basic-test.cpp @@ -26,7 +26,8 @@ //#include "lib/util.hpp" #include "proc/engine/nodefactory.hpp" #include "proc/engine/nodewiring.hpp" -#include "proc/engine/render-invocation.hpp" +#include "proc/engine/stateproxy.hpp" +#include "proc/engine/buffhandle.hpp" #include "proc/mobject/session/effect.hpp" #include "lib/allocationcluster.hpp" @@ -54,7 +55,7 @@ namespace test { * happening in correct order. */ class TestContext - : public RenderInvocation + : public StateProxy { //////////////TODO: facility to verify the right access operations get called @@ -83,8 +84,9 @@ namespace test { ASSERT (pNode); TestContext simulatedInvocation; - pNode->pull(simulatedInvocation, 0); + BuffHandle result = pNode->pull(simulatedInvocation, 0); + ASSERT (result); // ASSERT we got calculated data in the result buffer } }; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 0e51d4faa..ef9aa91a0 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2237,12 +2237,12 @@ So, when creating a clip out of such a compound media asset, the clip has to be In the most general case the render network may be just a DAG (not just a tree). Especially, multiple exit points may lead down to the same node, and following each of this possible paths the node may be at a different depth on each. This rules out a simple counter starting from the exit level, leaving us with the possibility of either employing a rather convoluted addressing scheme or using arbitrary ID numbers.{{red{...which is what we do for now}}} -
+
The [[nodes|ProcNode]] are wired to form a "Directed Acyclic Graph"; each node knows its predecessor(s), but not its successor(s).  The RenderProcess is organized according to the ''pull principle'', thus we find an operation {{{pull()}}} at the core of this process. There is no such thing as an "engine object" calling nodes iteratively or table driven, rather, the nodes themselves issue recursive calls to their predecessor(s). For this to work, we need the nodes to adhere to a specific protocol:
 # Node is pulled, with a StateProxy object as parameter (encapsulating the access to the frames or buffers)
 # Node may now access current parameter values, using the state accessible via the StateProxy
 # using it's //input-output and wiring descriptor,// the Node creates a StateAdapter wrapping the StateProxy for allocating buffers and accessing the required input
-# StateAdapter first tries to get the output frames from the Cache in the Backend. In case of failure, a {{{process()}}} call is prepared by generating {{{pull()}}} call(s) for the input
+# StateAdapter might first try to get the output frames from the Cache in the Backend. In case of failure, a {{{process()}}} call is prepared by generating {{{pull()}}} call(s) for the input
 # as late as possible, typically on return, these recursive pull-calls have allocated a buffer containing the input data.
 # when input is ready prior to the {{{process()}}} call, output buffers will be allocated, either from the cache, or (if not caching) from the "parent" StateAdapter up the callstack.
 # after all buffers are available, the StateAdapter issues the {{{process()}}} call back to the originating node, which now may dereference the frame pointers and do its calculations