diff --git a/src/steam/engine/connectivity-obsolete.hpp b/src/steam/engine/connectivity-obsolete.hpp new file mode 100644 index 000000000..7b1ca684b --- /dev/null +++ b/src/steam/engine/connectivity-obsolete.hpp @@ -0,0 +1,218 @@ +/* + PROC-NODE.hpp - Key abstraction of the Render Engine: a Processing Node + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file connectivity-obsolete.hpp + ** @deprecated 2024 old variant of render node definition stashed away to keep other obsolete code buildable. + ** + ** Actually, there are three different interfaces to consider + ** - the ProcNode#pull is the invocation interface. It is function-call style + ** - the builder interface, comprised by the NodeFactory and the WiringFactory. + ** - the actual processing function is supposed to be a C function and will be + ** hooked up within a thin wrapper. + ** + ** By using the builder interface, concrete node and wiring descriptor classes are created, + ** based on some templates. These concrete classes form the "glue" to tie the node network + ** together and contain much of the operation behaviour in a hard wired fashion. + ** + ** @todo WIP-WIP-WIP 2024 delete this file!!!! + ** + ** @see nodefactory.hpp + ** @see operationpoint.hpp + */ + +#ifndef STEAM_ENGINE_CONNECTIVITY_OBSOLETE_H +#define STEAM_ENGINE_CONNECTIVITY_OBSOLETE_H + +#ifdef STEAM_ENGINE_PROC_NODE_H + #error "can not include both the old and new Render Node Connectivity scheme" +#endif + +#include "lib/error.hpp" +#include "steam/common.hpp" +#include "steam/asset/proc.hpp" +#include "steam/mobject/parameter.hpp" +#include "steam/engine/state-closure-obsolete.hpp" /////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation +#include "steam/engine/channel-descriptor.hpp" +#include "steam/engine/turnout-system.hpp" +#include "lib/frameid.hpp" +#include "lib/ref-array.hpp" + +#include + + + +namespace steam { +namespace engine { + + using std::vector; + using lumiera::NodeID; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + class ProcNode; + typedef ProcNode* PNode; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + class Port + { + public: + virtual ~Port(); ///< this is an interface + + virtual TurnoutSystem enactTurnout() =0; + }; + + /** + * Interface: Description of the input and output ports, + * processing function and predecessor nodes for a given ProcNode. + * + * @todo the design of this part is messy in several respects. + * Basically, its left-over from a first prototypical implementation from 2008 + * As of 1/2012, we're re-shaping that engine interface and invocation with a top-down approach, + * starting from the player. Anyhow, you can expect the basic setup to remain as-is: there will + * be a ProcNode and a Connectivity descriptor, telling how it's connected to its predecessors, + * and defining how the Node is supposed to operate + * + * @todo WIP-WIP-WIP 2024 Node-Invocation is reworked from ground up for the »Playback Vertical Slice« + */ + class Connectivity + { + public: /* === public information record describing the node graph === */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + uint nrO; + uint nrI; + + lib::RefArray& out; + lib::RefArray& in; + + typedef asset::Proc::ProcFunc ProcFunc; + + ProcFunc* procFunction; + + NodeID const& nodeID; + + virtual ~Connectivity() {} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + protected: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + Connectivity (lib::RefArray& o, + lib::RefArray& i, + ProcFunc pFunc, NodeID const& nID) + : out(o), in(i), + procFunction(pFunc), + nodeID(nID) + { + nrO = out.size(); + nrI = in.size(); + } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + /* ==== strategy API for configuring the node operation ==== */ + + friend class ProcNode; /////////////////////////////////TODO 1/12 : wouldn't it be better to extract that API into a distinct strategy? + + /** the wiring-dependent part of the node operation. + * Includes the creation of a one-way state object on the stack + * holding the actual buffer pointers and issuing the recursive pull() calls + * @see NodeWiring#callDown default implementation + */ + virtual BuffHandle + callDown (StateClosure_OBSOLETE& currentProcess, uint requiredOutputNr) const =0; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + }; + + + + + /** + * Key abstraction of the Render Engine: A Data processing Node + * + * @todo it's not clear as of 9/09 if ProcNode shall be an ABC/Interface + * It might be used as ABC (as was the original intention) when implementing + * several query/information functions. In that case, the ctor will become protected. + * The alternative would be to push down these information-retrieval part into a + * configurable element within Connectivity, in which case we even might drop + * ProcNode as a frontend entirely. + * @todo WIP-WIP-WIP 2024 Node-Invocation is reworked from ground up for the »Playback Vertical Slice« + */ + class ProcNode + : util::NonCopyable + { + typedef mobject::Parameter Param; //////TODO: just a placeholder for automation as of 6/2008 + vector params; + + const Connectivity& wiringConfig_; + + public: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + ProcNode (Connectivity const& wd) + : wiringConfig_(wd) + { } + + virtual ~ProcNode() {}; /////////////////////////TODO: do we still intend to build a hierarchy below ProcNode??? +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + + public: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + bool isValid() const; + + /** output channel count */ + uint nrO() { return wiringConfig_.nrO; } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + + /** 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 + * calculates a multichannel output, only one channel can be + * retrieved by such a \c pull() call, but you can expect data + * of the other channels to be processed and fed to cache. + * @param currentProcess the current processing state for + * managing buffers and accessing current parameter values + * @param requestedOutputNr the output channel requested + * (in case this node delivers more than one output channel) + * @return handle to the buffer containing the calculated result. + */ + BuffHandle + pull (StateClosure_OBSOLETE& currentProcess, uint requestedOutputNr=0) const + { + return this->wiringConfig_.callDown (currentProcess, requestedOutputNr); + } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + + }; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + inline bool + ProcNode::isValid() const + { + UNIMPLEMENTED ("ProcNode validity self-check"); + return false; //////////////////////////TODO + } + + +}} // namespace steam::engine +#endif /*STEAM_ENGINE_CONNECTIVITY_OBSOLETE_H*/ diff --git a/src/steam/engine/feed-manifold-obsolete.hpp b/src/steam/engine/feed-manifold-obsolete.hpp new file mode 100644 index 000000000..569816856 --- /dev/null +++ b/src/steam/engine/feed-manifold-obsolete.hpp @@ -0,0 +1,195 @@ +/* + FEED-MANIFOLD.hpp - data feed connection system for render nodes + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + 2023, Hermann Vosseler + + This program 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file feed-manifold-obsolete.hpp + ** @todo staled since 2009, picked up in 2024 in an attempt to finish the node invocation. + ** deprecated 2024 this file is a dead-end! It is retained in tree to keep other obsolete code buildable + ** @see nodeinvocation.hpp + */ + + +#ifndef ENGINE_FEED_MANIFOLD_OBSOLETE_H +#define ENGINE_FEED_MANIFOLD_OBSOLETE_H + + +#include "lib/error.hpp" +#include "lib/nocopy.hpp" +#include "steam/engine/channel-descriptor.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO this is a dead end +#include "steam/engine/connectivity-obsolete.hpp" + +#include +#include + + +////////////////////////////////TICKET #826 will be reworked alltogether + +namespace steam { +namespace engine { + + using std::pair; + using std::vector; + + + /** + * Obsolete, to be rewritten /////TICKET #826 + * + * Tables of buffer handles and corresponding dereferenced buffer pointers. + * Used within the invocation of a processing node to calculate data. + * The tables are further differentiated into input data buffers and output + * data buffers. The tables are supposed to be implemented as bare "C" arrays, + * thus the array of real buffer pointers can be fed directly to the + * processing function of the respective node. + * + * @todo this whole design is a first attempt and rather clumsy. It should be reworked + * to use a single contiguous memory area and just layer the object structure on top + * (by using placement new). Yet the idea of an stack-like organisation should be retained + */ + struct FeedManifold ///////////////////////////////////OOO rename into FeedManifold + { + typedef BuffHandle * PHa; + typedef BuffHandle::PBuff * PBu; + typedef pair Chunk; + + PHa outHandle; + PHa inHandle; + PBu outBuff; + PBu inBuff; + }; + + class BufferDescriptor; + + /** Obsolete, to be rewritten /////TICKET #826 */ + class BuffTableStorage + { + /////////////////////////////////////////////////////////////////////////TICKET #826 need to be reworked entirely + /** just a placeholder to decouple the existing code + * from the reworked BuffHandle logic. The existing + * code in turn will be reworked rather fundamentally + */ + struct BuffHaXXXX + : BuffHandle + { + BuffHaXXXX() : BuffHandle(just_satisfy_the_compiler()) { /* wont work ever */ } + static BufferDescriptor const& + just_satisfy_the_compiler() { } + }; + + ////////////////////////////////////TICKET #825 should be backed by mpool and integrated with node invocation + vector hTab_; + vector pTab_; + size_t level_; + + public: + BuffTableStorage (const size_t maxSiz) + : hTab_(maxSiz), + pTab_(maxSiz), + level_(0) + { } + + ~BuffTableStorage() { ASSERT (0==level_, "buffer management logic broken."); } + + protected: + + friend class BuffTableChunk; + + /** allocate the given number of slots + * starting at current level to be used + * by the newly created BuffTableChunk + */ + FeedManifold::Chunk + claim (uint slots) + { + ASSERT (pTab_.size() == hTab_.size()); + REQUIRE (level_+slots <= hTab_.size()); + + size_t prev_level (level_); + level_ += slots; + return std::make_pair (&hTab_[prev_level], + &pTab_[prev_level]); + } + + void + release (uint slots) + { + ASSERT (slots <= level_); + REQUIRE (level_ <= hTab_.size()); + REQUIRE (level_ <= pTab_.size()); + + level_ -= slots; + } + + bool + level_check (FeedManifold::Chunk& prev_level) + { + return prev_level.first == &hTab_[level_] + && prev_level.second == &pTab_[level_]; + } + }; + + + /** Obsolete, to be rewritten /////TICKET #826 + * to be allocated on the stack while evaluating a ProcNode#pull() call. + * The "current" State (StateProxy) maintains a BuffTableStorage (=pool), + * which can be used to crate such chunks. The claiming and releasing of + * slots in the BuffTableStorage is automatically tied to BuffTableChunk + * object's lifecycle. + */ + class BuffTableChunk + : public FeedManifold, + util::NonCopyable + { + const uint siz_; + FeedManifold::Chunk tab_; + BuffTableStorage& sto_; + + public: + BuffTableChunk (Connectivity const& wd, BuffTableStorage& storage) + : siz_(wd.nrI + wd.nrO), + tab_(storage.claim (siz_)), + sto_(storage) + { + const uint nrO(wd.nrO); + + // Setup the publicly visible table locations + this->outHandle = &tab_.first[ 0 ]; + this->inHandle = &tab_.first[nrO]; + this->outBuff = &tab_.second[ 0 ]; + this->inBuff = &tab_.second[nrO]; + } + + ~BuffTableChunk () + { + sto_.release (siz_); + ASSERT ( sto_.level_check (tab_), + "buffer management logic broken."); + } + }; + + + + + +}} // namespace steam::engine +#endif /*ENGINE_FEED_MANIFOLD_OBSOLETE_H*/ diff --git a/src/steam/engine/feed-manifold.hpp b/src/steam/engine/feed-manifold.hpp index f4631bf19..33af4ff4a 100644 --- a/src/steam/engine/feed-manifold.hpp +++ b/src/steam/engine/feed-manifold.hpp @@ -65,7 +65,7 @@ namespace engine { * to use a single contiguous memory area and just layer the object structure on top * (by using placement new). Yet the idea of an stack-like organisation should be retained */ - struct FeedManifold ///////////////////////////////////OOO rename into FeedManifold + struct FeedManifold { typedef BuffHandle * PHa; typedef BuffHandle::PBuff * PBu; @@ -77,6 +77,7 @@ namespace engine { PBu inBuff; }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : presumably obsolete class BufferDescriptor; /** Obsolete, to be rewritten /////TICKET #826 */ @@ -185,7 +186,7 @@ namespace engine { "buffer management logic broken."); } }; - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : (End)presumably obsolete diff --git a/src/steam/engine/node-factory.cpp b/src/steam/engine/node-factory.cpp index a5e053814..ee45114cc 100644 --- a/src/steam/engine/node-factory.cpp +++ b/src/steam/engine/node-factory.cpp @@ -35,7 +35,7 @@ #include "steam/mobject/session/effect.hpp" #include "lib/allocation-cluster.hpp" -#include "steam/engine/nodewiring.hpp" +//#include "steam/engine/nodewiring-obsolete.hpp" namespace steam { namespace engine { @@ -62,12 +62,15 @@ namespace engine { PNode NodeFactory::operator() (Placement const& effect, WiringSituation& intendedWiring) { +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation intendedWiring.resolveProcessor(effect->getProcAsset()); Connectivity& wiring = wiringFac_(intendedWiring); ProcNode& newNode = alloc_.create (wiring); ENSURE (newNode.isValid()); return &newNode; +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation + UNIMPLEMENTED ("Node Factory for reworked Render Node Connectivity"); } diff --git a/src/steam/engine/node-factory.hpp b/src/steam/engine/node-factory.hpp index 71d8561fc..c43ad94e3 100644 --- a/src/steam/engine/node-factory.hpp +++ b/src/steam/engine/node-factory.hpp @@ -35,7 +35,7 @@ #include "steam/engine/proc-node.hpp" #include "steam/mobject/placement.hpp" -#include "steam/engine/nodewiring.hpp" +//#include "steam/engine/nodewiring-obsolete.hpp" /////////////////////////////////////////////////////////TICKET #1367 : Adapt to rework of Node Invocation ////////////////////////////////////TODO: make inclusions / forward definitions a bit more orthogonal.... @@ -72,12 +72,16 @@ namespace engine { class NodeFactory { AllocationCluster& alloc_; +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation WiringFactory wiringFac_; +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation public: NodeFactory (AllocationCluster& a) : alloc_(a) +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation , wiringFac_(alloc_) +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation { } diff --git a/src/steam/engine/node-wiring-builder.hpp b/src/steam/engine/node-wiring-builder.hpp index d81f3e128..319c96d6b 100644 --- a/src/steam/engine/node-wiring-builder.hpp +++ b/src/steam/engine/node-wiring-builder.hpp @@ -42,7 +42,8 @@ #define ENGINE_NODE_WIRING_BUILDER_H -#include "steam/engine/proc-node.hpp" +//#include "steam/engine/proc-node.hpp" //////////////////////////////////////////////////////////////////TICKET #1367 : switch to new Node Invocation scheme +#include "steam/engine/connectivity-obsolete.hpp" #include "lib/ref-array.hpp" #include "lib/util-foreach.hpp" #include "lib/nocopy.hpp" @@ -183,7 +184,34 @@ namespace engine { } }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation + class NodeWiringBuilder + : util::MoveOnly + { + public: + + /****************************************************//** + * Terminal: complete the Connectivity defined thus far. + */ +// Connectivity + void* /////////////////////////////////////////////////OOO Connectivity no longer needs to be abstract + build() + { + UNIMPLEMENTED("Node-Connectivity Setup"); + } + }; + + + /** + * Entrance point for building node Connectivity + */ + template + auto + buildPatternFor() + { + UNIMPLEMENTED("instantiate Domain Ontology Facade and outfit the NodeWiringBuilder"); + } }} // namespace steam::engine diff --git a/src/steam/engine/nodeinvocation.hpp b/src/steam/engine/nodeinvocation.hpp index 6d62d1560..31c0d2f5e 100644 --- a/src/steam/engine/nodeinvocation.hpp +++ b/src/steam/engine/nodeinvocation.hpp @@ -55,10 +55,11 @@ #define ENGINE_NODEINVOCATION_H -#include "steam/engine/proc-node.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO clarify if required further on +#include "steam/engine/connectivity-obsolete.hpp" #include "steam/engine/state-closure-obsolete.hpp" #include "steam/engine/channel-descriptor.hpp" -#include "steam/engine/feed-manifold.hpp" +#include "steam/engine/feed-manifold-obsolete.hpp" diff --git a/src/steam/engine/nodeoperation.hpp b/src/steam/engine/nodeoperation.hpp index 0ab1b1a21..1266b7d19 100644 --- a/src/steam/engine/nodeoperation.hpp +++ b/src/steam/engine/nodeoperation.hpp @@ -57,11 +57,12 @@ #define ENGINE_NODEOPERATION_H -#include "steam/engine/proc-node.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO clarify if required further on +#include "steam/engine/connectivity-obsolete.hpp" #include "steam/engine/state-closure-obsolete.hpp" #include "steam/engine/channel-descriptor.hpp" #include "steam/engine/nodeinvocation.hpp" -#include "steam/engine/feed-manifold.hpp" +#include "steam/engine/feed-manifold-obsolete.hpp" #include "lib/meta/util.hpp" #include "lib/meta/configflags.hpp" diff --git a/src/steam/engine/nodewiring.hpp b/src/steam/engine/nodewiring-obsolete.hpp similarity index 85% rename from src/steam/engine/nodewiring.hpp rename to src/steam/engine/nodewiring-obsolete.hpp index 856aa4d97..633782d8a 100644 --- a/src/steam/engine/nodewiring.hpp +++ b/src/steam/engine/nodewiring-obsolete.hpp @@ -24,16 +24,22 @@ /** @file nodewiring.hpp ** Mechanism to wire ProcNode instances for a render network ** @todo unfinished draft from 2009 regarding the render process + ** @deprecated 2024 this header will likely be obsoleted + ** @see node-wiring-builder.hpp for the rewritten node-builder */ -#ifndef ENGINE_NODEWIRING_H -#define ENGINE_NODEWIRING_H +#ifndef ENGINE_NODEWIRING_OBSOLETE_H +#define ENGINE_NODEWIRING_OBSOLETE_H -#include "steam/engine/proc-node.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO clarify if required further on +#include "steam/engine/connectivity-obsolete.hpp" #include "steam/engine/node-wiring-builder.hpp" #include "lib/allocation-cluster.hpp" +#include "lib/ref-array.hpp" +#include "lib/util-foreach.hpp" +#include "lib/nocopy.hpp" #include diff --git a/src/steam/engine/nodewiring.cpp b/src/steam/engine/nodewiring.cpp index d94120f63..0e6201266 100644 --- a/src/steam/engine/nodewiring.cpp +++ b/src/steam/engine/nodewiring.cpp @@ -27,8 +27,9 @@ */ -#include "steam/engine/proc-node.hpp" -#include "steam/engine/nodewiring.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO clarify if required further on +#include "steam/engine/connectivity-obsolete.hpp" +#include "steam/engine/nodewiring-obsolete.hpp" #include "steam/engine/nodeoperation.hpp" #include "steam/engine/nodewiring-config.hpp" diff --git a/src/steam/engine/proc-node.hpp b/src/steam/engine/proc-node.hpp index d0c87956a..b8f1c11a4 100644 --- a/src/steam/engine/proc-node.hpp +++ b/src/steam/engine/proc-node.hpp @@ -46,7 +46,8 @@ #include "steam/common.hpp" #include "steam/asset/proc.hpp" #include "steam/mobject/parameter.hpp" -#include "steam/engine/state-closure-obsolete.hpp" /////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation +//#include "steam/engine/state-closure-obsolete.hpp" ///////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation +#include "steam/engine/state-closure.hpp" /////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation #include "steam/engine/channel-descriptor.hpp" #include "steam/engine/turnout-system.hpp" #include "lib/frameid.hpp" @@ -132,8 +133,10 @@ namespace engine { * holding the actual buffer pointers and issuing the recursive pull() calls * @see NodeWiring#callDown default implementation */ +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation virtual BuffHandle callDown (StateClosure_OBSOLETE& currentProcess, uint requiredOutputNr) const =0; +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation }; @@ -191,11 +194,13 @@ namespace engine { * (in case this node delivers more than one output channel) * @return handle to the buffer containing the calculated result. */ +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation BuffHandle pull (StateClosure_OBSOLETE& currentProcess, uint requestedOutputNr=0) const { return this->wiringConfig_.callDown (currentProcess, requestedOutputNr); } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation }; diff --git a/src/steam/engine/render-invocation.hpp b/src/steam/engine/render-invocation.hpp index b58e576ba..9843b809c 100644 --- a/src/steam/engine/render-invocation.hpp +++ b/src/steam/engine/render-invocation.hpp @@ -37,7 +37,8 @@ //#include "steam/engine/state-closure.hpp" -#include "steam/engine/proc-node.hpp" +//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO clarify if required further on +#include "steam/engine/connectivity-obsolete.hpp" #include "steam/engine/buffhandle.hpp" //#include "steam/engine/bufftable-obsolete.hpp" diff --git a/tests/core/steam/engine/feed-manifold-test.cpp b/tests/core/steam/engine/feed-manifold-test.cpp index da084e1a3..75349d6c6 100644 --- a/tests/core/steam/engine/feed-manifold-test.cpp +++ b/tests/core/steam/engine/feed-manifold-test.cpp @@ -77,8 +77,10 @@ namespace test { virtual uint getNrI() const { return ii; } virtual uint getNrO() const { return oo; } +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation virtual BuffHandle callDown (StateClosure_OBSOLETE&, uint) const { throw lumiera::Error("not intended to be called"); } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation }; diff --git a/tests/core/steam/engine/job-planning-test.cpp b/tests/core/steam/engine/job-planning-test.cpp index 10a0008dc..3a2fba4ab 100644 --- a/tests/core/steam/engine/job-planning-test.cpp +++ b/tests/core/steam/engine/job-planning-test.cpp @@ -143,7 +143,7 @@ namespace test { setupDependentJob() { MockDispatcher dispatcher{MakeRec() // »master job« for each frame - .attrib("runtime", Duration{Time{30,0}}) + .attrib("runtime", Duration{Time{30,0}}) .scope(MakeRec() // a »prerequisite job« on which the »master job« depends .attrib("runtime", Duration{Time{50,0}}) .genNode()) diff --git a/tests/core/steam/engine/node-basic-test.cpp b/tests/core/steam/engine/node-basic-test.cpp index 442529936..340a62251 100644 --- a/tests/core/steam/engine/node-basic-test.cpp +++ b/tests/core/steam/engine/node-basic-test.cpp @@ -27,7 +27,7 @@ #include "lib/test/run.hpp" #include "steam/engine/node-factory.hpp" -#include "steam/engine/nodewiring.hpp" +//#include "steam/engine/nodewiring-obsolete.hpp" /////////////////////////////////////////////////////TICKET #1367 : sort out dependencies for reworked Node Invocation #include "steam/engine/turnout-system.hpp" #include "steam/engine/channel-descriptor.hpp" #include "steam/mobject/session/effect.hpp" @@ -87,11 +87,13 @@ namespace test { ProcNode * testSource; ///////////TODO: how to fabricate a test Source-Node???? +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation WiringSituation setup(testSource); PEffect pEffect = createTestEffectMObject(); ProcNode* pNode = nodeFab (pEffect, setup); CHECK (pNode); +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation TestContext simulatedInvocation; #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 1bd12d549..7b6c7dbe3 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1250,7 +1250,7 @@ Beyond that, it can be necessary to associate at least a state flag with //indiv __Note__: while the API to access this service is uniform, conceptually there is a difference between just using the (shared) type information and associating individual metadata, like the buffer state. Type-~IDs, once allocated, will never be discarded (within the lifetime of an Lumiera application instance -- buffer associations aren't persistent). To the contrary, individual metadata //will be discarded,// when releasing the corresponding buffer. According to the ''prototype pattern'', individual metadata is treated as a one-way-off specialisation. -
+
It turns out that --  throughout the render engine implementation -- we never need direct access to the buffers holding actual media data. Buffers are just some entity to be //managed,// i.e. "allocated", "locked" and "released"; the //actual meaning of these operations can be left to the implementation.// The code within the render engine just pushes around ''smart-prt like handles''. These [[buffer handles|BuffHandle]] act as a front-end, being created by and linked to a buffer provider implementation. There is no need to manage the lifecycle of buffers automatically, because the use of buffers is embedded into the render calculation cycle, which follows a rather strict protocol anyway. Relying on the [[capabilities of the scheduler|SchedulerRequirements]], the sequence of individual jobs in the engine ensures...
 * that the availability of a buffer was ensured prior to planning a job ("buffer allocation")
 * that a buffer handle was obtained ("locked") prior to any operation requiring a buffer
