mesa: retain gl_shader_programs after glDeleteProgram if they are in use
authorTimothy Arceri <t_arceri@yahoo.com.au>
Thu, 26 Jan 2017 08:29:20 +0000 (19:29 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 16 Feb 2017 04:01:41 +0000 (15:01 +1100)
Fixes regressions from c505d6d852220f4aaaee161465dd2c579647e672.

Switching from using gl_shader_program to gl_program for the pipline
objects CurrentProgram array meant we were freeing gl_shader_programs
immediately after glDeleteProgram was called, but the spec states
the program should only get deleted once it is no longer in use.

To work around this we add a new ReferencedPrograms array to track
gl_shader_programs in use.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/common/meta.c
src/mesa/main/mtypes.h
src/mesa/main/pipelineobj.c
src/mesa/main/shaderapi.c
src/mesa/main/shaderapi.h

index 5b99c6b..2db4668 100644 (file)
@@ -962,7 +962,7 @@ _mesa_meta_end(struct gl_context *ctx)
           * program object must be NULL.  _mesa_use_program is a no-op
           * in that case.
           */
-         _mesa_use_program(ctx, i, save->Program[i],  &ctx->Shader);
+         _mesa_use_program(ctx, i, NULL, save->Program[i],  &ctx->Shader);
 
          /* Do this *before* killing the reference. :)
           */
index 08bd929..efe0cbc 100644 (file)
@@ -2875,6 +2875,8 @@ struct gl_pipeline_object
     */
    struct gl_program *CurrentProgram[MESA_SHADER_STAGES];
 
+   struct gl_shader_program *ReferencedPrograms[MESA_SHADER_STAGES];
+
    struct gl_program *_CurrentFragmentProgram;
 
    /**
index ec5df89..c1dd8d7 100644 (file)
@@ -60,8 +60,10 @@ _mesa_delete_pipeline_object(struct gl_context *ctx,
 
    _mesa_reference_program(ctx, &obj->_CurrentFragmentProgram, NULL);
 
-   for (i = 0; i < MESA_SHADER_STAGES; i++)
+   for (i = 0; i < MESA_SHADER_STAGES; i++) {
       _mesa_reference_program(ctx, &obj->CurrentProgram[i], NULL);
+      _mesa_reference_shader_program(ctx, &obj->ReferencedPrograms[i], NULL);
+   }
 
    _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
    mtx_destroy(&obj->Mutex);
@@ -227,7 +229,7 @@ use_program_stage(struct gl_context *ctx, GLenum type,
    if (shProg && shProg->_LinkedShaders[stage])
       prog = shProg->_LinkedShaders[stage]->Program;
 
-   _mesa_use_program(ctx, stage, prog, pipe);
+   _mesa_use_program(ctx, stage, shProg, prog, pipe);
 }
 
 /**
index 3de0a7e..86ce0bc 100644 (file)
@@ -1128,7 +1128,7 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
          if (shProg->_LinkedShaders[stage])
             prog = shProg->_LinkedShaders[stage]->Program;
 
-         _mesa_use_program(ctx, stage, prog, ctx->_Shader);
+         _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader);
       }
    }
 
@@ -1243,7 +1243,8 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
 
 static void
 use_program(struct gl_context *ctx, gl_shader_stage stage,
-            struct gl_program *new_prog, struct gl_pipeline_object *shTarget)
+            struct gl_shader_program *shProg, struct gl_program *new_prog,
+            struct gl_pipeline_object *shTarget)
 {
    struct gl_program **target;
 
@@ -1279,6 +1280,9 @@ use_program(struct gl_context *ctx, gl_shader_stage stage,
         break;
       }
 
+      _mesa_reference_shader_program(ctx,
+                                     &shTarget->ReferencedPrograms[stage],
+                                     shProg);
       _mesa_reference_program(ctx, target, new_prog);
       return;
    }
@@ -1296,7 +1300,7 @@ _mesa_use_shader_program(struct gl_context *ctx,
       struct gl_program *new_prog = NULL;
       if (shProg && shProg->_LinkedShaders[i])
          new_prog = shProg->_LinkedShaders[i]->Program;
-      use_program(ctx, i, new_prog, &ctx->Shader);
+      use_program(ctx, i, shProg, new_prog, &ctx->Shader);
    }
    _mesa_active_program(ctx, shProg, "glUseProgram");
 }
@@ -2180,10 +2184,10 @@ invalid_value:
 
 void
 _mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
-                  struct gl_program *prog,
+                  struct gl_shader_program *shProg, struct gl_program *prog,
                   struct gl_pipeline_object *shTarget)
 {
-   use_program(ctx, stage, prog, shTarget);
+   use_program(ctx, stage, shProg, prog, shTarget);
 }
 
 
index a89dbfb..99b4fe8 100644 (file)
@@ -215,7 +215,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value);
 
 void
 _mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
-                  struct gl_program *prog,
+                  struct gl_shader_program *shProg, struct gl_program *prog,
                   struct gl_pipeline_object *shTarget);
 
 extern void