minor API refactor of for EvalLimit :

- Replaced EvalData and EvalVertexData classes with a simpler DataStream class that only
  accesses a single data stream, binds and unbinds it

- DataStream has both an input and an output version which avoids much of the const-ness
  const-related ambiguity of the previous design pattern

- Vertex, varying and face-varying data now all have a dedicate struct (VertexData, VaryingData, FaceVaryingData)
  as a way of gathering the various data-streams required to perform sampling

- renamd some "Buffers" into "Tables" for better naming consistency with Far
This commit is contained in:
manuelk 2013-06-17 18:13:13 -07:00
parent 077f95b8f0
commit bbe4435b19
5 changed files with 310 additions and 257 deletions

View File

@ -442,19 +442,19 @@ updateGeom() {
// Bind/Unbind of the vertex buffers to the context needs to happen // Bind/Unbind of the vertex buffers to the context needs to happen
// outside of the parallel loop // outside of the parallel loop
g_evalCtx->BindVertexBuffers( g_idesc, g_vertexData, g_odesc, g_Q, g_dQu, g_dQv ); 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 // 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 // g_Q has a stride of 6 and g_vdesc sets the offset to 3, while g_odesc sets
// the offset to 0 // the offset to 0
switch (g_drawMode) { switch (g_drawMode) {
case kVARYING : g_evalCtx->BindVaryingBuffers( g_idesc, g_varyingData, g_vdesc, g_Q ); break; case kVARYING : g_evalCtx->GetVaryingData().Bind( g_idesc, g_varyingData, g_vdesc, g_Q ); break;
case kFACEVARYING : g_evalCtx->BindFaceVaryingBuffers( g_fvidesc, g_fvodesc, g_Q ); case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Bind( g_fvidesc, g_fvodesc, g_Q );
case kUV : case kUV :
default : g_evalCtx->UnbindVaryingBuffers(); break; default : g_evalCtx->GetVaryingData().Unbind(); break;
} }
#define USE_OPENMP #define USE_OPENMP
@ -490,7 +490,15 @@ updateGeom() {
} }
} }
g_evalCtx->UnbindVertexBuffers(); g_evalCtx->GetVertexData().Unbind();
switch (g_drawMode) {
case kVARYING : g_evalCtx->GetVaryingData().Unbind(); break;
case kFACEVARYING : g_evalCtx->GetFaceVaryingData().Unbind(); break;
default : break;
}
g_Q->BindVBO(); g_Q->BindVBO();

View File

@ -78,39 +78,6 @@ OsdCpuEvalLimitContext::Create(FarMesh<OsdVertex> const * farmesh, bool requireF
return new OsdCpuEvalLimitContext(farmesh, requireFVarData); return new OsdCpuEvalLimitContext(farmesh, requireFVarData);
} }
void
OsdCpuEvalLimitContext::EvalData::Unbind() {
_inDesc.Reset();
_inQ=0;
_outDesc.Reset();
_outQ = 0;
}
void
OsdCpuEvalLimitContext::EvalVertexData::Unbind() {
EvalData::Unbind();
_outdQu = _outdQv = 0;
}
void
OsdCpuEvalLimitContext::UnbindVertexBuffers() {
_vertexData.Unbind();
}
void
OsdCpuEvalLimitContext::UnbindVaryingBuffers() {
_varyingData.Unbind();
}
void
OsdCpuEvalLimitContext::UnbindFaceVaryingBuffers() {
_faceVaryingData.Unbind();
}
OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh, bool requireFVarData) : OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh, bool requireFVarData) :
OsdEvalLimitContext(farmesh) { OsdEvalLimitContext(farmesh) {
@ -122,9 +89,9 @@ OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmes
_patchArrays = patchTables->GetPatchArrayVector(); _patchArrays = patchTables->GetPatchArrayVector();
_vertexValenceBuffer = patchTables->GetVertexValenceTable(); _vertexValenceTable = patchTables->GetVertexValenceTable();
_quadOffsetBuffer = patchTables->GetQuadOffsetTable(); _quadOffsetTable = patchTables->GetQuadOffsetTable();
_maxValence = patchTables->GetMaxValence(); _maxValence = patchTables->GetMaxValence();
@ -165,5 +132,36 @@ OsdCpuEvalLimitContext::~OsdCpuEvalLimitContext() {
delete _patchMap; 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_VERSION
} // end namespace OpenSubdiv } // end namespace OpenSubdiv

View File

@ -87,185 +87,220 @@ public:
virtual ~OsdCpuEvalLimitContext(); virtual ~OsdCpuEvalLimitContext();
/// Limit evaluation data descriptor
class EvalData {
/// A container able to bind vertex buffer data as input or output streams.
class DataStream {
public: public:
OsdVertexBufferDescriptor const & GetInputDesc() const { /// Constructor
return _inDesc; 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;
} }
float const * GetInputData() const { /// True if the stream has been bound
return _inQ;
}
OsdVertexBufferDescriptor const & GetOutputDesc() const {
return _outDesc;
}
float const * GetOutputData(int index=0) const {
return _outQ + index * _outDesc.stride;
}
template <class BUFFER>
void BindInputData( BUFFER * inQ ) {
_inQ = inQ ? inQ->BindCpuBuffer() : 0;
}
template <class BUFFER>
void BindOutputData( BUFFER * outQ ) {
_outQ = outQ ? outQ->BindCpuBuffer() : 0;
}
bool IsBound() const { bool IsBound() const {
return _inQ and _outQ; return (_data!=NULL);
} }
private: /// Unbinds the stream
friend class OsdCpuEvalLimitContext; void Unbind() {
_data=0;
EvalData() : _inQ(0), _outQ(0) { } }
OsdVertexBufferDescriptor _inDesc; // input data protected:
float * _inQ; float * _data;
OsdVertexBufferDescriptor _outDesc; // output data
float * _outQ;
/// Resets the descriptors & pointers
void Unbind();
}; };
/// Limit evaluation data descriptor with derivatives /// \brief Input (const) data stream
class EvalVertexData : public EvalData { class InputDataStream : public DataStream {
public: public:
float const * GetOutputDU(int index=0) const { /// Const accessor
return _outdQu + index * _outDesc.stride; float const * GetData() const {
return _data;
} }
float const * GetOutputDV(int index=0) const {
return _outdQv + index * _outDesc.stride;
}
template <class BUFFER>
void BindOutputDerivData( BUFFER * outdQu, BUFFER * outdQv ) {
_outdQu = outdQu ? outdQu->BindCpuBuffer() : 0;
_outdQv = outdQv ? outdQv->BindCpuBuffer() : 0;
}
private:
friend class OsdCpuEvalLimitContext;
EvalVertexData() : _outdQu(0), _outdQv(0) { }
/// Resets the descriptors & pointers
void Unbind();
float * _outdQu, // U derivative of output data
* _outdQv; // V derivative of output 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;
/// Binds the vertex-interpolated data buffers. /// input vertex-interpolated data stream
/// InputDataStream in;
/// @param inDesc vertex buffer data descriptor shared by all input data buffers
///
/// @param inQ input vertex data
///
/// @param outDesc vertex buffer data descriptor shared by all output data buffers
///
/// @param outQ output vertex data
///
/// @param outdQu optional output derivative along "u" of the vertex data
///
/// @param outdQv optional output derivative along "v" of the vertex data
///
template<class VERTEX_BUFFER, class OUTPUT_BUFFER>
void BindVertexBuffers( OsdVertexBufferDescriptor const & inDesc, VERTEX_BUFFER *inQ,
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ,
OUTPUT_BUFFER *outdQu=0,
OUTPUT_BUFFER *outdQv=0) {
_vertexData._inDesc = inDesc;
_vertexData.BindInputData( inQ );
_vertexData._outDesc = outDesc;
_vertexData.BindOutputData( outQ );
_vertexData.BindOutputDerivData( outdQu, outdQv );
}
/// Unbind the vertex data buffers /// output vertex-interpolated data descriptor
void UnbindVertexBuffers(); 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 /// Returns an Eval data descriptor of the vertex-interpolated data currently
/// bound to this EvalLimitContext. /// bound to this EvalLimitContext.
EvalVertexData const & GetVertexData() const { VertexData & GetVertexData() {
return _vertexData; return _vertexData;
} }
/// Binds the varying-interpolated data buffers.
///
/// @param inDesc varying buffer data descriptor shared by all input data buffers
///
/// @param inQ input varying data
///
/// @param outDesc varying buffer data descriptor shared by all output data buffers
///
/// @param outQ output varying data
///
template<class VARYING_BUFFER, class OUTPUT_BUFFER>
void BindVaryingBuffers( OsdVertexBufferDescriptor const & inDesc, VARYING_BUFFER *inQ,
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ) {
_varyingData._inDesc = inDesc;
_varyingData.BindInputData( inQ );
_varyingData._outDesc = outDesc;
_varyingData.BindOutputData( outQ );
}
/// Unbind the varying data buffers /// Varying-interpolated streams
void UnbindVaryingBuffers(); 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 /// Returns an Eval data descriptor of the varying-interpolated data currently
/// bound to this EvalLimitContext. /// bound to this EvalLimitContext.
EvalData const & GetVaryingData() const { VaryingData & GetVaryingData() {
return _varyingData; return _varyingData;
} }
/// Binds the face-varying-interpolated data buffers. /// Face-Varying-interpolated streams
/// struct FaceVaryingData {
/// Note : currently we only support bilinear boundary interpolation rules
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets, /// input face-varying-interpolated data descriptor
/// the feature-adaptive patch interpolation code currently does not support OsdVertexBufferDescriptor inDesc;
/// them, and neither does this EvalContext
///
/// @param inDesc varying buffer data descriptor shared by all input data buffers
///
/// @param inQ input varying data
///
/// @param outDesc varying buffer data descriptor shared by all output data buffers
///
/// @param outQ output varying data
///
template<class OUTPUT_BUFFER>
void BindFaceVaryingBuffers( OsdVertexBufferDescriptor const & inDesc,
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ) {
_faceVaryingData._inDesc = inDesc;
_faceVaryingData._outDesc = outDesc;
_faceVaryingData.BindOutputData( outQ );
}
/// Unbind the varying data buffers /// output face-varying-interpolated data descriptor
void UnbindFaceVaryingBuffers(); 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 /// Returns an Eval data descriptor of the face-varying-interpolated data
/// currently bound to this EvalLimitContext. /// currently bound to this EvalLimitContext.
EvalData const & GetFaceVaryingData() const { FaceVaryingData & GetFaceVaryingData() {
return _faceVaryingData; return _faceVaryingData;
} }
/// Returns the vector of patch arrays /// Returns the vector of patch arrays
const FarPatchTables::PatchArrayVector & GetPatchArrayVector() const { const FarPatchTables::PatchArrayVector & GetPatchArrayVector() const {
return _patchArrays; return _patchArrays;
@ -282,13 +317,13 @@ public:
} }
/// Returns the vertex-valence buffer used for Gregory patch computations /// Returns the vertex-valence buffer used for Gregory patch computations
const int * GetVertexValenceBuffer() const { FarPatchTables::VertexValenceTable const & GetVertexValenceTable() const {
return &_vertexValenceBuffer[0]; return _vertexValenceTable;
} }
/// Returns the Quad-Offsets buffer used for Gregory patch computations /// Returns the Quad-Offsets buffer used for Gregory patch computations
const unsigned int *GetQuadOffsetBuffer() const { FarPatchTables::QuadOffsetTable const & GetQuadOffsetTable() const {
return &_quadOffsetBuffer[0]; return _quadOffsetTable;
} }
/// Returns the face-varying data patch table /// Returns the face-varying data patch table
@ -321,16 +356,16 @@ private:
FarPatchTables::PTable _patches; // patch control vertices FarPatchTables::PTable _patches; // patch control vertices
std::vector<FarPatchParam::BitField> _patchBitFields; // per-patch parametric info std::vector<FarPatchParam::BitField> _patchBitFields; // per-patch parametric info
FarPatchTables::VertexValenceTable _vertexValenceBuffer; // extra Gregory patch data buffers FarPatchTables::VertexValenceTable _vertexValenceTable; // extra Gregory patch data buffers
FarPatchTables::QuadOffsetTable _quadOffsetBuffer; FarPatchTables::QuadOffsetTable _quadOffsetTable;
FarPatchTables::FVarDataTable _fvarData; FarPatchTables::FVarDataTable _fvarData;
FarPatchMap * _patchMap; // map of the sub-patches given a face index FarPatchMap * _patchMap; // map of the sub-patches given a face index
EvalVertexData _vertexData; // vertex-interpolated data descriptor VertexData _vertexData; // vertex-interpolated data descriptor
EvalData _varyingData, // varying-interpolated data descriptor VaryingData _varyingData; // varying-interpolated data descriptor
_faceVaryingData; // face-varying-interpolated data descriptor FaceVaryingData _faceVaryingData; // face-varying-interpolated data descriptor
int _maxValence, int _maxValence,
_fvarwidth; _fvarwidth;

View File

@ -70,7 +70,7 @@ OsdCpuEvalLimitController::~OsdCpuEvalLimitController() {
int int
OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords, OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords,
OsdCpuEvalLimitContext const *context, OsdCpuEvalLimitContext * context,
unsigned int index ) { unsigned int index ) {
float u=coords.u, float u=coords.u,
v=coords.v; v=coords.v;
@ -92,70 +92,80 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ]; unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ];
OsdCpuEvalLimitContext::EvalVertexData const & vertexData = context->GetVertexData(); OsdCpuEvalLimitContext::VertexData & vertexData = context->GetVertexData();
// Position lookup pointers at the indexed vertex if (vertexData.IsBound()) {
float const * inQ = vertexData.GetInputData();
float * outQ = const_cast<float *>(vertexData.GetOutputData(index)); int offset = vertexData.outDesc.stride * index;
float * outdQu = const_cast<float *>(vertexData.GetOutputDU(index));
float * outdQv = const_cast<float *>(vertexData.GetOutputDV(index)); // Based on patch type - go execute interpolation
switch( parray.GetDescriptor().GetType() ) {
// Based on patch type - go execute interpolation case FarPatchTables::REGULAR : if (vertexData.IsBound()) {
switch( parray.GetDescriptor().GetType() ) { evalBSpline( v, u, cvs,
vertexData.inDesc,
vertexData.in.GetData(),
vertexData.outDesc,
vertexData.out.GetData()+offset,
vertexData.outDu.GetData()+offset,
vertexData.outDv.GetData()+offset );
} break;
case FarPatchTables::REGULAR : if (vertexData.IsBound()) { case FarPatchTables::BOUNDARY : if (vertexData.IsBound()) {
evalBSpline( v, u, cvs, evalBoundary( v, u, cvs,
vertexData.GetInputDesc(), vertexData.inDesc,
inQ, vertexData.in.GetData(),
vertexData.GetOutputDesc(), vertexData.outDesc,
outQ, outdQu, outdQv ); vertexData.out.GetData()+offset,
} break; vertexData.outDu.GetData()+offset,
vertexData.outDv.GetData()+offset );
} break;
case FarPatchTables::BOUNDARY : if (vertexData.IsBound()) { case FarPatchTables::CORNER : if (vertexData.IsBound()) {
evalBoundary( v, u, cvs, evalCorner( v, u, cvs,
vertexData.GetInputDesc(), vertexData.inDesc,
inQ, vertexData.in.GetData(),
vertexData.GetOutputDesc(), vertexData.outDesc,
outQ, outdQu, outdQv ); vertexData.out.GetData()+offset,
} break; vertexData.outDu.GetData()+offset,
vertexData.outDv.GetData()+offset );
case FarPatchTables::CORNER : if (vertexData.IsBound()) { } break;
evalCorner( v, u, cvs,
vertexData.GetInputDesc(),
inQ,
vertexData.GetOutputDesc(),
outQ, outdQu, outdQv);
} break;
case FarPatchTables::GREGORY : if (vertexData.IsBound()) { case FarPatchTables::GREGORY : if (vertexData.IsBound()) {
evalGregory( v, u, cvs, evalGregory( v, u, cvs,
context->GetVertexValenceBuffer(), &context->GetVertexValenceTable()[0],
context->GetQuadOffsetBuffer() + parray.GetQuadOffsetIndex() + handle->vertexOffset, &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
context->GetMaxValence(), context->GetMaxValence(),
vertexData.GetInputDesc(), vertexData.inDesc,
inQ, vertexData.in.GetData(),
vertexData.GetOutputDesc(), vertexData.outDesc,
outQ, outdQu, outdQv); vertexData.out.GetData()+offset,
} break; vertexData.outDu.GetData()+offset,
vertexData.outDv.GetData()+offset );
} break;
case FarPatchTables::GREGORY_BOUNDARY : case FarPatchTables::GREGORY_BOUNDARY :
if (vertexData.IsBound()) { if (vertexData.IsBound()) {
evalGregoryBoundary(v, u, cvs, evalGregoryBoundary(v, u, cvs,
context->GetVertexValenceBuffer(), &context->GetVertexValenceTable()[0],
context->GetQuadOffsetBuffer() + parray.GetQuadOffsetIndex() + handle->vertexOffset, &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
context->GetMaxValence(), context->GetMaxValence(),
vertexData.GetInputDesc(), vertexData.inDesc,
inQ, vertexData.in.GetData(),
vertexData.GetOutputDesc(), vertexData.outDesc,
outQ, outdQu, outdQv); vertexData.out.GetData()+offset,
} break; vertexData.outDu.GetData()+offset,
vertexData.outDv.GetData()+offset );
} break;
default: default:
assert(0); assert(0);
}
} }
OsdCpuEvalLimitContext::EvalData const & varyingData = context->GetVaryingData(); OsdCpuEvalLimitContext::VaryingData & varyingData = context->GetVaryingData();
if (varyingData.IsBound()) { if (varyingData.IsBound()) {
static int indices[5][4] = { {5, 6,10, 9}, // regular static int indices[5][4] = { {5, 6,10, 9}, // regular
@ -166,16 +176,18 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
int type = (int)(parray.GetDescriptor().GetType() - FarPatchTables::REGULAR); int type = (int)(parray.GetDescriptor().GetType() - FarPatchTables::REGULAR);
int offset = varyingData.outDesc.stride * index;
unsigned int zeroRing[4] = { cvs[indices[type][0]], unsigned int zeroRing[4] = { cvs[indices[type][0]],
cvs[indices[type][1]], cvs[indices[type][1]],
cvs[indices[type][2]], cvs[indices[type][2]],
cvs[indices[type][3]] }; cvs[indices[type][3]] };
evalBilinear( v, u, zeroRing, evalBilinear( v, u, zeroRing,
varyingData.GetInputDesc(), varyingData.inDesc,
varyingData.GetInputData(), varyingData.in.GetData(),
varyingData.GetOutputDesc(), varyingData.outDesc,
const_cast<float *>(varyingData.GetOutputData(index)) ); varyingData.out.GetData()+offset);
} }
@ -183,22 +195,22 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
// for face-varying data. Although Hbr supports 3 additional smooth rule // for face-varying data. Although Hbr supports 3 additional smooth rule
// sets, the feature-adaptive patch interpolation code currently does not // sets, the feature-adaptive patch interpolation code currently does not
// support them, and neither does this EvalContext. // support them, and neither does this EvalContext.
OsdCpuEvalLimitContext::EvalData const & faceVaryingData = context->GetFaceVaryingData(); OsdCpuEvalLimitContext::FaceVaryingData & faceVaryingData = context->GetFaceVaryingData();
if (faceVaryingData.GetOutputData()) { if (faceVaryingData.IsBound()) {
FarPatchTables::FVarDataTable const & fvarData = context->GetFVarData(); FarPatchTables::FVarDataTable const & fvarData = context->GetFVarData();
if (not fvarData.empty()) { if (not fvarData.empty()) {
float const * fvar = &fvarData[ handle->patchIdx * 4 * context->GetFVarWidth() ]; int offset = faceVaryingData.outDesc.stride * index;
static unsigned int zeroRing[4] = {0,1,2,3}; static unsigned int zeroRing[4] = {0,1,2,3};
evalBilinear( v, u, zeroRing, evalBilinear( v, u, zeroRing,
faceVaryingData.GetInputDesc(), faceVaryingData.inDesc,
fvar, &fvarData[ handle->patchIdx * 4 * context->GetFVarWidth() ],
faceVaryingData.GetOutputDesc(), faceVaryingData.outDesc,
const_cast<float *>(faceVaryingData.GetOutputData(index)) ); faceVaryingData.out.GetData()+offset);
} }
} }

View File

@ -130,7 +130,7 @@ public:
private: private:
int _EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords, int _EvalLimitSample( OpenSubdiv::OsdEvalCoords const & coords,
OsdCpuEvalLimitContext const * context, OsdCpuEvalLimitContext * context,
unsigned int index ); unsigned int index );
}; };