From 1185b3f32d97a260dfd388bd0ca032bc6a380bbf Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Fri, 24 Jul 2020 16:50:15 +0200 Subject: [PATCH] zink: pre-hash gfx-pipeline-state Store a hash in `zink_gfx_pipeline_state` to keep track of state changes and avoid to recompute it when the state has not changed. Signed-off-by: Antonio Caggiano Reviewed-by: Mike Blumenkrantz Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_context.c | 3 +++ src/gallium/drivers/zink/zink_pipeline.h | 4 ++++ src/gallium/drivers/zink/zink_program.c | 20 ++++++++++++------ src/gallium/drivers/zink/zink_state.c | 26 ++++++++++++++++++++---- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index c5ec154cf3c..786de9c095c 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -612,6 +612,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx, ctx->gfx_pipeline_state.rast_samples = MAX2(state->samples, 1); ctx->gfx_pipeline_state.num_attachments = state->nr_cbufs; + ctx->gfx_pipeline_state.hash = 0; struct zink_batch *batch = zink_batch_no_rp(ctx); @@ -1050,6 +1051,8 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) if (!ctx) goto fail; + ctx->gfx_pipeline_state.hash = 0; + ctx->base.screen = pscreen; ctx->base.priv = priv; diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index 757bae6266f..116ce656405 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -53,6 +53,10 @@ struct zink_gfx_pipeline_state { uint8_t rast_samples; bool primitive_restart; + + /* Pre-hashed value for table lookup, invalid when zero. + * Members after this point are not included in pipeline state hash key */ + uint32_t hash; }; VkPipeline diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index f8462e04107..ef6fa7a2457 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -163,13 +163,13 @@ update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_ static uint32_t hash_gfx_pipeline_state(const void *key) { - return _mesa_hash_data(key, sizeof(struct zink_gfx_pipeline_state)); + return _mesa_hash_data(key, offsetof(struct zink_gfx_pipeline_state, hash)); } static bool equals_gfx_pipeline_state(const void *a, const void *b) { - return memcmp(a, b, sizeof(struct zink_gfx_pipeline_state)) == 0; + return memcmp(a, b, offsetof(struct zink_gfx_pipeline_state, hash)) == 0; } struct zink_gfx_program * @@ -319,9 +319,16 @@ zink_get_gfx_pipeline(struct zink_screen *screen, { assert(mode <= ARRAY_SIZE(prog->pipelines)); - /* TODO: use pre-hashed versions to save some time (can re-hash only when - state changes) */ - struct hash_entry *entry = _mesa_hash_table_search(prog->pipelines[mode], state); + struct hash_entry *entry = NULL; + + if (!state->hash) { + state->hash = hash_gfx_pipeline_state(state); + /* make sure the hash is not zero, as we take it as invalid. + * TODO: rework this using a separate dirty-bit */ + assert(state->hash != 0); + } + entry = _mesa_hash_table_search_pre_hashed(prog->pipelines[mode], state->hash, state); + if (!entry) { VkPrimitiveTopology vkmode = primitive_topology(mode); VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog, @@ -336,7 +343,8 @@ zink_get_gfx_pipeline(struct zink_screen *screen, memcpy(&pc_entry->state, state, sizeof(*state)); pc_entry->pipeline = pipeline; - entry = _mesa_hash_table_insert(prog->pipelines[mode], &pc_entry->state, pc_entry); + assert(state->hash); + entry = _mesa_hash_table_insert_pre_hashed(prog->pipelines[mode], state->hash, state, pc_entry); assert(entry); reference_render_pass(screen, prog, state->render_pass); diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index bec8d05d585..95f23c273ba 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -81,6 +81,7 @@ zink_bind_vertex_elements_state(struct pipe_context *pctx, struct zink_context *ctx = zink_context(pctx); struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state; ctx->element_state = cso; + state->hash = 0; if (cso) { state->element_state = &ctx->element_state->hw_state; struct zink_vertex_elements_state *ves = cso; @@ -256,7 +257,12 @@ zink_create_blend_state(struct pipe_context *pctx, static void zink_bind_blend_state(struct pipe_context *pctx, void *cso) { - zink_context(pctx)->gfx_pipeline_state.blend_state = cso; + struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state; + + if (state->blend_state != cso) { + state->blend_state = cso; + state->hash = 0; + } } static void @@ -348,7 +354,12 @@ zink_create_depth_stencil_alpha_state(struct pipe_context *pctx, static void zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso) { - zink_context(pctx)->gfx_pipeline_state.depth_stencil_alpha_state = cso; + struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state; + + if (state->depth_stencil_alpha_state != cso) { + state->depth_stencil_alpha_state = cso; + state->hash = 0; + } } static void @@ -423,8 +434,15 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso) ctx->rast_state = cso; if (ctx->rast_state) { - ctx->gfx_pipeline_state.rast_state = &ctx->rast_state->hw_state; - ctx->line_width = ctx->rast_state->line_width; + if (ctx->gfx_pipeline_state.rast_state != &ctx->rast_state->hw_state) { + ctx->gfx_pipeline_state.rast_state = &ctx->rast_state->hw_state; + ctx->gfx_pipeline_state.hash = 0; + } + + if (ctx->line_width != ctx->rast_state->line_width) { + ctx->line_width = ctx->rast_state->line_width; + ctx->gfx_pipeline_state.hash = 0; + } } } -- 2.30.2