From ff1941aa08337aa2f39565887c74e3461f7e72bd Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 1 Apr 2021 16:52:27 -0400 Subject: [PATCH] zink: split vertex state pipeline hashing into its own value by creating a separate hash value for vertex state, changes to the vbos and bindings requires massively less overhead as it doesn't require the rest of the pipeline state to be rehashed Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_draw.c | 13 +--------- src/gallium/drivers/zink/zink_pipeline.h | 7 ++++-- src/gallium/drivers/zink/zink_program.c | 43 +++++++++++++++++++------------- src/gallium/drivers/zink/zink_program.h | 2 +- src/gallium/drivers/zink/zink_state.c | 3 ++- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index e945a82..b6f229d 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -339,17 +339,6 @@ zink_draw_vbo(struct pipe_context *pctx, ctx->gfx_pipeline_state.dirty = true; ctx->gfx_pipeline_state.primitive_restart = !!dinfo->primitive_restart; - if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) { - for (unsigned i = 0; i < ctx->element_state->hw_state.num_bindings; i++) { - unsigned binding = ctx->element_state->binding_map[i]; - const struct pipe_vertex_buffer *vb = ctx->vertex_buffers + binding; - if (ctx->gfx_pipeline_state.vertex_strides[i] != vb->stride) { - ctx->gfx_pipeline_state.vertex_strides[i] = vb->stride; - ctx->gfx_pipeline_state.dirty = true; - } - } - } - enum pipe_prim_type reduced_prim = u_reduced_prim(dinfo->mode); bool depth_bias = false; @@ -488,7 +477,7 @@ zink_draw_vbo(struct pipe_context *pctx, vkCmdSetBlendConstants(batch->state->cmdbuf, ctx->blend_constants); - VkPipeline pipeline = zink_get_gfx_pipeline(screen, gfx_program, + VkPipeline pipeline = zink_get_gfx_pipeline(ctx, gfx_program, &ctx->gfx_pipeline_state, dinfo->mode); vkCmdBindPipeline(batch->state->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index 27a68ee..8105da9 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -40,8 +40,6 @@ struct zink_vertex_elements_state; struct zink_gfx_pipeline_state { struct zink_render_pass *render_pass; - struct zink_vertex_elements_hw_state *element_state; - uint32_t num_attachments; struct zink_blend_state *blend_state; @@ -68,6 +66,11 @@ struct zink_gfx_pipeline_state { uint32_t combined_hash; bool combined_dirty; + struct zink_vertex_elements_hw_state *element_state; + bool vertex_state_dirty; + + uint32_t final_hash; + uint32_t vertex_buffers_enabled_mask; uint32_t vertex_strides[PIPE_MAX_ATTRIBS]; bool have_EXT_extended_dynamic_state; diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index ddad8ef..b5368ed 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -371,17 +371,6 @@ update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_ static uint32_t hash_gfx_pipeline_state(const void *key) { - const struct zink_gfx_pipeline_state *state = key; - uint32_t hash = 0; - if (!state->have_EXT_extended_dynamic_state) { - /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ - uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask; - hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash); - while (vertex_buffers_enabled_mask) { - unsigned idx = u_bit_scan(&vertex_buffers_enabled_mask); - hash = XXH32(&state->vertex_strides[idx], sizeof(uint32_t), hash); - } - } return _mesa_hash_data(key, offsetof(struct zink_gfx_pipeline_state, hash)); } @@ -390,9 +379,9 @@ equals_gfx_pipeline_state(const void *a, const void *b) { const struct zink_gfx_pipeline_state *sa = a; const struct zink_gfx_pipeline_state *sb = b; - if (sa->vertex_buffers_enabled_mask != sb->vertex_buffers_enabled_mask) - return false; if (!sa->have_EXT_extended_dynamic_state) { + if (sa->vertex_buffers_enabled_mask != sb->vertex_buffers_enabled_mask) + return false; /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ uint32_t mask_a = sa->vertex_buffers_enabled_mask; uint32_t mask_b = sb->vertex_buffers_enabled_mask; @@ -890,26 +879,44 @@ primitive_topology(enum pipe_prim_type mode) } VkPipeline -zink_get_gfx_pipeline(struct zink_screen *screen, +zink_get_gfx_pipeline(struct zink_context *ctx, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode) { + struct zink_screen *screen = zink_screen(ctx->base.screen); VkPrimitiveTopology vkmode = primitive_topology(mode); assert(vkmode <= ARRAY_SIZE(prog->pipelines)); struct hash_entry *entry = NULL; - + if (state->dirty) { - state->combined_dirty = true; + state->vertex_state_dirty = state->combined_dirty = true; state->hash = hash_gfx_pipeline_state(state); state->dirty = false; } if (state->combined_dirty) { + state->vertex_state_dirty = true; state->combined_hash = XXH32(&state->module_hash, sizeof(uint32_t), state->hash); state->combined_dirty = false; } - entry = _mesa_hash_table_search_pre_hashed(prog->pipelines[vkmode], state->combined_hash, state); + if (state->vertex_state_dirty) { + uint32_t hash = state->combined_hash; + if (!state->have_EXT_extended_dynamic_state) { + /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ + uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask; + hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash); + + for (unsigned i = 0; i < state->element_state->num_bindings; i++) { + struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i]; + state->vertex_strides[i] = vb->buffer.resource ? vb->stride : 0; + hash = XXH32(&state->vertex_strides[i], sizeof(uint32_t), hash); + } + } + state->final_hash = XXH32(&state->element_state, sizeof(void*), hash); + state->vertex_state_dirty = false; + } + entry = _mesa_hash_table_search_pre_hashed(prog->pipelines[vkmode], state->final_hash, state); if (!entry) { VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog, @@ -924,7 +931,7 @@ zink_get_gfx_pipeline(struct zink_screen *screen, memcpy(&pc_entry->state, state, sizeof(*state)); pc_entry->pipeline = pipeline; - entry = _mesa_hash_table_insert_pre_hashed(prog->pipelines[vkmode], state->combined_hash, state, pc_entry); + entry = _mesa_hash_table_insert_pre_hashed(prog->pipelines[vkmode], state->final_hash, state, pc_entry); assert(entry); } diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h index e61a25a..204556b 100644 --- a/src/gallium/drivers/zink/zink_program.h +++ b/src/gallium/drivers/zink/zink_program.h @@ -149,7 +149,7 @@ zink_destroy_gfx_program(struct zink_screen *screen, struct zink_gfx_program *prog); VkPipeline -zink_get_gfx_pipeline(struct zink_screen *screen, +zink_get_gfx_pipeline(struct zink_context *ctx, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode); diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 33ad942..5ea13a7 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -95,8 +95,9 @@ 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->dirty = true; if (cso) { + if (state->element_state != &ctx->element_state->hw_state) + state->vertex_state_dirty = true; state->element_state = &ctx->element_state->hw_state; } else state->element_state = NULL; -- 2.7.4