Fix T97086: corrupted UVs with GPU subdivision

When multiple objects are in edit mode, UVs for the objects, except for
the first one (in rendering order) appear corrupted. The corruption is
because the UVs are not evaluated as the compute shader is not bound,
thus we read unitialized memory.

We keep track of the currently bound shader in the GPU context in order
to avoid unnecessary shader switches in case the same shader is used in
consecutive calls. However, the shader used by the OpenSubdiv evaluator
is not part of Blender and therefore not tracked via the GPU context.

When extracting UVs for multiple objects, we only ever run a single
shader (FVar evaluation). However, between the compute calls, we also
call the OpenSubdiv stencil evaluation shader, which uses `glUseProgram`
modifying the current program, outside of our control, which then also
unbinds the Blender compute shader making the compute dispatch fail ("No
active compute shader").

The fact that extracting the UVs for the first rendered object works is
because another (Blender) shader was bound in the GPU context prior to
our binding of our evaluation shader.

To fix this, we remember, in the OpenSubdiv evaluator, the current
program so that it can be reset after the stencil program is done.

Differential Revision: https://developer.blender.org/D15064
This commit is contained in:
Kévin Dietrich 2022-05-30 16:40:50 +02:00
parent 18a17d4291
commit 344a8fb3d4
Notes: blender-bot 2023-02-14 08:06:33 +01:00
Referenced by issue #97086, GPU subdivision: UVs display wrong with multiple objects in edit mode
1 changed files with 6 additions and 2 deletions

View File

@ -396,6 +396,8 @@ bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
if (dvvWeightsBuffer)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer);
GLint activeProgram;
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
glUseProgram(_stencilKernel.program);
glUniform1i(_stencilKernel.uniformStart, start);
@ -420,7 +422,7 @@ bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
DispatchCompute(count);
glUseProgram(0);
glUseProgram(activeProgram);
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
for (int i = 0; i < 16; ++i) {
@ -501,6 +503,8 @@ bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer);
GLint activeProgram;
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
glUseProgram(_patchKernel.program);
glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
@ -534,7 +538,7 @@ bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
DispatchCompute(numPatchCoords);
glUseProgram(0);
glUseProgram(activeProgram);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);