Blender V4.3
gl_compute_evaluator.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2015 Pixar
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <epoxy/gl.h>
6
7/* There are few aspects here:
8 * - macOS is strict about including both gl.h and gl3.h
9 * - libepoxy only pretends to be a replacement for gl.h
10 * - OpenSubdiv internally uses `OpenGL/gl3.h` on macOS
11 *
12 * In order to silence the warning pretend that gl3 has been included, fully relying on symbols
13 * from the epoxy.
14 *
15 * This works differently from how OpenSubdiv internally will use `OpenGL/gl3.h` without epoxy.
16 * Sounds fragile, but so far things seems to work. */
17#if defined(__APPLE__)
18# define __gl3_h_
19#endif
20
22
23#include <opensubdiv/far/error.h>
24#include <opensubdiv/far/patchDescriptor.h>
25#include <opensubdiv/far/stencilTable.h>
26#include <opensubdiv/osd/glslPatchShaderSource.h>
27
28#include <cassert>
29#include <cmath>
30#include <sstream>
31#include <string>
32#include <vector>
33
34using OpenSubdiv::Far::LimitStencilTable;
35using OpenSubdiv::Far::StencilTable;
36using OpenSubdiv::Osd::BufferDescriptor;
37using OpenSubdiv::Osd::PatchArray;
38using OpenSubdiv::Osd::PatchArrayVector;
39
41
42namespace blender::opensubdiv {
43
44template<class T> GLuint createSSBO(std::vector<T> const &src)
45{
46 if (src.empty()) {
47 return 0;
48 }
49
50 GLuint devicePtr = 0;
51
52#if defined(GL_ARB_direct_state_access)
53 if (epoxy_has_gl_extension("GL_ARB_direct_state_access")) {
54 glCreateBuffers(1, &devicePtr);
55 glNamedBufferData(devicePtr, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
56 }
57 else
58#endif
59 {
60 GLint prev = 0;
61 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
62 glGenBuffers(1, &devicePtr);
63 glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
64 glBufferData(GL_SHADER_STORAGE_BUFFER, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
65 glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
66 }
67
68 return devicePtr;
69}
70
71GLStencilTableSSBO::GLStencilTableSSBO(StencilTable const *stencilTable)
72{
73 _numStencils = stencilTable->GetNumStencils();
74 if (_numStencils > 0) {
75 _sizes = createSSBO(stencilTable->GetSizes());
76 _offsets = createSSBO(stencilTable->GetOffsets());
77 _indices = createSSBO(stencilTable->GetControlIndices());
78 _weights = createSSBO(stencilTable->GetWeights());
79 _duWeights = _dvWeights = 0;
80 _duuWeights = _duvWeights = _dvvWeights = 0;
81 }
82 else {
83 _sizes = _offsets = _indices = _weights = 0;
84 _duWeights = _dvWeights = 0;
85 _duuWeights = _duvWeights = _dvvWeights = 0;
86 }
87}
88
89GLStencilTableSSBO::GLStencilTableSSBO(LimitStencilTable const *limitStencilTable)
90{
91 _numStencils = limitStencilTable->GetNumStencils();
92 if (_numStencils > 0) {
93 _sizes = createSSBO(limitStencilTable->GetSizes());
94 _offsets = createSSBO(limitStencilTable->GetOffsets());
95 _indices = createSSBO(limitStencilTable->GetControlIndices());
96 _weights = createSSBO(limitStencilTable->GetWeights());
97 _duWeights = createSSBO(limitStencilTable->GetDuWeights());
98 _dvWeights = createSSBO(limitStencilTable->GetDvWeights());
99 _duuWeights = createSSBO(limitStencilTable->GetDuuWeights());
100 _duvWeights = createSSBO(limitStencilTable->GetDuvWeights());
101 _dvvWeights = createSSBO(limitStencilTable->GetDvvWeights());
102 }
103 else {
104 _sizes = _offsets = _indices = _weights = 0;
105 _duWeights = _dvWeights = 0;
106 _duuWeights = _duvWeights = _dvvWeights = 0;
107 }
108}
109
111{
112 if (_sizes) {
113 glDeleteBuffers(1, &_sizes);
114 }
115 if (_offsets) {
116 glDeleteBuffers(1, &_offsets);
117 }
118 if (_indices) {
119 glDeleteBuffers(1, &_indices);
120 }
121 if (_weights) {
122 glDeleteBuffers(1, &_weights);
123 }
124 if (_duWeights) {
125 glDeleteBuffers(1, &_duWeights);
126 }
127 if (_dvWeights) {
128 glDeleteBuffers(1, &_dvWeights);
129 }
130 if (_duuWeights) {
131 glDeleteBuffers(1, &_duuWeights);
132 }
133 if (_duvWeights) {
134 glDeleteBuffers(1, &_duvWeights);
135 }
136 if (_dvvWeights) {
137 glDeleteBuffers(1, &_dvvWeights);
138 }
139}
140
141// ---------------------------------------------------------------------------
142
143GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(0)
144{
145 memset((void *)&_stencilKernel, 0, sizeof(_stencilKernel));
146 memset((void *)&_patchKernel, 0, sizeof(_patchKernel));
147}
148
150{
151 if (_patchArraysSSBO) {
152 glDeleteBuffers(1, &_patchArraysSSBO);
153 }
154}
155
156static GLuint compileKernel(BufferDescriptor const &srcDesc,
157 BufferDescriptor const &dstDesc,
158 BufferDescriptor const &duDesc,
159 BufferDescriptor const &dvDesc,
160 BufferDescriptor const &duuDesc,
161 BufferDescriptor const &duvDesc,
162 BufferDescriptor const &dvvDesc,
163 const char *kernelDefine,
164 int workGroupSize)
165{
166 GLuint program = glCreateProgram();
167
168 GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
169
170 std::string patchBasisShaderSource =
171 OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
172 const char *patchBasisShaderSourceDefine = "#define OSD_PATCH_BASIS_GLSL\n";
173
174 std::ostringstream defines;
175 defines << "#define LENGTH " << srcDesc.length << "\n"
176 << "#define SRC_STRIDE " << srcDesc.stride << "\n"
177 << "#define DST_STRIDE " << dstDesc.stride << "\n"
178 << "#define WORK_GROUP_SIZE " << workGroupSize << "\n"
179 << kernelDefine << "\n"
180 << patchBasisShaderSourceDefine << "\n";
181
182 bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0);
183 bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0);
184 if (deriv1) {
185 defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n";
186 }
187 if (deriv2) {
188 defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES\n";
189 }
190
191 std::string defineStr = defines.str();
192
193 const char *shaderSources[4] = {"#version 430\n", 0, 0, 0};
194
195 shaderSources[1] = defineStr.c_str();
196 shaderSources[2] = patchBasisShaderSource.c_str();
197 shaderSources[3] = datatoc_glsl_compute_kernel_glsl;
198 glShaderSource(shader, 4, shaderSources, NULL);
199 glCompileShader(shader);
200 glAttachShader(program, shader);
201
202 GLint linked = 0;
203 glLinkProgram(program);
204 glGetProgramiv(program, GL_LINK_STATUS, &linked);
205
206 if (linked == GL_FALSE) {
207 char buffer[1024];
208 glGetShaderInfoLog(shader, 1024, NULL, buffer);
209 OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
210
211 glGetProgramInfoLog(program, 1024, NULL, buffer);
212 OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
213
214 glDeleteProgram(program);
215 return 0;
216 }
217
218 glDeleteShader(shader);
219
220 return program;
221}
222
223bool GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
224 BufferDescriptor const &dstDesc,
225 BufferDescriptor const &duDesc,
226 BufferDescriptor const &dvDesc,
227 BufferDescriptor const &duuDesc,
228 BufferDescriptor const &duvDesc,
229 BufferDescriptor const &dvvDesc)
230{
231
232 // create a stencil kernel
233 if (!_stencilKernel.Compile(
234 srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize))
235 {
236 return false;
237 }
238
239 // create a patch kernel
240 if (!_patchKernel.Compile(
241 srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize))
242 {
243 return false;
244 }
245
246 // create a patch arrays buffer
247 if (!_patchArraysSSBO) {
248 glGenBuffers(1, &_patchArraysSSBO);
249 }
250
251 return true;
252}
253
254/* static */
255void GLComputeEvaluator::Synchronize(void * /*kernel*/)
256{
257 // XXX: this is currently just for the performance measuring purpose.
258 // need to be reimplemented by fence and sync.
259 glFinish();
260}
261
262int GLComputeEvaluator::GetDispatchSize(int count) const
263{
264 return (count + _workGroupSize - 1) / _workGroupSize;
265}
266
267void GLComputeEvaluator::DispatchCompute(int totalDispatchSize) const
268{
269 int maxWorkGroupCount[2] = {0, 0};
270
271 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &maxWorkGroupCount[0]);
272 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &maxWorkGroupCount[1]);
273
274 const GLuint maxResX = static_cast<GLuint>(maxWorkGroupCount[0]);
275
276 const int dispatchSize = GetDispatchSize(totalDispatchSize);
277 GLuint dispatchRX = static_cast<GLuint>(dispatchSize);
278 GLuint dispatchRY = 1u;
279 if (dispatchRX > maxResX) {
280 /* Since there are some limitations with regards to the maximum work group size (could be as
281 * low as 64k elements per call), we split the number elements into a "2d" number, with the
282 * final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum
283 * work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements
284 * total, which should be enough. If not, we could also use the 3rd dimension. */
285 /* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and
286 * get the smallest rect fitting the requirements. */
287 dispatchRX = dispatchRY = std::ceil(std::sqrt(dispatchSize));
288 /* Avoid a completely empty dispatch line caused by rounding. */
289 if ((dispatchRX * (dispatchRY - 1)) >= dispatchSize) {
290 dispatchRY -= 1;
291 }
292 }
293
294 /* X and Y dimensions may have different limits so the above computation may not be right, but
295 * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore,
296 * we presume it all fits. */
297 assert(dispatchRY < static_cast<GLuint>(maxWorkGroupCount[1]));
298
299 glDispatchCompute(dispatchRX, dispatchRY, 1);
300}
301
302bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
303 BufferDescriptor const &srcDesc,
304 GLuint dstBuffer,
305 BufferDescriptor const &dstDesc,
306 GLuint duBuffer,
307 BufferDescriptor const &duDesc,
308 GLuint dvBuffer,
309 BufferDescriptor const &dvDesc,
310 GLuint sizesBuffer,
311 GLuint offsetsBuffer,
312 GLuint indicesBuffer,
313 GLuint weightsBuffer,
314 GLuint duWeightsBuffer,
315 GLuint dvWeightsBuffer,
316 int start,
317 int end) const
318{
319
320 return EvalStencils(srcBuffer,
321 srcDesc,
322 dstBuffer,
323 dstDesc,
324 duBuffer,
325 duDesc,
326 dvBuffer,
327 dvDesc,
328 0,
329 BufferDescriptor(),
330 0,
331 BufferDescriptor(),
332 0,
333 BufferDescriptor(),
334 sizesBuffer,
335 offsetsBuffer,
336 indicesBuffer,
337 weightsBuffer,
338 duWeightsBuffer,
339 dvWeightsBuffer,
340 0,
341 0,
342 0,
343 start,
344 end);
345}
346
347bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
348 BufferDescriptor const &srcDesc,
349 GLuint dstBuffer,
350 BufferDescriptor const &dstDesc,
351 GLuint duBuffer,
352 BufferDescriptor const &duDesc,
353 GLuint dvBuffer,
354 BufferDescriptor const &dvDesc,
355 GLuint duuBuffer,
356 BufferDescriptor const &duuDesc,
357 GLuint duvBuffer,
358 BufferDescriptor const &duvDesc,
359 GLuint dvvBuffer,
360 BufferDescriptor const &dvvDesc,
361 GLuint sizesBuffer,
362 GLuint offsetsBuffer,
363 GLuint indicesBuffer,
364 GLuint weightsBuffer,
365 GLuint duWeightsBuffer,
366 GLuint dvWeightsBuffer,
367 GLuint duuWeightsBuffer,
368 GLuint duvWeightsBuffer,
369 GLuint dvvWeightsBuffer,
370 int start,
371 int end) const
372{
373
374 if (!_stencilKernel.program) {
375 return false;
376 }
377 int count = end - start;
378 if (count <= 0) {
379 return true;
380 }
381
382 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
383 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
384 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
385 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
386 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
387 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
388 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
389 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer);
390 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
391 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
392 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
393 if (duWeightsBuffer) {
394 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
395 }
396 if (dvWeightsBuffer) {
397 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);
398 }
399 if (duuWeightsBuffer) {
400 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer);
401 }
402 if (duvWeightsBuffer) {
403 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer);
404 }
405 if (dvvWeightsBuffer) {
406 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer);
407 }
408
409 GLint activeProgram;
410 glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
411 glUseProgram(_stencilKernel.program);
412
413 glUniform1i(_stencilKernel.uniformStart, start);
414 glUniform1i(_stencilKernel.uniformEnd, end);
415 glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
416 glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset);
417 if (_stencilKernel.uniformDuDesc > 0) {
418 glUniform3i(_stencilKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
419 }
420 if (_stencilKernel.uniformDvDesc > 0) {
421 glUniform3i(_stencilKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
422 }
423 if (_stencilKernel.uniformDuuDesc > 0) {
424 glUniform3i(_stencilKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
425 }
426 if (_stencilKernel.uniformDuvDesc > 0) {
427 glUniform3i(_stencilKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
428 }
429 if (_stencilKernel.uniformDvvDesc > 0) {
430 glUniform3i(_stencilKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
431 }
432
433 DispatchCompute(count);
434
435 glUseProgram(activeProgram);
436
437 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
438 for (int i = 0; i < 16; ++i) {
439 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
440 }
441
442 return true;
443}
444
445bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
446 BufferDescriptor const &srcDesc,
447 GLuint dstBuffer,
448 BufferDescriptor const &dstDesc,
449 GLuint duBuffer,
450 BufferDescriptor const &duDesc,
451 GLuint dvBuffer,
452 BufferDescriptor const &dvDesc,
453 int numPatchCoords,
454 GLuint patchCoordsBuffer,
455 const PatchArrayVector &patchArrays,
456 GLuint patchIndexBuffer,
457 GLuint patchParamsBuffer) const
458{
459
460 return EvalPatches(srcBuffer,
461 srcDesc,
462 dstBuffer,
463 dstDesc,
464 duBuffer,
465 duDesc,
466 dvBuffer,
467 dvDesc,
468 0,
469 BufferDescriptor(),
470 0,
471 BufferDescriptor(),
472 0,
473 BufferDescriptor(),
474 numPatchCoords,
475 patchCoordsBuffer,
476 patchArrays,
477 patchIndexBuffer,
478 patchParamsBuffer);
479}
480
481bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
482 BufferDescriptor const &srcDesc,
483 GLuint dstBuffer,
484 BufferDescriptor const &dstDesc,
485 GLuint duBuffer,
486 BufferDescriptor const &duDesc,
487 GLuint dvBuffer,
488 BufferDescriptor const &dvDesc,
489 GLuint duuBuffer,
490 BufferDescriptor const &duuDesc,
491 GLuint duvBuffer,
492 BufferDescriptor const &duvDesc,
493 GLuint dvvBuffer,
494 BufferDescriptor const &dvvDesc,
495 int numPatchCoords,
496 GLuint patchCoordsBuffer,
497 const PatchArrayVector &patchArrays,
498 GLuint patchIndexBuffer,
499 GLuint patchParamsBuffer) const
500{
501
502 if (!_patchKernel.program) {
503 return false;
504 }
505
506 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
507 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
508 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
509 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
510 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
511 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
512 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
513 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchCoordsBuffer);
514 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer);
515 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer);
516
517 GLint activeProgram;
518 glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
519 glUseProgram(_patchKernel.program);
520
521 glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
522 glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
523
524 int patchArraySize = sizeof(PatchArray);
525 glBindBuffer(GL_SHADER_STORAGE_BUFFER, _patchArraysSSBO);
526 glBufferData(
527 GL_SHADER_STORAGE_BUFFER, patchArrays.size() * patchArraySize, NULL, GL_STATIC_DRAW);
528 for (int i = 0; i < (int)patchArrays.size(); ++i) {
529 glBufferSubData(
530 GL_SHADER_STORAGE_BUFFER, i * patchArraySize, sizeof(PatchArray), &patchArrays[i]);
531 }
532 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _patchArraysSSBO);
533
534 if (_patchKernel.uniformDuDesc > 0) {
535 glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
536 }
537 if (_patchKernel.uniformDvDesc > 0) {
538 glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
539 }
540 if (_patchKernel.uniformDuuDesc > 0) {
541 glUniform3i(_patchKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
542 }
543 if (_patchKernel.uniformDuvDesc > 0) {
544 glUniform3i(_patchKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
545 }
546 if (_patchKernel.uniformDvvDesc > 0) {
547 glUniform3i(_patchKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
548 }
549
550 DispatchCompute(numPatchCoords);
551
552 glUseProgram(activeProgram);
553
554 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
555 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
556 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
557 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
558 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
559 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
560 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);
561
562 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, 0);
563 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, 0);
564 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, 0);
565
566 return true;
567}
568// ---------------------------------------------------------------------------
569
570GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0) {}
571GLComputeEvaluator::_StencilKernel::~_StencilKernel()
572{
573 if (program) {
574 glDeleteProgram(program);
575 }
576}
577
578bool GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
579 BufferDescriptor const &dstDesc,
580 BufferDescriptor const &duDesc,
581 BufferDescriptor const &dvDesc,
582 BufferDescriptor const &duuDesc,
583 BufferDescriptor const &duvDesc,
584 BufferDescriptor const &dvvDesc,
585 int workGroupSize)
586{
587 // create stencil kernel
588 if (program) {
589 glDeleteProgram(program);
590 }
591
592 const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n";
593
594 program = compileKernel(
595 srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
596 if (program == 0) {
597 return false;
598 }
599
600 // cache uniform locations (TODO: use uniform block)
601 uniformStart = glGetUniformLocation(program, "batchStart");
602 uniformEnd = glGetUniformLocation(program, "batchEnd");
603 uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
604 uniformDstOffset = glGetUniformLocation(program, "dstOffset");
605 uniformDuDesc = glGetUniformLocation(program, "duDesc");
606 uniformDvDesc = glGetUniformLocation(program, "dvDesc");
607 uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
608 uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
609 uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
610
611 return true;
612}
613
614// ---------------------------------------------------------------------------
615
616GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0) {}
617GLComputeEvaluator::_PatchKernel::~_PatchKernel()
618{
619 if (program) {
620 glDeleteProgram(program);
621 }
622}
623
624bool GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
625 BufferDescriptor const &dstDesc,
626 BufferDescriptor const &duDesc,
627 BufferDescriptor const &dvDesc,
628 BufferDescriptor const &duuDesc,
629 BufferDescriptor const &duvDesc,
630 BufferDescriptor const &dvvDesc,
631 int workGroupSize)
632{
633 // create stencil kernel
634 if (program) {
635 glDeleteProgram(program);
636 }
637
638 const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n";
639
640 program = compileKernel(
641 srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
642 if (program == 0) {
643 return false;
644 }
645
646 // cache uniform locations
647 uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
648 uniformDstOffset = glGetUniformLocation(program, "dstOffset");
649 uniformPatchArray = glGetUniformLocation(program, "patchArray");
650 uniformDuDesc = glGetUniformLocation(program, "duDesc");
651 uniformDvDesc = glGetUniformLocation(program, "dvDesc");
652 uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
653 uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
654 uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
655
656 return true;
657}
658
659} // namespace blender::opensubdiv
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())
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)
Generic limit eval function. This function has a same signature as other device kernels have so that ...
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)
Generic static stencil function. This function has a same signature as other device kernels have so t...
static void Synchronize(void *deviceContext)
Wait the dispatched kernel finishes.
~GLComputeEvaluator()
Destructor. note that the GL context must be made current.
GLStencilTableSSBO(OpenSubdiv::Far::StencilTable const *stencilTable)
#define NULL
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
char datatoc_glsl_compute_kernel_glsl[]
int count
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 createSSBO(std::vector< T > const &src)