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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-02-16 18:55:35 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-02-17 15:14:19 +0300
commitc5dcfb63d9e40138f03c135346bfa779abcb0e58 (patch)
tree061a135b08eed01a98f66f434176dc75958ff2b3
parentbe3047c500bebcbf82ec95158a5d24703c104f3d (diff)
Fix T94881: GPU subdivision fails with high polycount coarse meshes
Coarse meshes with high polycount would show as corrupted when GPU subdivision is used with AMD cards This was caused by the OpenSubdiv library not taking `GL_MAX_COMPUTE_WORK_GROUP_COUNT` into account when dispatching computes. AMD drivers tend to set the limit lower than NVidia ones (2^16 for the former, and 2^32 for the latter, at least on my machine). This moves the `GLComputeEvaluator` from the OpenSubdiv library into `intern/opensubdiv` and modifies it to compute a dispatch size in a similar way as for the draw code: we split the dispatch size into a 2 dimensional value based on `GL_MAX_COMPUTE_WORK_GROUP_COUNT` and manually compute an index in the shader. We could have patched the OpenSubdiv library and sent the fix upstream (which can still be done), however, moving it to our side allows us to better control the `GLComputeEvaluator` and in the future remove some redundant work that it does compared to Blender (see T94644) and probably prepare the ground for Vulkan support. As a matter of fact, this patch also removes the OpenGL initialization that OpenSubdiv would do here. This removal is not related to the bug fix, but necessary to not have to copy more files/code over. Differential Revision: https://developer.blender.org/D14131
-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