zink: cache framebuffers
authorErik Faye-Lund <erik.faye-lund@collabora.com>
Wed, 19 Jun 2019 18:52:35 +0000 (20:52 +0200)
committerErik Faye-Lund <erik.faye-lund@collabora.com>
Mon, 28 Oct 2019 08:51:45 +0000 (08:51 +0000)
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_context.h
src/gallium/drivers/zink/zink_framebuffer.c
src/gallium/drivers/zink/zink_framebuffer.h

index f35017a..a4bd82f 100644 (file)
@@ -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;
index 0ee1988..977b831 100644 (file)
@@ -83,6 +83,7 @@ struct zink_context {
    unsigned dirty;
 
    struct hash_table *render_pass_cache;
+   struct hash_table *framebuffer_cache;
 
    struct primconvert_context *primconvert;
 
index 9a80758..6031ad2 100644 (file)
@@ -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);
index 4e7e5ca..63dd362 100644 (file)
 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,