clean-up: finally discard remainders form the first Render Engine draft
During the early stage of the Project, at some point I attempted to »attack« the topic of Engine and Render Nodes following a ''top down path.'' This effort went into a dead end eventually — due to the total lack of tangible reference points to relate to. However, the implementation at that time prompted the development of several supporting facilities, which remain relevant until today. And it resulted in a ''free wheeling'' compound of implementation structures, which could even be operated through some highly convoluted unit test. This piece of implementation code was valuable as starting point for th »Playback Vertical Slice« in 2024 — resulting in a new design which was ''re-oriented'' towards a new degree of freedom (the »Domain Ontology«) while handling the configuration and connectivity of Render Nodes in a rather fixed and finite way. This new approach seems to be much more successful, as we're now able to build, connect and invoke Render Nodes, thereby mapping the processing through a functor binding into some arbitrary, external processing function (which will later be supplied by a media processing library — and thus be part of some »Domain Ontology«)
This commit is contained in:
parent
a317593822
commit
11322ad955
24 changed files with 65 additions and 2625 deletions
|
|
@ -41,6 +41,10 @@ namespace lumiera {
|
||||||
*
|
*
|
||||||
* @todo currently (10/08) this is a dummy implementation. We'll find out
|
* @todo currently (10/08) this is a dummy implementation. We'll find out
|
||||||
* what is needed once the outline of the render engine is complete.
|
* what is needed once the outline of the render engine is complete.
|
||||||
|
* @todo 5/2025 meanwhile a new effort to define the processing nodes was successful,
|
||||||
|
* but it is still not clear if the »Render Nodes« will expose any runtime logic
|
||||||
|
* beyond the mere ability to be invoked.
|
||||||
|
* ** This is a placeholder** — we are using ProcID instead
|
||||||
*/
|
*/
|
||||||
struct NodeID
|
struct NodeID
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
/*
|
|
||||||
CONFIGFLAGS.hpp - Building classes based on configuration cases
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 configflags.hpp
|
|
||||||
** Under some circumstances it is necessary to assemble functionality
|
|
||||||
** out of elementary building blocks. Especially, this assembly can be
|
|
||||||
** expressed as template specialisations directed by a configuration type.
|
|
||||||
** Thus, the purpose of this header is to encode flag-like configurations
|
|
||||||
** as distinct types, which can be used to select such specialisations.
|
|
||||||
** Each possible configuration can be encoded as a list of flags, which allows
|
|
||||||
** to generate, filter and process those configurations. The final goal is to
|
|
||||||
** automatically generate a factory which is able to deliver objects
|
|
||||||
** configured according to the situation encoded in the flags.
|
|
||||||
**
|
|
||||||
** @note currently there is an inherent limitation to configurations defined by
|
|
||||||
** a maximum of 5 independent flags. While it is easy to increase this limit,
|
|
||||||
** you should consider that the final goal is to generate template instantiations,
|
|
||||||
** which would lead to more and more code bloat with growing number of possible
|
|
||||||
** combinations.
|
|
||||||
**
|
|
||||||
** @see steam::engine::config::Strategy usage example
|
|
||||||
** @see steam::engine::config::ConfigSelector
|
|
||||||
** @see typelist.hpp
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef LIB_META_CONFIGFLAGS_H
|
|
||||||
#define LIB_META_CONFIGFLAGS_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/meta/typelist.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
|
||||||
namespace meta{
|
|
||||||
|
|
||||||
const size_t CONFIG_FLAGS_MAX = 5;
|
|
||||||
|
|
||||||
|
|
||||||
template<uint bit> struct Flag { typedef Flag ID; };
|
|
||||||
template<> struct Flag<0> { typedef NullType ID; };
|
|
||||||
|
|
||||||
|
|
||||||
template< uint f1=0
|
|
||||||
, uint f2=0
|
|
||||||
, uint f3=0
|
|
||||||
, uint f4=0
|
|
||||||
, uint f5=0
|
|
||||||
>
|
|
||||||
struct Flags
|
|
||||||
{
|
|
||||||
typedef typename Types< typename Flag<f1>::ID
|
|
||||||
, typename Flag<f2>::ID
|
|
||||||
, typename Flag<f3>::ID
|
|
||||||
, typename Flag<f4>::ID
|
|
||||||
, typename Flag<f5>::ID
|
|
||||||
>::List
|
|
||||||
Tuple;
|
|
||||||
typedef Tuple List;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template< uint f1=0
|
|
||||||
, uint f2=0
|
|
||||||
, uint f3=0
|
|
||||||
, uint f4=0
|
|
||||||
, uint f5=0
|
|
||||||
>
|
|
||||||
struct Config ///< distinct type representing a configuration
|
|
||||||
{
|
|
||||||
typedef typename Flags<f1,f2,f3,f4,f5>::Tuple Flags;
|
|
||||||
typedef Flags List;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<uint Fl, class CONF>
|
|
||||||
struct ConfigSetFlag; ///< set (prepend) the Flag to the given config
|
|
||||||
|
|
||||||
template< uint Fl
|
|
||||||
, uint f1
|
|
||||||
, uint f2
|
|
||||||
, uint f3
|
|
||||||
, uint f4
|
|
||||||
, uint IGN
|
|
||||||
>
|
|
||||||
struct ConfigSetFlag<Fl, Config<f1,f2,f3,f4,IGN>>
|
|
||||||
{
|
|
||||||
typedef lib::meta::Config<Fl,f1,f2,f3,f4> Config;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** build a configuration type from a list-of-flags */
|
|
||||||
template<class FLAGS, class CONF=Config<> >
|
|
||||||
struct BuildConfigFromFlags
|
|
||||||
{
|
|
||||||
typedef CONF Config;
|
|
||||||
typedef Config Type;
|
|
||||||
};
|
|
||||||
template<uint Fl, class FLAGS, class CONF>
|
|
||||||
struct BuildConfigFromFlags< Node<Flag<Fl>,FLAGS>, CONF>
|
|
||||||
{
|
|
||||||
typedef typename ConfigSetFlag< Fl
|
|
||||||
, typename BuildConfigFromFlags<FLAGS,CONF>::Config
|
|
||||||
>::Config Config;
|
|
||||||
typedef Config Type;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** create a configuration type for the given list-of-flags */
|
|
||||||
template<class FLAGS>
|
|
||||||
struct DefineConfigByFlags : BuildConfigFromFlags<FLAGS> { };
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
/** helper comparing enum values and flags */
|
|
||||||
template<uint ii, uint jj>
|
|
||||||
struct maxC
|
|
||||||
{
|
|
||||||
enum{ VAL = ii < jj? jj : ii };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for calculating values and for
|
|
||||||
* invoking runtime code based on a given FlagTuple.
|
|
||||||
* Can also be used on a Typelist of several Configs.
|
|
||||||
* The latter case is typically used to invoke an operation
|
|
||||||
* while enumerating all Flag-Configurations defined in Code.
|
|
||||||
* An example would be to build (at runtime) an dispatcher table.
|
|
||||||
* Explanation: For the Case covering a List of Configs, we provide
|
|
||||||
* a templated visitation function, which can accept a functor object
|
|
||||||
* to be invoked on each Configuration.
|
|
||||||
*/
|
|
||||||
template<class FLAGS>
|
|
||||||
struct FlagInfo;
|
|
||||||
|
|
||||||
template<uint ff, class FLAGS>
|
|
||||||
struct FlagInfo<Node<Flag<ff>, FLAGS>>
|
|
||||||
{
|
|
||||||
enum{ BITS = maxC< ff, FlagInfo<FLAGS>::BITS> ::VAL
|
|
||||||
, CODE = (1<<ff) | FlagInfo<FLAGS>::CODE
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct FlagInfo<NullType>
|
|
||||||
{
|
|
||||||
enum{ BITS = 0
|
|
||||||
, CODE = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class FUNC>
|
|
||||||
static typename FUNC::Ret
|
|
||||||
accept (FUNC& functor)
|
|
||||||
{
|
|
||||||
return functor.done();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class CONF, class TAIL>
|
|
||||||
struct FlagInfo<Node<CONF, TAIL>>
|
|
||||||
{
|
|
||||||
typedef typename CONF::Flags ThisFlags;
|
|
||||||
enum{
|
|
||||||
BITS = maxC< FlagInfo<ThisFlags>::BITS, FlagInfo<TAIL>::BITS > ::VAL
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class FUNC>
|
|
||||||
static typename FUNC::Ret
|
|
||||||
accept (FUNC& functor)
|
|
||||||
{
|
|
||||||
functor.template visit<CONF>(FlagInfo<ThisFlags>::CODE);
|
|
||||||
return FlagInfo<TAIL>::accept (functor);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace lib::meta
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
CHANNEL-DESCRIPTOR.hpp - Channel / Buffer type representation for the engine
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 channel-descriptor-obsolete.hpp
|
|
||||||
** Representation of the Media type of a data channel used within the engine.
|
|
||||||
**
|
|
||||||
** @todo as it stands (11/2011) this file is obsoleted and needs to be refactored,
|
|
||||||
** alongside with adapting the node invocation to the new BufferProvider interface.
|
|
||||||
** @todo as of 5/2024, this will be retained as part of the `FeedManifold`,
|
|
||||||
** which in turn takes on some aspects of the old buffer table draft.
|
|
||||||
** @deprecated 12/2024 it is now clear that the low-level-Model will be really low-level,
|
|
||||||
** implying that any connection to the usage domain will be completely resolved in the builder
|
|
||||||
**
|
|
||||||
** @see nodewiring-def.hpp
|
|
||||||
** @see nodeoperation.hpp
|
|
||||||
** @see bufftable-obsolete.hpp storage for the buffer table
|
|
||||||
** @see engine::RenderInvocation
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ENGINE_CHANNEL_DESCRIPTOR_H
|
|
||||||
#define ENGINE_CHANNEL_DESCRIPTOR_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
#include "lib/hash-value.h"
|
|
||||||
#include "steam/streamtype.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
namespace error = lumiera::error;
|
|
||||||
|
|
||||||
using lib::HashVal;
|
|
||||||
|
|
||||||
class BuffDescr;
|
|
||||||
class BuffHandle;
|
|
||||||
class BufferProvider;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ProcNode_Obsolete;
|
|
||||||
typedef ProcNode_Obsolete* PNode;
|
|
||||||
|
|
||||||
|
|
||||||
struct ChannelDescriptor ///////TODO really need to define that here? it is needed for node wiring only
|
|
||||||
{
|
|
||||||
const lumiera::StreamType * bufferType; /////////////////////////////////////////TICKET #828
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InChanDescriptor : ChannelDescriptor
|
|
||||||
{
|
|
||||||
PNode dataSrc; ///< the ProcNode to pull this input from
|
|
||||||
uint srcChannel; ///< output channel to use on the predecessor node
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
/*
|
|
||||||
PROC-NODE.hpp - Key abstraction of the Render Engine: a Processing Node
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 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-obsolete.hpp"
|
|
||||||
#include "lib/frameid.hpp"
|
|
||||||
#include "lib/ref-array.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using lumiera::NodeID;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
class ProcNode_Obsolete;
|
|
||||||
typedef ProcNode_Obsolete* PNode;
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<ChannelDescriptor>& out;
|
|
||||||
lib::RefArray<InChanDescriptor>& 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<ChannelDescriptor>& o,
|
|
||||||
lib::RefArray<InChanDescriptor>& 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_Obsolete; /////////////////////////////////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_Obsolete
|
|
||||||
: util::NonCopyable
|
|
||||||
{
|
|
||||||
typedef mobject::Parameter<double> Param; //////TODO: just a placeholder for automation as of 6/2008
|
|
||||||
vector<Param> params;
|
|
||||||
|
|
||||||
const Connectivity& wiringConfig_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
ProcNode_Obsolete (Connectivity const& wd)
|
|
||||||
: wiringConfig_(wd)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~ProcNode_Obsolete() {}; /////////////////////////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_Obsolete::isValid() const
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("ProcNode validity self-check");
|
|
||||||
return false; //////////////////////////TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif /*STEAM_ENGINE_CONNECTIVITY_OBSOLETE_H*/
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
/*
|
|
||||||
FEED-MANIFOLD.hpp - data feed connection system for render nodes
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 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-obsolete.hpp"
|
|
||||||
//#include "steam/engine/proc-node.hpp" ///////////////////////////////TODO this is a dead end
|
|
||||||
#include "steam/engine/connectivity-obsolete.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////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_BuffTable_OBSOLETE ///////////////////////////////////OOO this is obliterated by the new implementation of FeedManifold_BuffTable_OBSOLETE
|
|
||||||
{
|
|
||||||
typedef BuffHandle * PHa;
|
|
||||||
typedef BuffHandle::PBuff * PBu;
|
|
||||||
typedef pair<PHa const,PBu const> Chunk;
|
|
||||||
|
|
||||||
PHa outHandle;
|
|
||||||
PHa inHandle;
|
|
||||||
PBu outBuff;
|
|
||||||
PBu inBuff;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BuffDescr;
|
|
||||||
|
|
||||||
/** 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 BuffDescr const&
|
|
||||||
just_satisfy_the_compiler() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////TICKET #825 should be backed by mpool and integrated with node invocation
|
|
||||||
vector<BuffHaXXXX> hTab_;
|
|
||||||
vector<BuffHandle::PBuff> 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_BuffTable_OBSOLETE::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_BuffTable_OBSOLETE::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_BuffTable_OBSOLETE,
|
|
||||||
util::NonCopyable
|
|
||||||
{
|
|
||||||
const uint siz_;
|
|
||||||
FeedManifold_BuffTable_OBSOLETE::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*/
|
|
||||||
|
|
@ -42,27 +42,6 @@ namespace engine {
|
||||||
} // (END) Details of node fabrication
|
} // (END) Details of node fabrication
|
||||||
|
|
||||||
|
|
||||||
using mobject::Placement;
|
|
||||||
using mobject::session::Effect;
|
|
||||||
|
|
||||||
|
|
||||||
/** create a processing node able to render an effect
|
|
||||||
* @todo as of 2016 this is the only (placeholder) implementation
|
|
||||||
* to indicate how building and wiring of nodes was meant to happen
|
|
||||||
*/
|
|
||||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
PNode
|
|
||||||
NodeFactory::operator() (Placement<Effect> const& effect, WiringSituation& intendedWiring)
|
|
||||||
{
|
|
||||||
intendedWiring.resolveProcessor(effect->getProcAsset());
|
|
||||||
Connectivity& wiring = wiringFac_(intendedWiring);
|
|
||||||
|
|
||||||
ProcNode& newNode = alloc_.create<ProcNode> (wiring);
|
|
||||||
ENSURE (newNode.isValid());
|
|
||||||
return &newNode;
|
|
||||||
}
|
|
||||||
UNIMPLEMENTED ("Node Factory for reworked Render Node Connectivity");
|
|
||||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace engine
|
}} // namespace engine
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include "steam/engine/proc-node.hpp"
|
#include "steam/engine/proc-node.hpp"
|
||||||
#include "steam/mobject/placement.hpp"
|
#include "steam/mobject/placement.hpp"
|
||||||
//#include "steam/engine/nodewiring-obsolete.hpp" /////////////////////////////////////////////////////////TICKET #1367 : Adapt to rework of Node Invocation
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////TODO: make inclusions / forward definitions a bit more orthogonal....
|
////////////////////////////////////TODO: make inclusions / forward definitions a bit more orthogonal....
|
||||||
|
|
@ -59,23 +58,11 @@ namespace engine {
|
||||||
class NodeFactory
|
class NodeFactory
|
||||||
{
|
{
|
||||||
AllocationCluster& alloc_;
|
AllocationCluster& alloc_;
|
||||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
WiringFactory wiringFac_;
|
|
||||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NodeFactory (AllocationCluster& a)
|
NodeFactory (AllocationCluster& a)
|
||||||
: alloc_(a)
|
: alloc_(a)
|
||||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
, wiringFac_(alloc_)
|
|
||||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
PNode operator() (mobject::session::PEffect const&, WiringSituation&);
|
|
||||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
/*
|
|
||||||
NODEINVOCATION.hpp - Organise the invocation state within a single pull() call
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 nodeinvocation-obsolete.hpp
|
|
||||||
** Organise the state related to the invocation of s single ProcNode::pull() call
|
|
||||||
** This header defines part of the "glue" which holds together the render node network
|
|
||||||
** and enables to pull result frames from the nodes. Doing so requires some invocation
|
|
||||||
** local state to be maintained, especially a table of buffers used to carry out the
|
|
||||||
** calculations. Further, getting the input buffers filled requires to issue recursive
|
|
||||||
** \c pull() calls, which on the whole creates a stack-like assembly of local invocation
|
|
||||||
** state.
|
|
||||||
** The actual steps to be carried out for a \c pull() call are dependent on the configuration
|
|
||||||
** of the node to pull. Each node has been preconfigured by the builder with a Connectivity
|
|
||||||
** descriptor and a concrete type of a StateAdapter. The actual sequence of steps is defined
|
|
||||||
** in the header nodeoperation.hpp out of a set of basic operation steps. These steps all use
|
|
||||||
** the passed in Invocation object (a sub-interface of StateAdapter) to access the various
|
|
||||||
** aspects of the invocation state.
|
|
||||||
**
|
|
||||||
** # composition of the Invocation State
|
|
||||||
**
|
|
||||||
** For each individual ProcNode#pull() call, the WiringAdapter#callDown() builds an StateAdapter
|
|
||||||
** instance directly on the stack, managing the actual buffer pointers and state references. Using this
|
|
||||||
** StateAdapter, the predecessor nodes are pulled. The way these operations are carried out is encoded
|
|
||||||
** in the actual StateAdapter type known to the NodeWiring (WiringAdapter) instance. All of these actual
|
|
||||||
** StateAdapter types are built as implementing the engine::StateClosure interface.
|
|
||||||
**
|
|
||||||
** @deprecated 12/2024 the internal systematic within the Render Engine has been re-arranged altogether
|
|
||||||
**
|
|
||||||
** @todo relies still on an [obsoleted implementation draft](\ref bufftable-obsolete.hpp)
|
|
||||||
** @see engine::ProcNode
|
|
||||||
** @see engine::StateProxy
|
|
||||||
** @see engine::FeedManifold_BuffTable_OBSOLETE
|
|
||||||
** @see nodewiring.hpp interface for building/wiring the nodes
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ENGINE_NODEINVOCATION_H
|
|
||||||
#define ENGINE_NODEINVOCATION_H
|
|
||||||
|
|
||||||
|
|
||||||
//#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-obsolete.hpp"
|
|
||||||
#include "steam/engine/feed-manifold-obsolete.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter to shield the ProcNode from the actual buffer management,
|
|
||||||
* allowing the processing function within ProcNode to use logical
|
|
||||||
* buffer IDs. StateAdapter is created on the stack for each pull()
|
|
||||||
* call, using setup/wiring data preconfigured by the builder.
|
|
||||||
* Its job is to provide the actual implementation of the Cache
|
|
||||||
* push / fetch and recursive downcall to render the source frames.
|
|
||||||
*/
|
|
||||||
class StateAdapter
|
|
||||||
: public StateClosure_OBSOLETE
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
StateClosure_OBSOLETE& parent_;
|
|
||||||
StateClosure_OBSOLETE& current_;
|
|
||||||
|
|
||||||
StateAdapter (StateClosure_OBSOLETE& callingProcess)
|
|
||||||
: parent_ (callingProcess),
|
|
||||||
current_(callingProcess.getCurrentImplementation())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual StateClosure_OBSOLETE& getCurrentImplementation () { return current_; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public: /* === proxying the StateClosure interface === */
|
|
||||||
|
|
||||||
virtual void releaseBuffer (BuffHandle& bh) { current_.releaseBuffer (bh); }
|
|
||||||
|
|
||||||
virtual void is_calculated (BuffHandle const& bh) { current_.is_calculated (bh); }
|
|
||||||
|
|
||||||
virtual BuffHandle fetch (FrameID const& fID) { return current_.fetch (fID); }
|
|
||||||
|
|
||||||
virtual BuffTableStorage& getBuffTableStorage() { return current_.getBuffTableStorage(); }
|
|
||||||
|
|
||||||
// note: allocateBuffer() is chosen specifically based on the actual node wiring
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invocation context state.
|
|
||||||
* A ref to this type is carried through the chain of NEXT::step() functions
|
|
||||||
* which form the actual invocation sequence. The various operations in this sequence
|
|
||||||
* access the context via the references in this struct, while also using the inherited
|
|
||||||
* public State interface. The object instance actually used as Invocation is created
|
|
||||||
* on the stack and parametrised according to the necessities of the invocation sequence
|
|
||||||
* actually configured. Initially, this real instance is configured without FeedManifold_BuffTable_OBSOLETE,
|
|
||||||
* because the invocation may be short-circuited due to Cache hit. Otherwise, when
|
|
||||||
* the invocation sequence actually prepares to call the process function of this
|
|
||||||
* ProcNode, a buffer table chunk is allocated by the StateProxy and wired in.
|
|
||||||
*/
|
|
||||||
struct Invocation
|
|
||||||
: StateAdapter
|
|
||||||
{
|
|
||||||
Connectivity const& wiring;
|
|
||||||
const uint outNr;
|
|
||||||
|
|
||||||
FeedManifold_BuffTable_OBSOLETE* feedManifold;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** creates a new invocation context state, without FeedManifold_BuffTable_OBSOLETE */
|
|
||||||
Invocation (StateClosure_OBSOLETE& callingProcess, Connectivity const& w, uint o)
|
|
||||||
: StateAdapter(callingProcess),
|
|
||||||
wiring(w), outNr(o),
|
|
||||||
feedManifold(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint nrO() const { return wiring.nrO; }
|
|
||||||
uint nrI() const { return wiring.nrI; }
|
|
||||||
uint buffTabSize() const { return nrO()+nrI(); }
|
|
||||||
|
|
||||||
/** setup the link to an externally allocated buffer table */
|
|
||||||
void setBuffTab (FeedManifold_BuffTable_OBSOLETE* b) { this->feedManifold = b; }
|
|
||||||
|
|
||||||
bool
|
|
||||||
buffTab_isConsistent ()
|
|
||||||
{
|
|
||||||
return (feedManifold)
|
|
||||||
&& (0 < buffTabSize())
|
|
||||||
&& (nrO()+nrI() <= buffTabSize())
|
|
||||||
&& (feedManifold->inBuff == &feedManifold->outBuff[nrO()] )
|
|
||||||
&& (feedManifold->inHandle == &feedManifold->outHandle[nrO()])
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** specialised version filling in the additional information, i.e
|
|
||||||
* the concrete node id and the channel number in question */
|
|
||||||
virtual FrameID const&
|
|
||||||
genFrameID ()
|
|
||||||
{
|
|
||||||
return current_.genFrameID(wiring.nodeID, outNr);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual FrameID const&
|
|
||||||
genFrameID (NodeID const& nID, uint chanNo)
|
|
||||||
{
|
|
||||||
return current_.genFrameID (nID,chanNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
////////////TICKET #249 this strategy should better be hidden within the BuffHandle ctor (and type-erased after creation)
|
|
||||||
struct AllocBufferFromParent ///< using the parent StateAdapter for buffer allocations
|
|
||||||
: Invocation
|
|
||||||
{
|
|
||||||
AllocBufferFromParent (StateClosure_OBSOLETE& sta, Connectivity const& w, const uint outCh)
|
|
||||||
: Invocation(sta, w, outCh) {}
|
|
||||||
|
|
||||||
virtual BuffHandle
|
|
||||||
allocateBuffer (const lumiera::StreamType* ty) { return parent_.allocateBuffer(ty); } ////////////TODO: actually implement the "allocate from parent" logic!
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AllocBufferFromCache ///< using the global current StateClosure, which will delegate to Cache
|
|
||||||
: Invocation
|
|
||||||
{
|
|
||||||
AllocBufferFromCache (StateClosure_OBSOLETE& sta, Connectivity const& w, const uint outCh)
|
|
||||||
: Invocation(sta, w, outCh) {}
|
|
||||||
|
|
||||||
virtual BuffHandle
|
|
||||||
allocateBuffer (const lumiera::StreamType* ty) { return current_.allocateBuffer(ty); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The real invocation context state implementation. It is created
|
|
||||||
* by the NodeWiring (Connectivity) of the processing node which
|
|
||||||
* is pulled by this invocation, hereby using the internal configuration
|
|
||||||
* information to guide the selection of the real call sequence
|
|
||||||
*
|
|
||||||
* \par assembling the call sequence implementation
|
|
||||||
* Each ProcNode#pull() call creates such a StateAdapter subclass on the stack,
|
|
||||||
* with a concrete type according to the Connectivity of the node to pull.
|
|
||||||
* This concrete type encodes a calculation Strategy, which is assembled
|
|
||||||
* as a chain of policy templates on top of OperationBase. For each of the
|
|
||||||
* possible configurations we define such a chain (see bottom of nodeoperation.hpp).
|
|
||||||
* The WiringFactory defined in nodewiring.cpp actually drives the instantiation
|
|
||||||
* of all those possible combinations.
|
|
||||||
*/
|
|
||||||
template<class Strategy, class BufferProvider>
|
|
||||||
class ActualInvocationProcess
|
|
||||||
: public BufferProvider
|
|
||||||
, private Strategy
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ActualInvocationProcess (StateClosure_OBSOLETE& callingProcess, Connectivity const& w, const uint outCh)
|
|
||||||
: BufferProvider(callingProcess, w, outCh)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** contains the details of Cache query and recursive calls
|
|
||||||
* to the predecessor node(s), eventually followed by the
|
|
||||||
* ProcNode::process() callback
|
|
||||||
*/
|
|
||||||
BuffHandle retrieve ()
|
|
||||||
{
|
|
||||||
return Strategy::step (*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,337 +0,0 @@
|
||||||
/*
|
|
||||||
NODEOPERATION.hpp - Specify how the nodes call each other and how processing is organized
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 nodeoperation-obsolete.hpp
|
|
||||||
** Chunks of operation for invoking the rendernodes.
|
|
||||||
** This header defines part of the "glue" which holds together the render node network
|
|
||||||
** and enables to pull a result frames from the nodes. Especially, the aspect of
|
|
||||||
** buffer management and cache query is covered here. Each node has been preconfigured by
|
|
||||||
** the builder with a WiringDescriptor and a concrete type of a StateAdapter, including
|
|
||||||
** a specific Configuration, because the node can be built to
|
|
||||||
** - participate in the Caching or ignore the cache
|
|
||||||
** - actually process a result or just pull frames from a source
|
|
||||||
** - employ in-Place calculations or use separate in/out buffers
|
|
||||||
** Additionally, each node may have a given number of input/output pins, expecting to
|
|
||||||
** be provided with buffers holding a specific kind of data.
|
|
||||||
**
|
|
||||||
** \par composition of the invocation Strategy
|
|
||||||
** For each individual ProcNode#pull() call, the WiringAdapter#callDown() builds an Invocation state
|
|
||||||
** instance directly on the stack, holding references to the actual buffer pointers and state. Using this
|
|
||||||
** StateAdapter, the predecessor nodes are pulled. The way these operations are carried out is encoded
|
|
||||||
** in the actual type of Strategy, which is defined at the bottom of this header. Each Strategy is a chain
|
|
||||||
** of elementary operations invoking each other (\c NEXT::step(invocation) ). Notably, all those possible
|
|
||||||
** configurations are pre-built while compiling (it's a small number below 32 configuration instance).
|
|
||||||
** To be able to select the Strategy for each configuration, we need a Factory (ConfigSelector defined in
|
|
||||||
** nodewiring-config.hpp). which is actually instantiated and used in nodewiring.cpp, which is the object
|
|
||||||
** file holding all those instantiations.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** @deprecated 12/2024 the internal systematic within the Render Engine has been re-arranged altogether.
|
|
||||||
** The general operation scheme is now conceptualised as a weaving-pattern
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** @see engine::ProcNode
|
|
||||||
** @see engine::Invocation
|
|
||||||
** @see engine::StateClosure
|
|
||||||
** @see engine::NodeFactory
|
|
||||||
** @see nodewiring-config.hpp
|
|
||||||
** @see nodewiring.hpp interface for building/wiring the nodes
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ENGINE_NODEOPERATION_H
|
|
||||||
#define ENGINE_NODEOPERATION_H
|
|
||||||
|
|
||||||
|
|
||||||
//#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-obsolete.hpp"
|
|
||||||
#include "steam/engine/nodeinvocation-obsolete.hpp"
|
|
||||||
#include "steam/engine/feed-manifold-obsolete.hpp"
|
|
||||||
|
|
||||||
#include "lib/meta/util.hpp"
|
|
||||||
#include "lib/meta/configflags.hpp"
|
|
||||||
#include "lib/frameid.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
namespace config {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class of all concrete invocation sequences.
|
|
||||||
* Provides a collection of functions used to build up the invocation sequence.
|
|
||||||
* Additionally providing a marker used to detect the existence of an concrete
|
|
||||||
* definition/specialisation for a given specific configuration.
|
|
||||||
*/
|
|
||||||
struct OperationBase
|
|
||||||
{
|
|
||||||
typedef lib::meta::Yes_t is_defined;
|
|
||||||
|
|
||||||
BuffHandle
|
|
||||||
getSource (Invocation& ivo, uint chanNo)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("retrieve source data provided by the vault/scheduler");
|
|
||||||
}
|
|
||||||
|
|
||||||
BuffHandle
|
|
||||||
pullPredecessor (Invocation& ivo, uint chanNo)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("invoke pull() on the denoted predecessor node");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
releaseBuffers(BuffHandle* table, uint slotCnt, uint slot_to_retain) //////////////TODO this is going to be implemented rather by smart-handle, Ticket #249
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("release all buffers with the exception of the desired output");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validateBuffers (Invocation& ivo)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("Do a final, specifically tailored validation step on the buffers prior to invoking the process function");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct QueryCache : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
BuffHandle fetched = ivo.fetch (ivo.genFrameID());
|
|
||||||
if (fetched)
|
|
||||||
return fetched;
|
|
||||||
else
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct AllocBufferTable : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
BuffTableChunk buffTab (ivo.wiring, ivo.getBuffTableStorage());
|
|
||||||
ivo.setBuffTab(&buffTab);
|
|
||||||
ASSERT (ivo.feedManifold);
|
|
||||||
ASSERT (ivo.buffTab_isConsistent());
|
|
||||||
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct PullInput : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
BuffHandle * inH = ivo.feedManifold->inHandle;
|
|
||||||
BuffHandle::PBuff *inBuff = ivo.feedManifold->inBuff;
|
|
||||||
|
|
||||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
|
||||||
{
|
|
||||||
inBuff[i] =
|
|
||||||
&*(inH[i] = this->pullPredecessor(ivo,i)); // invoke predecessor
|
|
||||||
// now Input #i is ready...
|
|
||||||
}
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct ReadSource : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
BuffHandle *inH = ivo.feedManifold->inHandle;
|
|
||||||
BuffHandle *outH = ivo.feedManifold->outHandle;
|
|
||||||
BuffHandle::PBuff *inBuff = ivo.feedManifold->inBuff;
|
|
||||||
BuffHandle::PBuff *outBuff = ivo.feedManifold->outBuff;
|
|
||||||
|
|
||||||
ASSERT (ivo.nrO() == ivo.nrI() );
|
|
||||||
|
|
||||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
|
||||||
{
|
|
||||||
inBuff[i] = outBuff[i] =
|
|
||||||
&*(inH[i] = outH[i] = this->getSource(ivo,i));
|
|
||||||
// now Input #i is ready...
|
|
||||||
}
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct AllocOutput : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
ASSERT (ivo.feedManifold);
|
|
||||||
ASSERT (ivo.nrO() < ivo.buffTabSize());
|
|
||||||
BuffHandle *outH = ivo.feedManifold->outHandle;
|
|
||||||
BuffHandle::PBuff *outBuff = ivo.feedManifold->outBuff;
|
|
||||||
|
|
||||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
|
||||||
{
|
|
||||||
outBuff[i] =
|
|
||||||
&*(outH[i] = ivo.allocateBuffer (ivo.wiring.out[i].bufferType));
|
|
||||||
// now Output buffer for channel #i is available...
|
|
||||||
}
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct ProcessData : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
ASSERT (ivo.feedManifold);
|
|
||||||
ASSERT (ivo.buffTab_isConsistent());
|
|
||||||
ASSERT (this->validateBuffers(ivo));
|
|
||||||
|
|
||||||
// Invoke our own process() function,
|
|
||||||
// providing the array of outBuffer+inBuffer ptrs
|
|
||||||
(*ivo.wiring.procFunction) (*ivo.feedManifold->outBuff);
|
|
||||||
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct FeedCache : NEXT
|
|
||||||
{
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
|
||||||
{
|
|
||||||
// declare all Outputs as finished
|
|
||||||
ivo.is_calculated(ivo.feedManifold->outHandle[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NEXT::step (ivo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class NEXT>
|
|
||||||
struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor??
|
|
||||||
{ ///////////////// this would require BuffHandle to be a smart ref.... --> ///TICKET #249
|
|
||||||
BuffHandle
|
|
||||||
step (Invocation& ivo)
|
|
||||||
{
|
|
||||||
// all buffers besides the required Output no longer needed
|
|
||||||
this->releaseBuffers(ivo.feedManifold->outHandle,
|
|
||||||
ivo.buffTabSize(),
|
|
||||||
ivo.outNr);
|
|
||||||
|
|
||||||
return ivo.feedManifold->outHandle[ivo.outNr];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* =============================================================== */
|
|
||||||
/* === declare the possible Assembly of these elementary steps === */
|
|
||||||
|
|
||||||
enum Cases
|
|
||||||
{
|
|
||||||
CACHING = 1,
|
|
||||||
PROCESS,
|
|
||||||
INPLACE,
|
|
||||||
|
|
||||||
NOT_SET = 0,
|
|
||||||
NUM_Cases = INPLACE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
using lib::meta::Config;
|
|
||||||
///////////////////////TODO: selecting this way isn't especially readable,
|
|
||||||
///////////////////////////: but BufferProvider selection is going to be solved differently anyway, see Ticket #249
|
|
||||||
template<class CONF>
|
|
||||||
struct SelectBuffProvider { typedef AllocBufferFromParent Type; };
|
|
||||||
template<uint PROC_ign, uint INPLA_ign>
|
|
||||||
struct SelectBuffProvider< Config<CACHING, PROC_ign, INPLA_ign>> { typedef AllocBufferFromCache Type; };
|
|
||||||
|
|
||||||
|
|
||||||
template<class Config>
|
|
||||||
struct Strategy ;
|
|
||||||
|
|
||||||
|
|
||||||
template<uint INPLACE_ign>
|
|
||||||
struct Strategy< Config<CACHING,PROCESS,INPLACE_ign>>
|
|
||||||
: QueryCache<
|
|
||||||
AllocBufferTable<
|
|
||||||
PullInput<
|
|
||||||
AllocOutput<
|
|
||||||
ProcessData<
|
|
||||||
FeedCache<
|
|
||||||
ReleaseBuffers<
|
|
||||||
OperationBase > > > > > > >
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template<uint INPLACE_ign>
|
|
||||||
struct Strategy< Config<PROCESS,INPLACE_ign>>
|
|
||||||
: AllocBufferTable<
|
|
||||||
PullInput<
|
|
||||||
AllocOutput<
|
|
||||||
ProcessData<
|
|
||||||
ReleaseBuffers<
|
|
||||||
OperationBase > > > > >
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Strategy< Config<> >
|
|
||||||
: AllocBufferTable<
|
|
||||||
ReadSource<
|
|
||||||
ReleaseBuffers<
|
|
||||||
OperationBase > > >
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Strategy< Config<INPLACE> > : Strategy< Config<> > { };
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Strategy< Config<CACHING> >
|
|
||||||
: AllocBufferTable<
|
|
||||||
ReadSource<
|
|
||||||
AllocOutput<
|
|
||||||
ProcessData< // wiring_.processFunction is supposed to do just buffer copying here
|
|
||||||
ReleaseBuffers<
|
|
||||||
OperationBase > > > > >
|
|
||||||
{ };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}} // namespace steam::engine::config
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
/*
|
|
||||||
NODEWIRING-CONFIG.hpp - Helper for representing and selecting the wiring case
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 nodewiring-config.hpp
|
|
||||||
** Sometimes we need to choose a different implementation for dealing with
|
|
||||||
** some special cases. While for simple cases, just testing a flag or using a
|
|
||||||
** switch statement will do the job, matters get more difficult when we have to
|
|
||||||
** employ a completely different execution path for each of the different cases,
|
|
||||||
** while using a set of common building blocks.
|
|
||||||
** \par
|
|
||||||
** In the Lumiera render engine, right on the critical path, we need some glue code
|
|
||||||
** for invoking the predecessor nodes when pulling a given processing node. The actual
|
|
||||||
** sequence is quite dependent on the specific situation each node is wired up, regarding
|
|
||||||
** buffer allocation, cache querying and the possible support for GPU processing and
|
|
||||||
** render farms. The solution is to define specialisations of a Strategy template
|
|
||||||
** using the specific configuration as template argument. Based on these, we can
|
|
||||||
** create a collection of factories, which in turn will build the internal wiring
|
|
||||||
** for the individual ProcNode instances in accordance to the situation determined
|
|
||||||
** for this node, expressed as a set of flags. As a net result, each node has an
|
|
||||||
** individual configuration (as opposed to creating a lot of hand-written individual
|
|
||||||
** ProcNode subclasses), but parts of this configuration assembly is done already at
|
|
||||||
** compile time, allowing for additional checks by typing and for possible optimisation.
|
|
||||||
**
|
|
||||||
** @see steam::engine::config::Strategy
|
|
||||||
** @see nodewiring.hpp
|
|
||||||
** @see configflags.hpp
|
|
||||||
** @see config-flags-test.cpp
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENGINE_NODEWIRING_CONFIG_H
|
|
||||||
#define ENGINE_NODEWIRING_CONFIG_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/meta/configflags.hpp"
|
|
||||||
#include "lib/meta/util.hpp"
|
|
||||||
#include "lib/util.hpp"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <bitset>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
namespace config {
|
|
||||||
|
|
||||||
using util::contains;
|
|
||||||
using lib::meta::FlagInfo;
|
|
||||||
|
|
||||||
using lib::meta::CONFIG_FLAGS_MAX;
|
|
||||||
|
|
||||||
typedef size_t IxID; ///////////////////////////////TICKET #863
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for fabricating ProcNode Wiring configurations.
|
|
||||||
* This object builds a table of factories, holding one factory
|
|
||||||
* for each possible node configuration. Provided with the desired
|
|
||||||
* configuration encoded as bits, the related factory can be invoked,
|
|
||||||
* thus producing a product object for the given configuration.
|
|
||||||
*
|
|
||||||
* \par implementation notes
|
|
||||||
* The actual factory class is templated, so it will be defined
|
|
||||||
* at the use site of ConfigSelector. Moreover, this factory
|
|
||||||
* usually expects an ctor argument, which will be fed through
|
|
||||||
* when creating the ConfigSelector instance. This is one of
|
|
||||||
* the reasons why we go through all these complicated factory
|
|
||||||
* building: this ctor argument usually brings in a reference
|
|
||||||
* to the actual memory allocator. Thus we have to rebuild the
|
|
||||||
* ConfigSelector each time we switch and rebuild the ProcNode
|
|
||||||
* factories, which in turn happens each time we use a new
|
|
||||||
* bulk allocation memory block -- typically for each separate
|
|
||||||
* segment of the Timeline and processing node graph.
|
|
||||||
*
|
|
||||||
* Now the selection of the possible flag configurations, for which
|
|
||||||
* Factory instances are created in the table, is governed by the
|
|
||||||
* type parameter of the ConfigSelector ctor. This type parameter
|
|
||||||
* needs to be a Typelist of Typelists, each representing a flag
|
|
||||||
* configuration. The intention is to to drive this selection by
|
|
||||||
* the use of template metaprogramming for extracting all
|
|
||||||
* currently defined StateProxy object configurations.
|
|
||||||
* @todo as the factories live only within the enclosed table (map)
|
|
||||||
* we could allocate them in-place. Unfortunately this is
|
|
||||||
* non-trivial, because the STL containers employ
|
|
||||||
* value semantics and thus do a copy even on insert.
|
|
||||||
* Thus, for now we use a shared_ptr to hold the factory
|
|
||||||
* heap allocated. ---> see Ticket #248
|
|
||||||
*/
|
|
||||||
template< template<class CONF> class Factory
|
|
||||||
, typename FUNC ///< common function type of all Factory instances
|
|
||||||
, typename PAR ///< ctor parameter of the Factories
|
|
||||||
>
|
|
||||||
class ConfigSelector
|
|
||||||
{
|
|
||||||
typedef std::function<FUNC> FacFunction;
|
|
||||||
|
|
||||||
template<class FAC>
|
|
||||||
struct FactoryHolder ///< impl type erasure
|
|
||||||
: private FAC,
|
|
||||||
public FacFunction
|
|
||||||
{
|
|
||||||
FactoryHolder(PAR p)
|
|
||||||
: FAC(p),
|
|
||||||
FacFunction (static_cast<FAC&> (*this))
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::shared_ptr<FacFunction> PFunc;
|
|
||||||
typedef std::map<IxID, PFunc> ConfigTable;
|
|
||||||
|
|
||||||
ConfigTable possibleConfig_; ///< Table of factories
|
|
||||||
|
|
||||||
|
|
||||||
/** Helper: a visitor usable with FlagInfo.
|
|
||||||
* Used to create a factory for each config */
|
|
||||||
struct FactoryTableBuilder
|
|
||||||
{
|
|
||||||
PAR ctor_param_;
|
|
||||||
ConfigTable& factories_;
|
|
||||||
|
|
||||||
FactoryTableBuilder (ConfigTable& tab, PAR p)
|
|
||||||
: ctor_param_(p),
|
|
||||||
factories_(tab) { }
|
|
||||||
|
|
||||||
|
|
||||||
/* === visitation interface === */
|
|
||||||
|
|
||||||
typedef void Ret;
|
|
||||||
|
|
||||||
template<class CONF>
|
|
||||||
void
|
|
||||||
visit (IxID code)
|
|
||||||
{
|
|
||||||
PFunc pFactory (new FactoryHolder<Factory<CONF>> (ctor_param_));
|
|
||||||
factories_[code] = pFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void done() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<class CONFS>
|
|
||||||
ConfigSelector(CONFS const&, PAR factory_ctor_param)
|
|
||||||
{
|
|
||||||
FactoryTableBuilder buildTable(this->possibleConfig_,
|
|
||||||
factory_ctor_param );
|
|
||||||
// store a new Factory instance
|
|
||||||
// for each possible Flag-Configuration
|
|
||||||
FlagInfo<CONFS>::accept (buildTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
FacFunction&
|
|
||||||
operator[] (IxID configFlags) ///< retrieve the factory corresponding to the given config
|
|
||||||
{
|
|
||||||
if (contains (possibleConfig_, configFlags))
|
|
||||||
return *possibleConfig_[configFlags];
|
|
||||||
else
|
|
||||||
throw lumiera::error::Invalid("ConfigSelector: No preconfigured factory for config-bits="
|
|
||||||
+std::bitset<CONFIG_FLAGS_MAX>(configFlags).to_string());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using lib::meta::Yes_t;
|
|
||||||
using lib::meta::No_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template for semi-automatic detection if instantiation is possible.
|
|
||||||
* Requires help by the template to be tested, which needs to define a type member
|
|
||||||
* `is_defined`. The embedded metafunction Test can be used as a predicate for
|
|
||||||
* filtering types which may yield a valid instantiation of the candidate template
|
|
||||||
* in question.
|
|
||||||
* @todo 1/2016 is there no better way to achieve this, based on new language features /////////////TICKET #986
|
|
||||||
* Basically we want a SFINAE helper not only to check if a specific instantiation
|
|
||||||
* can be formed (which would be trivial), but rather, if a specific instantiation
|
|
||||||
* has _already been defined_. An automated solution for this problem seems questionable
|
|
||||||
* by theoretic reasons; such would endanger the "One Definition Rule", since the state
|
|
||||||
* of definedness of any type may change during the course of a translation unit from
|
|
||||||
* "unknown" to "declared", "partially defined" to "fully defined". To hinge the existence
|
|
||||||
* of another type on this transitory state would introduce a dangerous statefulness into
|
|
||||||
* the meta-language, which is assumed to be stateless.
|
|
||||||
* @todo what _could_ be done though is to detect if a given template can be _default constructed_,
|
|
||||||
* which, by logical weakening, implies it has be defined at all. Would that satisfy our
|
|
||||||
* purpose here?
|
|
||||||
* @todo 1/2016 also I'm not happy with the name "Instantiation". It should be something like `is_XYZ`
|
|
||||||
*/
|
|
||||||
template<template<class> class _CandidateTemplate_>
|
|
||||||
struct Instantiation
|
|
||||||
{
|
|
||||||
|
|
||||||
template<class X>
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
typedef _CandidateTemplate_<X> Instance;
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
static Yes_t check(typename U::is_defined *);
|
|
||||||
template<class U>
|
|
||||||
static No_t check(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const bool value = (sizeof(Yes_t)==sizeof(check<Instance>(0)));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}} // namespace steam::engine::config
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
NodeWiring - Implementation of the node network and operation control
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 nodewiring-obsolete.cpp
|
|
||||||
** Implementation of node wiring to build a render node network
|
|
||||||
** @todo unfinished draft from 2009 regarding the render process
|
|
||||||
**
|
|
||||||
** @deprecated 12/2024 the internal systematic within the Render Engine has been re-arranged altogether;
|
|
||||||
** instead of orchestrating generic invocation building-blocks, a collection of generic
|
|
||||||
** _weaving-patterns_ will be instantiated directly in the library-adapter plug-ins
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//#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-obsolete.hpp"
|
|
||||||
#include "steam/engine/nodewiring-config.hpp"
|
|
||||||
|
|
||||||
#include "lib/meta/typelist-manip.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
namespace config {
|
|
||||||
|
|
||||||
using lib::meta::Flags;
|
|
||||||
using lib::meta::CombineFlags;
|
|
||||||
using lib::meta::DefineConfigByFlags;
|
|
||||||
using lib::meta::Apply;
|
|
||||||
using lib::meta::Filter;
|
|
||||||
|
|
||||||
using lib::AllocationCluster;
|
|
||||||
|
|
||||||
|
|
||||||
typedef Flags<CACHING,PROCESS,INPLACE>::Tuple AllFlags;
|
|
||||||
|
|
||||||
/** build the list of all possible flag combinations */
|
|
||||||
typedef CombineFlags<AllFlags> AllFlagCombinations;
|
|
||||||
|
|
||||||
/** build a configuration type for each of those flag combinations */
|
|
||||||
typedef Apply<AllFlagCombinations::List, DefineConfigByFlags> AllConfigs;
|
|
||||||
|
|
||||||
/** filter those configurations which actually define a wiring strategy */
|
|
||||||
typedef Filter<AllConfigs::List, Instantiation<Strategy>::Test> PossibleConfigs;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// internal details: setting up a factory for each required configuration
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fabricating a Connectivity descriptor
|
|
||||||
* tailored for a specific node wiring situation.
|
|
||||||
*/
|
|
||||||
template<class CONF>
|
|
||||||
class WiringDescriptorFactory
|
|
||||||
{
|
|
||||||
AllocationCluster& alloc_;
|
|
||||||
|
|
||||||
/* ==== pick actual wiring code ==== */
|
|
||||||
typedef typename SelectBuffProvider<CONF>::Type BuffProvider;
|
|
||||||
typedef ActualInvocationProcess<Strategy<CONF>, BuffProvider> InvocationStateType;
|
|
||||||
|
|
||||||
// the concrete implementation of the glue code...
|
|
||||||
typedef NodeWiring<InvocationStateType> ActualWiring;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
WiringDescriptorFactory(AllocationCluster& a)
|
|
||||||
: alloc_(a) {}
|
|
||||||
|
|
||||||
Connectivity&
|
|
||||||
operator() (WiringSituation const& intendedWiring)
|
|
||||||
{
|
|
||||||
return alloc_.create<ActualWiring> (intendedWiring);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** invocation signature of the factories */
|
|
||||||
typedef Connectivity& (FunctionType)(WiringSituation const&);
|
|
||||||
|
|
||||||
/** preconfigured table of all possible factories */
|
|
||||||
typedef ConfigSelector< WiringDescriptorFactory ///< Factory template to instantiate
|
|
||||||
, FunctionType ///< function signature of the Factories
|
|
||||||
, AllocationCluster& ///< allocator fed to all factories
|
|
||||||
> WiringSelector;
|
|
||||||
|
|
||||||
|
|
||||||
struct WiringFactoryImpl
|
|
||||||
{
|
|
||||||
WiringSelector selector;
|
|
||||||
|
|
||||||
WiringFactoryImpl (AllocationCluster& alloc)
|
|
||||||
: selector(config::PossibleConfigs::List(), alloc)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // (END) internals (namespace config)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** As the WiringFactory (and all the embedded factories
|
|
||||||
* for the specific wiring situations) use the AllocationCluster
|
|
||||||
* of the current build process, we need to create a new instance
|
|
||||||
* for each newly built segment of the low-level model.
|
|
||||||
* @note This ctor creates a WiringFactoryImpl instance, thus
|
|
||||||
* compiling this definition actually drives the necessary
|
|
||||||
* template instantiations for all cases encountered while
|
|
||||||
* building the node network.
|
|
||||||
*/
|
|
||||||
WiringFactory::WiringFactory (lib::AllocationCluster& a)
|
|
||||||
: alloc_(a),
|
|
||||||
pImpl_(new config::WiringFactoryImpl (alloc_))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
WiringFactory::~WiringFactory () {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** create and configure a concrete wiring descriptor to tie
|
|
||||||
* a ProcNode to its predecessor nodes. This includes selecting
|
|
||||||
* the actual StateAdapter type, configuring it based on operation
|
|
||||||
* control templates (policy classes).
|
|
||||||
* The created WiringDescriptor object is bulk allocated similar to the ProcNode
|
|
||||||
* objects for a given segment of the Timeline. It should be further configured
|
|
||||||
* with the actual predecessor nodes pointers and can then be used to create
|
|
||||||
* the new processing node to be wired up.
|
|
||||||
*/
|
|
||||||
Connectivity&
|
|
||||||
WiringFactory::operator() (WiringSituation const& setup)
|
|
||||||
{
|
|
||||||
long config = setup.getFlags();
|
|
||||||
return pImpl_->selector[config] (setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
/*
|
|
||||||
NODEWIRING.hpp - Implementation of the node network and operation control
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 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_OBSOLETE_H
|
|
||||||
#define ENGINE_NODEWIRING_OBSOLETE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "steam/engine/connectivity-obsolete.hpp"
|
|
||||||
#include "lib/allocation-cluster.hpp"
|
|
||||||
#include "lib/ref-array.hpp"
|
|
||||||
#include "lib/util-foreach.hpp"
|
|
||||||
#include "lib/nocopy.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
|
|
||||||
class WiringFactory;
|
|
||||||
|
|
||||||
namespace config { class WiringFactoryImpl; }
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : inlined here and then dropped in node-wiring-builder.hpp
|
|
||||||
using lib::RefArray;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finding out about a concrete way of wiring up a
|
|
||||||
* ProcNode about to be built. Such a (temporary) setup object
|
|
||||||
* is used while building the low-level model. It is loaded with
|
|
||||||
* information concerning the intended connections to be made
|
|
||||||
* and then used to initialise the wiring descriptor, which
|
|
||||||
* in turn allows us to setup the ProcNode.
|
|
||||||
*
|
|
||||||
* \par intended usage pattern
|
|
||||||
* The goal is to describe the constellation of a new node to be built.
|
|
||||||
* Thus, we start with one or several existing nodes, specifying which
|
|
||||||
* output should go to which input pin of the yet-to-be created new node.
|
|
||||||
* When intending to create a source node, a default WiringSituation
|
|
||||||
* should be used, without adding any connection information.
|
|
||||||
*
|
|
||||||
* @deprecated WIP-WIP-WIP 2024 Node-Invocation is reworked from ground up for the »Playback Vertical Slice«
|
|
||||||
*/
|
|
||||||
class WiringSituation
|
|
||||||
: util::NonCopyable
|
|
||||||
{
|
|
||||||
long flags_;
|
|
||||||
asset::Proc::ProcFunc* function_;
|
|
||||||
|
|
||||||
public: /* === API for querying collected data === */
|
|
||||||
RefArray<ChannelDescriptor>&
|
|
||||||
makeOutDescriptor() const
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("build new output descriptors for the node under construction"); //////////TODO: where to get the information about the output channels???
|
|
||||||
}
|
|
||||||
|
|
||||||
RefArray<InChanDescriptor>&
|
|
||||||
makeInDescriptor() const
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("build new input descriptors for the node under construction");
|
|
||||||
}
|
|
||||||
|
|
||||||
Connectivity::ProcFunc*
|
|
||||||
resolveProcessingFunction() const
|
|
||||||
{
|
|
||||||
REQUIRE (function_);
|
|
||||||
return function_;
|
|
||||||
}
|
|
||||||
|
|
||||||
lumiera::NodeID const&
|
|
||||||
createNodeID() const
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("initiate generation of a new unique node-ID"); // see rendergraph.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public: /* === API for specifying the desired wiring === */
|
|
||||||
|
|
||||||
/** A default WiringSituation doesn't specify any connections.
|
|
||||||
* It can be used as-is for building a source node, or augmented
|
|
||||||
* with connection information later on.
|
|
||||||
*/
|
|
||||||
WiringSituation()
|
|
||||||
: flags_(0)
|
|
||||||
, function_(0)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("representation of the intended wiring");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Continue the wiring by hooking directly into the output
|
|
||||||
* of an existing predecessor node
|
|
||||||
*/
|
|
||||||
WiringSituation (PNode predecessor)
|
|
||||||
: flags_(0)
|
|
||||||
, function_(0)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("wiring representation; hook up connections 1:1");
|
|
||||||
REQUIRE (predecessor);
|
|
||||||
|
|
||||||
//////////////////////////TODO: see Ticket 254
|
|
||||||
// for_each (predecessor->outputs(), ..... see also Ticket 183 (invoking member fun in for_each)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** set up a connection leading to a specific input pin of the new node */
|
|
||||||
WiringSituation&
|
|
||||||
defineInput (uint inPin, PNode pred, uint outPin)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("wiring representation; define new connection");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** set up the next input connection,
|
|
||||||
* originating at a specific output pin of the predecessor */
|
|
||||||
WiringSituation&
|
|
||||||
defineInput (PNode pred, uint outPin)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("wiring representation; define new connection");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** set up the next input connection to a specific input pin,
|
|
||||||
* originating at a the next/sole output pin of the predecessor */
|
|
||||||
WiringSituation&
|
|
||||||
defineInput (uint inPin, PNode pred)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("wiring representation; define new connection");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** set detail flags regarding the desired node operation mode */
|
|
||||||
WiringSituation&
|
|
||||||
setFlag (long code)
|
|
||||||
{
|
|
||||||
flags_ |= code;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getFlags () const { return flags_; }
|
|
||||||
|
|
||||||
|
|
||||||
/** trigger resolving of the actual processing function */
|
|
||||||
WiringSituation&
|
|
||||||
resolveProcessor (asset::Proc const& procAsset)
|
|
||||||
{
|
|
||||||
function_ = procAsset.resolveProcessor();
|
|
||||||
ENSURE (function_);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : (END)inlined here and then dropped in node-wiring-builder.hpp
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actual implementation of the link between nodes,
|
|
||||||
* also acting as "track switch" for the execution path
|
|
||||||
* chosen while operating the node network for rendering.
|
|
||||||
* @param STATE Invocation state object controlling the
|
|
||||||
* behaviour of callDown() while rendering.
|
|
||||||
* @see StateAdapter
|
|
||||||
* @see NodeFactory
|
|
||||||
*/
|
|
||||||
template<class STATE>
|
|
||||||
class NodeWiring
|
|
||||||
: public Connectivity
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
NodeWiring(WiringSituation const& setup)
|
|
||||||
: Connectivity(setup.makeOutDescriptor(),
|
|
||||||
setup.makeInDescriptor(),
|
|
||||||
setup.resolveProcessingFunction(),
|
|
||||||
setup.createNodeID())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual BuffHandle
|
|
||||||
callDown (StateClosure_OBSOLETE& currentProcess, uint requestedOutputNr) const
|
|
||||||
{
|
|
||||||
STATE thisStep (currentProcess, *this, requestedOutputNr);
|
|
||||||
return thisStep.retrieve (); // fetch or calculate results
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WiringFactory
|
|
||||||
{
|
|
||||||
lib::AllocationCluster& alloc_;
|
|
||||||
std::unique_ptr<config::WiringFactoryImpl> pImpl_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
WiringFactory (lib::AllocationCluster& a);
|
|
||||||
~WiringFactory ();
|
|
||||||
|
|
||||||
Connectivity&
|
|
||||||
operator() (WiringSituation const& setup);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif
|
|
||||||
|
|
@ -168,39 +168,17 @@ namespace engine {
|
||||||
class Connectivity
|
class Connectivity
|
||||||
{
|
{
|
||||||
public: /* === public information record describing the node graph === */
|
public: /* === public information record describing the node graph === */
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
using Ports = lib::Several<Port>;
|
using Ports = lib::Several<Port>;
|
||||||
using Leads = lib::Several<ProcNodeRef>;
|
using Leads = lib::Several<ProcNodeRef>;
|
||||||
|
|
||||||
Ports ports;
|
Ports ports;
|
||||||
Leads leads;
|
Leads leads;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
// protected:
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
Connectivity (Ports&& pr, Leads&& lr)
|
Connectivity (Ports&& pr, Leads&& lr)
|
||||||
: ports(move(pr))
|
: ports(move(pr))
|
||||||
, leads(move(lr))
|
, leads(move(lr))
|
||||||
{ }
|
{ }
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
/* ==== strategy API for configuring the node operation ==== */
|
|
||||||
|
|
||||||
friend class ProcNode; /////////////////////////////////OOO who needs friendship?
|
|
||||||
|
|
||||||
/** 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
|
|
||||||
*/
|
|
||||||
#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
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
RenderEngine - a complete network of processing nodes usable for rendering
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 renderengine.cpp
|
|
||||||
** @deprecated a pile of crap, leftovers and started drafts, stalled since 2011 -- but maybe here to stay...
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
#include "steam/engine/renderengine.hpp"
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
|
|
||||||
RenderEngine::RenderEngine()
|
|
||||||
: RenderGraph()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED("wtf... a video editor without implemented render engine??");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace engine
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
RENDERENGINE.hpp - a complete network of processing nodes usable for rendering
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 renderengine.hpp
|
|
||||||
** (Planned) access point to the render engine as service.
|
|
||||||
** @deprecated a pile of crap, leftovers and started drafts, stalled since 2011 -- but maybe here to stay...
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef STEAM_ENGINE_RENDERENGINE_H
|
|
||||||
#define STEAM_ENGINE_RENDERENGINE_H
|
|
||||||
|
|
||||||
#include "steam/engine/rendergraph.hpp"
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////TODO 7/11 this is a piece of debris, left over from the first attempt to complete the render nodes network.
|
|
||||||
/////////////////////////////TODO Meanwhile the intention is to treat the render nodes network more like a data structure,
|
|
||||||
/////////////////////////////TODO consequently this will become some kind of root or anchor point for this network
|
|
||||||
|
|
||||||
//////////TODO for the "real" engine API: look at engine-serivce.hpp
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
using std::list;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo this was planned to become the frontend
|
|
||||||
* to the render node network, which can be considered
|
|
||||||
* at the lower end of the middle layer; the actual
|
|
||||||
* render operations are mostly implemented by the vault layer
|
|
||||||
* ////////TODO WIP as of 12/2010
|
|
||||||
*/
|
|
||||||
class RenderEngine
|
|
||||||
: public RenderGraph
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
///// TODO: find out about the public operations
|
|
||||||
// note: the play controller lives in the steam-layer,
|
|
||||||
// but is a subsystem separate of the session.
|
|
||||||
RenderEngine();
|
|
||||||
|
|
||||||
private:
|
|
||||||
list<RenderGraph> renderSegments;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif /*STEAM_ENGINE_RENDERENGINE_H*/
|
|
||||||
|
|
@ -18,8 +18,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "steam/engine/rendergraph.hpp"
|
#include "steam/engine/rendergraph.hpp"
|
||||||
#include "steam/engine/state-closure-obsolete.hpp"
|
#include "lib/frameid.hpp" //////////////////////////////////////////////////////////////////////////////TICKET #1367 : role of frameid.hpp and NodeID could not yet be clarified (5/25)
|
||||||
#include "lib/frameid.hpp"
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@
|
||||||
|
|
||||||
/** @file rendergraph.hpp
|
/** @file rendergraph.hpp
|
||||||
** @deprecated a pile of crap, leftovers and started drafts, stalled since 2011 -- but maybe here to stay...
|
** @deprecated a pile of crap, leftovers and started drafts, stalled since 2011 -- but maybe here to stay...
|
||||||
|
** @todo 5/2025 the »Playback Vertical Slice« was not yet helpful to clarify
|
||||||
|
** how the top-level of the low-level-model will be organised.
|
||||||
|
** Some considerations were made regarding ExitNode, but nothing implemented yet.
|
||||||
|
** Might become relevant for the next »Vertical Slice«, where we want to add a clip
|
||||||
|
** and then actually invoke a real Builder implementation. Future work!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -21,13 +26,13 @@
|
||||||
#define STEAM_ENGINE_RENDERGRAPH_H
|
#define STEAM_ENGINE_RENDERGRAPH_H
|
||||||
|
|
||||||
#include "steam/common.hpp"
|
#include "steam/common.hpp"
|
||||||
#include "steam/engine/state-closure-obsolete.hpp"
|
|
||||||
#include "lib/time/timevalue.hpp"
|
#include "lib/time/timevalue.hpp"
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////TODO 7/11 this is a piece of debris, left over from the first attempt to complete the render nodes network.
|
/////////////////////////////TODO 7/11 this is a piece of debris, left over from the first attempt to complete the render nodes network.
|
||||||
/////////////////////////////TODO Meanwhile the intention is to treat the render nodes network more like a data structure,
|
/////////////////////////////TODO Meanwhile the intention is to treat the render nodes network more like a data structure,
|
||||||
/////////////////////////////TODO consequently this will become some kind of root or anchor point for this network
|
/////////////////////////////TODO consequently this will become some kind of root or anchor point for this network
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////TICKET #1367 : 5/25 left in tree for now; purpose unclear, maybe relevant for the next »Vertical Slice« ?
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
namespace steam {
|
||||||
|
|
@ -52,7 +57,8 @@ namespace engine {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RenderGraph()
|
RenderGraph()
|
||||||
: segment_(Time::ZERO, FSecs(5))
|
: output{nullptr}
|
||||||
|
, segment_(Time::ZERO, FSecs(5))
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("anything regarding the Fixture datastructure");
|
UNIMPLEMENTED ("anything regarding the Fixture datastructure");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
STATE-CLOSURE.hpp - Key Interface representing a render process and encapsulating state
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 state-closure.hpp
|
|
||||||
** Access point to an ongoing render's processing state.
|
|
||||||
**
|
|
||||||
** @deprecated 2024 Node-Invocation is reworked from ground up for the »Playback Vertical Slice«
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef STEAM_ENGINE_STATE_CLOSURE_OBSOLETE_H
|
|
||||||
#define STEAM_ENGINE_STATE_CLOSURE_OBSOLETE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
#include "lib/frameid.hpp"
|
|
||||||
#include "steam/engine/buffhandle.hpp"
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
using lumiera::FrameID;
|
|
||||||
using lumiera::NodeID;
|
|
||||||
|
|
||||||
class StateAdapter;
|
|
||||||
class BuffTableStorage;
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
|
|
||||||
/**
|
|
||||||
* Abstraction to access the state of a currently ongoing render/calculation process,
|
|
||||||
* as it is tied to the supporting facilities of the vault layer. An StateClosure (subclass) instance
|
|
||||||
* is the sole connection for the render node to invoke services of the vault needed
|
|
||||||
* to carry out the calculations.
|
|
||||||
*
|
|
||||||
* @see engine::RenderInvocation top-level entrance point
|
|
||||||
* @see nodeinvocation.hpp impl. used from \em within the nodes
|
|
||||||
*/
|
|
||||||
class StateClosure_OBSOLETE
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////TICKET #826 expected to be reworked to quite some extent (9/2011)
|
|
||||||
public:
|
|
||||||
/** allocate a new writable buffer with type and size according to
|
|
||||||
* the BuffDescr. The actual provider of this buffer depends
|
|
||||||
* on the StateClosure implementation; it could be a temporary, located in
|
|
||||||
* the cache, used for feeding calculated frames over a network, etc.
|
|
||||||
* @return a BuffHandle encapsulating the information necessary to get
|
|
||||||
* at the actual buffer address and for releasing the buffer.
|
|
||||||
*/
|
|
||||||
virtual BuffHandle allocateBuffer (const lumiera::StreamType*) =0;
|
|
||||||
|
|
||||||
/** resign control of the buffer denoted by the handle */
|
|
||||||
virtual void releaseBuffer (BuffHandle&) =0;
|
|
||||||
|
|
||||||
/** declare the data contained in the Buffer to be ready.
|
|
||||||
* The caller is required to restrain itself from modifying the data
|
|
||||||
* afterwards, as this buffer now can be used (readonly) by other
|
|
||||||
* calculation processes in parallel.
|
|
||||||
*/
|
|
||||||
virtual void is_calculated (BuffHandle const&) =0;
|
|
||||||
|
|
||||||
/** generate (or calculate) an ID denoting a media data frame
|
|
||||||
* appearing at the given position in the render network,
|
|
||||||
* for the time point this rendering process is currently
|
|
||||||
* calculating data for.
|
|
||||||
* @param NodeID the unique identification of a specific node
|
|
||||||
* @param chanNo the number of the output channel of this node
|
|
||||||
* @return a complete FrameID which unambiguously denotes this
|
|
||||||
* specific frame and can be used for caching
|
|
||||||
*/
|
|
||||||
virtual FrameID const& genFrameID (NodeID const&, uint chanNo) =0;
|
|
||||||
|
|
||||||
/** try to fetch an existing buffer containing the denoted frame
|
|
||||||
* from a cache or similar backing system (e.g. network peer).
|
|
||||||
* @return either a handle to a readonly buffer, or a null handle
|
|
||||||
* @note the client is responsible for not modifying the provided data
|
|
||||||
*/
|
|
||||||
virtual BuffHandle fetch (FrameID const&) =0;
|
|
||||||
|
|
||||||
/** necessary for creating a local BuffTableChunk */
|
|
||||||
virtual BuffTableStorage& getBuffTableStorage() =0;
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~StateClosure_OBSOLETE() {};
|
|
||||||
|
|
||||||
/** resolves to the StateClosure object currently "in charge".
|
|
||||||
* Intended as a performance shortcut to avoid calling
|
|
||||||
* up through a chain of virtual functions when deep down
|
|
||||||
* in chained ProcNode::pull() calls. This allows derived
|
|
||||||
* classes to proxy the state interface.
|
|
||||||
*/
|
|
||||||
virtual StateClosure_OBSOLETE& getCurrentImplementation () =0;
|
|
||||||
|
|
||||||
friend class engine::StateAdapter;
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespace steam::engine
|
|
||||||
#endif /*STEAM_ENGINE_STATE_CLOSURE_OBSOLETE_H*/
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
Assembler - building facility (implementation of the build process)
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 assembler.cpp
|
|
||||||
** @todo initially generated code of unclear relevance
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
|
||||||
#include "steam/mobject/builder/assembler.hpp"
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace mobject {
|
|
||||||
namespace builder {
|
|
||||||
|
|
||||||
|
|
||||||
engine::RenderEngine &
|
|
||||||
Assembler::build ()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("the builder...");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}} // namespace steam::mobject::builder
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
ASSEMBLER.hpp - building facility (implementation of the build process)
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 assembler.hpp
|
|
||||||
** @todo initially generated code of unclear relevance
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MOBJECT_BUILDER_ASSEMBLER_H
|
|
||||||
#define MOBJECT_BUILDER_ASSEMBLER_H
|
|
||||||
|
|
||||||
#include "steam/engine/renderengine.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace steam {
|
|
||||||
namespace mobject {
|
|
||||||
namespace builder {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the actual building facility:
|
|
||||||
* provided the correct tools and associations,
|
|
||||||
* it serves to build and connect the individual ProcNode objects
|
|
||||||
*/
|
|
||||||
class Assembler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
engine::RenderEngine&
|
|
||||||
build ();
|
|
||||||
// TODO: allocation, GC???
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}} // namespace steam::mobject::builder
|
|
||||||
#endif
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace builder {
|
||||||
|
|
||||||
/** receive the finished product of the build process; effectively
|
/** receive the finished product of the build process; effectively
|
||||||
* releases any other builder tool object
|
* releases any other builder tool object
|
||||||
* @todo unclear what to do and to return here
|
* @todo 2025 unclear what to do and to return here ///////////////////////////////////////////////TICKET #1367 : 5/25 left in tree for now; purpose unclear, maybe relevant for the next »Vertical Slice« ?
|
||||||
*/
|
*/
|
||||||
engine::RenderGraph& getProduct ();
|
engine::RenderGraph& getProduct ();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -87,109 +87,6 @@ return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
TEST "ConfigFlags_test" ConfigFlags_test <<END
|
|
||||||
out-lit: Conf0 :-
|
|
||||||
out-lit: Conf1 :-<1>-
|
|
||||||
out-lit: Conf2 :-<2>-
|
|
||||||
out-lit: Conf3 :-<3>-
|
|
||||||
out-lit: Conf4 :-<2>-<4>-
|
|
||||||
out-lit: AllFlags :-<1>-<2>-<3>-<4>-
|
|
||||||
out-lit: __________________________
|
|
||||||
out-lit: __________________________ check_flags()
|
|
||||||
out-lit: Flags1 :-<2>-<4>-
|
|
||||||
out-lit: Flags2 :-<2>-<4>-
|
|
||||||
out-lit: SimpleConfig_defined_by_Typelist :-<1>-
|
|
||||||
out-lit: AnotherConfig_defined_by_Typelist :-<1>-<2>-<3>-<4>-
|
|
||||||
out-lit: __________________________
|
|
||||||
out-lit: __________________________ check_instantiation()
|
|
||||||
out-lit: defined Conf0? ---> 0
|
|
||||||
out-lit: defined Conf1? ---> 1
|
|
||||||
out-lit: defined Conf2? ---> 1
|
|
||||||
out-lit: defined Conf3? ---> 1
|
|
||||||
out-lit: defined Conf4? ---> 1
|
|
||||||
out-lit: defined Trash? ---> 0
|
|
||||||
out-lit: __________________________
|
|
||||||
out-lit: __________________________ check_filter()
|
|
||||||
out-lit: SomeFlagsets :
|
|
||||||
out-lit: +---<1>-<3>-+
|
|
||||||
out-lit: +---<2>-<4>-+-
|
|
||||||
out-lit: Configs_defined_by_Flagsets :
|
|
||||||
out-lit: +-Conf-[-<1>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]-
|
|
||||||
out-lit: Filter_possible_Configs :
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]-
|
|
||||||
out-lit: AllFlagCombinations :
|
|
||||||
out-lit: +---<1>-<2>-<3>-<4>-<·>-+
|
|
||||||
out-lit: +---<1>-<2>-<3>-<·>-+
|
|
||||||
out-lit: +---<1>-<2>-<4>-<·>-+
|
|
||||||
out-lit: +---<1>-<2>-<·>-+
|
|
||||||
out-lit: +---<1>-<3>-<4>-<·>-+
|
|
||||||
out-lit: +---<1>-<3>-<·>-+
|
|
||||||
out-lit: +---<1>-<4>-<·>-+
|
|
||||||
out-lit: +---<1>-<·>-+
|
|
||||||
out-lit: +---<2>-<3>-<4>-<·>-+
|
|
||||||
out-lit: +---<2>-<3>-<·>-+
|
|
||||||
out-lit: +---<2>-<4>-<·>-+
|
|
||||||
out-lit: +---<2>-<·>-+
|
|
||||||
out-lit: +---<3>-<4>-<·>-+
|
|
||||||
out-lit: +---<3>-<·>-+
|
|
||||||
out-lit: +---<4>-<·>-+
|
|
||||||
out-lit: +---<·>-+-
|
|
||||||
out-lit: ListAllConfigs :
|
|
||||||
out-lit: +-Conf-[-<1>-<2>-<3>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<2>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<2>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<2>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<3>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<1>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<1>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<3>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<2>-]
|
|
||||||
out-lit: +-Conf-[-<3>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<3>-]
|
|
||||||
out-lit: +-Conf-[-<4>-]
|
|
||||||
out-lit: +-Conf-[-]-
|
|
||||||
out-lit: Filter_all_possible_Configs :
|
|
||||||
out-lit: +-Conf-[-<1>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<2>-]
|
|
||||||
out-lit: +-Conf-[-<3>-]-
|
|
||||||
out-lit: __________________________
|
|
||||||
out-lit: __________________________ check_FlagInfo()
|
|
||||||
out-lit: Flags1 :-<1>-<3>-
|
|
||||||
out-lit: max bit : 3
|
|
||||||
out-lit: binary code: 10
|
|
||||||
out-lit: SomeConfigs :
|
|
||||||
out-lit: +-Conf-[-<1>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]-
|
|
||||||
out-lit: max bit in [SomeConfigs] : 4
|
|
||||||
out-lit: TestVisitor application:
|
|
||||||
out-lit: visit(code=10) -->
|
|
||||||
out-lit: +-Conf-[-<1>-<3>-]-
|
|
||||||
out-lit: visit(code=20) -->
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]-
|
|
||||||
out-lit: __________________________
|
|
||||||
out-lit: __________________________ check_ConfigSelector()
|
|
||||||
out-lit: Possible_Configs :
|
|
||||||
out-lit: +-Conf-[-<1>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<3>-]
|
|
||||||
out-lit: +-Conf-[-<2>-<4>-]
|
|
||||||
out-lit: +-Conf-[-<2>-]
|
|
||||||
out-lit: +-Conf-[-<3>-]-
|
|
||||||
out-lit: Flag-code = 2 ConfigSelector() ---> 1010
|
|
||||||
out-lit: Flag-code = 12 ConfigSelector() ---> 1023
|
|
||||||
out-lit: Flag-code = 20 ConfigSelector() ---> 1024
|
|
||||||
out-lit: Flag-code = 4 ConfigSelector() ---> 1020
|
|
||||||
out-lit: Flag-code = 8 ConfigSelector() ---> 1030
|
|
||||||
out: LUMIERA_ERROR_INVALID:invalid input or parameters.+No preconfigured factory for config-bits=10111
|
|
||||||
return: 0
|
|
||||||
END
|
|
||||||
|
|
||||||
|
|
||||||
TEST "Duck typing support" DuckDetector_test <<END
|
TEST "Duck typing support" DuckDetector_test <<END
|
||||||
out: HasNested_Core<PropperGander> : Yes
|
out: HasNested_Core<PropperGander> : Yes
|
||||||
out: HasNested_Core<Propaganda> : No
|
out: HasNested_Core<Propaganda> : No
|
||||||
|
|
|
||||||
|
|
@ -1,328 +0,0 @@
|
||||||
/*
|
|
||||||
ConfigFlags(Test) - generating a configuration type defined by flags
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
|
||||||
|
|
||||||
**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 config-flags-test.cpp
|
|
||||||
** \par build a type representing a single configuration defined by a set of flags
|
|
||||||
**
|
|
||||||
** The semi-automatic assembly of processing node invocation code utilises some
|
|
||||||
** metaprogramming to generate a factory, which in turn produces node wiring objects
|
|
||||||
** according to the configuration to be used for the corresponding ProcNode. This relies on
|
|
||||||
** generating a distinct type based on a given set of configuration flags,
|
|
||||||
** which is covered by this test.
|
|
||||||
**
|
|
||||||
** @see configflags.hpp
|
|
||||||
** @see typelistmanip.hpp
|
|
||||||
** @see nodewiring-config.hpp real world usage example
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/test/run.hpp"
|
|
||||||
#include "lib/format-string.hpp"
|
|
||||||
#include "lib/meta/generator.hpp"
|
|
||||||
#include "lib/meta/typelist-manip.hpp"
|
|
||||||
#include "lib/meta/configflags.hpp"
|
|
||||||
#include "meta/typelist-diagnostics.hpp"
|
|
||||||
#include "steam/engine/nodewiring-config.hpp"
|
|
||||||
#include "lib/format-cout.hpp"
|
|
||||||
#include "lib/util.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using ::test::Test;
|
|
||||||
using util::_Fmt;
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
|
||||||
namespace meta {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
using steam::engine::config::Instantiation;
|
|
||||||
|
|
||||||
namespace { // internal definitions
|
|
||||||
|
|
||||||
enum Cases
|
|
||||||
{ ONE = 1
|
|
||||||
, TWO
|
|
||||||
, THR
|
|
||||||
, FOU
|
|
||||||
, NUM_Cases = FOU
|
|
||||||
|
|
||||||
, NOT_SET = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* === Test data === */
|
|
||||||
typedef Config<> Conf0;
|
|
||||||
typedef Config<ONE> Conf1;
|
|
||||||
typedef Config<TWO> Conf2;
|
|
||||||
typedef Config<THR> Conf3;
|
|
||||||
typedef Config<TWO,FOU> Conf4;
|
|
||||||
|
|
||||||
typedef Flags<ONE,THR>::Tuple Flags1;
|
|
||||||
typedef Flags<TWO,FOU>::Tuple Flags2;
|
|
||||||
typedef Types<Flags1,Flags2> SomeFlagsets;
|
|
||||||
|
|
||||||
typedef Flags<ONE,TWO,THR,FOU>::Tuple AllFlags;
|
|
||||||
typedef CombineFlags<AllFlags> AllFlagCombinations;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** a type which is only partially defined, for some configs.
|
|
||||||
* In ConfigFlags_test::check_filter() we use the metaprogramming machinery
|
|
||||||
* to figure out all possible configs for which \c struct Maybe is defined.
|
|
||||||
* (for this to work, the "defined" specialisations need to provide a
|
|
||||||
* typedef \c is_defined )
|
|
||||||
*/
|
|
||||||
template<class CONF> struct Maybe;
|
|
||||||
|
|
||||||
struct Indeed { typedef Yes_t is_defined; };
|
|
||||||
template<> struct Maybe<Conf1> : Indeed { enum{ CODE = 10 }; };
|
|
||||||
template<> struct Maybe<Conf3> : Indeed { enum{ CODE = 30 }; };
|
|
||||||
|
|
||||||
template<uint Fl>
|
|
||||||
struct Maybe<Config<TWO,Fl>>
|
|
||||||
{
|
|
||||||
typedef Yes_t is_defined;
|
|
||||||
|
|
||||||
enum{ CODE = 20 + Fl };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // (End) internal defs
|
|
||||||
|
|
||||||
#define PRINT_DELIMITER(TITLE) \
|
|
||||||
cout << "__________________________\n" \
|
|
||||||
"__________________________ " \
|
|
||||||
<< STRINGIFY(TITLE) << "\n";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
* @test check the handling of types representing a specific configuration.
|
|
||||||
* Basically, this is a bitset like feature, but working on types
|
|
||||||
* instead of runtime values. The Goal is to detect automatically
|
|
||||||
* all possible defined specialisations of some template based on
|
|
||||||
* such configuration-tuples. This allows us to assemble the glue code
|
|
||||||
* for pulling data from processing nodes out of small building blocks
|
|
||||||
* in all possible configurations.
|
|
||||||
*/
|
|
||||||
class ConfigFlags_test : public Test
|
|
||||||
{
|
|
||||||
virtual void run(Arg)
|
|
||||||
{
|
|
||||||
check_testdata ();
|
|
||||||
check_flags();
|
|
||||||
check_instantiation ();
|
|
||||||
check_filter ();
|
|
||||||
check_FlagInfo ();
|
|
||||||
check_ConfigSelector ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void check_testdata ()
|
|
||||||
{
|
|
||||||
DISPLAY (Conf0);
|
|
||||||
DISPLAY (Conf1);
|
|
||||||
DISPLAY (Conf2);
|
|
||||||
DISPLAY (Conf3);
|
|
||||||
DISPLAY (Conf4);
|
|
||||||
|
|
||||||
DISPLAY (AllFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @test conversion between list-of-flags and a config-type in both directions */
|
|
||||||
void check_flags ()
|
|
||||||
{
|
|
||||||
PRINT_DELIMITER (check_flags());
|
|
||||||
|
|
||||||
typedef Config<TWO,FOU> Flags1;
|
|
||||||
typedef Flags<TWO,FOU> Flags2;
|
|
||||||
DISPLAY (Flags1);
|
|
||||||
DISPLAY (Flags2);
|
|
||||||
// should denote the same type
|
|
||||||
Flags1::Flags flags1 = Flags2::Tuple();
|
|
||||||
Flags2::Tuple flags2 = flags1;
|
|
||||||
CHECK (1==sizeof(flags1)); // pure marker-type without content
|
|
||||||
CHECK (1==sizeof(flags2));
|
|
||||||
|
|
||||||
typedef DefineConfigByFlags<Node<Flag<ONE>,NullType>>::Config SimpleConfig_defined_by_Typelist;
|
|
||||||
DISPLAY (SimpleConfig_defined_by_Typelist);
|
|
||||||
|
|
||||||
typedef DefineConfigByFlags<AllFlags>::Config AnotherConfig_defined_by_Typelist;
|
|
||||||
DISPLAY (AnotherConfig_defined_by_Typelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @test creates a predicate template (metafunction) returning true
|
|
||||||
* iff the template \c Maybe is defined for the configuration in question
|
|
||||||
*/
|
|
||||||
void check_instantiation ()
|
|
||||||
{
|
|
||||||
#define CAN_INSTANTIATE(NAME) \
|
|
||||||
cout << "defined " \
|
|
||||||
<< STRINGIFY(NAME) \
|
|
||||||
<< "? ---> " \
|
|
||||||
<< Instantiation<Maybe>::Test<NAME>::value << "\n";
|
|
||||||
|
|
||||||
PRINT_DELIMITER (check_instantiation());
|
|
||||||
|
|
||||||
CAN_INSTANTIATE (Conf0);
|
|
||||||
CAN_INSTANTIATE (Conf1);
|
|
||||||
CAN_INSTANTIATE (Conf2);
|
|
||||||
CAN_INSTANTIATE (Conf3);
|
|
||||||
CAN_INSTANTIATE (Conf4);
|
|
||||||
|
|
||||||
typedef Config<THR,THR> Trash;
|
|
||||||
CAN_INSTANTIATE (Trash);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @test given a list of flag-tuples, we first create config-types out of them
|
|
||||||
* and then filter out those configs for which \c template Maybe is defined
|
|
||||||
*/
|
|
||||||
void check_filter ()
|
|
||||||
{
|
|
||||||
PRINT_DELIMITER (check_filter());
|
|
||||||
|
|
||||||
DISPLAY (SomeFlagsets);
|
|
||||||
|
|
||||||
typedef Apply<SomeFlagsets::List, DefineConfigByFlags> Configs_defined_by_Flagsets;
|
|
||||||
DISPLAY (Configs_defined_by_Flagsets);
|
|
||||||
|
|
||||||
typedef Filter<Configs_defined_by_Flagsets::List,Instantiation<Maybe>::Test> Filter_possible_Configs;
|
|
||||||
DISPLAY (Filter_possible_Configs);
|
|
||||||
|
|
||||||
|
|
||||||
DISPLAY (AllFlagCombinations);
|
|
||||||
typedef Apply<AllFlagCombinations::List, DefineConfigByFlags> ListAllConfigs;
|
|
||||||
DISPLAY (ListAllConfigs);
|
|
||||||
|
|
||||||
typedef Filter<ListAllConfigs::List,Instantiation<Maybe>::Test> Filter_all_possible_Configs;
|
|
||||||
DISPLAY (Filter_all_possible_Configs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct TestVisitor
|
|
||||||
{
|
|
||||||
string result; ///< metafunction result
|
|
||||||
|
|
||||||
TestVisitor() : result ("TestVisitor application:\n") {}
|
|
||||||
|
|
||||||
/* === visitation interface === */
|
|
||||||
typedef string Ret;
|
|
||||||
|
|
||||||
Ret done() {return result; }
|
|
||||||
|
|
||||||
template<class CONF>
|
|
||||||
void
|
|
||||||
visit (ulong code)
|
|
||||||
{
|
|
||||||
result += string (_Fmt ("visit(code=%u) -->%s\n")
|
|
||||||
% code % Printer<CONF>::print() );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @test FlagInfo metafunction, which takes as argument a list-of-flags
|
|
||||||
* as well as a list-of-lists-of-flags and especially allows to
|
|
||||||
* apply a visitor object to the latter
|
|
||||||
*/
|
|
||||||
void check_FlagInfo()
|
|
||||||
{
|
|
||||||
PRINT_DELIMITER (check_FlagInfo());
|
|
||||||
|
|
||||||
DISPLAY (Flags1);
|
|
||||||
cout << "max bit : " << FlagInfo<Flags1>::BITS <<"\n";
|
|
||||||
cout << "binary code: " << FlagInfo<Flags1>::CODE <<"\n";
|
|
||||||
|
|
||||||
typedef Apply<SomeFlagsets::List, DefineConfigByFlags> SomeConfigs;
|
|
||||||
DISPLAY (SomeConfigs);
|
|
||||||
cout << "max bit in [SomeConfigs] : " << FlagInfo<SomeConfigs::List>::BITS <<"\n";
|
|
||||||
|
|
||||||
TestVisitor visitor;
|
|
||||||
cout << FlagInfo<SomeConfigs::List>::accept (visitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class CONF>
|
|
||||||
struct TestFactory
|
|
||||||
{
|
|
||||||
uint operator() () { return offset_ + Maybe<CONF>::CODE; }
|
|
||||||
TestFactory(long o) : offset_(o) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
long offset_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @test use the ConfigSelector template to build a set of factories,
|
|
||||||
* based on a set of configurations. Then invoke the appropriate
|
|
||||||
* factory by specifying the configuration bit code
|
|
||||||
*/
|
|
||||||
void check_ConfigSelector()
|
|
||||||
{
|
|
||||||
PRINT_DELIMITER (check_ConfigSelector());
|
|
||||||
|
|
||||||
typedef Apply<AllFlagCombinations::List, DefineConfigByFlags> ListAllConfigs;
|
|
||||||
typedef Filter<ListAllConfigs::List,Instantiation<Maybe>::Test> Possible_Configs;
|
|
||||||
DISPLAY (Possible_Configs);
|
|
||||||
|
|
||||||
using steam::engine::config::ConfigSelector;
|
|
||||||
typedef ConfigSelector< TestFactory // Factory template
|
|
||||||
, uint(void) // Factory function type
|
|
||||||
, long // common ctor argument
|
|
||||||
> TestFactorySelector;
|
|
||||||
|
|
||||||
const long offset = 1000; // parameter fed to all TestFactory ctors
|
|
||||||
TestFactorySelector testConfigSelector (Possible_Configs::List(), offset);
|
|
||||||
|
|
||||||
|
|
||||||
#define INVOKE_CONFIG_SELECTOR(CODE) \
|
|
||||||
cout << " Flag-code = " << CODE \
|
|
||||||
<< " ConfigSelector() ---> " \
|
|
||||||
<< testConfigSelector[CODE] () << "\n";
|
|
||||||
|
|
||||||
INVOKE_CONFIG_SELECTOR (2);
|
|
||||||
INVOKE_CONFIG_SELECTOR (12);
|
|
||||||
INVOKE_CONFIG_SELECTOR (20);
|
|
||||||
INVOKE_CONFIG_SELECTOR (4);
|
|
||||||
INVOKE_CONFIG_SELECTOR (8);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
INVOKE_CONFIG_SELECTOR (23);
|
|
||||||
NOTREACHED ();
|
|
||||||
}
|
|
||||||
catch (lumiera::error::Invalid& err)
|
|
||||||
{
|
|
||||||
cout << err.what() << "\n";
|
|
||||||
lumiera_error (); // reset error flag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** Register this test class... */
|
|
||||||
LAUNCHER (ConfigFlags_test, "unit common");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}} // namespace lib::meta::test
|
|
||||||
|
|
@ -162820,7 +162820,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
<arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/>
|
<arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/>
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
<node COLOR="#435e98" CREATED="1744719728307" ID="ID_1783840760" MODIFIED="1748489965153" TEXT="siehe steam/external/libgavl.hpp">
|
<node COLOR="#435e98" CREATED="1744719728307" FOLDED="true" ID="ID_1783840760" MODIFIED="1748489965153" TEXT="siehe steam/external/libgavl.hpp">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -162838,7 +162838,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#166d3d" CREATED="1747489147636" ID="ID_1626357015" MODIFIED="1747524236658" TEXT="gavl_time_t ersetzen">
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#166d3d" CREATED="1747489147636" FOLDED="true" ID="ID_1626357015" MODIFIED="1747524236658" TEXT="gavl_time_t ersetzen">
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1747489190149" ID="ID_395347682" LINK="https://issues.lumiera.org/ticket/1261" MODIFIED="1747489218934" TEXT="siehe Design-Skizze in #1261">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1747489190149" ID="ID_395347682" LINK="https://issues.lumiera.org/ticket/1261" MODIFIED="1747489218934" TEXT="siehe Design-Skizze in #1261">
|
||||||
<icon BUILTIN="idea"/>
|
<icon BUILTIN="idea"/>
|
||||||
|
|
@ -162865,7 +162865,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1747489277561" ID="ID_1782395866" MODIFIED="1747489284084" TEXT="einzige Ausnahme: Time.cpp"/>
|
<node CREATED="1747489277561" ID="ID_1782395866" MODIFIED="1747489284084" TEXT="einzige Ausnahme: Time.cpp"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#bcd0c6" COLOR="#338800" CREATED="1747520420088" ID="ID_1585137684" MODIFIED="1748490000277" TEXT="C-Library für Time-Handling auflösen">
|
<node BACKGROUND_COLOR="#bcd0c6" COLOR="#338800" CREATED="1747520420088" FOLDED="true" ID="ID_1585137684" MODIFIED="1748490000277" TEXT="C-Library für Time-Handling auflösen">
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
<node CREATED="1747520433501" ID="ID_1627011016" MODIFIED="1747520503864" TEXT="die ist mir schon lange ein »Dorn im Auge«">
|
<node CREATED="1747520433501" ID="ID_1627011016" MODIFIED="1747520503864" TEXT="die ist mir schon lange ein »Dorn im Auge«">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
|
@ -163407,8 +163407,53 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1746059870062" TEXT="auch altes RenderNode-Framework zurückbauen">
|
<node COLOR="#338800" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1748563719621" TEXT="auch altes RenderNode-Framework zurückbauen">
|
||||||
<icon BUILTIN="flag-yellow"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#338800" CREATED="1748561872884" ID="ID_962941766" MODIFIED="1748563677391" TEXT="Ansatzpunkte">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
<node COLOR="#338800" CREATED="1748561878800" ID="ID_384659073" MODIFIED="1748562139320" TEXT="suche Verwendungen von frameid.hpp">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#338800" CREATED="1748561923626" ID="ID_282276348" MODIFIED="1748561938045" TEXT="lösche alles um renderengine.hpp|cpp">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1748562090488" ID="ID_672562159" MODIFIED="1748562131826" TEXT="channel-descriptor_obsolete">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#435e98" CREATED="1748561916132" ID="ID_1417094608" MODIFIED="1748562136917" TEXT="lasse rendergraph.hpp bestehen">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
<node CREATED="1748561946315" ID="ID_1051187114" MODIFIED="1748561956269" TEXT="Übergangspunkt zum Builder-Entwurf"/>
|
||||||
|
<node CREATED="1748561956900" ID="ID_544436989" MODIFIED="1748561985361" TEXT="das sind auch alles Stubs">
|
||||||
|
<icon BUILTIN="broken-line"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1748561964860" ID="ID_904849096" MODIFIED="1748561979175" TEXT="aber relevante Platzhalter">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1748561897480" ID="ID_1077832767" MODIFIED="1748563664819" TEXT="nodewiring-conf.hpp aufklären">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#338800" CREATED="1748562174413" ID="ID_1385748288" MODIFIED="1748563666964" TEXT="configflags.hpp kann weg!">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head/>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
das ist der Ansatz mit den Feature-Flags in Metaprogramming.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Dieser Weg ist definitiv obsolet!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Habe stattdessen die Feed-Manifold, und der flexible Teil besteht nun Richtung Weaving Pattern und Domain Ontologies
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html></richcontent>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#e304be" CREATED="1748563681452" ID="ID_223953539" MODIFIED="1748563712702" TEXT="hat Spaß gemacht">
|
||||||
|
<font ITALIC="true" NAME="SansSerif" SIZE="15"/>
|
||||||
|
<icon BUILTIN="ksmiletris"/>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1744756270441" ID="ID_831819953" LINK="https://issues.lumiera.org/ticket/473" MODIFIED="1746059845274" TEXT="RefArray und ScopedHolder müssen jetzt wirklich mal weg">
|
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1744756270441" ID="ID_831819953" LINK="https://issues.lumiera.org/ticket/473" MODIFIED="1746059845274" TEXT="RefArray und ScopedHolder müssen jetzt wirklich mal weg">
|
||||||
<arrowlink COLOR="#fd26d0" DESTINATION="ID_1135941103" ENDARROW="Default" ENDINCLINATION="-1048;89;" ID="Arrow_ID_1050531240" STARTARROW="None" STARTINCLINATION="-1120;-23;"/>
|
<arrowlink COLOR="#fd26d0" DESTINATION="ID_1135941103" ENDARROW="Default" ENDINCLINATION="-1048;89;" ID="Arrow_ID_1050531240" STARTARROW="None" STARTINCLINATION="-1120;-23;"/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue