diff options
Diffstat (limited to 'intern/opensubdiv/internal/evaluator/evaluator_impl.cc')
-rw-r--r-- | intern/opensubdiv/internal/evaluator/evaluator_impl.cc | 649 |
1 files changed, 157 insertions, 492 deletions
diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc index 4f4f332ff15..755b8bfbc81 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc @@ -28,9 +28,6 @@ #include <opensubdiv/far/patchMap.h> #include <opensubdiv/far/patchTable.h> #include <opensubdiv/far/patchTableFactory.h> -#include <opensubdiv/osd/cpuEvaluator.h> -#include <opensubdiv/osd/cpuPatchTable.h> -#include <opensubdiv/osd/cpuVertexBuffer.h> #include <opensubdiv/osd/mesh.h> #include <opensubdiv/osd/types.h> #include <opensubdiv/version.h> @@ -38,19 +35,20 @@ #include "MEM_guardedalloc.h" #include "internal/base/type.h" +#include "internal/evaluator/eval_output_cpu.h" +#include "internal/evaluator/eval_output_gpu.h" +#include "internal/evaluator/evaluator_cache_impl.h" +#include "internal/evaluator/patch_map.h" #include "internal/topology/topology_refiner_impl.h" +#include "opensubdiv_evaluator_capi.h" #include "opensubdiv_topology_refiner_capi.h" -using OpenSubdiv::Far::PatchMap; using OpenSubdiv::Far::PatchTable; using OpenSubdiv::Far::PatchTableFactory; using OpenSubdiv::Far::StencilTable; using OpenSubdiv::Far::StencilTableFactory; using OpenSubdiv::Far::TopologyRefiner; -using OpenSubdiv::Osd::BufferDescriptor; -using OpenSubdiv::Osd::CpuEvaluator; -using OpenSubdiv::Osd::CpuPatchTable; -using OpenSubdiv::Osd::CpuVertexBuffer; +using OpenSubdiv::Osd::PatchArray; using OpenSubdiv::Osd::PatchCoord; namespace blender { @@ -140,407 +138,9 @@ template<typename T, int kNumMaxElementsOnStack> class StackOrHeapArray { // 32 is a number of inner vertices along the patch size at subdivision level 6. typedef StackOrHeapArray<PatchCoord, 32 * 32> StackOrHeapPatchCoordArray; -// Buffer which implements API required by OpenSubdiv and uses an existing memory as an underlying -// storage. -template<typename T> class RawDataWrapperBuffer { - public: - RawDataWrapperBuffer(T *data) : data_(data) - { - } - - T *BindCpuBuffer() - { - return data_; - } - - // TODO(sergey): Support UpdateData(). - - protected: - T *data_; -}; - -template<typename T> class RawDataWrapperVertexBuffer : public RawDataWrapperBuffer<T> { - public: - RawDataWrapperVertexBuffer(T *data, int num_vertices) - : RawDataWrapperBuffer<T>(data), num_vertices_(num_vertices) - { - } - - int GetNumVertices() - { - return num_vertices_; - } - - protected: - int num_vertices_; -}; - -class ConstPatchCoordWrapperBuffer : public RawDataWrapperVertexBuffer<const PatchCoord> { - public: - ConstPatchCoordWrapperBuffer(const PatchCoord *data, int num_vertices) - : RawDataWrapperVertexBuffer(data, num_vertices) - { - } -}; - -template<typename EVAL_VERTEX_BUFFER, - typename STENCIL_TABLE, - typename PATCH_TABLE, - typename EVALUATOR, - typename DEVICE_CONTEXT = void> -class FaceVaryingVolatileEval { - public: - typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache; - - FaceVaryingVolatileEval(int face_varying_channel, - const StencilTable *face_varying_stencils, - int face_varying_width, - PATCH_TABLE *patch_table, - EvaluatorCache *evaluator_cache = NULL, - DEVICE_CONTEXT *device_context = NULL) - : face_varying_channel_(face_varying_channel), - src_face_varying_desc_(0, face_varying_width, face_varying_width), - patch_table_(patch_table), - evaluator_cache_(evaluator_cache), - device_context_(device_context) - { - using OpenSubdiv::Osd::convertToCompatibleStencilTable; - num_coarse_face_varying_vertices_ = face_varying_stencils->GetNumControlVertices(); - const int num_total_face_varying_vertices = face_varying_stencils->GetNumControlVertices() + - face_varying_stencils->GetNumStencils(); - src_face_varying_data_ = EVAL_VERTEX_BUFFER::Create( - 2, num_total_face_varying_vertices, device_context); - face_varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(face_varying_stencils, - device_context_); - } - - ~FaceVaryingVolatileEval() - { - delete src_face_varying_data_; - delete face_varying_stencils_; - } - - void updateData(const float *src, int start_vertex, int num_vertices) - { - src_face_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_); - } - - void refine() - { - BufferDescriptor dst_face_varying_desc = src_face_varying_desc_; - dst_face_varying_desc.offset += num_coarse_face_varying_vertices_ * - src_face_varying_desc_.stride; - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_face_varying_desc_, dst_face_varying_desc, device_context_); - // in and out points to same buffer so output is put directly after coarse vertices, needed in - // adaptive mode - EVALUATOR::EvalStencils(src_face_varying_data_, - src_face_varying_desc_, - src_face_varying_data_, - dst_face_varying_desc, - face_varying_stencils_, - eval_instance, - device_context_); - } - - // NOTE: face_varying must point to a memory of at least float[2]*num_patch_coords. - void evalPatches(const PatchCoord *patch_coord, const int num_patch_coords, float *face_varying) - { - RawDataWrapperBuffer<float> face_varying_data(face_varying); - BufferDescriptor face_varying_desc(0, 2, 2); - ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_face_varying_desc_, face_varying_desc, device_context_); - - // src_face_varying_data_ always contains coarse vertices at the beginning. - // In adaptive mode they are followed by number of blocks for intermediate - // subdivision levels, and this is what OSD expects in this mode. - // In non-adaptive mode (generateIntermediateLevels == false), - // they are followed by max subdivision level, but they break interpolation as OSD - // expects only one subd level in this buffer. - // So in non-adaptive mode we put offset into buffer descriptor to skip over coarse vertices. - BufferDescriptor src_desc = src_face_varying_desc_; - if (!patch_table_->GetPatchArrayBuffer()[0].GetDescriptor().IsAdaptive()) { - src_desc.offset += num_coarse_face_varying_vertices_ * src_face_varying_desc_.stride; - } - - EVALUATOR::EvalPatchesFaceVarying(src_face_varying_data_, - src_desc, - &face_varying_data, - face_varying_desc, - patch_coord_buffer.GetNumVertices(), - &patch_coord_buffer, - patch_table_, - face_varying_channel_, - eval_instance, - device_context_); - } - - protected: - int face_varying_channel_; - - BufferDescriptor src_face_varying_desc_; - - int num_coarse_face_varying_vertices_; - EVAL_VERTEX_BUFFER *src_face_varying_data_; - const STENCIL_TABLE *face_varying_stencils_; - - // NOTE: We reference this, do not own it. - PATCH_TABLE *patch_table_; - - EvaluatorCache *evaluator_cache_; - DEVICE_CONTEXT *device_context_; -}; - -// Volatile evaluator which can be used from threads. -// -// TODO(sergey): Make it possible to evaluate coordinates in chunks. -// TODO(sergey): Make it possible to evaluate multiple face varying layers. -// (or maybe, it's cheap to create new evaluator for existing -// topology to evaluate all needed face varying layers?) -template<typename SRC_VERTEX_BUFFER, - typename EVAL_VERTEX_BUFFER, - typename STENCIL_TABLE, - typename PATCH_TABLE, - typename EVALUATOR, - typename DEVICE_CONTEXT = void> -class VolatileEvalOutput { - public: - typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache; - typedef FaceVaryingVolatileEval<EVAL_VERTEX_BUFFER, - STENCIL_TABLE, - PATCH_TABLE, - EVALUATOR, - DEVICE_CONTEXT> - FaceVaryingEval; - - VolatileEvalOutput(const StencilTable *vertex_stencils, - const StencilTable *varying_stencils, - const vector<const StencilTable *> &all_face_varying_stencils, - const int face_varying_width, - const PatchTable *patch_table, - EvaluatorCache *evaluator_cache = NULL, - DEVICE_CONTEXT *device_context = NULL) - : src_desc_(0, 3, 3), - src_varying_desc_(0, 3, 3), - face_varying_width_(face_varying_width), - evaluator_cache_(evaluator_cache), - device_context_(device_context) - { - // Total number of vertices = coarse points + refined points + local points. - int num_total_vertices = vertex_stencils->GetNumControlVertices() + - vertex_stencils->GetNumStencils(); - num_coarse_vertices_ = vertex_stencils->GetNumControlVertices(); - using OpenSubdiv::Osd::convertToCompatibleStencilTable; - src_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_); - src_varying_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_); - patch_table_ = PATCH_TABLE::Create(patch_table, device_context_); - vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(vertex_stencils, - device_context_); - varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils, - device_context_); - // Create evaluators for every face varying channel. - face_varying_evaluators.reserve(all_face_varying_stencils.size()); - int face_varying_channel = 0; - for (const StencilTable *face_varying_stencils : all_face_varying_stencils) { - face_varying_evaluators.push_back(new FaceVaryingEval(face_varying_channel, - face_varying_stencils, - face_varying_width, - patch_table_, - evaluator_cache_, - device_context_)); - ++face_varying_channel; - } - } - - ~VolatileEvalOutput() - { - delete src_data_; - delete src_varying_data_; - delete patch_table_; - delete vertex_stencils_; - delete varying_stencils_; - for (FaceVaryingEval *face_varying_evaluator : face_varying_evaluators) { - delete face_varying_evaluator; - } - } - - // TODO(sergey): Implement binding API. - - void updateData(const float *src, int start_vertex, int num_vertices) - { - src_data_->UpdateData(src, start_vertex, num_vertices, device_context_); - } - - void updateVaryingData(const float *src, int start_vertex, int num_vertices) - { - src_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_); - } - - void updateFaceVaryingData(const int face_varying_channel, - const float *src, - int start_vertex, - int num_vertices) - { - assert(face_varying_channel >= 0); - assert(face_varying_channel < face_varying_evaluators.size()); - face_varying_evaluators[face_varying_channel]->updateData(src, start_vertex, num_vertices); - } - - bool hasVaryingData() const - { - // return varying_stencils_ != NULL; - // TODO(sergey): Check this based on actual topology. - return false; - } - - bool hasFaceVaryingData() const - { - return face_varying_evaluators.size() != 0; - } - - void refine() - { - // Evaluate vertex positions. - BufferDescriptor dst_desc = src_desc_; - dst_desc.offset += num_coarse_vertices_ * src_desc_.stride; - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_desc_, dst_desc, device_context_); - EVALUATOR::EvalStencils(src_data_, - src_desc_, - src_data_, - dst_desc, - vertex_stencils_, - eval_instance, - device_context_); - // Evaluate varying data. - if (hasVaryingData()) { - BufferDescriptor dst_varying_desc = src_varying_desc_; - dst_varying_desc.offset += num_coarse_vertices_ * src_varying_desc_.stride; - eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_varying_desc_, dst_varying_desc, device_context_); - EVALUATOR::EvalStencils(src_varying_data_, - src_varying_desc_, - src_varying_data_, - dst_varying_desc, - varying_stencils_, - eval_instance, - device_context_); - } - // Evaluate face-varying data. - if (hasFaceVaryingData()) { - for (FaceVaryingEval *face_varying_evaluator : face_varying_evaluators) { - face_varying_evaluator->refine(); - } - } - } - - // NOTE: P must point to a memory of at least float[3]*num_patch_coords. - void evalPatches(const PatchCoord *patch_coord, const int num_patch_coords, float *P) - { - RawDataWrapperBuffer<float> P_data(P); - // TODO(sergey): Support interleaved vertex-varying data. - BufferDescriptor P_desc(0, 3, 3); - ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_desc_, P_desc, device_context_); - EVALUATOR::EvalPatches(src_data_, - src_desc_, - &P_data, - P_desc, - patch_coord_buffer.GetNumVertices(), - &patch_coord_buffer, - patch_table_, - eval_instance, - device_context_); - } - - // NOTE: P, dPdu, dPdv must point to a memory of at least float[3]*num_patch_coords. - void evalPatchesWithDerivatives(const PatchCoord *patch_coord, - const int num_patch_coords, - float *P, - float *dPdu, - float *dPdv) - { - assert(dPdu); - assert(dPdv); - RawDataWrapperBuffer<float> P_data(P); - RawDataWrapperBuffer<float> dPdu_data(dPdu), dPdv_data(dPdv); - // TODO(sergey): Support interleaved vertex-varying data. - BufferDescriptor P_desc(0, 3, 3); - BufferDescriptor dpDu_desc(0, 3, 3), pPdv_desc(0, 3, 3); - ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_desc_, P_desc, dpDu_desc, pPdv_desc, device_context_); - EVALUATOR::EvalPatches(src_data_, - src_desc_, - &P_data, - P_desc, - &dPdu_data, - dpDu_desc, - &dPdv_data, - pPdv_desc, - patch_coord_buffer.GetNumVertices(), - &patch_coord_buffer, - patch_table_, - eval_instance, - device_context_); - } - - // NOTE: varying must point to a memory of at least float[3]*num_patch_coords. - void evalPatchesVarying(const PatchCoord *patch_coord, - const int num_patch_coords, - float *varying) - { - RawDataWrapperBuffer<float> varying_data(varying); - BufferDescriptor varying_desc(3, 3, 6); - ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>( - evaluator_cache_, src_varying_desc_, varying_desc, device_context_); - EVALUATOR::EvalPatchesVarying(src_varying_data_, - src_varying_desc_, - &varying_data, - varying_desc, - patch_coord_buffer.GetNumVertices(), - &patch_coord_buffer, - patch_table_, - eval_instance, - device_context_); - } - - void evalPatchesFaceVarying(const int face_varying_channel, - const PatchCoord *patch_coord, - const int num_patch_coords, - float face_varying[2]) - { - assert(face_varying_channel >= 0); - assert(face_varying_channel < face_varying_evaluators.size()); - face_varying_evaluators[face_varying_channel]->evalPatches( - patch_coord, num_patch_coords, face_varying); - } - - private: - SRC_VERTEX_BUFFER *src_data_; - SRC_VERTEX_BUFFER *src_varying_data_; - PATCH_TABLE *patch_table_; - BufferDescriptor src_desc_; - BufferDescriptor src_varying_desc_; - - int num_coarse_vertices_; - - const STENCIL_TABLE *vertex_stencils_; - const STENCIL_TABLE *varying_stencils_; - - int face_varying_width_; - vector<FaceVaryingEval *> face_varying_evaluators; - - EvaluatorCache *evaluator_cache_; - DEVICE_CONTEXT *device_context_; -}; - void convertPatchCoordsToArray(const OpenSubdiv_PatchCoord *patch_coords, const int num_patch_coords, - const OpenSubdiv::Far::PatchMap *patch_map, + const PatchMap *patch_map, StackOrHeapPatchCoordArray *array) { array->resize(num_patch_coords); @@ -553,79 +153,50 @@ void convertPatchCoordsToArray(const OpenSubdiv_PatchCoord *patch_coords, } // namespace -// Note: Define as a class instead of typedef to make it possible -// to have anonymous class in opensubdiv_evaluator_internal.h -class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer, - CpuVertexBuffer, - StencilTable, - CpuPatchTable, - CpuEvaluator> { - public: - CpuEvalOutput(const StencilTable *vertex_stencils, - const StencilTable *varying_stencils, - const vector<const StencilTable *> &all_face_varying_stencils, - const int face_varying_width, - const PatchTable *patch_table, - EvaluatorCache *evaluator_cache = NULL) - : VolatileEvalOutput<CpuVertexBuffer, - CpuVertexBuffer, - StencilTable, - CpuPatchTable, - CpuEvaluator>(vertex_stencils, - varying_stencils, - all_face_varying_stencils, - face_varying_width, - patch_table, - evaluator_cache) - { - } -}; - //////////////////////////////////////////////////////////////////////////////// // Evaluator wrapper for anonymous API. -CpuEvalOutputAPI::CpuEvalOutputAPI(CpuEvalOutput *implementation, - OpenSubdiv::Far::PatchMap *patch_map) - : implementation_(implementation), patch_map_(patch_map) +EvalOutputAPI::EvalOutputAPI(EvalOutput *implementation, PatchMap *patch_map) + : patch_map_(patch_map), implementation_(implementation) { } -CpuEvalOutputAPI::~CpuEvalOutputAPI() +EvalOutputAPI::~EvalOutputAPI() { delete implementation_; } -void CpuEvalOutputAPI::setCoarsePositions(const float *positions, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setCoarsePositions(const float *positions, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. implementation_->updateData(positions, start_vertex_index, num_vertices); } -void CpuEvalOutputAPI::setVaryingData(const float *varying_data, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setVaryingData(const float *varying_data, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. implementation_->updateVaryingData(varying_data, start_vertex_index, num_vertices); } -void CpuEvalOutputAPI::setFaceVaryingData(const int face_varying_channel, - const float *face_varying_data, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setFaceVaryingData(const int face_varying_channel, + const float *face_varying_data, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. implementation_->updateFaceVaryingData( face_varying_channel, face_varying_data, start_vertex_index, num_vertices); } -void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(const void *buffer, - const int start_offset, - const int stride, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setCoarsePositionsFromBuffer(const void *buffer, + const int start_offset, + const int stride, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. const unsigned char *current_buffer = (unsigned char *)buffer; @@ -638,11 +209,11 @@ void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(const void *buffer, } } -void CpuEvalOutputAPI::setVaryingDataFromBuffer(const void *buffer, - const int start_offset, - const int stride, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setVaryingDataFromBuffer(const void *buffer, + const int start_offset, + const int stride, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. const unsigned char *current_buffer = (unsigned char *)buffer; @@ -655,12 +226,12 @@ void CpuEvalOutputAPI::setVaryingDataFromBuffer(const void *buffer, } } -void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(const int face_varying_channel, - const void *buffer, - const int start_offset, - const int stride, - const int start_vertex_index, - const int num_vertices) +void EvalOutputAPI::setFaceVaryingDataFromBuffer(const int face_varying_channel, + const void *buffer, + const int start_offset, + const int stride, + const int start_vertex_index, + const int num_vertices) { // TODO(sergey): Add sanity check on indices. const unsigned char *current_buffer = (unsigned char *)buffer; @@ -675,17 +246,17 @@ void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(const int face_varying_chann } } -void CpuEvalOutputAPI::refine() +void EvalOutputAPI::refine() { implementation_->refine(); } -void CpuEvalOutputAPI::evaluateLimit(const int ptex_face_index, - float face_u, - float face_v, - float P[3], - float dPdu[3], - float dPdv[3]) +void EvalOutputAPI::evaluateLimit(const int ptex_face_index, + float face_u, + float face_v, + float P[3], + float dPdu[3], + float dPdv[3]) { assert(face_u >= 0.0f); assert(face_u <= 1.0f); @@ -701,10 +272,10 @@ void CpuEvalOutputAPI::evaluateLimit(const int ptex_face_index, } } -void CpuEvalOutputAPI::evaluateVarying(const int ptex_face_index, - float face_u, - float face_v, - float varying[3]) +void EvalOutputAPI::evaluateVarying(const int ptex_face_index, + float face_u, + float face_v, + float varying[3]) { assert(face_u >= 0.0f); assert(face_u <= 1.0f); @@ -715,11 +286,11 @@ void CpuEvalOutputAPI::evaluateVarying(const int ptex_face_index, implementation_->evalPatchesVarying(&patch_coord, 1, varying); } -void CpuEvalOutputAPI::evaluateFaceVarying(const int face_varying_channel, - const int ptex_face_index, - float face_u, - float face_v, - float face_varying[2]) +void EvalOutputAPI::evaluateFaceVarying(const int face_varying_channel, + const int ptex_face_index, + float face_u, + float face_v, + float face_varying[2]) { assert(face_u >= 0.0f); assert(face_u <= 1.0f); @@ -730,11 +301,11 @@ void CpuEvalOutputAPI::evaluateFaceVarying(const int face_varying_channel, implementation_->evalPatchesFaceVarying(face_varying_channel, &patch_coord, 1, face_varying); } -void CpuEvalOutputAPI::evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_coords, - const int num_patch_coords, - float *P, - float *dPdu, - float *dPdv) +void EvalOutputAPI::evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_coords, + const int num_patch_coords, + float *P, + float *dPdu, + float *dPdv) { StackOrHeapPatchCoordArray patch_coords_array; convertPatchCoordsToArray(patch_coords, num_patch_coords, patch_map_, &patch_coords_array); @@ -747,6 +318,73 @@ void CpuEvalOutputAPI::evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_c } } +void EvalOutputAPI::getPatchMap(OpenSubdiv_Buffer *patch_map_handles, + OpenSubdiv_Buffer *patch_map_quadtree, + int *min_patch_face, + int *max_patch_face, + int *max_depth, + int *patches_are_triangular) +{ + *min_patch_face = patch_map_->getMinPatchFace(); + *max_patch_face = patch_map_->getMaxPatchFace(); + *max_depth = patch_map_->getMaxDepth(); + *patches_are_triangular = patch_map_->getPatchesAreTriangular(); + + const std::vector<PatchTable::PatchHandle> &handles = patch_map_->getHandles(); + PatchTable::PatchHandle *buffer_handles = static_cast<PatchTable::PatchHandle *>( + patch_map_handles->alloc(patch_map_handles, handles.size())); + memcpy(buffer_handles, &handles[0], sizeof(PatchTable::PatchHandle) * handles.size()); + + const std::vector<PatchMap::QuadNode> &quadtree = patch_map_->nodes(); + PatchMap::QuadNode *buffer_nodes = static_cast<PatchMap::QuadNode *>( + patch_map_quadtree->alloc(patch_map_quadtree, quadtree.size())); + memcpy(buffer_nodes, &quadtree[0], sizeof(PatchMap::QuadNode) * quadtree.size()); +} + +void EvalOutputAPI::fillPatchArraysBuffer(OpenSubdiv_Buffer *patch_arrays_buffer) +{ + implementation_->fillPatchArraysBuffer(patch_arrays_buffer); +} + +void EvalOutputAPI::wrapPatchIndexBuffer(OpenSubdiv_Buffer *patch_index_buffer) +{ + implementation_->wrapPatchIndexBuffer(patch_index_buffer); +} + +void EvalOutputAPI::wrapPatchParamBuffer(OpenSubdiv_Buffer *patch_param_buffer) +{ + implementation_->wrapPatchParamBuffer(patch_param_buffer); +} + +void EvalOutputAPI::wrapSrcBuffer(OpenSubdiv_Buffer *src_buffer) +{ + implementation_->wrapSrcBuffer(src_buffer); +} + +void EvalOutputAPI::fillFVarPatchArraysBuffer(const int face_varying_channel, + OpenSubdiv_Buffer *patch_arrays_buffer) +{ + implementation_->fillFVarPatchArraysBuffer(face_varying_channel, patch_arrays_buffer); +} + +void EvalOutputAPI::wrapFVarPatchIndexBuffer(const int face_varying_channel, + OpenSubdiv_Buffer *patch_index_buffer) +{ + implementation_->wrapFVarPatchIndexBuffer(face_varying_channel, patch_index_buffer); +} + +void EvalOutputAPI::wrapFVarPatchParamBuffer(const int face_varying_channel, + OpenSubdiv_Buffer *patch_param_buffer) +{ + implementation_->wrapFVarPatchParamBuffer(face_varying_channel, patch_param_buffer); +} + +void EvalOutputAPI::wrapFVarSrcBuffer(const int face_varying_channel, + OpenSubdiv_Buffer *src_buffer) +{ + implementation_->wrapFVarSrcBuffer(face_varying_channel, src_buffer); +} + } // namespace opensubdiv } // namespace blender @@ -763,8 +401,15 @@ OpenSubdiv_EvaluatorImpl::~OpenSubdiv_EvaluatorImpl() } OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal( - OpenSubdiv_TopologyRefiner *topology_refiner) + OpenSubdiv_TopologyRefiner *topology_refiner, + eOpenSubdivEvaluator evaluator_type, + OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr) { + // Only CPU and GLCompute are implemented at the moment. + if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU && + evaluator_type != OPENSUBDIV_EVALUATOR_GLSL_COMPUTE) { + return NULL; + } using blender::opensubdiv::vector; TopologyRefiner *refiner = topology_refiner->impl->topology_refiner; if (refiner == NULL) { @@ -867,14 +512,34 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal( } } // Create OpenSubdiv's CPU side evaluator. - // TODO(sergey): Make it possible to use different evaluators. - blender::opensubdiv::CpuEvalOutput *eval_output = new blender::opensubdiv::CpuEvalOutput( - vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table); - OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table); + blender::opensubdiv::EvalOutputAPI::EvalOutput *eval_output = nullptr; + + const bool use_gl_evaluator = evaluator_type == OPENSUBDIV_EVALUATOR_GLSL_COMPUTE; + if (use_gl_evaluator) { + blender::opensubdiv::GpuEvalOutput::EvaluatorCache *evaluator_cache = nullptr; + if (evaluator_cache_descr) { + evaluator_cache = static_cast<blender::opensubdiv::GpuEvalOutput::EvaluatorCache *>( + evaluator_cache_descr->eval_cache); + } + + eval_output = new blender::opensubdiv::GpuEvalOutput(vertex_stencils, + varying_stencils, + all_face_varying_stencils, + 2, + patch_table, + evaluator_cache); + } + else { + eval_output = new blender::opensubdiv::CpuEvalOutput( + vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table); + } + + blender::opensubdiv::PatchMap *patch_map = new blender::opensubdiv::PatchMap(*patch_table); // Wrap everything we need into an object which we control from our side. OpenSubdiv_EvaluatorImpl *evaluator_descr; evaluator_descr = new OpenSubdiv_EvaluatorImpl(); - evaluator_descr->eval_output = new blender::opensubdiv::CpuEvalOutputAPI(eval_output, patch_map); + + evaluator_descr->eval_output = new blender::opensubdiv::EvalOutputAPI(eval_output, patch_map); evaluator_descr->patch_map = patch_map; evaluator_descr->patch_table = patch_table; // TOOD(sergey): Look into whether we've got duplicated stencils arrays. |