From 33b2f914dbba3e8b291703122270627ed8f005c1 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Wed, 19 Jun 2019 20:52:35 +0200 Subject: [PATCH] zink: cache framebuffers Acked-by: Jordan Justen --- src/gallium/drivers/zink/zink_context.c | 60 +++++++++++++++++---- src/gallium/drivers/zink/zink_context.h | 1 + src/gallium/drivers/zink/zink_framebuffer.c | 33 +++++------- src/gallium/drivers/zink/zink_framebuffer.h | 11 +++- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index f35017a60d9..a4bd82f2230 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -476,12 +476,34 @@ static struct zink_framebuffer * get_framebuffer(struct zink_context *ctx) { struct zink_screen *screen = zink_screen(ctx->base.screen); - struct zink_render_pass *rp = get_render_pass(ctx); - // TODO: cache! - struct zink_framebuffer *ret = zink_create_framebuffer(screen, - &ctx->fb_state, - rp); - return ret; + + struct zink_framebuffer_state state = {}; + state.rp = get_render_pass(ctx); + for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { + struct pipe_surface *psurf = ctx->fb_state.cbufs[i]; + state.attachments[i] = zink_surface(psurf); + } + + state.num_attachments = ctx->fb_state.nr_cbufs; + if (ctx->fb_state.zsbuf) { + struct pipe_surface *psurf = ctx->fb_state.zsbuf; + state.attachments[state.num_attachments++] = zink_surface(psurf); + } + + state.width = ctx->fb_state.width; + state.height = ctx->fb_state.height; + state.layers = MAX2(ctx->fb_state.layers, 1); + + struct hash_entry *entry = _mesa_hash_table_search(ctx->framebuffer_cache, + &state); + if (!entry) { + struct zink_framebuffer *fb = zink_create_framebuffer(screen, &state); + entry = _mesa_hash_table_insert(ctx->framebuffer_cache, &state, fb); + if (!entry) + return NULL; + } + + return entry->data; } static void @@ -498,6 +520,7 @@ zink_begin_render_pass(struct zink_context *ctx, struct zink_batch *batch) { struct zink_screen *screen = zink_screen(ctx->base.screen); assert(batch == zink_context_curr_batch(ctx)); + assert(ctx->gfx_pipeline_state.render_pass); VkRenderPassBeginInfo rpbi = {}; rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -545,7 +568,6 @@ zink_set_framebuffer_state(struct pipe_context *pctx, struct zink_framebuffer *fb = get_framebuffer(ctx); zink_framebuffer_reference(screen, &ctx->framebuffer, fb); zink_render_pass_reference(screen, &ctx->gfx_pipeline_state.render_pass, fb->rp); - zink_framebuffer_reference(screen, &fb, NULL); ctx->gfx_pipeline_state.num_attachments = state->nr_cbufs; @@ -815,6 +837,20 @@ equals_render_pass_state(const void *a, const void *b) return memcmp(a, b, sizeof(struct zink_render_pass_state)) == 0; } +static uint32_t +hash_framebuffer_state(const void *key) +{ + struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)key; + return _mesa_hash_data(key, sizeof(struct zink_framebuffer_state) + sizeof(s->attachments) * s->num_attachments); +} + +static bool +equals_framebuffer_state(const void *a, const void *b) +{ + struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)a; + return memcmp(a, b, sizeof(struct zink_framebuffer_state) + sizeof(s->attachments) * s->num_attachments) == 0; +} + static struct zink_gfx_program * get_gfx_program(struct zink_context *ctx) { @@ -1335,13 +1371,15 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->program_cache = _mesa_hash_table_create(NULL, hash_gfx_program, equals_gfx_program); - if (!ctx->program_cache) - goto fail; - ctx->render_pass_cache = _mesa_hash_table_create(NULL, hash_render_pass_state, equals_render_pass_state); - if (!ctx->render_pass_cache) + ctx->framebuffer_cache = _mesa_hash_table_create(NULL, + hash_framebuffer_state, + equals_framebuffer_state); + + if (!ctx->program_cache || !ctx->render_pass_cache || + !ctx->framebuffer_cache) goto fail; ctx->dirty = ZINK_DIRTY_PROGRAM; diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 0ee19885c06..977b8317614 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -83,6 +83,7 @@ struct zink_context { unsigned dirty; struct hash_table *render_pass_cache; + struct hash_table *framebuffer_cache; struct primconvert_context *primconvert; diff --git a/src/gallium/drivers/zink/zink_framebuffer.c b/src/gallium/drivers/zink/zink_framebuffer.c index 9a80758e68b..6031ad24a24 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.c +++ b/src/gallium/drivers/zink/zink_framebuffer.c @@ -45,8 +45,7 @@ zink_destroy_framebuffer(struct zink_screen *screen, struct zink_framebuffer * zink_create_framebuffer(struct zink_screen *screen, - const struct pipe_framebuffer_state *fb, - struct zink_render_pass *rp) + struct zink_framebuffer_state *fb) { struct zink_framebuffer *fbuf = CALLOC_STRUCT(zink_framebuffer); if (!fbuf) @@ -54,31 +53,23 @@ zink_create_framebuffer(struct zink_screen *screen, pipe_reference_init(&fbuf->reference, 1); - VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1]; - for (int i = 0; i < fb->nr_cbufs; i++) { - struct pipe_surface *psurf = fb->cbufs[i]; - pipe_surface_reference(fbuf->surfaces + i, psurf); - attachments[i] = zink_surface(psurf)->image_view; + VkImageView attachments[ARRAY_SIZE(fb->attachments)]; + for (int i = 0; i < fb->num_attachments; i++) { + struct zink_surface *surf = fb->attachments[i]; + pipe_surface_reference(fbuf->surfaces + i, &surf->base); + attachments[i] = surf->image_view; } - int num_attachments = fb->nr_cbufs; - if (fb->zsbuf) { - struct pipe_surface *psurf = fb->zsbuf; - pipe_surface_reference(fbuf->surfaces + num_attachments, psurf); - attachments[num_attachments++] = zink_surface(psurf)->image_view; - } - - assert(rp); - zink_render_pass_reference(screen, &fbuf->rp, rp); + zink_render_pass_reference(screen, &fbuf->rp, fb->rp); VkFramebufferCreateInfo fci = {}; fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fci.renderPass = rp->render_pass; - fci.attachmentCount = num_attachments; + fci.renderPass = fbuf->rp->render_pass; + fci.attachmentCount = fb->num_attachments; fci.pAttachments = attachments; - fci.width = (uint32_t)fb->width; - fci.height = (uint32_t)fb->height; - fci.layers = (uint32_t)MAX2(fb->layers, 1); + fci.width = fb->width; + fci.height = fb->height; + fci.layers = fb->layers; if (vkCreateFramebuffer(screen->dev, &fci, NULL, &fbuf->fb) != VK_SUCCESS) { zink_destroy_framebuffer(screen, fbuf); diff --git a/src/gallium/drivers/zink/zink_framebuffer.h b/src/gallium/drivers/zink/zink_framebuffer.h index 4e7e5cad41e..63dd3621461 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.h +++ b/src/gallium/drivers/zink/zink_framebuffer.h @@ -32,6 +32,14 @@ struct zink_screen; struct zink_render_pass; +struct zink_framebuffer_state { + struct zink_render_pass *rp; + uint32_t width; + uint16_t height, layers; + uint8_t num_attachments; + struct zink_surface *attachments[PIPE_MAX_COLOR_BUFS + 1]; +}; + struct zink_framebuffer { struct pipe_reference reference; VkFramebuffer fb; @@ -42,8 +50,7 @@ struct zink_framebuffer { struct zink_framebuffer * zink_create_framebuffer(struct zink_screen *screen, - const struct pipe_framebuffer_state *fb, - struct zink_render_pass *rp); + struct zink_framebuffer_state *fb); void zink_destroy_framebuffer(struct zink_screen *screen, -- 2.30.2