From e6506b3cd2382a9a7e0a3494a964d2bafb3bebc3 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 26 Jan 2017 19:29:20 +1100 Subject: [PATCH] mesa: retain gl_shader_programs after glDeleteProgram if they are in use 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 --- src/mesa/drivers/common/meta.c | 2 +- src/mesa/main/mtypes.h | 2 ++ src/mesa/main/pipelineobj.c | 6 ++++-- src/mesa/main/shaderapi.c | 14 +++++++++----- src/mesa/main/shaderapi.h | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index 5b99c6baa52..2db4668ef7d 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -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. :) */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 08bd929255c..efe0cbcad75 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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; /** diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c index ec5df896c09..c1dd8d75c76 100644 --- a/src/mesa/main/pipelineobj.c +++ b/src/mesa/main/pipelineobj.c @@ -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); } /** diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 3de0a7eeabf..86ce0bc5fdf 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -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); } diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index a89dbfb564c..99b4fe84d82 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -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 -- 2.30.2