@@ -1264,6 +1264,8 @@ While BufferProvider is an interface meant to be backed by various different kin
 :this operation actually makes a buffer available for a specific client and returns a [[buffer handle|BuffHandle]]. The corresponding buffer is marked as used and can't be locked again unless released. If necessary, at that point the BufferProvider might allocate memory to accommodate (especially when the buffers weren't announced beforehand). The locking may fail and raise an exception. You may expect failure to be unlikely when buffers have been //announced beforehand.// To support additional sanity checks, the client may provide a token-ID with the lock-operation. This token may be retrieved later and it may be used to ensure the buffer is actually locked for //this token.//
 ;attaching
 :optionally the client may attach an object to a locked buffer. This object is placement-constructed into the buffer and will be destroyed automatically when releasing the buffer. Alternatively, the client may provide a pair of constructor- / destructor-functors, to be invoked in a similar way. This allows e.g. to install descriptor structures within the buffer, as required by an external library.
+;emitting
+:the client //may optionally mark a state transition// -- whose precise meaning remains implicit and implementation dependent. From the client's perspective, emitting and releasing may seem equivalent, since the buffer should not be touched after that point. However, conceivably there are usages where it matters for //the consumer// to be sure an expected result was actually achieved, since the producer may well acquire the buffer and then fail to complete the required work, prompting some clean-up safety mechanism to merely release the resources.
 ;releasing
 :buffers need to be released explicitly by the client code. This renders the corresponding BuffHandle invalid, (optionally) invokes a destructor function of an attached object and maybe reclaims the buffer memory
 
