WIP continued with refactoring the Invocation

This commit is contained in:
Fischlurch 2008-07-16 05:09:04 +02:00
parent cb5d1fd03b
commit 63d5684c12
7 changed files with 290 additions and 47 deletions

56
src/common/frameid.hpp Normal file
View file

@ -0,0 +1,56 @@
/*
FRAMEID.hpp - distinct identification of a single data frame
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FRAMEID_H
#define LUMIERA_FRAMEID_H
namespace lumiera
{
/**
* Identification tuple for addressing frames unambiguosly.
*
* @todo currently (7/08) this is a dummy implementation to find out
* what interface the Proc layer needs. Probably the backend will
* later on define what is actually needed; this header should then
* be replaced by a combined C/C++ header
*/
class FrameID : boost::totally_ordered<FrameID>
{
long dummy;
public:
FrameID(long dum=0) : dummy(dum) {}
operator long () { return dummy; }
bool operator< (const FrameID& of) const { return dummy < of.dummy; }
bool operator== (const FrameID& of) const { return dummy == of.dummy; }
};
} // namespace lumiera
#endif

View file

@ -0,0 +1,32 @@
/*
BuffHandle - Buffer handling support for the render engine
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "proc/engine/buffhandle.hpp"
namespace engine {
/** */
} // namespace engine

View file

@ -0,0 +1,111 @@
/*
BUFFHANDLE.hpp - Buffer handling support for the render engine
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file procnode.hpp
** Interface to the processing nodes and the render nodes network.
**
** Actually, there are three different interfaces to consider
** - the ProcNode#pull is the invocation interface. It is call-style (easily callable by C)
** - the builder interface, comprised by the NodeFactory and the WiringFactory. It's C++ (using templates)
** - the actual processing function is supposed to be a C function; it uses a set of C functions
** for accessing the frame buffers with the data to be processed.
**
** 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 beahviour in a hard wired fashion.
**
** @see nodefactory.hpp
** @see operationpoint.hpp
*/
#ifndef ENGINE_BUFFHANDLE_H
#define ENGINE_BUFFHANDLE_H
//#include "proc/mobject/parameter.hpp"
//#include <vector>
namespace engine {
// using std::vector;
/**
* Handle for a buffer for processing data, abstracting away the actual implementation.
* The real buffer pointer can be retrieved by dereferencing this smart-handle class.
*/
struct BuffHandle
{
typedef float Buff;
typedef Buff* PBuff;//////TODO define the Buffer type(s)
PBuff
operator->() const
{
return pBuffer_;
}
Buff&
operator* () const
{
ENSURE (pBuffer_);
return *pBuffer_;
}
protected:
PBuff pBuffer_;
long sourceID_;
};
/**
* Buffer Type information.
* Given a BufferDescriptor, it is possible to allocate a buffer
* of suitable size and type by using State::allocateBuffer().
*/
struct BufferDescriptor
{
char typeID_; ///////TODO define the Buffer type(s)
};
/**
* 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 any processing
* function
*/
struct BuffTable
{
BuffHandle *const outHandle;
BuffHandle *const inHandle;
BuffHandle::PBuff *const outBuff;
BuffHandle::PBuff *const inBuff;
};
} // namespace engine
#endif

View file

