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 <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10508>
This commit is contained in:
Mike Blumenkrantz 2021-04-01 16:52:27 -04:00 committed by Marge Bot
parent 7ca64c1c4d
commit ff1941aa08
5 changed files with 34 additions and 34 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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;