[Mesa-dev] [PATCH] mesa/glsl: delete previously linked shaders earlier when linking

Tapani Pälli tapani.palli at intel.com
Wed Nov 2 05:48:17 UTC 2016


Nice work!

Reviewed-by: Tapani Pälli <tapani.palli at intel.com>

On 11/02/2016 03:18 AM, Timothy Arceri wrote:
> This moves the delete linked shaders call to
> _mesa_clear_shader_program_data() which makes sure we delete them
> before returning due to any validation problems.
>
> It also reduces some code duplication.
>
> From the OpenGL 4.5 Core spec:
>
>    "If LinkProgram failed, any information about a previous link of
>    that program object is lost. Thus, a failed link does not restore
>    the old state of program.
>
>    ...
>
>    If one of these commands is called with a program for which
>    LinkProgram failed, no error is generated unless otherwise noted.
>    Implementations may return information on variables and interface
>    blocks that would have been active had the program been linked
>    successfully. In cases where the link failed because the program
>    required too many resources, these commands may help applications
>    determine why limits were exceeded."
>
> Therefore it's expected that we shouldn't be able to query the
> program that failed to link and retrieve inforemation about a
> previously successful link.
>
> Before this change the linker was doing validation before freeing
> the previously linked shaders and therefore could exit on failure
> before they were freed.
>
> This change also fixes an issue in compat profile where a program
> with no shaders attached is expect to fall back to fixed function
> but was instead trying to relink IR from a previous link.
>
> Cc: Matt Turner <mattst88 at gmail.com>
> Cc: Tapani Pälli <tapani.palli at intel.com>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97715
> Cc: "12.0 13.0" <mesa-stable at lists.freedesktop.org>
> ---
>  src/compiler/glsl/linker.cpp    |  8 --------
>  src/mesa/main/shaderobj.c       | 23 ++++++++++-------------
>  src/mesa/main/shaderobj.h       |  3 ++-
>  src/mesa/program/ir_to_mesa.cpp |  2 +-
>  4 files changed, 13 insertions(+), 23 deletions(-)
>
> diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
> index 215fcc4..686f233 100644
> --- a/src/compiler/glsl/linker.cpp
> +++ b/src/compiler/glsl/linker.cpp
> @@ -4795,14 +4795,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>                     "type of shader\n");
>     }
>
> -   for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
> -      if (prog->_LinkedShaders[i] != NULL) {
> -         _mesa_delete_linked_shader(ctx, prog->_LinkedShaders[i]);
> -      }
> -
> -      prog->_LinkedShaders[i] = NULL;
> -   }
> -
>     /* Link all shaders for a particular stage and validate the result.
>      */
>     for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) {
> diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
> index 136ac7b..8fd574e 100644
> --- a/src/mesa/main/shaderobj.c
> +++ b/src/mesa/main/shaderobj.c
> @@ -291,12 +291,18 @@ _mesa_new_shader_program(GLuint name)
>   * Clear (free) the shader program state that gets produced by linking.
>   */
>  void
> -_mesa_clear_shader_program_data(struct gl_shader_program *shProg)
> +_mesa_clear_shader_program_data(struct gl_context *ctx,
> +                                struct gl_shader_program *shProg)
>  {
> -   unsigned i;
> +   for (gl_shader_stage sh = 0; sh < MESA_SHADER_STAGES; sh++) {
> +      if (shProg->_LinkedShaders[sh] != NULL) {
> +         _mesa_delete_linked_shader(ctx, shProg->_LinkedShaders[sh]);
> +         shProg->_LinkedShaders[sh] = NULL;
> +      }
> +   }
>
>     if (shProg->UniformStorage) {
> -      for (i = 0; i < shProg->NumUniformStorage; ++i)
> +      for (unsigned i = 0; i < shProg->NumUniformStorage; ++i)
>           _mesa_uniform_detach_all_driver_storage(&shProg->UniformStorage[i]);
>        ralloc_free(shProg->UniformStorage);
>        shProg->NumUniformStorage = 0;
> @@ -347,11 +353,10 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
>                                 struct gl_shader_program *shProg)
>  {
>     GLuint i;
> -   gl_shader_stage sh;
>
>     assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
>
> -   _mesa_clear_shader_program_data(shProg);
> +   _mesa_clear_shader_program_data(ctx, shProg);
>
>     if (shProg->AttributeBindings) {
>        string_to_uint_map_dtor(shProg->AttributeBindings);
> @@ -385,14 +390,6 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
>     shProg->TransformFeedback.VaryingNames = NULL;
>     shProg->TransformFeedback.NumVarying = 0;
>
> -
> -   for (sh = 0; sh < MESA_SHADER_STAGES; sh++) {
> -      if (shProg->_LinkedShaders[sh] != NULL) {
> -	 _mesa_delete_linked_shader(ctx, shProg->_LinkedShaders[sh]);
> -	 shProg->_LinkedShaders[sh] = NULL;
> -      }
> -   }
> -
>     free(shProg->Label);
>     shProg->Label = NULL;
>  }
> diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h
> index 814a7f1..1249732 100644
> --- a/src/mesa/main/shaderobj.h
> +++ b/src/mesa/main/shaderobj.h
> @@ -99,7 +99,8 @@ extern struct gl_shader_program *
>  _mesa_new_shader_program(GLuint name);
>
>  extern void
> -_mesa_clear_shader_program_data(struct gl_shader_program *shProg);
> +_mesa_clear_shader_program_data(struct gl_context *ctx,
> +                                struct gl_shader_program *shProg);
>
>  extern void
>  _mesa_free_shader_program_data(struct gl_context *ctx,
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index 5776d15..f4c2ad6 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -3049,7 +3049,7 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
>  {
>     unsigned int i;
>
> -   _mesa_clear_shader_program_data(prog);
> +   _mesa_clear_shader_program_data(ctx, prog);
>
>     prog->LinkStatus = GL_TRUE;
>
>


More information about the mesa-dev mailing list