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