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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc')
-rw-r--r--intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc647
1 files changed, 647 insertions, 0 deletions
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