Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/opensubdiv/internal/evaluator/evaluator_impl.cc')
-rw-r--r--intern/opensubdiv/internal/evaluator/evaluator_impl.cc649
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.