From: Erik Faye-Lund Date: Tue, 26 Mar 2019 12:52:09 +0000 (+0100) Subject: zink: cache programs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1cdbeefd2c60426a763fc13730b65f99fda0d3b5;p=mesa.git zink: cache programs Acked-by: Jordan Justen --- diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index de77575ac9f..dd2d8d41822 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -257,12 +257,20 @@ zink_create_vs_state(struct pipe_context *pctx, return zink_compile_nir(zink_screen(pctx->screen), nir); } +static void +bind_stage(struct zink_context *ctx, enum pipe_shader_type stage, + struct zink_shader *shader) +{ + assert(stage < PIPE_SHADER_COMPUTE); + ctx->gfx_stages[stage] = shader; + ctx->dirty |= ZINK_DIRTY_PROGRAM; +} + static void zink_bind_vs_state(struct pipe_context *pctx, void *cso) { - struct zink_context *ctx = zink_context(pctx); - ctx->gfx_stages[PIPE_SHADER_VERTEX] = cso; + bind_stage(zink_context(pctx), PIPE_SHADER_VERTEX, cso); } static void @@ -289,8 +297,7 @@ static void zink_bind_fs_state(struct pipe_context *pctx, void *cso) { - struct zink_context *ctx = zink_context(pctx); - ctx->gfx_stages[PIPE_SHADER_FRAGMENT] = cso; + bind_stage(zink_context(pctx), PIPE_SHADER_FRAGMENT, cso); } static void @@ -770,6 +777,40 @@ begin_render_pass(struct zink_cmdbuf *cmdbuf, struct zink_render_pass *rp, vkCmdBeginRenderPass(cmdbuf->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE); } +static uint32_t +hash_gfx_program(const void *key) +{ + return _mesa_hash_data(key, sizeof(struct zink_shader *) * (PIPE_SHADER_TYPES - 1)); +} + +static bool +equals_gfx_program(const void *a, const void *b) +{ + return memcmp(a, b, sizeof(struct zink_shader *) * (PIPE_SHADER_TYPES - 1)) == 0; +} + +static struct zink_gfx_program * +get_gfx_program(struct zink_context *ctx) +{ + if (ctx->dirty & ZINK_DIRTY_PROGRAM) { + struct hash_entry *entry = _mesa_hash_table_search(ctx->program_cache, + ctx->gfx_stages); + if (!entry) { + struct zink_gfx_program *prog; + prog = zink_create_gfx_program(zink_screen(ctx->base.screen)->dev, + ctx->gfx_stages); + entry = _mesa_hash_table_insert(ctx->program_cache, prog->stages, prog); + if (!entry) + return NULL; + } + ctx->curr_program = entry->data; + ctx->dirty &= ~ZINK_DIRTY_PROGRAM; + } + + assert(ctx->curr_program); + return ctx->curr_program; +} + static void zink_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo) @@ -788,8 +829,7 @@ zink_draw_vbo(struct pipe_context *pctx, return; } - struct zink_gfx_program *gfx_program = zink_create_gfx_program(screen->dev, - ctx->gfx_stages); + struct zink_gfx_program *gfx_program = get_gfx_program(ctx); if (!gfx_program) return; @@ -1217,6 +1257,12 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) vkGetDeviceQueue(screen->dev, screen->gfx_queue, 0, &ctx->queue); + ctx->program_cache = _mesa_hash_table_create(NULL, hash_gfx_program, equals_gfx_program); + if (!ctx->program_cache) + goto fail; + + ctx->dirty = ZINK_DIRTY_PROGRAM; + return &ctx->base; fail: diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 81aeb337e7f..a0016ce81f3 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -36,12 +36,13 @@ struct blitter_context; struct primconvert_context; -struct zink_resource; -struct zink_vertex_elements_state; -struct zink_rasterizer_state; struct zink_blend_state; struct zink_depth_stencil_alpha_state; +struct zink_gfx_program; +struct zink_rasterizer_state; +struct zink_resource; +struct zink_vertex_elements_state; struct zink_sampler_view { struct pipe_sampler_view base; @@ -54,6 +55,8 @@ zink_sampler_view(struct pipe_sampler_view *pview) return (struct zink_sampler_view *)pview; } +#define ZINK_DIRTY_PROGRAM (1 << 0) + struct zink_context { struct pipe_context base; struct slab_child_pool transfer_pool; @@ -71,6 +74,9 @@ struct zink_context { struct zink_shader *gfx_stages[PIPE_SHADER_TYPES - 1]; struct zink_gfx_pipeline_state gfx_pipeline_state; + struct hash_table *program_cache; + struct zink_gfx_program *curr_program; + unsigned dirty; struct primconvert_context *primconvert;