pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
NAME
pfCycleBuffer, pfCycleMemory - pfCycleBuffer and pfCycleMemory obsoleted
by pfFlux and pfFluxMemory
FUNCTION SPECIFICATION
#include <Performer/pr/pfCycleBuffer.h>
pfCycleBuffer::pfCycleBuffer(size_t nbytes)
static pfType * pfCycleBuffer::getClassType(void);
void * pfCycleBuffer::getCurData();
pfCycleMemory * pfCycleBuffer::getCMem(int index);
void pfCycleBuffer::changed();
void pfCycleBuffer::init(void *data);
static int pfCycleBuffer::config(int numBuffers);
static int pfCycleBuffer::getConfig(void);
static int pfCycleBuffer::frame(void);
static int pfCycleBuffer::getFrameCount(void);
static int pfCycleBuffer::getCurIndex(void);
static void pfCycleBuffer::setCurIndex(int index);
static pfCycleBuffer * pfCycleBuffer::getCBuffer(void *data);
static pfType * pfCycleMemory::getClassType(void);
int pfCycleMemory::getFrame(void);
pfCycleBuffer * pfCycleMemory::getCBuffer(void);
PARENT CLASS FUNCTIONS
The OpenGL Performer class pfCycleBuffer is derived from the parent class
pfObject, so each of these member functions of class pfObject are also
directly usable with objects of class pfCycleBuffer. This is also true
for ancestor classes of class pfObject.
void* pfObject::operator new(size_t);
void* pfObject::operator new(size_t, void *arena);
void* pfObject::operator new(size_t, pfFluxMemory *fmem);
void pfObject::setUserData(void *data);
void pfObject::setUserData(int slot, void *data);
Page 1
pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
void* pfObject::getUserData(pfObject *obj);
void* pfObject::getUserData(pfObject *obj, int slot);
int pfObject::getNumUserData();
Since the class pfObject is itself derived from the parent class
pfMemory, objects of class pfCycleBuffer can also be used with these
functions designed for objects of class pfMemory.
void* pfMemory::getData(const void *ptr);
pfType * pfMemory::getType();
int pfMemory::isOfType(pfType *type);
int pfMemory::isExactType(pfType *type);
const char * pfMemory::getTypeName();
int pfMemory::copy(pfMemory *src);
int pfMemory::compare(const pfMemory *mem);
void pfMemory::print(uint which, uint verbose, char *prefix,
FILE *file);
int pfMemory::getArena(void *ptr);
void* pfMemory::getArena();
int pfMemory::ref();
int pfMemory::unref();
int pfMemory::unrefDelete();
int pfMemory::unrefGetRef();
int pfMemory::getRef();
int pfMemory::checkDelete();
int pfMemory::isFluxed();
void * pfMemory::getArena();
int pfMemory::getSize();
DESCRIPTION
Together, pfCycleBuffer and pfCycleMemory provide an automated mechanism
for managing dynamic data in a pipelined, multiprocessing environment.
In this kind of environment, data is typically modified at the head of
the pipeline and must propagate down it in a "frame-accurate" fashion.
For example, assume the coordinates of a pfGeoSet are modified for facial
animation. If a two-stage rendering pipeline is used, then it is likely
that the coordinates will be modified in the head of the pipeline, at the
same time they are being rendered in the tail of the pipeline. If only a
single memory buffer is used, then the pfGeoSet might be rendered when
its coordinates are only partially updated, potentially resulting in
cracks in the facial mesh or other anomalies.
A solution to this problem is to use two memory buffers for the
coordinates, one written to by the head and one read from by the tail of
the pipeline. In order for the new coordinates to propagate to the
rendering stage we could copy the newly updated buffer into the
renderer's buffer during a handshake period between the two stages.
However, if the buffer is large, the copy time could become
objectionable. Another alternative is to simply swap pointers to the two
buffers - the classic "double-buffering" approach. This is much more
efficient but requires that the contents of the buffer be completely
Page 2
pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
updated each frame. Otherwise the render stage will access a "stale"
buffer that represents the facial expression at a previous time so that
the animation will appear to go backwards.
The pfCycleBuffer/pfCycleMemory combination supports efficient dynamic
data management in an N-stage pipeline. A pfCycleBuffer logically
contains multiple pfCycleMemorys. Each process has a global index which
selects the currently active pfCycleMemory in each pfCycleBuffer. This
index can be advanced once a frame by pfCycleBuffer::setCurIndex so that
the buffers "cycle". By advancing the index appropriately in each
pipeline stage, dynamic data can be frame-accurately propagated down the
pipeline.
While pfCycleBuffers can be used for generic dynamic data, a prominent
use is as attribute arrays for pfGeoSets. The function pfGeoSet::setAttr
accepts pfCycleBuffer memory for attribute arrays and the pfGeoSet will
index the appropriate pfCycleMemory when rendering and intersection
testing. Currently, pfGeoSets do not support pfCycleBuffer index lists.
new(arena) allocates a pfCycleBuffer from the specified memory arena, or
from the process heap if arena is NULL. new allocates a pfCycleBuffer
from the default memory arena (see pfGetSharedArena). Like other
pfObjects, pfCycleBuffers cannot be created statically, automatically on
the stack or in arrays. The argument nbytes to the constructor specifies
the length of each associated pfCycleMemory. pfCycleBuffers should be
deleted with pfDelete rather than the delete operator.
The number of pfCycleMemorys allocated for each pfCycleBuffer is
specified by pfCBufferConfig which is typically called only once at
initialization time. pfGetCBufferConfig returns the number set by
pfCBufferConfig.
pfCycleBuffer::getClassType returns the pfType* for the class
pfCycleBuffer. The pfType* returned by pfCycleBuffer::getClassType is
the same as the pfType* returned by invoking the virtual function getType
on any instance of class pfCycleBuffer. Because OpenGL Performer allows
subclassing of built-in types, when decisions are made based on the type
of an object, it is usually better to use the member function isOfType
to test if an object is of a type derived from a Performer type rather
than to test for strict equality of the pfType*'s.
pfCycleMemory::getClassType returns the pfType* for the class
pfCycleMemory.
pfCycleBuffer::init initializes all pfCycleMemorys of a pfCycleBuffer to
the data referenced by data. data should be at least of size nbytes.
pfCycleMemory is derived from pfMemory and also provides access to its
raw data in the form of a void* pointer through the pfMemory::getData
call. Thus pfCycleBuffer memory is arranged in a hierarchy:
pfCycleBuffer -> pfCycleMemory -> void* and various routines exist which
convert one handle into another. These routines are listed in the
Page 3
pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
following table.
pfCycleBuffer* pfCycleMemory* pfMemory*
_____________________________________________________________
pfCycleBuffer* NA getCMem getCurData
pfCycleMemory* getCBuffer NA getData
void* getCBuffer getMemory NA
|
|
|
The currently active pfCycleMemory portion of a pfCycleBuffer is selected
by the global index specified by pfCycleBuffer::setCurIndex, and is
returned by pfCycleBuffer::getCurIndex. One can think of this in
pseudocode as
current pfCycleMemory = pfCycleBuffer[pfCurCBufferIndex]
Thus one should always get a new handle to the currently active data
whenever the global index changes. Data modification that is incremental,
(such as a += .2) must retain a handle to the previous data for proper
results (current a = previous a + .2).
As mentioned above, cycling buffer pointers is efficient but requires
that the buffers be completely updated each frame. If the data at some
time becomes static, it must then be copied into those buffers that are
out of date. pfCycleBuffer supports this copying automatically with
pfCycleBuffer::changed in conjunction with pfCycleBuffer::frame. The
member function frame advances a global frame counter that is used to
frame-stamp pfCycleMemorys. After the pfCycleBuffer has been updated,
changed frame-stamps the pfCycleBuffer with the current frame count.
Then if that pfCycleBuffer is not changed in a later frame, the member
function frame will automatically copy the latest pfCycleMemory into its
currently active, sibling pfCycleMemory. This copying will continue until
all selected pfCycleMemorys contain the latest data. To determine the
frame stamp of a pfCycleMemory, use the member function getFrame.
pfCycleBuffer::getFrameCount returns the current, global, pfCycleBuffer
frame count.
The following are examples of pfCycleBuffer usage for libpr-only and
libpf applications. When using libpf, pfConfig and pfFrame call
pfCycleBuffer::config and pfCycleBuffer::frame respectively so the
application should not call the latter routines. In addition, libpf
calls pfCurCBufferIndex in each process so that pfCycleBuffer changes are
properly propagated down the processing pipelines.
Example 1: libpr-only pfCycleBuffer example
pfVec3 *prevVerts, *curVerts;
/*
* Configure number of pfCycleMemorys per pfCycleBuffer
Page 4
pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
*/
numBuffers->config();
verts = new pfCycleBuffer(sizeof(pfVec3) * numVerts);
gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, verts, NULL);
while(!done)
{
static int index = 0;
index->setCurIndex();
curVerts = verts->getCurData();
/* Compute new positions of mass-spring system */
for (i=0; i<numVerts; i++)
curVerts[i] = prevVerts[i] + netForceVector * deltaTime;
/* Indicate that 'verts' has changed */
verts->changed();
prevVerts = curVerts;
/* Advance cyclebuffer frame count */
pfCycleBuffer::frame();
/* Advance buffer index. */
index = (index + 1) % numBuffers;
}
Example 2: libpf pfCycleBuffer example
pfVec3 *prevVerts, *curVerts;
pfInit();
pfMultiprocess(mpMode);
/*
* This calls pfCycleBuffer::config() with the number of buffers
* appropriate to the multiprocessing mode.
*/
pfConfig();
verts = new(pfGetSharedArena()) pfCycleBuffer(sizeof(pfVec3) * numVerts);
gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, verts, NULL);
while(!done)
Page 5
pfCycleBuffer OBSOLETE(3pf) OpenGL Performer 3.2.2 libpr C++ Reference Pages
{
curVerts = verts->getCurData();
/* Compute new positions of mass-spring system */
for (i=0; i<numVerts; i++)
curVerts[i] = prevVerts[i] + netForceVector * deltaTime;
/* Indicate that 'verts' has changed */
verts->changed();
prevVerts = curVerts;
/* This calls pfCycleBuffer::frame() */
pfFrame();
}
NOTES
The global index which selects the currently active pfCycleMemory is
unique for a given address space. Specifically, share group processes
like those spawned by sproc will share the same global index.
OBSOLETEpfCycleBuffer and pfCycleMemory have been obsoleted by pfFlux and
pfFluxMemory. See the pfFlux man page for examples on converting code
using pfCycleBuffer to pfFluxBuffer.
SEE ALSO
pfFlux, pfDelete, pfGetData, pfGetMemory, pfMemory
Page 6