Files
test2/intern/opensubdiv/internal/evaluator/evaluator_capi.cc
Hans Goudey 5e46e3d28a Subdiv: Remove topology refiner C-API wrapper
Remove the indirection previously used for the topology refiner
to separate C and C++ code. Instead retrieve the base level in
calling code and call opensubdiv API functions directly. This
avoids copying arrays of mesh indices and should reduce
function call overhead since index retrieval can now be inlined.
It also lets us remove a lot of boilerplate shim code.

The downside is increased need for WITH_OPENSUBDIV defines
in various parts of blenkernel, but I think that is required to avoid
the previous indirection and have the kernel deal with OpenSubdiv
more directly.

Pull Request: https://projects.blender.org/blender/blender/pulls/120825
2024-09-27 19:01:12 +02:00

310 lines
12 KiB
C++

/* SPDX-FileCopyrightText: 2015 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Author: Sergey Sharybin. */
#include "opensubdiv_evaluator_capi.hh"
#include <opensubdiv/osd/glslPatchShaderSource.h>
#include "MEM_guardedalloc.h"
#include <new>
#include "internal/evaluator/evaluator_cache_impl.h"
#include "internal/evaluator/evaluator_impl.h"
static void setSettings(struct OpenSubdiv_Evaluator *evaluator,
const OpenSubdiv_EvaluatorSettings *settings)
{
evaluator->impl->eval_output->setSettings(settings);
}
static void setCoarsePositions(OpenSubdiv_Evaluator *evaluator,
const float *positions,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setCoarsePositions(positions, start_vertex_index, num_vertices);
}
static void setVertexData(OpenSubdiv_Evaluator *evaluator,
const float *vertex_data,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setVertexData(vertex_data, start_vertex_index, num_vertices);
}
static void setVaryingData(OpenSubdiv_Evaluator *evaluator,
const float *varying_data,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setVaryingData(varying_data, start_vertex_index, num_vertices);
}
static void setFaceVaryingData(OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
const float *face_varying_data,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setFaceVaryingData(
face_varying_channel, face_varying_data, start_vertex_index, num_vertices);
}
static void setCoarsePositionsFromBuffer(OpenSubdiv_Evaluator *evaluator,
const void *buffer,
const int start_offset,
const int stride,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setCoarsePositionsFromBuffer(
buffer, start_offset, stride, start_vertex_index, num_vertices);
}
static void setVaryingDataFromBuffer(OpenSubdiv_Evaluator *evaluator,
const void *buffer,
const int start_offset,
const int stride,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setVaryingDataFromBuffer(
buffer, start_offset, stride, start_vertex_index, num_vertices);
}
static void setFaceVaryingDataFromBuffer(OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
const void *buffer,
const int start_offset,
const int stride,
const int start_vertex_index,
const int num_vertices)
{
evaluator->impl->eval_output->setFaceVaryingDataFromBuffer(
face_varying_channel, buffer, start_offset, stride, start_vertex_index, num_vertices);
}
static void refine(OpenSubdiv_Evaluator *evaluator)
{
evaluator->impl->eval_output->refine();
}
static void evaluateLimit(OpenSubdiv_Evaluator *evaluator,
const int ptex_face_index,
const float face_u,
const float face_v,
float P[3],
float dPdu[3],
float dPdv[3])
{
evaluator->impl->eval_output->evaluateLimit(ptex_face_index, face_u, face_v, P, dPdu, dPdv);
}
static void evaluatePatchesLimit(OpenSubdiv_Evaluator *evaluator,
const OpenSubdiv_PatchCoord *patch_coords,
const int num_patch_coords,
float *P,
float *dPdu,
float *dPdv)
{
evaluator->impl->eval_output->evaluatePatchesLimit(
patch_coords, num_patch_coords, P, dPdu, dPdv);
}
static void evaluateVertexData(OpenSubdiv_Evaluator *evaluator,
const int ptex_face_index,
float face_u,
float face_v,
float vertex_data[3])
{
evaluator->impl->eval_output->evaluateVertexData(ptex_face_index, face_u, face_v, vertex_data);
}
static void evaluateVarying(OpenSubdiv_Evaluator *evaluator,
const int ptex_face_index,
float face_u,
float face_v,
float varying[3])
{
evaluator->impl->eval_output->evaluateVarying(ptex_face_index, face_u, face_v, varying);
}
static void evaluateFaceVarying(OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
const int ptex_face_index,
float face_u,
float face_v,
float face_varying[2])
{
evaluator->impl->eval_output->evaluateFaceVarying(
face_varying_channel, ptex_face_index, face_u, face_v, face_varying);
}
static void getPatchMap(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *patch_map_handles,
struct OpenSubdiv_Buffer *patch_map_quadtree,
int *min_patch_face,
int *max_patch_face,
int *max_depth,
int *patches_are_triangular)
{
evaluator->impl->eval_output->getPatchMap(patch_map_handles,
patch_map_quadtree,
min_patch_face,
max_patch_face,
max_depth,
patches_are_triangular);
}
static void fillPatchArraysBuffer(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *patch_array_buffer)
{
evaluator->impl->eval_output->fillPatchArraysBuffer(patch_array_buffer);
}
static void wrapPatchIndexBuffer(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *patch_index_buffer)
{
evaluator->impl->eval_output->wrapPatchIndexBuffer(patch_index_buffer);
}
static void wrapPatchParamBuffer(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *patch_param_buffer)
{
evaluator->impl->eval_output->wrapPatchParamBuffer(patch_param_buffer);
}
static void wrapSrcBuffer(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *src_buffer)
{
evaluator->impl->eval_output->wrapSrcBuffer(src_buffer);
}
static void wrapSrcVertexDataBuffer(struct OpenSubdiv_Evaluator *evaluator,
struct OpenSubdiv_Buffer *src_buffer)
{
evaluator->impl->eval_output->wrapSrcVertexDataBuffer(src_buffer);
}
static void fillFVarPatchArraysBuffer(struct OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
struct OpenSubdiv_Buffer *patch_array_buffer)
{
evaluator->impl->eval_output->fillFVarPatchArraysBuffer(face_varying_channel,
patch_array_buffer);
}
static void wrapFVarPatchIndexBuffer(struct OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
struct OpenSubdiv_Buffer *patch_index_buffer)
{
evaluator->impl->eval_output->wrapFVarPatchIndexBuffer(face_varying_channel, patch_index_buffer);
}
static void wrapFVarPatchParamBuffer(struct OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
struct OpenSubdiv_Buffer *patch_param_buffer)
{
evaluator->impl->eval_output->wrapFVarPatchParamBuffer(face_varying_channel, patch_param_buffer);
}
static void wrapFVarSrcBuffer(struct OpenSubdiv_Evaluator *evaluator,
const int face_varying_channel,
struct OpenSubdiv_Buffer *src_buffer)
{
evaluator->impl->eval_output->wrapFVarSrcBuffer(face_varying_channel, src_buffer);
}
static bool hasVertexData(struct OpenSubdiv_Evaluator *evaluator)
{
return evaluator->impl->eval_output->hasVertexData();
}
static void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
{
evaluator->setSettings = setSettings;
evaluator->setCoarsePositions = setCoarsePositions;
evaluator->setVertexData = setVertexData;
evaluator->setVaryingData = setVaryingData;
evaluator->setFaceVaryingData = setFaceVaryingData;
evaluator->setCoarsePositionsFromBuffer = setCoarsePositionsFromBuffer;
evaluator->setVaryingDataFromBuffer = setVaryingDataFromBuffer;
evaluator->setFaceVaryingDataFromBuffer = setFaceVaryingDataFromBuffer;
evaluator->refine = refine;
evaluator->evaluateLimit = evaluateLimit;
evaluator->evaluateVarying = evaluateVarying;
evaluator->evaluateVertexData = evaluateVertexData;
evaluator->evaluateFaceVarying = evaluateFaceVarying;
evaluator->evaluatePatchesLimit = evaluatePatchesLimit;
evaluator->getPatchMap = getPatchMap;
evaluator->fillPatchArraysBuffer = fillPatchArraysBuffer;
evaluator->wrapPatchIndexBuffer = wrapPatchIndexBuffer;
evaluator->wrapPatchParamBuffer = wrapPatchParamBuffer;
evaluator->wrapSrcBuffer = wrapSrcBuffer;
evaluator->wrapSrcVertexDataBuffer = wrapSrcVertexDataBuffer;
evaluator->fillFVarPatchArraysBuffer = fillFVarPatchArraysBuffer;
evaluator->wrapFVarPatchIndexBuffer = wrapFVarPatchIndexBuffer;
evaluator->wrapFVarPatchParamBuffer = wrapFVarPatchParamBuffer;
evaluator->wrapFVarSrcBuffer = wrapFVarSrcBuffer;
evaluator->hasVertexData = hasVertexData;
}
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
blender::opensubdiv::TopologyRefinerImpl *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
OpenSubdiv_Evaluator *evaluator = MEM_new<OpenSubdiv_Evaluator>(__func__);
assignFunctionPointers(evaluator);
evaluator->impl = openSubdiv_createEvaluatorInternal(
topology_refiner, evaluator_type, evaluator_cache ? evaluator_cache->impl : nullptr);
evaluator->type = evaluator->impl ? evaluator_type : static_cast<eOpenSubdivEvaluator>(0);
return evaluator;
}
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator)
{
openSubdiv_deleteEvaluatorInternal(evaluator->impl);
MEM_delete(evaluator);
}
OpenSubdiv_EvaluatorCache *openSubdiv_createEvaluatorCache(eOpenSubdivEvaluator evaluator_type)
{
OpenSubdiv_EvaluatorCache *evaluator_cache = MEM_new<OpenSubdiv_EvaluatorCache>(__func__);
evaluator_cache->impl = openSubdiv_createEvaluatorCacheInternal(evaluator_type);
return evaluator_cache;
}
void openSubdiv_deleteEvaluatorCache(OpenSubdiv_EvaluatorCache *evaluator_cache)
{
if (!evaluator_cache) {
return;
}
openSubdiv_deleteEvaluatorCacheInternal(evaluator_cache->impl);
MEM_delete(evaluator_cache);
}
const char *openSubdiv_getGLSLPatchBasisSource(void)
{
/* Using a global string to avoid dealing with memory allocation/ownership. */
static std::string patch_basis_source;
if (patch_basis_source.empty()) {
patch_basis_source = OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
}
return patch_basis_source.c_str();
}