@@ -5104,9 +5106,9 @@ Thus the mapping is a copyable value object, using an associative array. It may
 First and foremost, mapping can be seen as a //functional abstraction.// As it's used at implementation level, encapsulation of detail types in't the primary concern, so it's a candidate for generic programming: For each of those use cases outlined above, a distinct mapping type is created by instantiating the {{{OutputMapping<DEF>}}} template with a specifically tailored definition context ({{{DEF}}}), which takes on the role of a strategy. Individual instances of this concrete mapping type may be default created and copied freely. This instantiation process includes picking up the concrete result type and building a functor object for resolving on the fly. Thus, in the way typical for generic programming, the more involved special details are moved out of sight, while being still in scope for the purpose of inlining. But there //is// a concern better to be encapsulated and concealed at the usage site, namely accessing the rules system. Thus mapping leads itself to the frequently used implementation pattern where there is a generic frontend as header, calling into opaque functions embedded within a separate compilation unit.
 
-
+
Within the Lumiera player and output subsystem, actually sending data to an external output requires to allocate an ''output slot''
-This is the central metaphor for the organisation of actual (system level) outputs; using this concept allows to separate and abstract the data calculation and the organisation of playback and rendering from the specifics of the actual output sink. Actual output possibilities (video in GUI window, video fullscreen, sound, Jack, rendering to file) can be added and removed dynamically from various components (Vault, Stage), all using the same resolution and mapping mechanisms (&rarr; OutputManagement)
+This is the central metaphor for the organisation of actual (system level) outputs; using this concept allows to separate and abstract the data calculation and the organisation of playback and rendering from the specifics of the actual output sink. Actual output possibilities (video in GUI window, video fullscreen, using a beamer, sound, Jack, rendering to file) can be added and removed dynamically from various components (Vault, Stage), all using the same resolution and mapping mechanisms (&rarr; OutputManagement)
 
 !Properties of an output slot
 Each OutputSlot is an unique and distinguishable entity. It corresponds explicitly to an external output, or a group of such outputs (e.g. left and right soundcard output channels), or an output file or similar capability accepting media content. First off, an output slot needs to be provided, configured and registered, using an implementation for the kind of media data to be output (sound, video) and the special circumstances of the output capability (render a file, display video in a GUI widget, send video to a full screen display, establish a Jack port, just use some kind of "sound out"). An output slot is always limited to a single kind of media, and to a single connection unit, but this connection may still be comprised of multiple channels (stereoscopic video, multichannel sound).
