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
{
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;
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;
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)
{
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;
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)
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);
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;
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,