From f2957564c57c7519452af06894d5f4930b0cc771 Mon Sep 17 00:00:00 2001 From: Vadim Girlin Date: Sat, 26 May 2012 02:15:00 +0400 Subject: [PATCH] r600g: use cache for shader variants Signed-off-by: Vadim Girlin --- src/gallium/drivers/r600/evergreen_state.c | 4 +- src/gallium/drivers/r600/r600_pipe.h | 27 ++++- src/gallium/drivers/r600/r600_shader.c | 17 +-- src/gallium/drivers/r600/r600_state.c | 12 +- src/gallium/drivers/r600/r600_state_common.c | 168 +++++++++++++++++--------- 5 files changed, 153 insertions(+), 75 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index ec0afe5..f135c2e 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -1842,12 +1842,12 @@ void evergreen_init_state_functions(struct r600_context *rctx) rctx->context.create_blend_state = evergreen_create_blend_state; rctx->context.create_depth_stencil_alpha_state = evergreen_create_dsa_state; - rctx->context.create_fs_state = r600_create_shader_state; + rctx->context.create_fs_state = r600_create_shader_state_ps; rctx->context.create_rasterizer_state = evergreen_create_rs_state; rctx->context.create_sampler_state = evergreen_create_sampler_state; rctx->context.create_sampler_view = evergreen_create_sampler_view; rctx->context.create_vertex_elements_state = r600_create_vertex_elements; - rctx->context.create_vs_state = r600_create_shader_state; + rctx->context.create_vs_state = r600_create_shader_state_vs; rctx->context.bind_blend_state = r600_bind_blend_state; rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state; rctx->context.bind_fragment_sampler_states = evergreen_bind_ps_sampler; diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index e5ba49c..3d9cd76 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -168,18 +168,30 @@ struct r600_vertex_element struct r600_pipe_state rstate; }; +struct r600_pipe_shader; + +struct r600_pipe_shader_selector { + struct r600_pipe_shader *current; + struct keymap *shaders; + struct tgsi_token *tokens; + struct pipe_stream_output_info so; + + /* PIPE_SHADER_xxx */ + unsigned type; +}; + struct r600_pipe_shader { + struct r600_pipe_shader_selector *selector; struct r600_shader shader; struct r600_pipe_state rstate; struct r600_resource *bo; struct r600_resource *bo_fetch; struct r600_vertex_element vertex_elements; - struct tgsi_token *tokens; unsigned sprite_coord_enable; unsigned flatshade; unsigned pa_cl_vs_out_cntl; unsigned ps_cb_shader_mask; - struct pipe_stream_output_info so; + unsigned key; }; struct r600_pipe_sampler_state { @@ -255,8 +267,8 @@ struct r600_context { struct pipe_stencil_ref stencil_ref; struct pipe_viewport_state viewport; struct pipe_clip_state clip; - struct r600_pipe_shader *ps_shader; - struct r600_pipe_shader *vs_shader; + struct r600_pipe_shader_selector *ps_shader; + struct r600_pipe_shader_selector *vs_shader; struct r600_pipe_rasterizer *rasterizer; struct r600_pipe_state vgt; struct r600_pipe_state spi; @@ -475,7 +487,12 @@ void r600_sampler_view_destroy(struct pipe_context *ctx, void r600_delete_state(struct pipe_context *ctx, void *state); void r600_bind_vertex_elements(struct pipe_context *ctx, void *state); void *r600_create_shader_state(struct pipe_context *ctx, - const struct pipe_shader_state *state); + const struct pipe_shader_state *state, + unsigned pipe_shader_type); +void *r600_create_shader_state_ps(struct pipe_context *ctx, + const struct pipe_shader_state *state); +void *r600_create_shader_state_vs(struct pipe_context *ctx, + const struct pipe_shader_state *state); void r600_bind_ps_shader(struct pipe_context *ctx, void *state); void r600_bind_vs_shader(struct pipe_context *ctx, void *state); void r600_delete_ps_shader(struct pipe_context *ctx, void *state); diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index dc208b9..d282e7c 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -109,6 +109,7 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s { static int dump_shaders = -1; struct r600_context *rctx = (struct r600_context *)ctx; + struct r600_pipe_shader_selector *sel = shader->selector; int r; /* Would like some magic "get_bool_option_once" routine. @@ -118,16 +119,16 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s if (dump_shaders) { fprintf(stderr, "--------------------------------------------------------------\n"); - tgsi_dump(shader->tokens, 0); + tgsi_dump(sel->tokens, 0); - if (shader->so.num_outputs) { + if (sel->so.num_outputs) { unsigned i; fprintf(stderr, "STREAMOUT\n"); - for (i = 0; i < shader->so.num_outputs; i++) { - unsigned mask = ((1 << shader->so.output[i].num_components) - 1) << - shader->so.output[i].start_component; + for (i = 0; i < sel->so.num_outputs; i++) { + unsigned mask = ((1 << sel->so.output[i].num_components) - 1) << + sel->so.output[i].start_component; fprintf(stderr, " %i: MEM_STREAM0_BUF%i OUT[%i].%s%s%s%s\n", i, - shader->so.output[i].output_buffer, shader->so.output[i].register_index, + sel->so.output[i].output_buffer, sel->so.output[i].register_index, mask & 1 ? "x" : "_", (mask >> 1) & 1 ? "y" : "_", (mask >> 2) & 1 ? "z" : "_", @@ -1082,8 +1083,8 @@ static int process_twoside_color_inputs(struct r600_shader_ctx *ctx) static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_shader *pipeshader) { struct r600_shader *shader = &pipeshader->shader; - struct tgsi_token *tokens = pipeshader->tokens; - struct pipe_stream_output_info so = pipeshader->so; + struct tgsi_token *tokens = pipeshader->selector->tokens; + struct pipe_stream_output_info so = pipeshader->selector->so; struct tgsi_full_immediate *immediate; struct tgsi_full_property *property; struct r600_shader_ctx ctx; diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 124eba2..465ab5e 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1806,12 +1806,12 @@ void r600_init_state_functions(struct r600_context *rctx) rctx->context.create_blend_state = r600_create_blend_state; rctx->context.create_depth_stencil_alpha_state = r600_create_dsa_state; - rctx->context.create_fs_state = r600_create_shader_state; + rctx->context.create_fs_state = r600_create_shader_state_ps; rctx->context.create_rasterizer_state = r600_create_rs_state; rctx->context.create_sampler_state = r600_create_sampler_state; rctx->context.create_sampler_view = r600_create_sampler_view; rctx->context.create_vertex_elements_state = r600_create_vertex_elements; - rctx->context.create_vs_state = r600_create_shader_state; + rctx->context.create_vs_state = r600_create_shader_state_vs; rctx->context.bind_blend_state = r600_bind_blend_state; rctx->context.bind_depth_stencil_alpha_state = r600_bind_dsa_state; rctx->context.bind_fragment_sampler_states = r600_bind_ps_samplers; @@ -1861,16 +1861,16 @@ void r600_adjust_gprs(struct r600_context *rctx) if (!rctx->ps_shader || !rctx->vs_shader) return; - if (rctx->ps_shader->shader.bc.ngpr > rctx->default_ps_gprs) + if (rctx->ps_shader->current->shader.bc.ngpr > rctx->default_ps_gprs) { - diff = rctx->ps_shader->shader.bc.ngpr - rctx->default_ps_gprs; + diff = rctx->ps_shader->current->shader.bc.ngpr - rctx->default_ps_gprs; num_vs_gprs -= diff; num_ps_gprs += diff; } - if (rctx->vs_shader->shader.bc.ngpr > rctx->default_vs_gprs) + if (rctx->vs_shader->current->shader.bc.ngpr > rctx->default_vs_gprs) { - diff = rctx->vs_shader->shader.bc.ngpr - rctx->default_vs_gprs; + diff = rctx->vs_shader->current->shader.bc.ngpr - rctx->default_vs_gprs; num_ps_gprs -= diff; num_vs_gprs += diff; } diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 00e1bd0..30c3702 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -29,6 +29,7 @@ #include "util/u_blitter.h" #include "util/u_upload_mgr.h" +#include "util/u_keymap.h" #include "tgsi/tgsi_parse.h" #include @@ -429,22 +430,89 @@ void *r600_create_vertex_elements(struct pipe_context *ctx, return v; } +static unsigned r600_shader_selector_key(struct pipe_context * ctx, unsigned type) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + + if (type == PIPE_SHADER_FRAGMENT) + return (rctx->nr_cbufs << 1) + rctx->two_side; + + return 0; +} + +static int r600_shader_select(struct pipe_context *ctx, struct r600_pipe_shader_selector* sel) +{ + unsigned key = r600_shader_selector_key(ctx, sel->type); + struct r600_pipe_shader * shader; + int state_dirty = 0; + + if (sel->current && sel->current->key == key) + return 0; + + shader = (struct r600_pipe_shader *)util_keymap_lookup(sel->shaders, &key); + + if (!shader) { + shader = CALLOC(1, sizeof(struct r600_pipe_shader)); + shader->selector = sel; + + r600_pipe_shader_create(ctx, shader); + + shader->key = key; + + util_keymap_insert(sel->shaders, &key, shader, NULL); + + state_dirty = 1; + } + + sel->current = shader; + return state_dirty; +} + +static void r600_pipe_shader_keymap_delete_func( + const struct keymap *map, + const void *key, void *data, + void *user) +{ + struct pipe_context *ctx = (struct pipe_context*)user; + struct r600_pipe_shader *shader = (struct r600_pipe_shader*)data; + + r600_pipe_shader_destroy(ctx, shader); + free(shader); +} + void *r600_create_shader_state(struct pipe_context *ctx, - const struct pipe_shader_state *state) + const struct pipe_shader_state *state, + unsigned pipe_shader_type) { - struct r600_pipe_shader *shader = CALLOC_STRUCT(r600_pipe_shader); + struct r600_pipe_shader_selector *sel = CALLOC_STRUCT(r600_pipe_shader_selector); int r; - shader->tokens = tgsi_dup_tokens(state->tokens); - shader->so = state->stream_output; + sel->type = pipe_shader_type; + sel->shaders = util_new_keymap(sizeof(unsigned), 16, r600_pipe_shader_keymap_delete_func); + sel->tokens = tgsi_dup_tokens(state->tokens); + sel->so = state->stream_output; - r = r600_pipe_shader_create(ctx, shader); - if (r) { - return NULL; - } - return shader; + r600_shader_select(ctx, sel); + + return sel; +} + +void *r600_create_shader_state_ps(struct pipe_context *ctx, + const struct pipe_shader_state *state) +{ + return r600_create_shader_state(ctx, state, PIPE_SHADER_FRAGMENT); +} + +void *r600_create_shader_state_vs(struct pipe_context *ctx, + const struct pipe_shader_state *state) +{ + return r600_create_shader_state(ctx, state, PIPE_SHADER_VERTEX); } + + + + void r600_bind_ps_shader(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; @@ -453,13 +521,14 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state) state = rctx->dummy_pixel_shader; } - rctx->ps_shader = (struct r600_pipe_shader *)state; + rctx->ps_shader = (struct r600_pipe_shader_selector *)state; r600_inval_shader_cache(rctx); - r600_context_pipe_state_set(rctx, &rctx->ps_shader->rstate); + r600_shader_select(ctx, rctx->ps_shader); + r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate); rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE; - rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(!!rctx->ps_shader->shader.fs_write_all); + rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(!!rctx->ps_shader->current->shader.fs_write_all); if (rctx->ps_shader && rctx->vs_shader) { r600_adjust_gprs(rctx); @@ -470,42 +539,48 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; - rctx->vs_shader = (struct r600_pipe_shader *)state; + rctx->vs_shader = (struct r600_pipe_shader_selector *)state; if (state) { r600_inval_shader_cache(rctx); - r600_context_pipe_state_set(rctx, &rctx->vs_shader->rstate); + r600_shader_select(ctx, rctx->vs_shader); + r600_context_pipe_state_set(rctx, &rctx->vs_shader->current->rstate); } if (rctx->ps_shader && rctx->vs_shader) { r600_adjust_gprs(rctx); } } +static void r600_delete_shader_selector(struct pipe_context *ctx, + struct r600_pipe_shader_selector *sel) +{ + free(sel->tokens); + util_delete_keymap(sel->shaders, ctx); + free(sel); +} + + void r600_delete_ps_shader(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; - struct r600_pipe_shader *shader = (struct r600_pipe_shader *)state; + struct r600_pipe_shader_selector *sel = (struct r600_pipe_shader_selector *)state; - if (rctx->ps_shader == shader) { + if (rctx->ps_shader == sel) { rctx->ps_shader = NULL; } - free(shader->tokens); - r600_pipe_shader_destroy(ctx, shader); - free(shader); + r600_delete_shader_selector(ctx, sel); } void r600_delete_vs_shader(struct pipe_context *ctx, void *state) { struct r600_context *rctx = (struct r600_context *)ctx; - struct r600_pipe_shader *shader = (struct r600_pipe_shader *)state; + struct r600_pipe_shader_selector *sel = (struct r600_pipe_shader_selector *)state; - if (rctx->vs_shader == shader) { + if (rctx->vs_shader == sel) { rctx->vs_shader = NULL; } - free(shader->tokens); - r600_pipe_shader_destroy(ctx, shader); - free(shader); + r600_delete_shader_selector(ctx, sel); } static void r600_update_alpha_ref(struct r600_context *rctx) @@ -661,24 +736,10 @@ void r600_set_so_targets(struct pipe_context *ctx, rctx->streamout_append_bitmask = append_bitmask; } -static int r600_shader_rebuild(struct pipe_context * ctx, struct r600_pipe_shader * shader) -{ - struct r600_context *rctx = (struct r600_context *)ctx; - int r; - - r600_pipe_shader_destroy(ctx, shader); - r = r600_pipe_shader_create(ctx, shader); - if (r) { - return r; - } - r600_context_pipe_state_set(rctx, &shader->rstate); - - return 0; -} - static void r600_update_derived_state(struct r600_context *rctx) { struct pipe_context * ctx = (struct pipe_context*)rctx; + int ps_dirty = 0; if (!rctx->blitter->running) { if (rctx->have_depth_fb || rctx->have_depth_texture) @@ -689,30 +750,29 @@ static void r600_update_derived_state(struct r600_context *rctx) r600_update_sampler_states(rctx); } - if ((rctx->ps_shader->shader.two_side != rctx->two_side) || - ((rctx->chip_class >= EVERGREEN) && rctx->ps_shader->shader.fs_write_all && - (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs))) { - r600_shader_rebuild(&rctx->context, rctx->ps_shader); - } + ps_dirty = r600_shader_select(ctx, rctx->ps_shader); if (rctx->alpha_ref_dirty) { r600_update_alpha_ref(rctx); } if (rctx->ps_shader && ((rctx->sprite_coord_enable && - (rctx->ps_shader->sprite_coord_enable != rctx->sprite_coord_enable)) || - (rctx->rasterizer && rctx->rasterizer->flatshade != rctx->ps_shader->flatshade))) { + (rctx->ps_shader->current->sprite_coord_enable != rctx->sprite_coord_enable)) || + (rctx->rasterizer && rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade))) { if (rctx->chip_class >= EVERGREEN) - evergreen_pipe_shader_ps(ctx, rctx->ps_shader); + evergreen_pipe_shader_ps(ctx, rctx->ps_shader->current); else - r600_pipe_shader_ps(ctx, rctx->ps_shader); + r600_pipe_shader_ps(ctx, rctx->ps_shader->current); - r600_context_pipe_state_set(rctx, &rctx->ps_shader->rstate); + ps_dirty = 1; } + if (ps_dirty) + r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate); + if (rctx->dual_src_blend) - rctx->cb_shader_mask = rctx->ps_shader->ps_cb_shader_mask | rctx->fb_cb_shader_mask; + rctx->cb_shader_mask = rctx->ps_shader->current->ps_cb_shader_mask | rctx->fb_cb_shader_mask; else rctx->cb_shader_mask = rctx->fb_cb_shader_mask; } @@ -827,12 +887,12 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo) if (rctx->chip_class <= R700) r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_color_control); r600_pipe_state_mod_reg(&rctx->vgt, - rctx->vs_shader->pa_cl_vs_out_cntl | - (rctx->rasterizer->clip_plane_enable & rctx->vs_shader->shader.clip_dist_write)); + rctx->vs_shader->current->pa_cl_vs_out_cntl | + (rctx->rasterizer->clip_plane_enable & rctx->vs_shader->current->shader.clip_dist_write)); r600_pipe_state_mod_reg(&rctx->vgt, rctx->pa_cl_clip_cntl | - (rctx->vs_shader->shader.clip_dist_write || - rctx->vs_shader->shader.vs_prohibit_ucps ? + (rctx->vs_shader->current->shader.clip_dist_write || + rctx->vs_shader->current->shader.vs_prohibit_ucps ? 0 : rctx->rasterizer->clip_plane_enable & 0x3F)); r600_context_pipe_state_set(rctx, &rctx->vgt); -- 1.7.10.2