@@ -5125,7 +5127,7 @@ Besides the sink handles, allocation of an output slot defines some timing const
 The assumption is for the client to have elaborate timing capabilities at his disposal. More specifically, the client is assumed to be a job running within the engine scheduler and thus can be configured to run //after// another job has finished, and to run within certain time limits. Thus the client is able to provide a //current nominal time// -- which is suitably close to the actual wall clock time. This enables the output slot implementation to work out from this time specification if the call is timely or overdue -- and react accordingly.
 
 !!!output modes
-some concrete output connections and drivers embody a specific operation mode (e.g. sample rate or number of channels). The decision and setup of these operational configuration is initiated together with the [[resolution|OutputMapping]] of an OutputDesignation within the OutputManager, finally leading to an output slot (reference), which can be assumed to be suitably configured, before the client allocates this slot for active use. Moreover, an individual output sink (corresponding to a single channel) may just remain unused -- until there is an {{{emit()}}} call and successful data handover, this channel will just feature silence or remain black. (More flexible system, e.g. Jack, allow to generate an arbitrary number of output pins -- Lumiera will support this by allowing to set up additional output slots and attach this information to the current session &rarr; SessionConfigurationAttachment)
+some concrete output connections and drivers embody a specific operation mode (e.g. sample rate or number of channels). The decision and setup of these operational configuration is initiated together with the [[resolution|OutputMapping]] of an OutputDesignation within the OutputManager, finally leading to an output slot (reference), which can be assumed to be suitably configured, before the client allocates this slot for active use. Moreover, an individual output sink (corresponding to a single channel) may just remain unused -- until there is an {{{emit()}}} call and successful data handover, this channel will just feature silence or remain black. (There are some output systems with additional flexibility, e.g. ~Jack-Audio, that allow to generate an arbitrary number of output pins -- Lumiera will support this by allowing to set up additional output slots and attach this information to the current session &rarr; SessionConfigurationAttachment)
 
 !!!Lifecycle and storage
 The concrete OutputSlot implementation is owned and managed by the facility actually providing the output possibility in question. For example, the GUI provides viewer widgets, while some sound output backend provides sound ports. The associated OutputSlot implementation object is required to stay alive as long as it's registered with some OutputManager. It needs to be de-registered explicitly prior to destruction -- and this deregistration may block until all clients using this slot did terminate. Beyond that, an output slot implementation is expected to handle all kinds of failures gracefully -- preferably just emitting a signal (callback functor).
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index b8304588f..c672ab7fd 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -68347,6 +68347,7 @@
 
 
 
