[Mesa-dev] [PATCH 64/88] i965: don't recreate program struct on cache fallback

Timothy Arceri timothy.arceri at collabora.com
Sat Sep 24 05:25:45 UTC 2016


We already have the struct and paramlist we don't want to recreate
them as this is unnecessary and would mean we would need to remap
anything using the old paramlist to the addresses of the new one.
---
 src/compiler/glsl/linker.cpp                 |  5 ++++
 src/mesa/drivers/dri/i965/brw_link.cpp       | 44 ++++++++++++++++------------
 src/mesa/drivers/dri/i965/brw_shader_cache.c | 28 +++++++++++-------
 src/mesa/main/mtypes.h                       |  5 ++++
 src/mesa/main/shaderobj.c                    |  3 +-
 5 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index df864d9..9b4c2e9 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -72,6 +72,7 @@
 #include "ir.h"
 #include "program.h"
 #include "program/prog_instruction.h"
+#include "program/program.h"
 #include "util/set.h"
 #include "util/string_to_uint_map.h"
 #include "linker.h"
@@ -4761,6 +4762,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog,
 
    for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
       if (prog->_LinkedShaders[i] != NULL) {
+         if (is_cache_fallback) {
+            prog->cache_progs[i] = prog->_LinkedShaders[i]->Program;
+         }
+
 	 _mesa_delete_linked_shader(ctx, prog->_LinkedShaders[i]);
       }
 
diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp
index 1c7830f..6a8b352 100644
--- a/src/mesa/drivers/dri/i965/brw_link.cpp
+++ b/src/mesa/drivers/dri/i965/brw_link.cpp
@@ -223,24 +223,31 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
       if (!shader)
          continue;
 
-      struct gl_program *prog =
-         ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(stage),
-                                0);
+      struct gl_program *prog;
+      if (!is_cache_fallback) {
+         prog =
+            ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(stage),
+                                   0);
+      } else {
+         prog = shProg->cache_progs[stage];
+      }
+
       if (!prog)
         return false;
 
-      _mesa_copy_linked_program_data((gl_shader_stage) stage, shProg, prog);
-
       process_glsl_ir((gl_shader_stage) stage, brw, shProg, shader);
 
-      /* Make a pass over the IR to add state references for any built-in
-       * uniforms that are used.  This has to be done now (during linking).
-       * Code generation doesn't happen until the first time this shader is
-       * used for rendering.  Waiting until then to generate the parameters is
-       * too late.  At that point, the values for the built-in uniforms won't
-       * get sent to the shader.
-       */
       if (!is_cache_fallback) {
+         _mesa_copy_linked_program_data((gl_shader_stage) stage, shProg,
+                                        prog);
+
+         /* Make a pass over the IR to add state references for any built-in
+          * uniforms that are used.  This has to be done now (during linking).
+          * Code generation doesn't happen until the first time this shader is
+          * used for rendering.  Waiting until then to generate the parameters
+          * is too late.  At that point, the values for the built-in uniforms
+          * won't get sent to the shader.
+          */
          prog->Parameters = _mesa_new_parameter_list();
          foreach_in_list(ir_instruction, node, shader->ir) {
             ir_variable *var = node->as_variable();
@@ -257,18 +264,17 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
                                          (gl_state_index *) slots[i].tokens);
             }
          }
-      }
 
-      do_set_program_inouts(shader->ir, prog, shader->Stage);
+         do_set_program_inouts(shader->ir, prog, shader->Stage);
 
-      prog->SamplersUsed = shader->active_samplers;
-      prog->ShadowSamplers = shader->shadow_samplers;
-      _mesa_update_shader_textures_used(shProg, prog);
+         prog->SamplersUsed = shader->active_samplers;
+         prog->ShadowSamplers = shader->shadow_samplers;
+         _mesa_update_shader_textures_used(shProg, prog);
+         brw_add_texrect_params(prog);
+      }
 
       _mesa_reference_program(ctx, &shader->Program, prog);
 
-      brw_add_texrect_params(prog);
-
       prog->nir = brw_create_nir(brw, shProg, prog, (gl_shader_stage) stage,
                                  compiler->scalar_stage[stage]);
 
diff --git a/src/mesa/drivers/dri/i965/brw_shader_cache.c b/src/mesa/drivers/dri/i965/brw_shader_cache.c
index 3e00010..b21eaad 100644
--- a/src/mesa/drivers/dri/i965/brw_shader_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_shader_cache.c
@@ -104,34 +104,42 @@ fallback_to_full_recompile(struct brw_context *brw,
       struct gl_shader_program *shProg =
          brw->ctx._Shader->CurrentProgram[MESA_SHADER_VERTEX];
 
+      struct gl_program *vp =
+         shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
+      struct gl_program *fp = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] ?
+         shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program : NULL;
+
+      vp->cache_fallback = true;
+      if (fp)
+         fp->cache_fallback = true;
+
       for (unsigned i = 0; i < shProg->NumShaders; i++) {
          _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false,
                                    false, true);
       }
       _mesa_glsl_link_shader(&brw->ctx, shProg, true);
 
-      struct gl_program *vp =
-         shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
-      brw->vertex_program = gl_vertex_program(vp);
-
-      struct gl_program *fp =
-         shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
-      brw->fragment_program = gl_fragment_program(fp);
+      vp->cache_fallback = false;
+      if (fp)
+         fp->cache_fallback = false;
    }
 
    if (brw->fragment_program->Base.nir == NULL) {
       struct gl_shader_program *shProg =
          brw->ctx._Shader->_CurrentFragmentProgram;
 
+      struct gl_program *fp =
+         shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
+
+      fp->cache_fallback = true;
+
       for (unsigned i = 0; i < shProg->NumShaders; i++) {
          _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false,
                                    false, true);
       }
       _mesa_glsl_link_shader(&brw->ctx, shProg, true);
 
-      struct gl_program *fp =
-         shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
-      brw->fragment_program = gl_fragment_program(fp);
+      fp->cache_fallback = false;
    }
 }
 
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index b90f028..a1c074b 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1982,6 +1982,9 @@ struct gl_program
    GLuint NumNativeTexInstructions;
    GLuint NumNativeTexIndirections;
    /*@}*/
+
+   bool cache_fallback;   /**< used to prevent a gl_program that may be in use
+                               from being freed during a cache fallback */
 };
 
 
@@ -2889,6 +2892,8 @@ struct gl_shader_program
     * #extension ARB_fragment_coord_conventions: enable
     */
    GLboolean ARB_fragment_coord_conventions_enable;
+
+   struct gl_program *cache_progs[MESA_SHADER_STAGES];
 };   
 
 
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 109e79f..98f7b9e 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -149,7 +149,8 @@ void
 _mesa_delete_linked_shader(struct gl_context *ctx,
                            struct gl_linked_shader *sh)
 {
-   _mesa_reference_program(ctx, &sh->Program, NULL);
+   if (sh->Program && !sh->Program->cache_fallback)
+      _mesa_reference_program(ctx, &sh->Program, NULL);
    ralloc_free(sh);
 }
 
-- 
2.7.4



More information about the mesa-dev mailing list