This refactor idetnfies as much common code as possible across the various
stages within brw_upload_programs. The resulting code is a loop over all
relevant stages and various accessory functions (per_stage_state_dirty,
per_stage_populate_key, per_stage_codegen, and per_stage_vue_map_update),
whenever the code needs to vary from one stage to another.

This code is intended to have no functional change, and has been verified with
piglit across several Intel platforms.

From here, any remaining conditionals within brw_upload_programs indicate code
that could benefit from some simplification, (such as combinining the FF_GS
and GS stages or otherwise reducing some special cases).

This refactoring is intended to progress toward a point where on-disk
shader-cache lookups can be inserted after brw_search_cache has been called
for each stage, but before the per_stage_codegen function has been called for
any stage. But before we can do that, the vue_map_update code will need to be
reworked in some form or another. (The current code hangs all of the vue_map
state off of prog_data such that it cannot be performed until after codegen,
but the vue_map update code also modifies state that will be examined by the
state_dirty calls of subsequent stages. So this will need to be disentangled
before we can make further progress to prepare for the shader-cache here.)
---
 src/mesa/drivers/dri/i965/brw_state_upload.c | 304 ++++++++++++++++++---------
 1 file changed, 207 insertions(+), 97 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c 
b/src/mesa/drivers/dri/i965/brw_state_upload.c
index 7fa434f..c75eef0 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -615,138 +615,248 @@ brw_print_dirty_count(struct dirty_bit_map *bit_map)
    }
 }
 
-static inline void
-brw_upload_programs(struct brw_context *brw,
-                    enum brw_pipeline pipeline)
+static bool
+per_stage_state_dirty(struct brw_context *brw,
+                     enum brw_cache_id stage)
+{
+   switch (stage) {
+   case BRW_CACHE_VS_PROG:
+      return brw_vs_state_dirty(brw);
+   case BRW_CACHE_FF_GS_PROG:
+      return brw_ff_gs_state_dirty(brw);
+   case BRW_CACHE_GS_PROG:
+      return brw_gs_state_dirty(brw);
+   case BRW_CACHE_FS_PROG:
+      return brw_wm_state_dirty(brw);
+   default:
+      unreachable("not reached");
+   }
+}
+
+struct key_block
 {
-   struct gl_context *ctx = &brw->ctx;
-   struct gl_shader_program **current = ctx->_Shader->CurrentProgram;
-   struct gl_shader_program *current_fp = 
ctx->_Shader->_CurrentFragmentProgram;
    struct brw_vs_prog_key vs_key;
    struct brw_ff_gs_prog_key ff_gs_key;
    struct brw_gs_prog_key gs_key;
    struct brw_wm_prog_key wm_key;
-   struct brw_stage_state *stage_state = &brw->gs.base;
-   struct brw_vertex_program *vp =
-      (struct brw_vertex_program *) brw->vertex_program;
-   struct brw_geometry_program *gp =
-      (struct brw_geometry_program *) brw->geometry_program;
-   struct brw_fragment_program *fp =
-      (struct brw_fragment_program *) brw->fragment_program;
+};
 
-   if (pipeline == BRW_RENDER_PIPELINE) {
+static void
+per_stage_populate_key(struct brw_context *brw,
+                       enum brw_cache_id stage,
+                       struct key_block *key_block,
+                       void **key_ret,
+                       size_t *key_size_ret,
+                       uint32_t **prog_offset_ret,
+                       void **prog_data_ret)
+{
+   switch (stage) {
+   case BRW_CACHE_VS_PROG:
+      brw_vs_populate_key(brw, &key_block->vs_key);
+      *key_ret = &key_block->vs_key;
+      *key_size_ret = sizeof(key_block->vs_key);
+      *prog_offset_ret = &brw->vs.base.prog_offset;
+      *prog_data_ret = &brw->vs.prog_data;
+      break;
+   case BRW_CACHE_FF_GS_PROG:
+      brw_ff_gs_populate_key(brw, &key_block->ff_gs_key);
+      *key_ret = &key_block->ff_gs_key;
+      *key_size_ret = sizeof(key_block->ff_gs_key);
+      *prog_offset_ret = &brw->ff_gs.prog_offset;
+      *prog_data_ret = &brw->ff_gs.prog_data;
+      break;
+   case BRW_CACHE_GS_PROG:
+      brw_gs_populate_key(brw, &key_block->gs_key);
+      *key_ret = &key_block->gs_key;
+      *key_size_ret = sizeof(key_block->gs_key);
+      *prog_offset_ret = &brw->gs.base.prog_offset;
+      *prog_data_ret = &brw->gs.prog_data;
+      break;
+   case BRW_CACHE_FS_PROG:
+      brw_wm_populate_key(brw, &key_block->wm_key);
+      *key_ret = &key_block->wm_key;
+      *key_size_ret = sizeof(key_block->wm_key);
+      *prog_offset_ret = &brw->wm.base.prog_offset;
+      *prog_data_ret = &brw->wm.prog_data;
+      break;
+   default:
+      unreachable("not reached");
+      break;
+   }
+}
 
-      if (brw_vs_state_dirty(brw)) {
+static bool
+per_stage_codegen(struct brw_context *brw,
+                  enum brw_cache_id stage,
+                  struct key_block *key_block)
+{
+   struct gl_context *ctx = &brw->ctx;
 
-         brw_vs_populate_key(brw, &vs_key);
+   switch (stage) {
+   case BRW_CACHE_VS_PROG:
+   {
+      struct brw_vertex_program *vp =
+        (struct brw_vertex_program *) brw->vertex_program;
+      return brw_codegen_vs_prog(brw,
+                                 
ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX],
+                                 vp, &key_block->vs_key);
+   }
+   case BRW_CACHE_FF_GS_PROG:
+      brw_codegen_ff_gs_prog(brw, &key_block->ff_gs_key);
+      return true;
+   case BRW_CACHE_GS_PROG:
+   {
+      struct brw_geometry_program *gp =
+        (struct brw_geometry_program *) brw->geometry_program;
+      return brw_codegen_gs_prog(brw,
+                                 
ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY],
+                                 gp, &key_block->gs_key);
+   }
+   case BRW_CACHE_FS_PROG:
+   {
+      struct brw_fragment_program *fp =
+        (struct brw_fragment_program *) brw->fragment_program;
+      return brw_codegen_wm_prog(brw, ctx->_Shader->_CurrentFragmentProgram,
+                                 fp, &key_block->wm_key);
+   }
+   default:
+      unreachable("not reached");
+      break;
+   }
+}
 
