WIP: implementation of a node fabrication code path
This commit is contained in:
parent
32612a1a97
commit
1430965798
13 changed files with 163 additions and 88 deletions
|
|
@ -23,8 +23,13 @@
|
|||
|
||||
#include "proc/asset/effect.hpp"
|
||||
|
||||
namespace asset
|
||||
namespace asset {
|
||||
|
||||
Proc::ProcFunc*
|
||||
Effect::resolveProcessor() const
|
||||
{
|
||||
UNIMPLEMENTED ("do the actual resolution plugin -> callable processing function");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
|
||||
|
||||
namespace asset
|
||||
{
|
||||
namespace asset {
|
||||
|
||||
/**
|
||||
* Effect or media processing component
|
||||
|
|
@ -38,22 +37,18 @@ namespace asset
|
|||
{
|
||||
|
||||
public:
|
||||
/** resolve any plugin and configuration info
|
||||
* to yield the actual media data processing function.
|
||||
* @return a function ready to be invoked; either the
|
||||
* "real thing" or a suitable placeholder.
|
||||
* @throw lumiera::error::Fatal if unable to provide
|
||||
* any usable function or placeholder. This case
|
||||
* can be considered exceptional and justifies a
|
||||
* subsystem failure.
|
||||
*/
|
||||
ProcFunc*
|
||||
resolveProcessor();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
/** implementation of how to resolve the corresponding plugin
|
||||
* to yield an actual media data processing function. */
|
||||
ProcFunc*
|
||||
resolveProcessor() const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace asset
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -82,6 +82,20 @@ namespace asset {
|
|||
typedef void (ProcFunc) (PBuff);
|
||||
|
||||
|
||||
/** resolve any plugin and configuration info
|
||||
* to yield the actual media data processing function.
|
||||
* @return a function ready to be invoked; either the
|
||||
* "real thing" or a suitable placeholder.
|
||||
* @throw lumiera::error::Fatal if unable to provide
|
||||
* any usable function or placeholder. This case
|
||||
* can be considered exceptional and justifies a
|
||||
* subsystem failure.
|
||||
*/
|
||||
virtual ProcFunc*
|
||||
resolveProcessor() const =0;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
Proc (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
|
||||
friend class ProcFactory;
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@
|
|||
** thus it makes sense to utilise a single large buffer pointer array per pull() calldown
|
||||
** sequence and dynamically claim small chunks for each node.
|
||||
**
|
||||
** @see nodewiring-def.hpp
|
||||
** @see nodeoperation.hpp
|
||||
** @see bufftable.hpp storage for the buffer table
|
||||
** @see engine::Invocation
|
||||
** @see engine::RenderInvocation
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_BUFFHANDLE_H
|
||||
|
|
@ -116,7 +117,6 @@ namespace engine {
|
|||
};
|
||||
|
||||
|
||||
//////TODO: invent an input/output description pattern, which can be passed to the wiring factory
|
||||
|
||||
} // namespace engine
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,45 +31,8 @@ namespace engine {
|
|||
|
||||
namespace { // Details of node fabrication
|
||||
|
||||
using lib::AllocationCluster;
|
||||
|
||||
template<class NODE>
|
||||
NODE &
|
||||
makeNode ()
|
||||
{
|
||||
////TODO: this is a draft how it /might/ work
|
||||
////TODO: of course this can't be hard wired....
|
||||
|
||||
ProcNode * predecessor1, predecessor2;
|
||||
|
||||
WiringSituation setup;
|
||||
setup.defineInput (4, predecessor1, 2);
|
||||
setup.defineInput (2, predecessor2);
|
||||
|
||||
WiringFactory* wFac;
|
||||
|
||||
AllocationCluster allocator;
|
||||
bool doCache = (2 == 2); // find out Cache should be used for this node
|
||||
|
||||
WiringDescriptor & wDesc = (*wFac)(setup,doCache);
|
||||
|
||||
NODE* newNode = allocator.create<NODE> (wDesc);
|
||||
|
||||
return *newNode;
|
||||
|
||||
/*
|
||||
* Problems to be solved: /////////////TODO: see Ticket #247
|
||||
* - write a generic allocator, which later on can be augmented to do block wise bulk allocation /////////////DONE: AllocationCluster
|
||||
* - the allocator needs to keep track of the objects; actually he owns the objects /////////////DONE
|
||||
* - we need to access the wiring descriptor of the predecessor nodes. Which means, the code
|
||||
* must be in the body of NodeFactory (because the latter is friend of ProcNode and can access the wiring descriptor)
|
||||
* - btw reconsider if this level of protection is necessary, or if the const WiringDescriptor cant be just on the public interface of ProcNode
|
||||
* - find out how the Caching/ReadInput/InPlace detection can work
|
||||
* - think about a sensible Ctor for NodeFactory. This one must create the WiringFactory and pass the Allocator.
|
||||
* - all of this will be installed into the ToolFactory, i.e. it is part of the build process
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////TODO: still needed?
|
||||
|
||||
} // (END) Details of node fabrication
|
||||
|
||||
|
||||
|
|
@ -78,10 +41,16 @@ namespace engine {
|
|||
|
||||
|
||||
/** create a processing node able to render an effect */
|
||||
PTrafo
|
||||
NodeFactory::operator() (Placement<Effect> const&)
|
||||
PNode
|
||||
NodeFactory::operator() (Placement<Effect> const& effect, WiringSituation& intendedWiring)
|
||||
{
|
||||
UNIMPLEMENTED ("create proc node for Effect/Plugin");
|
||||
intendedWiring.resolveProcessor(effect->getProcAsset());
|
||||
WiringDescriptor& wiring = wiringFac_(intendedWiring);
|
||||
|
||||
PNode newNode = alloc_.create<ProcNode> (wiring);
|
||||
ENSURE (newNode);
|
||||
ENSURE (newNode->isValid());
|
||||
return newNode;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,12 @@
|
|||
|
||||
#include "proc/engine/procnode.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/engine/nodewiring.hpp"
|
||||
|
||||
|
||||
////////////////////////////////////TODO: make inclusions / forward definitions a bit more orthogonal....
|
||||
|
||||
namespace lib { class AllocationCluster; }
|
||||
|
||||
namespace mobject {
|
||||
namespace session {
|
||||
|
|
@ -43,9 +47,13 @@ namespace session {
|
|||
namespace engine {
|
||||
|
||||
using std::vector;
|
||||
using lib::AllocationCluster;
|
||||
|
||||
///////////////////////////// TODO: as of 9/09, it seems no longer necessary to use any subclasses of ProcNode
|
||||
class Trafo;
|
||||
typedef Trafo* PTrafo; ///< @note ProcNode is handled by pointer and bulk allocated/deallocated
|
||||
typedef Trafo* PTrafo; ///< @note ProcNode is handled by pointer and bulk allocated/deallocated
|
||||
|
||||
class WiringSituation;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -53,10 +61,17 @@ namespace engine {
|
|||
*/
|
||||
class NodeFactory
|
||||
{
|
||||
AllocationCluster& alloc_;
|
||||
WiringFactory wiringFac_;
|
||||
|
||||
public:
|
||||
|
||||
PTrafo operator() (mobject::session::PEffect const&);
|
||||
public:
|
||||
NodeFactory (AllocationCluster& a)
|
||||
: alloc_(a)
|
||||
, wiringFac_(alloc_)
|
||||
{ }
|
||||
|
||||
|
||||
PNode operator() (mobject::session::PEffect const&, WiringSituation&);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
** @see proc::engine::config::Strategy
|
||||
** @see nodewiring.hpp
|
||||
** @see configflags.hpp
|
||||
** @see config-flags-test.cpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
|
||||
#include "proc/engine/procnode.hpp"
|
||||
#include "lib/refarray.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
//#include <boost/scoped_ptr.hpp>
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
|
||||
namespace engine {
|
||||
|
||||
using lib::RefArray;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -70,6 +72,9 @@ namespace engine {
|
|||
class WiringSituation
|
||||
: boost::noncopyable
|
||||
{
|
||||
long flags_;
|
||||
asset::Proc::ProcFunc* function_;
|
||||
|
||||
protected:
|
||||
RefArray<ChannelDescriptor>& makeOutDescriptor() ;
|
||||
RefArray<InChanDescriptor>& makeInDescriptor() ;
|
||||
|
|
@ -86,6 +91,8 @@ namespace engine {
|
|||
* with connection informations later on.
|
||||
*/
|
||||
WiringSituation()
|
||||
: flags_(0)
|
||||
, function_(0)
|
||||
{
|
||||
UNIMPLEMENTED ("representation of the intended wiring");
|
||||
}
|
||||
|
|
@ -95,6 +102,8 @@ namespace engine {
|
|||
* of an existing predecessor node
|
||||
*/
|
||||
WiringSituation (PNode predecessor)
|
||||
: flags_(0)
|
||||
, function_(0)
|
||||
{
|
||||
UNIMPLEMENTED ("wiring representation; hook up connections 1:1");
|
||||
REQUIRE (predecessor);
|
||||
|
|
@ -105,6 +114,51 @@ namespace engine {
|
|||
}
|
||||
|
||||
|
||||
/** 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_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ namespace engine {
|
|||
{
|
||||
WiringSelector selector;
|
||||
|
||||
WiringFactoryImpl (Alloc& alloc)
|
||||
WiringFactoryImpl (AllocationCluster& alloc)
|
||||
: selector(config::PossibleConfigs::List(), alloc)
|
||||
{ }
|
||||
};
|
||||
|
|
@ -119,42 +119,40 @@ namespace engine {
|
|||
|
||||
|
||||
|
||||
/** As the WiringFactory (an all the embedded factories
|
||||
/** 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 As this ctor creates a WiringFactoryImpl instance,
|
||||
* compiling this invocation 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 out of some operation
|
||||
* control templates (policy classes). Compiling this operator function
|
||||
* actually drives the necessary template instantiations for all cases
|
||||
* encountered while building the node network.
|
||||
* 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.
|
||||
*/
|
||||
WiringDescriptor&
|
||||
WiringFactory::operator() (WiringSituation& setup, bool cache)
|
||||
WiringFactory::operator() (WiringSituation const& setup)
|
||||
{
|
||||
UNIMPLEMENTED ("build the actual wiring descriptor based on given operation options");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////TODO: how to get the WiringSituation into the factory????
|
||||
|
||||
|
||||
// Bits config (FlagInfo<Config>::CODE);
|
||||
// return pImpl_->selector[config]();
|
||||
////
|
||||
/////TODO: change the FunctionType to take an "input/output description pattern"
|
||||
/////TODO: invent such a pattern ---> buffhandle.hpp
|
||||
long config = setup.getFlags();
|
||||
return pImpl_->selector[config] (setup);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -90,9 +90,10 @@ namespace engine {
|
|||
|
||||
public:
|
||||
WiringFactory (lib::AllocationCluster& a);
|
||||
~WiringFactory ();
|
||||
|
||||
WiringDescriptor&
|
||||
operator() (WiringSituation& setup, bool cache); //////////////////TODO: of course this will accept *all* the relevant flags (not only "cache")
|
||||
operator() (WiringSituation const& setup);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ namespace engine {
|
|||
* holding the actual buffer pointers and issuing the recursive pull() calls
|
||||
* @see NodeWiring#callDown default implementation
|
||||
*/
|
||||
virtual BuffHandle callDown (State& currentProcess, uint requiredOutputNr) const =0;
|
||||
virtual BuffHandle
|
||||
callDown (State& currentProcess, uint requiredOutputNr) const =0;
|
||||
|
||||
friend class ProcNode;
|
||||
|
||||
|
|
@ -125,17 +126,20 @@ namespace engine {
|
|||
: wiringConfig_(wd)
|
||||
{ }
|
||||
|
||||
virtual ~ProcNode() {};
|
||||
|
||||
friend class NodeFactory;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
virtual ~ProcNode() {}; /////////////////////////TODO: do we still intend to build a hierarchy below ProcNode???
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
/** output channel count */
|
||||
uint nrO() { return wiringConfig_.nrO; }
|
||||
|
||||
|
||||
/** Engine Core operation: render and pull output from this node.
|
||||
* On return, currentProcess will hold onto output buffer(s)
|
||||
* containing the calculated result frames. In case this node
|
||||
|
|
@ -156,5 +160,14 @@ namespace engine {
|
|||
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
ProcNode::isValid() const
|
||||
{
|
||||
UNIMPLEMENTED ("ProcNode validity self-check");
|
||||
return false; //////////////////////////TODO
|
||||
}
|
||||
|
||||
|
||||
} // namespace engine
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ using std::string;
|
|||
namespace mobject {
|
||||
namespace session {
|
||||
|
||||
using asset::PProc;
|
||||
|
||||
|
||||
class Effect : public AbstractMO
|
||||
{
|
||||
|
|
@ -45,6 +47,8 @@ namespace session {
|
|||
string pluginID;
|
||||
|
||||
public:
|
||||
/** access the underlying processing asset */
|
||||
PProc getProcAsset () const;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -77,9 +77,15 @@ namespace test {
|
|||
AllocationCluster alloc;
|
||||
NodeFactory nodeFab(alloc);
|
||||
|
||||
PEffect pEffect; /////////////////TODO how to get an simple Effect MObject for Tests???
|
||||
WiringSituation setup;
|
||||
ProcNode * testSource; ///////////TODO: how to fabricate a test-Node???
|
||||
|
||||
|
||||
WiringSituation setup(testSource);
|
||||
|
||||
setup.defineInput (4, predecessor1, 2);
|
||||
setup.defineInput (2, predecessor2);
|
||||
|
||||
PEffect pEffect; /////////////////TODO how to get an simple Effect MObject for Tests???
|
||||
ProcNode* pNode = nodeFab (pEffect, setup);
|
||||
ASSERT (pNode);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue