Mesa (master): zink: decouple renderpass from framebuffer state
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Jan 14 22:18:16 UTC 2021
Module: Mesa
Branch: master
Commit: 3d88e65e88cd0d38a559496294a636d42ed6d71a
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3d88e65e88cd0d38a559496294a636d42ed6d71a
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Thu Dec 24 09:42:24 2020 -0500
zink: decouple renderpass from framebuffer state
a framebuffer is based on the surfaces attached to it
a renderpass is based on the operations being performed
a zink_framebuffer object doesn't necessarily need to be changed
if the renderpass changes, as this might just indicate that a clear operation
is being used instead of a load, so we can cache the corresponding vk objects
into the zink_framebuffer based on the renderpass ops being used to (eventually)
reduce fb object thrashing by doing more incremental updates
Reviewed-by: Adam Jackson <ajax at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8227>
---
src/gallium/drivers/zink/zink_context.c | 9 ++--
src/gallium/drivers/zink/zink_framebuffer.c | 78 +++++++++++++++++++++++------
src/gallium/drivers/zink/zink_framebuffer.h | 11 +++-
3 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 3f0cea6a3f1..8e5a943ea55 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -709,7 +709,6 @@ create_framebuffer(struct zink_context *ctx)
struct pipe_surface *attachments[PIPE_MAX_COLOR_BUFS + 1] = {};
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] = psurf ? zink_surface(psurf)->image_view : VK_NULL_HANDLE;
@@ -728,7 +727,9 @@ create_framebuffer(struct zink_context *ctx)
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1);
state.samples = ctx->fb_state.samples;
- return zink_create_framebuffer(ctx, screen, &state, attachments);
+ struct zink_framebuffer *fb = zink_create_framebuffer(ctx, &state, attachments);
+ zink_init_framebuffer(screen, fb, get_render_pass(ctx));
+ return fb;
}
static void
@@ -814,7 +815,7 @@ zink_batch_rp(struct zink_context *ctx)
struct zink_batch *batch = zink_curr_batch(ctx);
if (!batch->in_rp) {
zink_begin_render_pass(ctx, batch);
- assert(batch->fb && batch->fb->state.rp);
+ assert(batch->fb && batch->fb->rp);
}
return batch;
}
@@ -847,7 +848,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
zink_framebuffer_reference(screen, &fb, NULL);
fb = create_framebuffer(ctx);
zink_framebuffer_reference(screen, &ctx->framebuffer, fb);
- ctx->gfx_pipeline_state.render_pass = fb->state.rp;
+ ctx->gfx_pipeline_state.render_pass = fb->rp;
uint8_t rast_samples = util_framebuffer_get_num_samples(state);
/* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */
diff --git a/src/gallium/drivers/zink/zink_framebuffer.c b/src/gallium/drivers/zink/zink_framebuffer.c
index 3baf8aca4e2..cbd0a5bb0ff 100644
--- a/src/gallium/drivers/zink/zink_framebuffer.c
+++ b/src/gallium/drivers/zink/zink_framebuffer.c
@@ -63,7 +63,14 @@ void
zink_destroy_framebuffer(struct zink_screen *screen,
struct zink_framebuffer *fb)
{
- vkDestroyFramebuffer(screen->dev, fb->fb, NULL);
+ hash_table_foreach(&fb->objects, he) {
+#if defined(_WIN64) || defined(__x86_64__)
+ vkDestroyFramebuffer(screen->dev, he->data, NULL);
+#else
+ VkFramebuffer *ptr = he->data;
+ vkDestroyFramebuffer(screen->dev, *ptr, NULL);
+#endif
+ }
for (int i = 0; i < ARRAY_SIZE(fb->surfaces); ++i)
pipe_surface_reference(fb->surfaces + i, NULL);
@@ -72,11 +79,60 @@ zink_destroy_framebuffer(struct zink_screen *screen,
ralloc_free(fb);
}
+void
+zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp)
+{
+ VkFramebuffer ret;
+
+ if (fb->rp == rp)
+ return;
+
+ uint32_t hash = _mesa_hash_pointer(rp);
+
+ struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&fb->objects, hash, rp);
+ if (he) {
+#if defined(_WIN64) || defined(__x86_64__)
+ ret = (VkFramebuffer)he->data;
+#else
+ VkFramebuffer *ptr = he->data;
+ ret = *ptr;
+#endif
+ goto out;
+ }
+
+ VkFramebufferCreateInfo fci = {};
+ fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fci.renderPass = rp->render_pass;
+ fci.attachmentCount = fb->state.num_attachments;
+ fci.pAttachments = fb->state.attachments;
+ fci.width = fb->state.width;
+ fci.height = fb->state.height;
+ fci.layers = fb->state.layers;
+
+ if (vkCreateFramebuffer(screen->dev, &fci, NULL, &ret) != VK_SUCCESS)
+ return;
+#if defined(_WIN64) || defined(__x86_64__)
+ _mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ret);
+#else
+ VkFramebuffer *ptr = ralloc(fb, VkFramebuffer);
+ if (!ptr) {
+ vkDestroyFramebuffer(screen->dev, ret, NULL);
+ return;
+ }
+ *ptr = ret;
+ _mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ptr);
+#endif
+out:
+ fb->rp = rp;
+ fb->fb = ret;
+}
+
struct zink_framebuffer *
-zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
+zink_create_framebuffer(struct zink_context *ctx,
struct zink_framebuffer_state *state,
struct pipe_surface **attachments)
{
+ struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_framebuffer *fb = rzalloc(NULL, struct zink_framebuffer);
if (!fb)
return NULL;
@@ -93,22 +149,14 @@ zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
}
}
- VkFramebufferCreateInfo fci = {};
- fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- fci.renderPass = state->rp->render_pass;
- fci.attachmentCount = state->num_attachments;
- fci.pAttachments = state->attachments;
- fci.width = state->width;
- fci.height = state->height;
- fci.layers = state->layers;
-
- if (vkCreateFramebuffer(screen->dev, &fci, NULL, &fb->fb) != VK_SUCCESS) {
- zink_destroy_framebuffer(screen, fb);
- return NULL;
- }
+ if (!_mesa_hash_table_init(&fb->objects, fb, _mesa_hash_pointer, _mesa_key_pointer_equal))
+ goto fail;
memcpy(&fb->state, state, sizeof(struct zink_framebuffer_state));
return fb;
+fail:
+ zink_destroy_framebuffer(screen, fb);
+ return NULL;
}
void
diff --git a/src/gallium/drivers/zink/zink_framebuffer.h b/src/gallium/drivers/zink/zink_framebuffer.h
index 1950ea23b0b..58d590e74fc 100644
--- a/src/gallium/drivers/zink/zink_framebuffer.h
+++ b/src/gallium/drivers/zink/zink_framebuffer.h
@@ -27,6 +27,7 @@
#include "pipe/p_state.h"
#include <vulkan/vulkan.h>
+#include "util/hash_table.h"
#include "util/u_inlines.h"
struct zink_context;
@@ -34,7 +35,6 @@ 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 samples;
@@ -44,18 +44,25 @@ struct zink_framebuffer_state {
struct zink_framebuffer {
struct pipe_reference reference;
+
+ /* current objects */
VkFramebuffer fb;
+ struct zink_render_pass *rp;
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
struct pipe_surface *null_surface; /* for use with unbound attachments */
struct zink_framebuffer_state state;
+ struct hash_table objects;
};
struct zink_framebuffer *
-zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
+zink_create_framebuffer(struct zink_context *ctx,
struct zink_framebuffer_state *fb,
struct pipe_surface **attachments);
+void
+zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp);
+
void
zink_destroy_framebuffer(struct zink_screen *screen,
struct zink_framebuffer *fbuf);
More information about the mesa-commit
mailing list