-         if (!brw_search_cache(&brw->cache, BRW_CACHE_VS_PROG,
-                               &vs_key, sizeof(vs_key),
-                               &brw->vs.base.prog_offset, &brw->vs.prog_data)) 
{
-            bool success = brw_codegen_vs_prog(brw, 
current[MESA_SHADER_VERTEX],
-                                               vp, &vs_key);
-            (void) success;
-            assert(success);
-         }
-         brw->vs.base.prog_data = &brw->vs.prog_data->base.base;
-
-         if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out,
-                    sizeof(brw->vue_map_geom_out)) != 0) {
-            brw->vue_map_vs = brw->vs.prog_data->base.vue_map;
-            brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_VS;
-            if (brw->gen < 6) {
-               /* No geometry shader support, so the VS VUE map is the VUE map
-                * for the output of the "geometry" portion of the pipeline.
-                */
-               brw->vue_map_geom_out = brw->vue_map_vs;
-               brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
-            }
+static void
+per_stage_vue_map_update(struct brw_context *brw, enum brw_cache_id stage)
+{
+   switch (stage) {
+   case BRW_CACHE_VS_PROG:
+      brw->vs.base.prog_data = &brw->vs.prog_data->base.base;
+
+      if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out,
+                 sizeof(brw->vue_map_geom_out)) != 0) {
+         brw->vue_map_vs = brw->vs.prog_data->base.vue_map;
+         brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_VS;
+         if (brw->gen < 6) {
+            /* No geometry shader support, so the VS VUE map is the VUE map
+             * for the output of the "geometry" portion of the pipeline.
+             */
+            brw->vue_map_geom_out = brw->vue_map_vs;
+            brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
          }
       }
+      break;
+   case BRW_CACHE_GS_PROG:
+      brw->gs.base.prog_data = &brw->gs.prog_data->base.base;
+
+      if (memcmp(&brw->gs.prog_data->base.vue_map, &brw->vue_map_geom_out,
+                 sizeof(brw->vue_map_geom_out)) != 0) {
+         brw->vue_map_geom_out = brw->gs.prog_data->base.vue_map;
+         brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
+      }
+      break;
+   case BRW_CACHE_FS_PROG:
+      brw->wm.base.prog_data = &brw->wm.prog_data->base;
+      break;
+   default:
+      break;
+   }
+}
 
