[Mesa-dev] [PATCH 2/2] i965: Refactor brw_upload_programs with a loop over each stage
Carl Worth
cworth at cworth.org
Fri May 15 17:09:58 PDT 2015
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
More information about the mesa-dev
mailing list