mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-24 08:41:18 +00:00
Reorganize EvalLimitContext and EvalLimitController
Moved transient states (current vertex buffer etc) to controller. ComputeContext becomes constant so that it's well suited for coarse-grain parallelism on cpu. Client-facing API has changed slightly - limitEval example has been adjusted
This commit is contained in:
parent
ec89f76038
commit
827efd14e3
@ -411,30 +411,30 @@ updateGeom() {
|
||||
|
||||
g_nsamplesFound=0;
|
||||
|
||||
// Bind/Unbind of the vertex buffers to the context needs to happen
|
||||
// outside of the parallel loop
|
||||
g_evalCtx->GetVertexData().Bind( g_idesc, g_vertexData, g_odesc, g_Q, g_dQu, g_dQv );
|
||||
|
||||
// The varying data ends-up interleaved in the same g_Q output buffer because
|
||||
// g_Q has a stride of 6 and g_vdesc sets the offset to 3, while g_odesc sets
|
||||
// the offset to 0
|
||||
switch (g_drawMode) {
|
||||
case kVARYING : g_evalCtx->GetVaryingData().Bind( g_idesc, g_varyingData, g_vdesc, g_Q ); break;
|
||||
case kVARYING : g_evalCtrl.BindVaryingBuffers( g_idesc, g_varyingData, g_vdesc, g_Q ); break;
|
||||
|
||||
case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Bind( g_fvidesc, g_fvodesc, g_Q );
|
||||
case kFACEVARYING : g_evalCtrl.BindFacevaryingBuffers( g_fvidesc, g_fvodesc, g_Q ); break;
|
||||
|
||||
case kUV :
|
||||
|
||||
default : g_evalCtx->GetVaryingData().Unbind(); break;
|
||||
default : g_evalCtrl.Unbind(); break;
|
||||
}
|
||||
|
||||
// Bind/Unbind of the vertex buffers to the context needs to happen
|
||||
// outside of the parallel loop
|
||||
g_evalCtrl.BindVertexBuffers( g_idesc, g_vertexData, g_odesc, g_Q, g_dQu, g_dQv );
|
||||
|
||||
#define USE_OPENMP
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP)
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=0; i<(int)g_coords.size(); ++i) {
|
||||
|
||||
int n = g_evalCtrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuGLVertexBuffer>( g_coords[i], g_evalCtx, i );
|
||||
int n = g_evalCtrl.EvalLimitSample( g_coords[i], g_evalCtx, i );
|
||||
|
||||
if (n) {
|
||||
// point colors
|
||||
@ -461,15 +461,7 @@ updateGeom() {
|
||||
}
|
||||
}
|
||||
|
||||
g_evalCtx->GetVertexData().Unbind();
|
||||
|
||||
switch (g_drawMode) {
|
||||
case kVARYING : g_evalCtx->GetVaryingData().Unbind(); break;
|
||||
|
||||
case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Unbind(); break;
|
||||
|
||||
default : break;
|
||||
}
|
||||
g_evalCtrl.Unbind();
|
||||
|
||||
g_Q->BindVBO();
|
||||
|
||||
|
@ -98,36 +98,5 @@ OsdCpuEvalLimitContext::~OsdCpuEvalLimitContext() {
|
||||
delete _patchMap;
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuEvalLimitContext::VertexData::Unbind() {
|
||||
|
||||
inDesc.Reset();
|
||||
in.Unbind();
|
||||
|
||||
outDesc.Reset();
|
||||
out.Unbind();
|
||||
outDu.Unbind();
|
||||
outDv.Unbind();
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuEvalLimitContext::VaryingData::Unbind() {
|
||||
|
||||
inDesc.Reset();
|
||||
in.Unbind();
|
||||
|
||||
outDesc.Reset();
|
||||
out.Unbind();
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuEvalLimitContext::FaceVaryingData::Unbind() {
|
||||
|
||||
inDesc.Reset();
|
||||
|
||||
outDesc.Reset();
|
||||
out.Unbind();
|
||||
}
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -56,219 +56,6 @@ public:
|
||||
virtual ~OsdCpuEvalLimitContext();
|
||||
|
||||
|
||||
|
||||
/// A container able to bind vertex buffer data as input or output streams.
|
||||
class DataStream {
|
||||
public:
|
||||
/// Constructor
|
||||
DataStream() : _data(0) { }
|
||||
|
||||
/// Binds the stream to the context (and moves the data to the appropriate
|
||||
/// compute device)
|
||||
///
|
||||
/// @param data a valid OsdVertexBuffer
|
||||
///
|
||||
template <class BUFFER> void Bind( BUFFER * data ) {
|
||||
_data = data ? data->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// True if the stream has been bound
|
||||
bool IsBound() const {
|
||||
return (_data!=NULL);
|
||||
}
|
||||
|
||||
/// Unbinds the stream
|
||||
void Unbind() {
|
||||
_data=0;
|
||||
}
|
||||
|
||||
protected:
|
||||
float * _data;
|
||||
};
|
||||
|
||||
/// \brief Input (const) data stream
|
||||
class InputDataStream : public DataStream {
|
||||
public:
|
||||
/// Const accessor
|
||||
float const * GetData() const {
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Output (const) data stream
|
||||
class OutputDataStream : public DataStream {
|
||||
public:
|
||||
/// Non-cont accessor
|
||||
float * GetData() {
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
|
||||
/// Vertex-interpolated streams
|
||||
struct VertexData {
|
||||
|
||||
/// input vertex-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor inDesc;
|
||||
|
||||
/// input vertex-interpolated data stream
|
||||
InputDataStream in;
|
||||
|
||||
/// output vertex-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor outDesc;
|
||||
|
||||
/// output vertex-interpolated data stream and parametric derivative streams
|
||||
OutputDataStream out,
|
||||
outDu,
|
||||
outDv;
|
||||
|
||||
/// Binds the vertex-interpolated data streams
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input vertex data
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outdQv output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
template<class VERTEX_BUFFER, class OUTPUT_BUFFER>
|
||||
void Bind( OsdVertexBufferDescriptor const & iDesc, VERTEX_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0) {
|
||||
inDesc = iDesc;
|
||||
in.Bind( inQ );
|
||||
|
||||
outDesc = oDesc;
|
||||
out.Bind( outQ );
|
||||
outDu.Bind( outdQu );
|
||||
outDv.Bind( outdQv );
|
||||
}
|
||||
|
||||
/// True if both the mandatory input and output streams have been bound
|
||||
bool IsBound() const {
|
||||
return in.IsBound() and out.IsBound();
|
||||
}
|
||||
|
||||
/// Unbind the vertex data streams
|
||||
void Unbind();
|
||||
};
|
||||
|
||||
/// Returns an Eval data descriptor of the vertex-interpolated data currently
|
||||
/// bound to this EvalLimitContext.
|
||||
VertexData & GetVertexData() {
|
||||
return _vertexData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Varying-interpolated streams
|
||||
struct VaryingData {
|
||||
|
||||
/// input varying-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor inDesc;
|
||||
|
||||
/// input varying-interpolated data stream
|
||||
InputDataStream in;
|
||||
|
||||
/// output varying-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor outDesc;
|
||||
|
||||
/// output varying-interpolated data stream
|
||||
OutputDataStream out;
|
||||
|
||||
/// Binds the varying-interpolated data streams
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input varying data
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
template<class VARYING_BUFFER, class OUTPUT_BUFFER>
|
||||
void Bind( OsdVertexBufferDescriptor const & iDesc, VARYING_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
inDesc = iDesc;
|
||||
in.Bind( inQ );
|
||||
|
||||
outDesc = oDesc;
|
||||
out.Bind( outQ );
|
||||
}
|
||||
|
||||
/// True if both the mandatory input and output streams have been bound
|
||||
bool IsBound() const {
|
||||
return in.IsBound() and out.IsBound();
|
||||
}
|
||||
|
||||
/// Unbind the vertex data streams
|
||||
void Unbind();
|
||||
};
|
||||
|
||||
/// Returns an Eval data descriptor of the varying-interpolated data currently
|
||||
/// bound to this EvalLimitContext.
|
||||
VaryingData & GetVaryingData() {
|
||||
return _varyingData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Face-Varying-interpolated streams
|
||||
struct FaceVaryingData {
|
||||
|
||||
/// input face-varying-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor inDesc;
|
||||
|
||||
/// output face-varying-interpolated data descriptor
|
||||
OsdVertexBufferDescriptor outDesc;
|
||||
|
||||
/// output face-varying-interpolated data stream and parametric derivative streams
|
||||
OutputDataStream out;
|
||||
|
||||
/// Binds the face-varying-interpolated data streams
|
||||
///
|
||||
/// Note : currently we only support bilinear boundary interpolation rules
|
||||
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
/// the feature-adaptive patch interpolation code currently does not support
|
||||
/// them, and neither does this EvalContext
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output face-varying data
|
||||
///
|
||||
template<class OUTPUT_BUFFER>
|
||||
void Bind( OsdVertexBufferDescriptor const & iDesc,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
inDesc = iDesc;
|
||||
|
||||
outDesc = oDesc;
|
||||
out.Bind( outQ );
|
||||
}
|
||||
|
||||
/// True if the output stream has been bound
|
||||
bool IsBound() const {
|
||||
return out.IsBound();
|
||||
}
|
||||
|
||||
/// Unbind the vertex data streams
|
||||
void Unbind();
|
||||
};
|
||||
|
||||
/// Returns an Eval data descriptor of the face-varying-interpolated data
|
||||
/// currently bound to this EvalLimitContext.
|
||||
FaceVaryingData & GetFaceVaryingData() {
|
||||
return _faceVaryingData;
|
||||
}
|
||||
|
||||
|
||||
/// Returns the vector of patch arrays
|
||||
const FarPatchTables::PatchArrayVector & GetPatchArrayVector() const {
|
||||
return _patchArrays;
|
||||
@ -331,10 +118,6 @@ private:
|
||||
|
||||
FarPatchMap * _patchMap; // map of the sub-patches given a face index
|
||||
|
||||
VertexData _vertexData; // vertex-interpolated data descriptor
|
||||
VaryingData _varyingData; // varying-interpolated data descriptor
|
||||
FaceVaryingData _faceVaryingData; // face-varying-interpolated data descriptor
|
||||
|
||||
int _maxValence,
|
||||
_fvarwidth;
|
||||
};
|
||||
|
@ -72,9 +72,9 @@ OsdCpuEvalLimitController::EvalLimitSample( OpenSubdiv::OsdEvalCoords const & co
|
||||
|
||||
unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ];
|
||||
|
||||
OsdCpuEvalLimitContext::VertexData & vertexData = context->GetVertexData();
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
if (vertexData.in.IsBound()) {
|
||||
if (vertexData.in) {
|
||||
|
||||
float * out = outQ ? outQ + outDesc.offset : 0,
|
||||
* outDu = outDQU ? outDQU + outDesc.offset : 0,
|
||||
@ -84,21 +84,21 @@ OsdCpuEvalLimitController::EvalLimitSample( OpenSubdiv::OsdEvalCoords const & co
|
||||
|
||||
case FarPatchTables::REGULAR : evalBSpline( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
|
||||
case FarPatchTables::BOUNDARY : evalBoundary( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
|
||||
case FarPatchTables::CORNER : evalCorner( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -109,7 +109,7 @@ OsdCpuEvalLimitController::EvalLimitSample( OpenSubdiv::OsdEvalCoords const & co
|
||||
&context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
|
||||
context->GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -120,7 +120,7 @@ OsdCpuEvalLimitController::EvalLimitSample( OpenSubdiv::OsdEvalCoords const & co
|
||||
&context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
|
||||
context->GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -154,39 +154,38 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
|
||||
unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ];
|
||||
|
||||
OsdCpuEvalLimitContext::VertexData & vertexData = context->GetVertexData();
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
if (vertexData.IsBound()) {
|
||||
if (vertexData.in) {
|
||||
|
||||
int offset = vertexData.outDesc.stride * index;
|
||||
|
||||
if (vertexData.out) {
|
||||
|
||||
if (vertexData.IsBound()) {
|
||||
|
||||
float * out = vertexData.out.GetData()+offset,
|
||||
* outDu = vertexData.outDu.IsBound() ? vertexData.outDu.GetData()+offset : 0,
|
||||
* outDv = vertexData.outDv.IsBound() ? vertexData.outDv.GetData()+offset : 0;
|
||||
float * out = vertexData.out+offset,
|
||||
* outDu = vertexData.outDu ? vertexData.outDu+offset : 0,
|
||||
* outDv = vertexData.outDv ? vertexData.outDv+offset : 0;
|
||||
|
||||
// Based on patch type - go execute interpolation
|
||||
switch( parray.GetDescriptor().GetType() ) {
|
||||
|
||||
case FarPatchTables::REGULAR : evalBSpline( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
|
||||
case FarPatchTables::BOUNDARY : evalBoundary( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
|
||||
case FarPatchTables::CORNER : evalCorner( v, u, cvs,
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -197,7 +196,7 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
&context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
|
||||
context->GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -208,7 +207,7 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
&context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
|
||||
context->GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in.GetData(),
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
@ -219,9 +218,9 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
}
|
||||
}
|
||||
|
||||
OsdCpuEvalLimitContext::VaryingData & varyingData = context->GetVaryingData();
|
||||
VaryingData const & varyingData = _currentBindState.varyingData;
|
||||
|
||||
if (varyingData.IsBound()) {
|
||||
if (varyingData.in and varyingData.out) {
|
||||
|
||||
static int indices[5][4] = { {5, 6,10, 9}, // regular
|
||||
{1, 2, 6, 5}, // boundary
|
||||
@ -240,9 +239,9 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
|
||||
evalBilinear( v, u, zeroRing,
|
||||
varyingData.inDesc,
|
||||
varyingData.in.GetData(),
|
||||
varyingData.in,
|
||||
varyingData.outDesc,
|
||||
varyingData.out.GetData()+offset);
|
||||
varyingData.out+offset);
|
||||
|
||||
}
|
||||
|
||||
@ -250,22 +249,24 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
// for face-varying data. Although Hbr supports 3 additional smooth rule
|
||||
// sets, the feature-adaptive patch interpolation code currently does not
|
||||
// support them, and neither does this EvalContext.
|
||||
OsdCpuEvalLimitContext::FaceVaryingData & faceVaryingData = context->GetFaceVaryingData();
|
||||
if (faceVaryingData.IsBound()) {
|
||||
|
||||
FacevaryingData const & facevaryingData = _currentBindState.facevaryingData;
|
||||
|
||||
if (facevaryingData.out) {
|
||||
|
||||
std::vector<float> const & fvarData = context->GetFVarData();
|
||||
|
||||
if (not fvarData.empty()) {
|
||||
|
||||
int offset = faceVaryingData.outDesc.stride * index;
|
||||
int offset = facevaryingData.outDesc.stride * index;
|
||||
|
||||
static unsigned int zeroRing[4] = {0,1,2,3};
|
||||
|
||||
evalBilinear( v, u, zeroRing,
|
||||
faceVaryingData.inDesc,
|
||||
facevaryingData.inDesc,
|
||||
&fvarData[ handle->patchIdx * 4 * context->GetFVarWidth() ],
|
||||
faceVaryingData.outDesc,
|
||||
faceVaryingData.out.GetData()+offset);
|
||||
facevaryingData.outDesc,
|
||||
facevaryingData.out+offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,23 @@ namespace OPENSUBDIV_VERSION {
|
||||
/// A CPU-driven controller that can be called to evaluate samples on the limit
|
||||
/// surface for a given EvalContext.
|
||||
///
|
||||
/// Warning : this eval controller is re-entrant but it breaks the Osd API pattern
|
||||
/// by requiring client code to bind and unbind the data buffers to the
|
||||
/// Controller before calling evaluation methods.
|
||||
///
|
||||
/// Ex :
|
||||
/// \code
|
||||
/// evalCtroller->BindVertexBuffers( ... );
|
||||
/// evalCtroller->BindVaryingBuffers( ... );
|
||||
/// evalCtroller->BindFacevaryingBuffers( ... );
|
||||
///
|
||||
/// parallel_for( int index=0; i<nsamples; ++index ) {
|
||||
/// evalCtroller->EvalLimitSample( coord, evalCtxt, index );
|
||||
/// }
|
||||
///
|
||||
/// evalCtroller->Unbind();
|
||||
/// \endcode
|
||||
///
|
||||
class OsdCpuEvalLimitController {
|
||||
|
||||
public:
|
||||
@ -54,13 +71,83 @@ public:
|
||||
float u,v; // local u,v
|
||||
};
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input vertex data
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outdQv output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVertexBuffers( OsdVertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0 ) {
|
||||
_currentBindState.vertexData.inDesc = iDesc;
|
||||
_currentBindState.vertexData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.vertexData.outDesc = oDesc;
|
||||
_currentBindState.vertexData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDu = outdQu ? outdQu->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDv = outdQv ? outdQv->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the varying-interpolated data streams
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input varying data
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVaryingBuffers( OsdVertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.varyingData.inDesc = iDesc;
|
||||
_currentBindState.varyingData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingData.outDesc = oDesc;
|
||||
_currentBindState.varyingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the face-varying-interpolated data streams
|
||||
///
|
||||
/// Note : currently we only support bilinear boundary interpolation rules
|
||||
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
/// the feature-adaptive patch interpolation code currently does not support
|
||||
/// them, and neither does this EvalContext
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param oDesc data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output face-varying data
|
||||
///
|
||||
template<class OUTPUT_BUFFER>
|
||||
void BindFacevaryingBuffers( OsdVertexBufferDescriptor const & iDesc,
|
||||
OsdVertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.facevaryingData.inDesc = iDesc;
|
||||
|
||||
_currentBindState.facevaryingData.outDesc = oDesc;
|
||||
_currentBindState.facevaryingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Vertex interpolation of a single sample at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a single sample on the surface limit.
|
||||
///
|
||||
/// This function is re-entrant and does not require the context to bind
|
||||
/// output vertex buffers.
|
||||
/// This function is re-entrant but does not require binding the
|
||||
/// output vertex buffers. Pointers to memory where the data is
|
||||
/// output are explicitly passed to the function.
|
||||
///
|
||||
/// @param coords location on the limit surface to be evaluated
|
||||
///
|
||||
@ -68,6 +155,12 @@ public:
|
||||
///
|
||||
/// @param outDesc data descriptor (offset, length, stride)
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outdQv output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
/// @return 1 if the sample was found
|
||||
///
|
||||
int EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coord,
|
||||
@ -77,27 +170,10 @@ public:
|
||||
float * outDQU,
|
||||
float * outDQV ) const;
|
||||
|
||||
|
||||
|
||||
/// \brief Vertex interpolation of samples at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a sample on the surface limit.
|
||||
///
|
||||
/// Warning : this function is re-entrant but it breaks the Osd API pattern
|
||||
/// by requiring the client code to bind and unbind the vertex buffers to
|
||||
/// the EvalLimitContext.
|
||||
///
|
||||
/// Ex :
|
||||
/// \code
|
||||
/// evalCtxt->BindVertexBuffers( ... );
|
||||
///
|
||||
/// parallel_for( int index=0; i<nsamples; ++index ) {
|
||||
/// evalCtrlr->EvalLimitSample( coord, evalCtxt, index );
|
||||
/// }
|
||||
///
|
||||
/// evalCtxt->UnbindVertexBuffers();
|
||||
/// \endcode
|
||||
///
|
||||
/// @param coords location on the limit surface to be evaluated
|
||||
///
|
||||
/// @param context the EvalLimitContext that the controller will evaluate
|
||||
@ -108,7 +184,6 @@ public:
|
||||
/// @return the number of samples found (0 if the location was tagged as a hole
|
||||
/// or the coordinate was invalid)
|
||||
///
|
||||
template<class VERTEX_BUFFER, class OUTPUT_BUFFER>
|
||||
int EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords,
|
||||
OsdCpuEvalLimitContext * context,
|
||||
unsigned int index ) const {
|
||||
@ -120,12 +195,92 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
void Unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// Vertex interpolated streams
|
||||
struct VertexData {
|
||||
|
||||
VertexData() : in(0), out(0), outDu(0), outDv(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = outDu = outDv = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
OsdVertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out,
|
||||
* outDu,
|
||||
* outDv;
|
||||
};
|
||||
|
||||
// Varying interpolated streams
|
||||
struct VaryingData {
|
||||
|
||||
VaryingData() : in(0), out(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
OsdVertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
// Facevarying interpolated streams
|
||||
struct FacevaryingData {
|
||||
|
||||
FacevaryingData() : out(0) { }
|
||||
|
||||
void Reset() {
|
||||
out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
OsdVertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * out;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int _EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords,
|
||||
OsdCpuEvalLimitContext * context,
|
||||
unsigned int index ) const;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() { }
|
||||
|
||||
void Reset() {
|
||||
vertexData.Reset();
|
||||
varyingData.Reset();
|
||||
facevaryingData.Reset();
|
||||
}
|
||||
|
||||
VertexData vertexData; // vertex interpolated data descriptor
|
||||
VaryingData varyingData; // varying interpolated data descriptor
|
||||
FacevaryingData facevaryingData; // face-varying interpolated data descriptor
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -156,14 +156,6 @@ OsdUtilAdaptiveEvaluator::Initialize(
|
||||
_evalLimitContext = OsdCpuEvalLimitContext::Create(
|
||||
fmesh->GetPatchTables(), /*requierFVarData*/ false);
|
||||
|
||||
// Setup evaluation context. Values are offset, length, stride */
|
||||
OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 0, 0);
|
||||
|
||||
OsdCpuEvalLimitContext::VertexData & vertexData =
|
||||
_evalLimitContext->GetVertexData();
|
||||
|
||||
vertexData.Bind<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(in_desc, _vertexBuffer, out_desc, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -217,6 +209,11 @@ OsdUtilAdaptiveEvaluator::EvaluateLimit(
|
||||
|
||||
static OsdVertexBufferDescriptor desc(0,3,3);
|
||||
|
||||
// Setup evaluation controller. Values are offset, length, stride */
|
||||
OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 0, 0);
|
||||
|
||||
cpuEvalLimitController.BindVertexBuffers<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(in_desc, _vertexBuffer, out_desc, NULL);
|
||||
|
||||
cpuEvalLimitController.EvalLimitSample(coords, _evalLimitContext, desc, P, dPdu, dPdv);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user