-      if (brw->gen < 6) {
+static inline void
+brw_upload_programs(struct brw_context *brw,
+                    enum brw_pipeline pipeline)
+{
+#define NUM_STAGES 4
+   bool need_new[NUM_STAGES];
+   enum brw_cache_id stage;
+   enum brw_cache_id stages[NUM_STAGES] = {BRW_CACHE_VS_PROG,
+                                           BRW_CACHE_FF_GS_PROG,
+                                           BRW_CACHE_GS_PROG,
+                                           BRW_CACHE_FS_PROG};
+   struct key_block key_block;
+   void *key;
+   uint32_t *prog_offset;
+   void *prog_data;
+   size_t key_size;
+   struct brw_geometry_program *gp =
+      (struct brw_geometry_program *) brw->geometry_program;
+   bool need_ff_gs = false;
+   int i;
 
-      UPLOAD_FF_GS_PROG:
+   if (pipeline == BRW_COMPUTE_PIPELINE) {
+      brw_upload_cs_prog(brw);
+      return;
+   }
 
-         if (brw_ff_gs_state_dirty(brw)) {
+   if (pipeline != BRW_RENDER_PIPELINE) {
+      return;
+   }
 
-            /* Populate the key:
-             */
-            brw_ff_gs_populate_key(brw, &ff_gs_key);
+   if (brw->gen < 6 ||
+       (gp == NULL && brw->gen == 6 &&
+        (brw->ctx.NewDriverState & BRW_NEW_TRANSFORM_FEEDBACK)))
+   {
+      need_ff_gs = true;
+   }
 
-            if (brw->ff_gs.prog_active != ff_gs_key.need_gs_prog) {
-               brw->ctx.NewDriverState |= BRW_NEW_FF_GS_PROG_DATA;
-               brw->ff_gs.prog_active = ff_gs_key.need_gs_prog;
-            }
+   for (i = 0; i < NUM_STAGES; i++) {
 
-            if (brw->ff_gs.prog_active) {
-               if (!brw_search_cache(&brw->cache, BRW_CACHE_FF_GS_PROG,
-                                     &ff_gs_key, sizeof(ff_gs_key),
-                                     &brw->ff_gs.prog_offset, 
&brw->ff_gs.prog_data)) {
-                  brw_codegen_ff_gs_prog(brw, &ff_gs_key);
-               }
-            }
-         }
-      } else {
+      stage = stages[i];
+      need_new[i] = per_stage_state_dirty(brw, stage);
 
-         if (brw_gs_state_dirty(brw)) {
+      if (stage == BRW_CACHE_FF_GS_PROG && !need_ff_gs)
+         continue;
 
-            if (gp == NULL) {
-               /* No geometry shader.  Vertex data just passes straight 
through. */
-               if (brw->ctx.NewDriverState & BRW_NEW_VUE_MAP_VS) {
-                  brw->vue_map_geom_out = brw->vue_map_vs;
-                  brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
-               }
+      if (stage == BRW_CACHE_GS_PROG && need_ff_gs)
+         continue;
 
-               if (brw->gen == 6 &&
-                   (brw->ctx.NewDriverState & BRW_NEW_TRANSFORM_FEEDBACK)) {
-                  goto UPLOAD_FF_GS_PROG;
-               }
+      if (need_new[i]) {
 
+         if ((stage == BRW_CACHE_FF_GS_PROG ||
+              stage == BRW_CACHE_GS_PROG) && gp == NULL)
+         {
+            /* No geometry shader.  Vertex data just passes straight
+             * through. */
+            if (brw->ctx.NewDriverState & BRW_NEW_VUE_MAP_VS) {
+               brw->vue_map_geom_out = brw->vue_map_vs;
+               brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
+            }
+
+            if (stage == BRW_CACHE_GS_PROG) {
                /* Other state atoms had better not try to access prog_data,
                 * since there's no GS program.
                 */
                brw->gs.prog_data = NULL;
                brw->gs.base.prog_data = NULL;
-            } else {
-
-               brw_gs_populate_key(brw, &gs_key);
-
-               if (!brw_search_cache(&brw->cache, BRW_CACHE_GS_PROG,
-                                     &gs_key, sizeof(gs_key),
-                                     &stage_state->prog_offset, 
&brw->gs.prog_data)) {
-                  bool success = brw_codegen_gs_prog(brw, 
current[MESA_SHADER_GEOMETRY],
-                                                     gp, &gs_key);
-                  assert(success);
-                  (void)success;
-               }
-               brw->gs.base.prog_data = &brw->gs.prog_data->base.base;
-
-               if (memcmp(&brw->gs.prog_data->base.vue_map, 
&brw->vue_map_geom_out,
-                          sizeof(brw->vue_map_geom_out)) != 0) {
-                  brw->vue_map_geom_out = brw->gs.prog_data->base.vue_map;
-                  brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT;
-               }
+
+               continue;
             }
          }
-      }
 
-      if (brw_wm_state_dirty(brw)) {
+         per_stage_populate_key (brw, stage, &key_block, &key, &key_size,
+                                 &prog_offset, &prog_data);
 
-         brw_wm_populate_key(brw, &wm_key);
+         if (stage == BRW_CACHE_FF_GS_PROG) {
 
-         if (!brw_search_cache(&brw->cache, BRW_CACHE_FS_PROG,
-                               &wm_key, sizeof(wm_key),
-                               &brw->wm.base.prog_offset, &brw->wm.prog_data)) 
{
-            bool success = brw_codegen_wm_prog(brw, current_fp, fp, &wm_key);
+            if (brw->ff_gs.prog_active != key_block.ff_gs_key.need_gs_prog) {
+               brw->ctx.NewDriverState |= BRW_NEW_FF_GS_PROG_DATA;
+               brw->ff_gs.prog_active = key_block.ff_gs_key.need_gs_prog;
+            }
+
+            if (!brw->ff_gs.prog_active)
+               continue;
+         }
+
+         if (!brw_search_cache(&brw->cache, stage, key, key_size,
+                               prog_offset, prog_data)) {
+            
+            bool success = per_stage_codegen(brw, stage, &key_block);
             (void) success;
             assert(success);
          }
-         brw->wm.base.prog_data = &brw->wm.prog_data->base;
-      }
 
-   } else if (pipeline == BRW_COMPUTE_PIPELINE) {
-      brw_upload_cs_prog(brw);
+         per_stage_vue_map_update(brw, stage);
+      }
    }
 }
 
-- 
2.1.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to