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 /intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl
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
Diffstat (limited to 'intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl')
-rw-r--r--intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl316
1 files changed, 316 insertions, 0 deletions
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