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
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/opensubdiv/CMakeLists.txt4
-rw-r--r--intern/opensubdiv/internal/evaluator/eval_output_gpu.h4
-rw-r--r--intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc647
-rw-r--r--intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h2465
-rw-r--r--intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl316
5 files changed, 3433 insertions, 3 deletions
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index f141689791f..2bc429d7844 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -83,6 +83,8 @@ if(WITH_OPENSUBDIV)
internal/evaluator/evaluator_capi.cc
internal/evaluator/evaluator_impl.cc
internal/evaluator/evaluator_impl.h
+ internal/evaluator/gl_compute_evaluator.cc
+ internal/evaluator/gl_compute_evaluator.h
internal/evaluator/patch_map.cc
internal/evaluator/patch_map.h
@@ -121,6 +123,8 @@ if(WITH_OPENSUBDIV)
add_definitions(-DNOMINMAX)
add_definitions(-D_USE_MATH_DEFINES)
endif()
+
+ data_to_c_simple(internal/evaluator/shaders/glsl_compute_kernel.glsl SRC)
else()
list(APPEND SRC
stub/opensubdiv_stub.cc
diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
index 783efd484aa..dc137e4322e 100644
--- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
+++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
@@ -20,13 +20,11 @@
#define OPENSUBDIV_EVAL_OUTPUT_GPU_H_
#include "internal/evaluator/eval_output.h"
+#include "internal/evaluator/gl_compute_evaluator.h"
-#include <opensubdiv/osd/glComputeEvaluator.h>
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/osd/glVertexBuffer.h>
-using OpenSubdiv::Osd::GLComputeEvaluator;
-using OpenSubdiv::Osd::GLStencilTableSSBO;
using OpenSubdiv::Osd::GLVertexBuffer;
namespace blender {
diff --git a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc b/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc
new file mode 100644
index 00000000000..0cab44518aa
--- /dev/null
+++ b/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc
@@ -0,0 +1,647 @@
+//
+// Copyright 2015 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+
+#include "gl_compute_evaluator.h"
+
+#include <GL/glew.h>
+
+#include <opensubdiv/far/error.h>
+#include <opensubdiv/far/patchDescriptor.h>
+#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/osd/glslPatchShaderSource.h>
+
+#include <cassert>
+#include <cmath>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using OpenSubdiv::Far::LimitStencilTable;
+using OpenSubdiv::Far::StencilTable;
+using OpenSubdiv::Osd::BufferDescriptor;
+using OpenSubdiv::Osd::PatchArray;
+using OpenSubdiv::Osd::PatchArrayVector;
+
+extern "C" char datatoc_glsl_compute_kernel_glsl[];
+
+namespace blender {
+namespace opensubdiv {
+
+template<class T> GLuint createSSBO(std::vector<T> const &src)
+{
+ if (src.empty()) {
+ return 0;
+ }
+
+ GLuint devicePtr = 0;
+
+#if defined(GL_ARB_direct_state_access)
+ if (GLEW_ARB_direct_state_access) {
+ glCreateBuffers(1, &devicePtr);
+ glNamedBufferData(devicePtr, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
+ }
+ else
+#endif
+ {
+ GLint prev = 0;
+ glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
+ glGenBuffers(1, &devicePtr);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
+ }
+
+ return devicePtr;
+}
+
+GLStencilTableSSBO::GLStencilTableSSBO(StencilTable const *stencilTable)
+{
+ _numStencils = stencilTable->GetNumStencils();
+ if (_numStencils > 0) {
+ _sizes = createSSBO(stencilTable->GetSizes());
+ _offsets = createSSBO(stencilTable->GetOffsets());
+ _indices = createSSBO(stencilTable->GetControlIndices());
+ _weights = createSSBO(stencilTable->GetWeights());
+ _duWeights = _dvWeights = 0;
+ _duuWeights = _duvWeights = _dvvWeights = 0;
+ }
+ else {
+ _sizes = _offsets = _indices = _weights = 0;
+ _duWeights = _dvWeights = 0;
+ _duuWeights = _duvWeights = _dvvWeights = 0;
+ }
+}
+
+GLStencilTableSSBO::GLStencilTableSSBO(LimitStencilTable const *limitStencilTable)
+{
+ _numStencils = limitStencilTable->GetNumStencils();
+ if (_numStencils > 0) {
+ _sizes = createSSBO(limitStencilTable->GetSizes());
+ _offsets = createSSBO(limitStencilTable->GetOffsets());
+ _indices = createSSBO(limitStencilTable->GetControlIndices());
+ _weights = createSSBO(limitStencilTable->GetWeights());
+ _duWeights = createSSBO(limitStencilTable->GetDuWeights());
+ _dvWeights = createSSBO(limitStencilTable->GetDvWeights());
+ _duuWeights = createSSBO(limitStencilTable->GetDuuWeights());
+ _duvWeights = createSSBO(limitStencilTable->GetDuvWeights());
+ _dvvWeights = createSSBO(limitStencilTable->GetDvvWeights());
+ }
+ else {
+ _sizes = _offsets = _indices = _weights = 0;
+ _duWeights = _dvWeights = 0;
+ _duuWeights = _duvWeights = _dvvWeights = 0;
+ }
+}
+
+GLStencilTableSSBO::~GLStencilTableSSBO()
+{
+ if (_sizes)
+ glDeleteBuffers(1, &_sizes);
+ if (_offsets)
+ glDeleteBuffers(1, &_offsets);
+ if (_indices)
+ glDeleteBuffers(1, &_indices);
+ if (_weights)
+ glDeleteBuffers(1, &_weights);
+ if (_duWeights)
+ glDeleteBuffers(1, &_duWeights);
+ if (_dvWeights)
+ glDeleteBuffers(1, &_dvWeights);
+ if (_duuWeights)
+ glDeleteBuffers(1, &_duuWeights);
+ if (_duvWeights)
+ glDeleteBuffers(1, &_duvWeights);
+ if (_dvvWeights)
+ glDeleteBuffers(1, &_dvvWeights);
+}
+
+// ---------------------------------------------------------------------------
+
+GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(0)
+{
+ memset(&_stencilKernel, 0, sizeof(_stencilKernel));
+ memset(&_patchKernel, 0, sizeof(_patchKernel));
+}
+
+GLComputeEvaluator::~GLComputeEvaluator()
+{
+ if (_patchArraysSSBO) {
+ glDeleteBuffers(1, &_patchArraysSSBO);
+ }
+}
+
+static GLuint compileKernel(BufferDescriptor const &srcDesc,
+ BufferDescriptor const &dstDesc,
+ BufferDescriptor const &duDesc,
+ BufferDescriptor const &dvDesc,
+ BufferDescriptor const &duuDesc,
+ BufferDescriptor const &duvDesc,
+ BufferDescriptor const &dvvDesc,
+ const char *kernelDefine,
+ int workGroupSize)
+{
+ GLuint program = glCreateProgram();
+
+ GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
+
+ std::string patchBasisShaderSource =
+ OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
+ const char *patchBasisShaderSourceDefine = "#define OSD_PATCH_BASIS_GLSL\n";
+
+ std::ostringstream defines;
+ defines << "#define LENGTH " << srcDesc.length << "\n"
+ << "#define SRC_STRIDE " << srcDesc.stride << "\n"
+ << "#define DST_STRIDE " << dstDesc.stride << "\n"
+ << "#define WORK_GROUP_SIZE " << workGroupSize << "\n"
+ << kernelDefine << "\n"
+ << patchBasisShaderSourceDefine << "\n";
+
+ bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0);
+ bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0);
+ if (deriv1) {
+ defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n";
+ }
+ if (deriv2) {
+ defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES\n";
+ }
+
+ std::string defineStr = defines.str();
+
+ const char *shaderSources[4] = {"#version 430\n", 0, 0, 0};
+
+ shaderSources[1] = defineStr.c_str();
+ shaderSources[2] = patchBasisShaderSource.c_str();
+ shaderSources[3] = datatoc_glsl_compute_kernel_glsl;
+ glShaderSource(shader, 4, shaderSources, NULL);
+ glCompileShader(shader);
+ glAttachShader(program, shader);
+
+ GLint linked = 0;
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &linked);
+
+ if (linked == GL_FALSE) {
+ char buffer[1024];
+ glGetShaderInfoLog(shader, 1024, NULL, buffer);
+ OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
+
+ glGetProgramInfoLog(program, 1024, NULL, buffer);
+ OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
+
+ glDeleteProgram(program);
+ return 0;
+ }
+
+ glDeleteShader(shader);
+
+ return program;
+}
+
+bool GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
+ BufferDescriptor const &dstDesc,
+ BufferDescriptor const &duDesc,
+ BufferDescriptor const &dvDesc,
+ BufferDescriptor const &duuDesc,
+ BufferDescriptor const &duvDesc,
+ BufferDescriptor const &dvvDesc)
+{
+
+ // create a stencil kernel
+ if (!_stencilKernel.Compile(
+ srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) {
+ return false;
+ }
+
+ // create a patch kernel
+ if (!_patchKernel.Compile(
+ srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) {
+ return false;
+ }
+
+ // create a patch arrays buffer
+ if (!_patchArraysSSBO) {
+ glGenBuffers(1, &_patchArraysSSBO);
+ }
+
+ return true;
+}
+
+/* static */
+void GLComputeEvaluator::Synchronize(void * /*kernel*/)
+{
+ // XXX: this is currently just for the performance measuring purpose.
+ // need to be reimplemented by fence and sync.
+ glFinish();
+}
+
+int GLComputeEvaluator::GetDispatchSize(int count) const
+{
+ return (count + _workGroupSize - 1) / _workGroupSize;
+}
+
+void GLComputeEvaluator::DispatchCompute(int totalDispatchSize) const
+{
+ int maxWorkGroupCount[2] = {0, 0};
+
+ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &maxWorkGroupCount[0]);
+ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &maxWorkGroupCount[1]);
+
+ const uint maxResX = static_cast<uint>(maxWorkGroupCount[0]);
+
+ const int dispatchSize = GetDispatchSize(totalDispatchSize);
+ uint dispatchRX = static_cast<uint>(dispatchSize);
+ uint dispatchRY = 1u;
+ if (dispatchRX > maxResX) {
+ /* Since there are some limitations with regards to the maximum work group size (could be as
+ * low as 64k elements per call), we split the number elements into a "2d" number, with the
+ * final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum
+ * work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements
+ * total, which should be enough. If not, we could also use the 3rd dimension. */
+ /* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and
+ * get the smallest rect fitting the requirements. */
+ dispatchRX = dispatchRY = std::ceil(std::sqrt(dispatchSize));
+ /* Avoid a completely empty dispatch line caused by rounding. */
+ if ((dispatchRX * (dispatchRY - 1)) >= dispatchSize) {
+ dispatchRY -= 1;
+ }
+ }
+
+ /* X and Y dimensions may have different limits so the above computation may not be right, but
+ * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore,
+ * we presume it all fits. */
+ assert(dispatchRY < static_cast<uint>(maxWorkGroupCount[1]));
+
+ glDispatchCompute(dispatchRX, dispatchRY, 1);
+}
+
+bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
+ BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ BufferDescriptor const &dvDesc,
+ GLuint sizesBuffer,
+ GLuint offsetsBuffer,
+ GLuint indicesBuffer,
+ GLuint weightsBuffer,
+ GLuint duWeightsBuffer,
+ GLuint dvWeightsBuffer,
+ int start,
+ int end) const
+{
+
+ return EvalStencils(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ 0,
+ BufferDescriptor(),
+ 0,
+ BufferDescriptor(),
+ 0,
+ BufferDescriptor(),
+ sizesBuffer,
+ offsetsBuffer,
+ indicesBuffer,
+ weightsBuffer,
+ duWeightsBuffer,
+ dvWeightsBuffer,
+ 0,
+ 0,
+ 0,
+ start,
+ end);
+}
+
+bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
+ BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ BufferDescriptor const &dvDesc,
+ GLuint duuBuffer,
+ BufferDescriptor const &duuDesc,
+ GLuint duvBuffer,
+ BufferDescriptor const &duvDesc,
+ GLuint dvvBuffer,
+ BufferDescriptor const &dvvDesc,
+ GLuint sizesBuffer,
+ GLuint offsetsBuffer,
+ GLuint indicesBuffer,
+ GLuint weightsBuffer,
+ GLuint duWeightsBuffer,
+ GLuint dvWeightsBuffer,
+ GLuint duuWeightsBuffer,
+ GLuint duvWeightsBuffer,
+ GLuint dvvWeightsBuffer,
+ int start,
+ int end) const
+{
+
+ if (!_stencilKernel.program)
+ return false;
+ int count = end - start;
+ if (count <= 0) {
+ return true;
+ }
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
+ if (duWeightsBuffer)
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
+ if (dvWeightsBuffer)
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);
+ if (duuWeightsBuffer)
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer);
+ if (duvWeightsBuffer)
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer);
+ if (dvvWeightsBuffer)
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer);
+
+ glUseProgram(_stencilKernel.program);
+
+ glUniform1i(_stencilKernel.uniformStart, start);
+ glUniform1i(_stencilKernel.uniformEnd, end);
+ glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
+ glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset);
+ if (_stencilKernel.uniformDuDesc > 0) {
+ glUniform3i(_stencilKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
+ }
+ if (_stencilKernel.uniformDvDesc > 0) {
+ glUniform3i(_stencilKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
+ }
+ if (_stencilKernel.uniformDuuDesc > 0) {
+ glUniform3i(_stencilKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
+ }
+ if (_stencilKernel.uniformDuvDesc > 0) {
+ glUniform3i(_stencilKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
+ }
+ if (_stencilKernel.uniformDvvDesc > 0) {
+ glUniform3i(_stencilKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
+ }
+
+ DispatchCompute(count);
+
+ glUseProgram(0);
+
+ glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
+ for (int i = 0; i < 16; ++i) {
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
+ }
+
+ return true;
+}
+
+bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
+ BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ GLuint patchCoordsBuffer,
+ const PatchArrayVector &patchArrays,
+ GLuint patchIndexBuffer,
+ GLuint patchParamsBuffer) const
+{
+
+ return EvalPatches(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ 0,
+ BufferDescriptor(),
+ 0,
+ BufferDescriptor(),
+ 0,
+ BufferDescriptor(),
+ numPatchCoords,
+ patchCoordsBuffer,
+ patchArrays,
+ patchIndexBuffer,
+ patchParamsBuffer);
+}
+
+bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
+ BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ BufferDescriptor const &dvDesc,
+ GLuint duuBuffer,
+ BufferDescriptor const &duuDesc,
+ GLuint duvBuffer,
+ BufferDescriptor const &duvDesc,
+ GLuint dvvBuffer,
+ BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ GLuint patchCoordsBuffer,
+ const PatchArrayVector &patchArrays,
+ GLuint patchIndexBuffer,
+ GLuint patchParamsBuffer) const
+{
+
+ if (!_patchKernel.program)
+ return false;
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchCoordsBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer);
+
+ glUseProgram(_patchKernel.program);
+
+ glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
+ glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
+
+ int patchArraySize = sizeof(PatchArray);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, _patchArraysSSBO);
+ glBufferData(
+ GL_SHADER_STORAGE_BUFFER, patchArrays.size() * patchArraySize, NULL, GL_STATIC_DRAW);
+ for (int i = 0; i < (int)patchArrays.size(); ++i) {
+ glBufferSubData(
+ GL_SHADER_STORAGE_BUFFER, i * patchArraySize, sizeof(PatchArray), &patchArrays[i]);
+ }
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _patchArraysSSBO);
+
+ if (_patchKernel.uniformDuDesc > 0) {
+ glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
+ }
+ if (_patchKernel.uniformDvDesc > 0) {
+ glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
+ }
+ if (_patchKernel.uniformDuuDesc > 0) {
+ glUniform3i(_patchKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
+ }
+ if (_patchKernel.uniformDuvDesc > 0) {
+ glUniform3i(_patchKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
+ }
+ if (_patchKernel.uniformDvvDesc > 0) {
+ glUniform3i(_patchKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
+ }
+
+ DispatchCompute(numPatchCoords);
+
+ glUseProgram(0);
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, 0);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, 0);
+
+ return true;
+}
+// ---------------------------------------------------------------------------
+
+GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0)
+{
+}
+GLComputeEvaluator::_StencilKernel::~_StencilKernel()
+{
+ if (program) {
+ glDeleteProgram(program);
+ }
+}
+
+bool GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
+ BufferDescriptor const &dstDesc,
+ BufferDescriptor const &duDesc,
+ BufferDescriptor const &dvDesc,
+ BufferDescriptor const &duuDesc,
+ BufferDescriptor const &duvDesc,
+ BufferDescriptor const &dvvDesc,
+ int workGroupSize)
+{
+ // create stencil kernel
+ if (program) {
+ glDeleteProgram(program);
+ }
+
+ const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n";
+
+ program = compileKernel(
+ srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
+ if (program == 0)
+ return false;
+
+ // cache uniform locations (TODO: use uniform block)
+ uniformStart = glGetUniformLocation(program, "batchStart");
+ uniformEnd = glGetUniformLocation(program, "batchEnd");
+ uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
+ uniformDstOffset = glGetUniformLocation(program, "dstOffset");
+ uniformDuDesc = glGetUniformLocation(program, "duDesc");
+ uniformDvDesc = glGetUniformLocation(program, "dvDesc");
+ uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
+ uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
+ uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
+
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+
+GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0)
+{
+}
+GLComputeEvaluator::_PatchKernel::~_PatchKernel()
+{
+ if (program) {
+ glDeleteProgram(program);
+ }
+}
+
+bool GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
+ BufferDescriptor const &dstDesc,
+ BufferDescriptor const &duDesc,
+ BufferDescriptor const &dvDesc,
+ BufferDescriptor const &duuDesc,
+ BufferDescriptor const &duvDesc,
+ BufferDescriptor const &dvvDesc,
+ int workGroupSize)
+{
+ // create stencil kernel
+ if (program) {
+ glDeleteProgram(program);
+ }
+
+ const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n";
+
+ program = compileKernel(
+ srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
+ if (program == 0)
+ return false;
+
+ // cache uniform locations
+ uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
+ uniformDstOffset = glGetUniformLocation(program, "dstOffset");
+ uniformPatchArray = glGetUniformLocation(program, "patchArray");
+ uniformDuDesc = glGetUniformLocation(program, "duDesc");
+ uniformDvDesc = glGetUniformLocation(program, "dvDesc");
+ uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
+ uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
+ uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
+
+ return true;
+}
+
+} // namespace opensubdiv
+} // namespace blender
diff --git a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h b/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h
new file mode 100644
index 00000000000..85c12f73b08
--- /dev/null
+++ b/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h
@@ -0,0 +1,2465 @@
+//
+// Copyright 2015 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+
+#ifndef OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_
+#define OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_
+
+#include <opensubdiv/osd/bufferDescriptor.h>
+#include <opensubdiv/osd/opengl.h>
+#include <opensubdiv/osd/types.h>
+#include <opensubdiv/version.h>
+
+namespace OpenSubdiv {
+namespace OPENSUBDIV_VERSION {
+namespace Far {
+class LimitStencilTable;
+class StencilTable;
+} // namespace Far
+} // namespace OPENSUBDIV_VERSION
+} // namespace OpenSubdiv
+
+namespace blender {
+namespace opensubdiv {
+
+/// \brief GL stencil table (Shader Storage buffer)
+///
+/// This class is a GLSL SSBO representation of OpenSubdiv::Far::StencilTable.
+///
+/// GLSLComputeKernel consumes this table to apply stencils
+///
+class GLStencilTableSSBO {
+ public:
+ static GLStencilTableSSBO *Create(OpenSubdiv::Far::StencilTable const *stencilTable,
+ void *deviceContext = NULL)
+ {
+ (void)deviceContext; // unused
+ return new GLStencilTableSSBO(stencilTable);
+ }
+ static GLStencilTableSSBO *Create(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable,
+ void *deviceContext = NULL)
+ {
+ (void)deviceContext; // unused
+ return new GLStencilTableSSBO(limitStencilTable);
+ }
+
+ explicit GLStencilTableSSBO(OpenSubdiv::Far::StencilTable const *stencilTable);
+ explicit GLStencilTableSSBO(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable);
+ ~GLStencilTableSSBO();
+
+ // interfaces needed for GLSLComputeKernel
+ GLuint GetSizesBuffer() const
+ {
+ return _sizes;
+ }
+ GLuint GetOffsetsBuffer() const
+ {
+ return _offsets;
+ }
+ GLuint GetIndicesBuffer() const
+ {
+ return _indices;
+ }
+ GLuint GetWeightsBuffer() const
+ {
+ return _weights;
+ }
+ GLuint GetDuWeightsBuffer() const
+ {
+ return _duWeights;
+ }
+ GLuint GetDvWeightsBuffer() const
+ {
+ return _dvWeights;
+ }
+ GLuint GetDuuWeightsBuffer() const
+ {
+ return _duuWeights;
+ }
+ GLuint GetDuvWeightsBuffer() const
+ {
+ return _duvWeights;
+ }
+ GLuint GetDvvWeightsBuffer() const
+ {
+ return _dvvWeights;
+ }
+ int GetNumStencils() const
+ {
+ return _numStencils;
+ }
+
+ private:
+ GLuint _sizes;
+ GLuint _offsets;
+ GLuint _indices;
+ GLuint _weights;
+ GLuint _duWeights;
+ GLuint _dvWeights;
+ GLuint _duuWeights;
+ GLuint _duvWeights;
+ GLuint _dvvWeights;
+ int _numStencils;
+};
+
+// ---------------------------------------------------------------------------
+
+class GLComputeEvaluator {
+ public:
+ typedef bool Instantiatable;
+ static GLComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ void *deviceContext = NULL)
+ {
+ return Create(srcDesc,
+ dstDesc,
+ duDesc,
+ dvDesc,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor(),
+ deviceContext);
+ }
+
+ static GLComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ void *deviceContext = NULL)
+ {
+ (void)deviceContext; // not used
+ GLComputeEvaluator *instance = new GLComputeEvaluator();
+ if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc))
+ return instance;
+ delete instance;
+ return NULL;
+ }
+
+ /// Constructor.
+ GLComputeEvaluator();
+
+ /// Destructor. note that the GL context must be made current.
+ ~GLComputeEvaluator();
+
+ /// ----------------------------------------------------------------------
+ ///
+ /// Stencil evaluations with StencilTable
+ ///
+ /// ----------------------------------------------------------------------
+
+ /// \brief Generic static stencil function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// transparently from OsdMesh template interface.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLSL kernel
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ static bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ STENCIL_TABLE const *stencilTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalStencils(srcBuffer, srcDesc, dstBuffer, dstDesc, stencilTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc,
+ dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor());
+ if (instance) {
+ bool r = instance->EvalStencils(srcBuffer, srcDesc, dstBuffer, dstDesc, stencilTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic static stencil function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// transparently from OsdMesh template interface.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLSL kernel
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ static bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ STENCIL_TABLE const *stencilTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalStencils(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ stencilTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc);
+ if (instance) {
+ bool r = instance->EvalStencils(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ stencilTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic static stencil function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// transparently from OsdMesh template interface.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLSL kernel
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ static bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ STENCIL_TABLE const *stencilTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalStencils(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ stencilTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc);
+ if (instance) {
+ bool r = instance->EvalStencils(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ stencilTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic stencil function.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ STENCIL_TABLE const *stencilTable) const
+ {
+ return EvalStencils(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ stencilTable->GetSizesBuffer(),
+ stencilTable->GetOffsetsBuffer(),
+ stencilTable->GetIndicesBuffer(),
+ stencilTable->GetWeightsBuffer(),
+ 0,
+ 0,
+ /* start = */ 0,
+ /* end = */ stencilTable->GetNumStencils());
+ }
+
+ /// \brief Generic stencil function.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ STENCIL_TABLE const *stencilTable) const
+ {
+ return EvalStencils(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ stencilTable->GetSizesBuffer(),
+ stencilTable->GetOffsetsBuffer(),
+ stencilTable->GetIndicesBuffer(),
+ stencilTable->GetWeightsBuffer(),
+ stencilTable->GetDuWeightsBuffer(),
+ stencilTable->GetDvWeightsBuffer(),
+ /* start = */ 0,
+ /* end = */ stencilTable->GetNumStencils());
+ }
+
+ /// \brief Generic stencil function.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param stencilTable stencil table to be applied. The table must have
+ /// SSBO interfaces.
+ ///
+ template<typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
+ bool EvalStencils(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ STENCIL_TABLE const *stencilTable) const
+ {
+ return EvalStencils(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ duuBuffer->BindVBO(),
+ duuDesc,
+ duvBuffer->BindVBO(),
+ duvDesc,
+ dvvBuffer->BindVBO(),
+ dvvDesc,
+ stencilTable->GetSizesBuffer(),
+ stencilTable->GetOffsetsBuffer(),
+ stencilTable->GetIndicesBuffer(),
+ stencilTable->GetWeightsBuffer(),
+ stencilTable->GetDuWeightsBuffer(),
+ stencilTable->GetDvWeightsBuffer(),
+ stencilTable->GetDuuWeightsBuffer(),
+ stencilTable->GetDuvWeightsBuffer(),
+ stencilTable->GetDvvWeightsBuffer(),
+ /* start = */ 0,
+ /* end = */ stencilTable->GetNumStencils());
+ }
+
+ /// \brief Dispatch the GLSL compute kernel on GPU asynchronously
+ /// returns false if the kernel hasn't been compiled yet.
+ ///
+ /// @param srcBuffer GL buffer of input primvar source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the srcBuffer
+ ///
+ /// @param dstBuffer GL buffer of output primvar destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer GL buffer of output derivative wrt u
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer GL buffer of output derivative wrt v
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param sizesBuffer GL buffer of the sizes in the stencil table
+ ///
+ /// @param offsetsBuffer GL buffer of the offsets in the stencil table
+ ///
+ /// @param indicesBuffer GL buffer of the indices in the stencil table
+ ///
+ /// @param weightsBuffer GL buffer of the weights in the stencil table
+ ///
+ /// @param duWeightsBuffer GL buffer of the du weights in the stencil table
+ ///
+ /// @param dvWeightsBuffer GL buffer of the dv weights in the stencil table
+ ///
+ /// @param start start index of stencil table
+ ///
+ /// @param end end index of stencil table
+ ///
+ bool EvalStencils(GLuint srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ GLuint sizesBuffer,
+ GLuint offsetsBuffer,
+ GLuint indicesBuffer,
+ GLuint weightsBuffer,
+ GLuint duWeightsBuffer,
+ GLuint dvWeightsBuffer,
+ int start,
+ int end) const;
+
+ /// \brief Dispatch the GLSL compute kernel on GPU asynchronously
+ /// returns false if the kernel hasn't been compiled yet.
+ ///
+ /// @param srcBuffer GL buffer of input primvar source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the srcBuffer
+ ///
+ /// @param dstBuffer GL buffer of output primvar destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the dstBuffer
+ ///
+ /// @param duBuffer GL buffer of output derivative wrt u
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer GL buffer of output derivative wrt v
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer GL buffer of output 2nd derivative wrt u
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer GL buffer of output 2nd derivative wrt u and v
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer GL buffer of output 2nd derivative wrt v
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param sizesBuffer GL buffer of the sizes in the stencil table
+ ///
+ /// @param offsetsBuffer GL buffer of the offsets in the stencil table
+ ///
+ /// @param indicesBuffer GL buffer of the indices in the stencil table
+ ///
+ /// @param weightsBuffer GL buffer of the weights in the stencil table
+ ///
+ /// @param duWeightsBuffer GL buffer of the du weights in the stencil table
+ ///
+ /// @param dvWeightsBuffer GL buffer of the dv weights in the stencil table
+ ///
+ /// @param duuWeightsBuffer GL buffer of the duu weights in the stencil table
+ ///
+ /// @param duvWeightsBuffer GL buffer of the duv weights in the stencil table
+ ///
+ /// @param dvvWeightsBuffer GL buffer of the dvv weights in the stencil table
+ ///
+ /// @param start start index of stencil table
+ ///
+ /// @param end end index of stencil table
+ ///
+ bool EvalStencils(GLuint srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ GLuint duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ GLuint duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ GLuint dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ GLuint sizesBuffer,
+ GLuint offsetsBuffer,
+ GLuint indicesBuffer,
+ GLuint weightsBuffer,
+ GLuint duWeightsBuffer,
+ GLuint dvWeightsBuffer,
+ GLuint duuWeightsBuffer,
+ GLuint duvWeightsBuffer,
+ GLuint dvvWeightsBuffer,
+ int start,
+ int end) const;
+
+ /// ----------------------------------------------------------------------
+ ///
+ /// Limit evaluations with PatchTable
+ ///
+ /// ----------------------------------------------------------------------
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatches(
+ srcBuffer, srcDesc, dstBuffer, dstDesc, numPatchCoords, patchCoords, patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc,
+ dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor());
+ if (instance) {
+ bool r = instance->EvalPatches(
+ srcBuffer, srcDesc, dstBuffer, dstDesc, numPatchCoords, patchCoords, patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatches(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc);
+ if (instance) {
+ bool r = instance->EvalPatches(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatches(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc);
+ if (instance) {
+ bool r = instance->EvalPatches(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetPatchArrays(),
+ patchTable->GetPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ /// \brief Generic limit eval function with derivatives. This function has
+ /// a same signature as other device kernels have so that it can be
+ /// called in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetPatchArrays(),
+ patchTable->GetPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ /// \brief Generic limit eval function with derivatives. This function has
+ /// a same signature as other device kernels have so that it can be
+ /// called in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatches(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ duuBuffer->BindVBO(),
+ duuDesc,
+ duvBuffer->BindVBO(),
+ duvDesc,
+ dvvBuffer->BindVBO(),
+ dvvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetPatchArrays(),
+ patchTable->GetPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ bool EvalPatches(GLuint srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ GLuint patchCoordsBuffer,
+ const OpenSubdiv::Osd::PatchArrayVector &patchArrays,
+ GLuint patchIndexBuffer,
+ GLuint patchParamsBuffer) const;
+
+ bool EvalPatches(GLuint srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ GLuint dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ GLuint duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ GLuint dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ GLuint duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ GLuint duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ GLuint dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ GLuint patchCoordsBuffer,
+ const OpenSubdiv::Osd::PatchArrayVector &patchArrays,
+ GLuint patchIndexBuffer,
+ GLuint patchParamsBuffer) const;
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesVarying(
+ srcBuffer, srcDesc, dstBuffer, dstDesc, numPatchCoords, patchCoords, patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc,
+ dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor());
+ if (instance) {
+ bool r = instance->EvalPatchesVarying(
+ srcBuffer, srcDesc, dstBuffer, dstDesc, numPatchCoords, patchCoords, patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetVaryingPatchArrays(),
+ patchTable->GetVaryingPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc);
+ if (instance) {
+ bool r = instance->EvalPatchesVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetVaryingPatchArrays(),
+ patchTable->GetVaryingPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc);
+ if (instance) {
+ bool r = instance->EvalPatchesVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ duuBuffer->BindVBO(),
+ duuDesc,
+ duvBuffer->BindVBO(),
+ duvDesc,
+ dvvBuffer->BindVBO(),
+ dvvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetVaryingPatchArrays(),
+ patchTable->GetVaryingPatchIndexBuffer(),
+ patchTable->GetPatchParamBuffer());
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc,
+ dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor());
+ if (instance) {
+ bool r = instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel = 0) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ 0,
+ OpenSubdiv::Osd::BufferDescriptor(),
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetFVarPatchArrays(fvarChannel),
+ patchTable->GetFVarPatchIndexBuffer(fvarChannel),
+ patchTable->GetFVarPatchParamBuffer(fvarChannel));
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc);
+ if (instance) {
+ bool r = instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel = 0) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetFVarPatchArrays(fvarChannel),
+ patchTable->GetFVarPatchIndexBuffer(fvarChannel),
+ patchTable->GetFVarPatchParamBuffer(fvarChannel));
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ /// @param instance cached compiled instance. Clients are supposed to
+ /// pre-compile an instance of this class and provide
+ /// to this function. If it's null the kernel still
+ /// compute by instantiating on-demand kernel although
+ /// it may cause a performance problem.
+ ///
+ /// @param deviceContext not used in the GLXFB evaluator
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ static bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel,
+ GLComputeEvaluator const *instance,
+ void *deviceContext = NULL)
+ {
+
+ if (instance) {
+ return instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ }
+ else {
+ // Create an instance on demand (slow)
+ (void)deviceContext; // unused
+ instance = Create(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc);
+ if (instance) {
+ bool r = instance->EvalPatchesFaceVarying(srcBuffer,
+ srcDesc,
+ dstBuffer,
+ dstDesc,
+ duBuffer,
+ duDesc,
+ dvBuffer,
+ dvDesc,
+ duuBuffer,
+ duuDesc,
+ duvBuffer,
+ duvDesc,
+ dvvBuffer,
+ dvvDesc,
+ numPatchCoords,
+ patchCoords,
+ patchTable,
+ fvarChannel);
+ delete instance;
+ return r;
+ }
+ return false;
+ }
+ }
+
+ /// \brief Generic limit eval function. This function has a same
+ /// signature as other device kernels have so that it can be called
+ /// in the same way.
+ ///
+ /// @param srcBuffer Input primvar buffer.
+ /// must have BindVBO() method returning a GL
+ /// buffer object of source data
+ ///
+ /// @param srcDesc vertex buffer descriptor for the input buffer
+ ///
+ /// @param dstBuffer Output primvar buffer
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dstDesc vertex buffer descriptor for the output buffer
+ ///
+ /// @param duBuffer Output buffer derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duDesc vertex buffer descriptor for the duBuffer
+ ///
+ /// @param dvBuffer Output buffer derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvDesc vertex buffer descriptor for the dvBuffer
+ ///
+ /// @param duuBuffer Output buffer 2nd derivative wrt u
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duuDesc vertex buffer descriptor for the duuBuffer
+ ///
+ /// @param duvBuffer Output buffer 2nd derivative wrt u and v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param duvDesc vertex buffer descriptor for the duvBuffer
+ ///
+ /// @param dvvBuffer Output buffer 2nd derivative wrt v
+ /// must have BindVBO() method returning a GL
+ /// buffer object of destination data
+ ///
+ /// @param dvvDesc vertex buffer descriptor for the dvvBuffer
+ ///
+ /// @param numPatchCoords number of patchCoords.
+ ///
+ /// @param patchCoords array of locations to be evaluated.
+ /// must have BindVBO() method returning an
+ /// array of PatchCoord struct in VBO.
+ ///
+ /// @param patchTable GLPatchTable or equivalent
+ ///
+ /// @param fvarChannel face-varying channel
+ ///
+ template<typename SRC_BUFFER,
+ typename DST_BUFFER,
+ typename PATCHCOORD_BUFFER,
+ typename PATCH_TABLE>
+ bool EvalPatchesFaceVarying(SRC_BUFFER *srcBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ DST_BUFFER *dstBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ DST_BUFFER *duBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ DST_BUFFER *dvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ DST_BUFFER *duuBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ DST_BUFFER *duvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ DST_BUFFER *dvvBuffer,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int numPatchCoords,
+ PATCHCOORD_BUFFER *patchCoords,
+ PATCH_TABLE *patchTable,
+ int fvarChannel = 0) const
+ {
+
+ return EvalPatches(srcBuffer->BindVBO(),
+ srcDesc,
+ dstBuffer->BindVBO(),
+ dstDesc,
+ duBuffer->BindVBO(),
+ duDesc,
+ dvBuffer->BindVBO(),
+ dvDesc,
+ duuBuffer->BindVBO(),
+ duuDesc,
+ duvBuffer->BindVBO(),
+ duvDesc,
+ dvvBuffer->BindVBO(),
+ dvvDesc,
+ numPatchCoords,
+ patchCoords->BindVBO(),
+ patchTable->GetFVarPatchArrays(fvarChannel),
+ patchTable->GetFVarPatchIndexBuffer(fvarChannel),
+ patchTable->GetFVarPatchParamBuffer(fvarChannel));
+ }
+
+ /// ----------------------------------------------------------------------
+ ///
+ /// Other methods
+ ///
+ /// ----------------------------------------------------------------------
+
+ /// Configure GLSL kernel. A valid GL context must be made current before
+ /// calling this function. Returns false if it fails to compile the kernel.
+ bool Compile(
+ OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc = OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc = OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc = OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc = OpenSubdiv::Osd::BufferDescriptor(),
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc = OpenSubdiv::Osd::BufferDescriptor());
+
+ /// Wait the dispatched kernel finishes.
+ static void Synchronize(void *deviceContext);
+
+ private:
+ struct _StencilKernel {
+ _StencilKernel();
+ ~_StencilKernel();
+ bool Compile(OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int workGroupSize);
+ GLuint program;
+ GLuint uniformStart;
+ GLuint uniformEnd;
+ GLuint uniformSrcOffset;
+ GLuint uniformDstOffset;
+ GLuint uniformDuDesc;
+ GLuint uniformDvDesc;
+ GLuint uniformDuuDesc;
+ GLuint uniformDuvDesc;
+ GLuint uniformDvvDesc;
+ } _stencilKernel;
+
+ struct _PatchKernel {
+ _PatchKernel();
+ ~_PatchKernel();
+ bool Compile(OpenSubdiv::Osd::BufferDescriptor const &srcDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dstDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duuDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &duvDesc,
+ OpenSubdiv::Osd::BufferDescriptor const &dvvDesc,
+ int workGroupSize);
+ GLuint program;
+ GLuint uniformSrcOffset;
+ GLuint uniformDstOffset;
+ GLuint uniformPatchArray;
+ GLuint uniformDuDesc;
+ GLuint uniformDvDesc;
+ GLuint uniformDuuDesc;
+ GLuint uniformDuvDesc;
+ GLuint uniformDvvDesc;
+ } _patchKernel;
+
+ int _workGroupSize;
+ GLuint _patchArraysSSBO;
+
+ int GetDispatchSize(int count) const;
+
+ void DispatchCompute(int totalDispatchSize) const;
+};
+} // namespace opensubdiv
+} // namespace blender
+
+#endif // OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_
diff --git a/intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl b/intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl
new file mode 100644
index 00000000000..2a58fa10ea0
--- /dev/null
+++ b/intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl
@@ -0,0 +1,316 @@
+//
+// Copyright 2013 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+
+//------------------------------------------------------------------------------
+
+
+layout(local_size_x=WORK_GROUP_SIZE, local_size_y=1, local_size_z=1) in;
+layout(std430) buffer;
+
+// source and destination buffers
+
+uniform int srcOffset = 0;
+uniform int dstOffset = 0;
+layout(binding=0) buffer src_buffer { float srcVertexBuffer[]; };
+layout(binding=1) buffer dst_buffer { float dstVertexBuffer[]; };
+
+// derivative buffers (if needed)
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
+uniform ivec3 duDesc;
+uniform ivec3 dvDesc;
+layout(binding=2) buffer du_buffer { float duBuffer[]; };
+layout(binding=3) buffer dv_buffer { float dvBuffer[]; };
+#endif
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
+uniform ivec3 duuDesc;
+uniform ivec3 duvDesc;
+uniform ivec3 dvvDesc;
+layout(binding=10) buffer duu_buffer { float duuBuffer[]; };
+layout(binding=11) buffer duv_buffer { float duvBuffer[]; };
+layout(binding=12) buffer dvv_buffer { float dvvBuffer[]; };
+#endif
+
+// stencil buffers
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
+
+uniform int batchStart = 0;
+uniform int batchEnd = 0;
+layout(binding=4) buffer stencilSizes { int _sizes[]; };
+layout(binding=5) buffer stencilOffsets { int _offsets[]; };
+layout(binding=6) buffer stencilIndices { int _indices[]; };
+layout(binding=7) buffer stencilWeights { float _weights[]; };
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
+layout(binding=8) buffer stencilDuWeights { float _duWeights[]; };
+layout(binding=9) buffer stencilDvWeights { float _dvWeights[]; };
+#endif
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
+layout(binding=13) buffer stencilDuuWeights { float _duuWeights[]; };
+layout(binding=14) buffer stencilDuvWeights { float _duvWeights[]; };
+layout(binding=15) buffer stencilDvvWeights { float _dvvWeights[]; };
+#endif
+
+uint getGlobalInvocationIndex()
+{
+ uint invocations_per_row = gl_WorkGroupSize.x * gl_NumWorkGroups.x;
+ return gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * invocations_per_row;
+}
+
+#endif
+
+// patch buffers
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
+
+layout(binding=4) buffer patchArray_buffer { OsdPatchArray patchArrayBuffer[]; };
+layout(binding=5) buffer patchCoord_buffer { OsdPatchCoord patchCoords[]; };
+layout(binding=6) buffer patchIndex_buffer { int patchIndexBuffer[]; };
+layout(binding=7) buffer patchParam_buffer { OsdPatchParam patchParamBuffer[]; };
+
+OsdPatchCoord GetPatchCoord(int coordIndex)
+{
+ return patchCoords[coordIndex];
+}
+
+OsdPatchArray GetPatchArray(int arrayIndex)
+{
+ return patchArrayBuffer[arrayIndex];
+}
+
+OsdPatchParam GetPatchParam(int patchIndex)
+{
+ return patchParamBuffer[patchIndex];
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+
+struct Vertex {
+ float vertexData[LENGTH];
+};
+
+void clear(out Vertex v) {
+ for (int i = 0; i < LENGTH; ++i) {
+ v.vertexData[i] = 0;
+ }
+}
+
+Vertex readVertex(int index) {
+ Vertex v;
+ int vertexIndex = srcOffset + index * SRC_STRIDE;
+ for (int i = 0; i < LENGTH; ++i) {
+ v.vertexData[i] = srcVertexBuffer[vertexIndex + i];
+ }
+ return v;
+}
+
+void writeVertex(int index, Vertex v) {
+ int vertexIndex = dstOffset + index * DST_STRIDE;
+ for (int i = 0; i < LENGTH; ++i) {
+ dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
+ }
+}
+
+void addWithWeight(inout Vertex v, const Vertex src, float weight) {
+ for (int i = 0; i < LENGTH; ++i) {
+ v.vertexData[i] += weight * src.vertexData[i];
+ }
+}
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
+void writeDu(int index, Vertex du) {
+ int duIndex = duDesc.x + index * duDesc.z;
+ for (int i = 0; i < LENGTH; ++i) {
+ duBuffer[duIndex + i] = du.vertexData[i];
+ }
+}
+
+void writeDv(int index, Vertex dv) {
+ int dvIndex = dvDesc.x + index * dvDesc.z;
+ for (int i = 0; i < LENGTH; ++i) {
+ dvBuffer[dvIndex + i] = dv.vertexData[i];
+ }
+}
+#endif
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
+void writeDuu(int index, Vertex duu) {
+ int duuIndex = duuDesc.x + index * duuDesc.z;
+ for (int i = 0; i < LENGTH; ++i) {
+ duuBuffer[duuIndex + i] = duu.vertexData[i];
+ }
+}
+
+void writeDuv(int index, Vertex duv) {
+ int duvIndex = duvDesc.x + index * duvDesc.z;
+ for (int i = 0; i < LENGTH; ++i) {
+ duvBuffer[duvIndex + i] = duv.vertexData[i];
+ }
+}
+
+void writeDvv(int index, Vertex dvv) {
+ int dvvIndex = dvvDesc.x + index * dvvDesc.z;
+ for (int i = 0; i < LENGTH; ++i) {
+ dvvBuffer[dvvIndex + i] = dvv.vertexData[i];
+ }
+}
+#endif
+
+//------------------------------------------------------------------------------
+#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
+
+void main() {
+ int current = int(getGlobalInvocationIndex()) + batchStart;
+
+ if (current>=batchEnd) {
+ return;
+ }
+
+ Vertex dst;
+ clear(dst);
+
+ int offset = _offsets[current],
+ size = _sizes[current];
+
+ for (int stencil = 0; stencil < size; ++stencil) {
+ int vindex = offset + stencil;
+ addWithWeight(
+ dst, readVertex(_indices[vindex]), _weights[vindex]);
+ }
+
+ writeVertex(current, dst);
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
+ Vertex du, dv;
+ clear(du);
+ clear(dv);
+ for (int i=0; i<size; ++i) {
+ // expects the compiler optimizes readVertex out here.
+ Vertex src = readVertex(_indices[offset+i]);
+ addWithWeight(du, src, _duWeights[offset+i]);
+ addWithWeight(dv, src, _dvWeights[offset+i]);
+ }
+
+ if (duDesc.y > 0) { // length
+ writeDu(current, du);
+ }
+ if (dvDesc.y > 0) {
+ writeDv(current, dv);
+ }
+#endif
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
+ Vertex duu, duv, dvv;
+ clear(duu);
+ clear(duv);
+ clear(dvv);
+ for (int i=0; i<size; ++i) {
+ // expects the compiler optimizes readVertex out here.
+ Vertex src = readVertex(_indices[offset+i]);
+ addWithWeight(duu, src, _duuWeights[offset+i]);
+ addWithWeight(duv, src, _duvWeights[offset+i]);
+ addWithWeight(dvv, src, _dvvWeights[offset+i]);
+ }
+
+ if (duuDesc.y > 0) { // length
+ writeDuu(current, duu);
+ }
+ if (duvDesc.y > 0) {
+ writeDuv(current, duv);
+ }
+ if (dvvDesc.y > 0) {
+ writeDvv(current, dvv);
+ }
+#endif
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
+
+// PERFORMANCE: stride could be constant, but not as significant as length
+
+void main() {
+
+ int current = int(gl_GlobalInvocationID.x);
+
+ OsdPatchCoord coord = GetPatchCoord(current);
+ OsdPatchArray array = GetPatchArray(coord.arrayIndex);
+ OsdPatchParam param = GetPatchParam(coord.patchIndex);
+
+ int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
+
+ float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
+ int nPoints = OsdEvaluatePatchBasis(patchType, param,
+ coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
+
+ Vertex dst, du, dv, duu, duv, dvv;
+ clear(dst);
+ clear(du);
+ clear(dv);
+ clear(duu);
+ clear(duv);
+ clear(dvv);
+
+ int indexBase = array.indexBase + array.stride *
+ (coord.patchIndex - array.primitiveIdBase);
+
+ for (int cv = 0; cv < nPoints; ++cv) {
+ int index = patchIndexBuffer[indexBase + cv];
+ addWithWeight(dst, readVertex(index), wP[cv]);
+ addWithWeight(du, readVertex(index), wDu[cv]);
+ addWithWeight(dv, readVertex(index), wDv[cv]);
+ addWithWeight(duu, readVertex(index), wDuu[cv]);
+ addWithWeight(duv, readVertex(index), wDuv[cv]);
+ addWithWeight(dvv, readVertex(index), wDvv[cv]);
+ }
+ writeVertex(current, dst);
+
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
+ if (duDesc.y > 0) { // length
+ writeDu(current, du);
+ }
+ if (dvDesc.y > 0) {
+ writeDv(current, dv);
+ }
+#endif
+#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
+ if (duuDesc.y > 0) { // length
+ writeDuu(current, duu);
+ }
+ if (duvDesc.y > 0) { // length
+ writeDuv(current, duv);
+ }
+ if (dvvDesc.y > 0) {
+ writeDvv(current, dvv);
+ }
+#endif
+}
+
+#endif