WIP: implementation of a node fabrication code path

This commit is contained in:
Fischlurch 2009-09-05 04:10:51 +02:00
parent 32612a1a97
commit 1430965798
13 changed files with 163 additions and 88 deletions

View file

@ -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");
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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&);
};

View file

@ -43,6 +43,7 @@
** @see proc::engine::config::Strategy
** @see nodewiring.hpp
** @see configflags.hpp
** @see config-flags-test.cpp
**
*/

View file

@ -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_);
}
};

View file

@ -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);
}

View file

@ -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);
};

View file

@ -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

View file

@ -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;
};

View file

@ -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);