+
 
 
 
@@ -79951,7 +79952,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80040,6 +80041,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ...für den »Playback Vertical Slice« wird eine Fixture fabriziert, wie sie vermutlich später mal vom Builder produziert werden wird (wenn es ihn dann endlich mal gibt) — tatsächlich sehe ich das als ersten prototypischen Entwurf, den ich hier nebenbei aus einer bottom-up-Bewegung gewinnen kann +

+ +
+
@@ -80429,8 +80442,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ beachte: dieser »eine Frame« kann durchaus noch inhärent strukturiert sein, beispielsweise mehrere Planes für ein planares Format enthalten oder ein Interleaved-Zyklus von Einzelframes für zusammengehörige Kanäle sein — entscheidend ist, daß dieses Datenelement jeweils als EInheit verwendet und zusammen produziert oder konsumiert wird. +

+ + +
+
- + @@ -80979,6 +81005,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + @@ -80993,17 +81028,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ +
- - - - - - - - - @@ -81042,7 +81070,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- In diese Kategorie fallen alle Verarbeitungsschritte, die sich nicht  auf komplett isolierte Primitiv-Operationen auf Einzelkanälen faktorisieren lassen. Beispiel wäre ein Resonanz- oder Reflexionsvorgang in einem Schallfeld, oder eine Überblende- oder Overlay-Operation mit mehreren Masken-Ebenen, die neben dem Basis-Farbwert sowohl Transparenz alsauch Luminanz umfaßt (also das Problem, das pre-multiplied Alpha nicht wirklich lösen kann). + In diese Kategorie fallen alle Verarbeitungsschritte, die sich nicht auf komplett isolierte Primitiv-Operationen auf Einzelkanälen faktorisieren lassen. Beispiel wäre ein Resonanz- oder Reflexionsvorgang in einem Schallfeld, oder eine Überblende- oder Overlay-Operation mit mehreren Masken-Ebenen, die neben dem Basis-Farbwert sowohl Transparenz alsauch Luminanz umfaßt (also das Problem, das pre-multiplied Alpha nicht wirklich lösen kann).

@@ -81309,8 +81337,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- - + + + + + @@ -81331,12 +81362,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +

- denn das high-Level-Model kann man genau deshalb im Kern (noch) nicht definieren, weil der Builder und das low-Level-Model fehlt + denn das high-Level-Model kann man genau deshalb im Kern (noch) nicht definieren, weil der Builder und das low-Level-Model fehlt — der eigentliche Grund dahinter aber war, daß ich den Sachverhalt noch nicht so weit verstanden hatte, daß ich für einen eignen Entwurf bereit war...

@@ -81362,6 +81393,37 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + +

+ aber erwartungsgemäß hat man das eben grade nicht +

+ + +
+
+ + + + + + +

+ ...sondern nur einen lokalen Kontext +

+ +
+
+
@@ -81373,6 +81435,107 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + +

+ ...und ich kann mich erinnern, daß ich sie auch damals nicht vestanden habe, sondern mich immer nur von Definition zu Definition hangelte... +

+ + +
+ +
+ + + + + + +

+ das ist die gradezu klassische »Top-down«-Falle: +

+
    +
  • + man definiert ausgehend von einem abstrakten Verständnis der Anforderungen (keinem echten Verständnis) +
  • +
  • + jedes ungelöste Problem und jedes fehlende Verständnis wird jeweils als Anforderung in die nächste Detail-Ebene verschoben +
  • +
  • + und beim Zusammenschalten der gebauten Teile steht man dann vor einem Wirrwarr, der nicht recht funktionieren will, aber immerhin alle präzise definierten (aber nicht verstandenen) Anforderungen erfüllt. +
  • +
