aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Faye-Lund <[email protected]>2019-06-19 20:52:35 +0200
committerErik Faye-Lund <[email protected]>2019-10-28 08:51:45 +0000
commit33b2f914dbba3e8b291703122270627ed8f005c1 (patch)
treee639b549838d7fd69c2884ed0dfaf7283c3c6ae2
parenta872f4636924db0198684be46cb48df9d2863916 (diff)
zink: cache framebuffers
Acked-by: Jordan Justen <[email protected]>
-rw-r--r--src/gallium/drivers/zink/zink_context.c60
-rw-r--r--src/gallium/drivers/zink/zink_context.h1
-rw-r--r--src/gallium/drivers/zink/zink_framebuffer.c33
-rw-r--r--src/gallium/drivers/zink/zink_framebuffer.h11
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,