@ -52,7 +52,9 @@
#define ENGINE_NODEOPERATION_H
#include "proc/state.hpp"
#include "proc/engine/procnode.hpp"
#include "proc/engine/buffhandle.hpp"
#include "proc/engine/nodewiringconfig.hpp"
#include "lib/appconfig.hpp"
@ -88,8 +90,6 @@ namespace engine {
State& parent_;
State& current_;
uint requiredOutputNr;
StateAdapter (State& callingProcess)
: parent_ (callingProcess),
current_(callingProcess.getCurrentImplementation())
@ -97,44 +97,71 @@ namespace engine {
virtual State& getCurrentImplementation () { return current_; }
public: /* === proxying the State 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); }
// note: allocateBuffer() is choosen specifically based on the actual node wiring
};
struct BuffTable
{
BuffHandle *const outHandle;
BuffHandle *const inHandle;
BuffHandle::PBuff *const outBuff;
BuffHandle::PBuff *const inBuff;
};
struct Invocation
: StateAdapter
{
WiringDescriptor const& wiring;
BuffTable& buffTab;
const uint outNr;
protected:
Invocation (WiringDescriptor const& w, BuffTable& b, uint o)
: wiring(w),
Invocation (State& callingProcess, WiringDescriptor const& w, BuffTable& b, uint o)
: StateAdapter(callingProcess),
wiring(w),
buffTab(b),
outNr(o)
{ }
};
template<uint SZ>
class BuffTableStorage
: public BuffTable
{
BuffHandle hTab_[SZ];
BuffHandle::PBuff pTab_[SZ];
protected:
BuffTableStorage (WiringDescriptor const& wd)
{
const uint nrI = wd.getNrI();
const uint nrO = wd.getNrO();
REQUIRE (nrI+nrO <= SZ);
this->outHandle = &hTab_[0];
this->inHandle = &hTab_[nrO];
this->outBuff = &pTab_[0];
this->inBuff = &pTab_[nrO];
}
};
template<uint SZ> /////////////////TODO: rather template on the BufferProvider
class InvocationImpl
: private StateAdapter,
private BuffTableStorage<SZ>,
: private BuffTableStorage<SZ>,
public Invocation
{
protected:
InvocationImpl (State& callingProcess, WiringDescriptor const& w, const uint outCh)
: StateAdapter(callingProcess),
BuffTableStorage(w),
Invocation(w, static_cast<BuffTable&>(*this), outCh)
: BuffTableStorage<SZ>(w),
Invocation(callingProcess, w, static_cast<BuffTable&>(*this), outCh)
{ }
/** contains the details of Cache query and recursive calls
@ -266,13 +293,13 @@ namespace engine {
template<>
struct OutBuffSource<PARENT>
{
State& getBufferProvider (InvocationStateBase& thisState) { return thisState.parent_; }
static State& getBufferProvider (Invocation& thisState) { return thisState.parent_; }
};
template<>
struct OutBuffSource<CACHE>
{
State& getBufferProvider (InvocationStateBase& thisState) { return thisState.current_; }
static State& getBufferProvider (Invocation& thisState) { return thisState.current_; }
};
@ -331,7 +358,7 @@ namespace engine {
struct Strategy ;
template<char CACE_Fl=0, char INPLACE_Fl=0>
template<char CACHE_Fl=0, char INPLACE_Fl=0>
struct SelectBuffProvider;
template<> struct SelectBuffProvider<CACHING> : OutBuffSource<CACHE> { };
@ -354,7 +381,7 @@ namespace engine {
{ };
template<char INPLACE_Fl>
struct Strategy< Config<PROCESS> >
struct Strategy< Config<PROCESS,INPLACE_Fl> >
: PullInput<
AllocOutput<SelectBuffProvider<NOT_SET,INPLACE_Fl>,
ProcessData<

View file

@ -49,9 +49,16 @@ namespace engine {
class NodeWiring
: public WiringDescriptor
{
const uint siz_;
const uint nrO_;
friend class WiringFactory;
public:
virtual uint getNrI() const { return siz_ - nrO_; }
virtual uint getNrO() const { return nrO_; }
protected:
virtual BuffHandle
callDown (State& currentProcess, uint requiredOutputNr) const

View file

@ -70,6 +70,9 @@ namespace engine {
public:
virtual ~WiringDescriptor() {}
virtual uint getNrI() const =0; ///////////TODO: indeed need a virtual function??
virtual uint getNrO() const =0;
protected:
/** the wiring-dependent part of the node operation.
* Includes the creation of a one-way state object on the stack

View file

@ -28,35 +28,17 @@
#include "pre.hpp"
#include "proc/lumiera.hpp"
#include "common/frameid.hpp"
#include "proc/engine/buffhandle.hpp"
#include <cstddef>
namespace engine {
class InvocationStateBase;
struct BuffHandle
{
typedef float Buff;
typedef Buff* PBuff;//////TODO define the Buffer type(s)
PBuff
operator->() const
{
return pBuffer_;
}
Buff&
operator* () const
{
ENSURE (pBuffer_);
return *pBuffer_;
}
protected:
PBuff pBuffer_;
long sourceID_;
};
using lumiera::FrameID;
class StateAdapter;
class State
@ -72,9 +54,34 @@ namespace engine {
*/
virtual State& getCurrentImplementation () =0;
friend class engine::InvocationStateBase;
friend class engine::StateAdapter;
public:
/** allocate a new writable buffer with type and size according to
* the BufferDescriptor. The actual provider of this buffer depends
* on the State 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 adress and for releasing the buffer.
*/
virtual BuffHandle allocateBuffer (BufferDescriptor const&) =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;
/** try to fetch an existing buffer containing the denoted frame from
* a cache or similar backing system (e.g. peer over the network).
* @return either a handle to a readonly buffer, or a null handle
* @note the client is resposible for not modifying the provided data
*/
virtual BuffHandle fetch (FrameID const&) =0;
};