+ + +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85012,7 +85175,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -85089,7 +85254,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + @@ -85131,13 +85302,24 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + - + + + + + + + + @@ -85155,7 +85337,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -85324,17 +85507,99 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + + + + + + + + + + + +

+ ...und zwar mit einer Gruppierung der Buffer nach Größe, und vermutlich auch pro Thread +

+ +
+
+ + + +
+ + + + + + + + +

+ Es kann durchaus sein, daß das jeweilige Output-System einzelne Teil-Kanäle in einem planaren Format haben möchte, also als einzelne, zusammenhängende Datenblöcke für jeden Kanal (Hue, Sat, Lum, bzw. Sound-L/R oder WXYZ...) +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ warum? weil es die BufferManager-Abstraktion unterläuft +

+ + +
+
+ + + + +
+
@@ -85408,6 +85673,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + @@ -85424,6 +85700,67 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85440,6 +85777,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ...weiterhin bleibt es dabei, daß der Zugang zum Buffer-Management über das Turnout-System (früher StateAdapter) läuft; aber dafür ist kein klassisches OO-Interface notwendig, sofern das Buffer-Handling seinerseits auf einem Interface aufbaut. Die Aufgabe, an der sich das entscheidet ist, wie der konkrete Turnout eine konkrete FeedManifold bauen kann (und ob er das überhaupt tut) +

+ + +
+
@@ -85455,7 +85805,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + @@ -85545,6 +85900,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + @@ -124390,24 +124750,32 @@ std::cout << tmpl.render({"what", "World"}) << s - + - + + + + + + + - + + + @@ -124460,6 +124828,32 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + + + + + + + + + + + + + + + + + + + + + + +