summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
commitb24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch)
tree658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c
parent57768bbb154c2879d34ec20e401b19472e77aaf7 (diff)
Import Mesa 21.3.7
Diffstat (limited to 'lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c')
-rw-r--r--lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c291
1 files changed, 246 insertions, 45 deletions
diff --git a/lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c b/lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c
index 3ddd2f0bc..192450dd3 100644
--- a/lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c
+++ b/lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c
@@ -28,53 +28,171 @@
#include "zink_screen.h"
#include "zink_surface.h"
+#include "util/u_framebuffer.h"
#include "util/u_memory.h"
#include "util/u_string.h"
-static struct pipe_surface *
-framebuffer_null_surface_init(struct zink_context *ctx, struct zink_framebuffer_state *state)
+void
+zink_destroy_framebuffer(struct zink_screen *screen,
+ struct zink_framebuffer *fb)
{
- struct pipe_surface surf_templ = {};
- unsigned idx = util_logbase2_ceil(MAX2(state->samples, 1));
-
- if (!ctx->null_buffers[idx]) {
- struct pipe_resource *pres;
- struct pipe_resource templ = {};
- templ.width0 = state->width;
- templ.height0 = state->height;
- templ.depth0 = 1;
- templ.format = PIPE_FORMAT_R8_UINT;
- templ.target = PIPE_TEXTURE_2D;
- templ.bind = PIPE_BIND_RENDER_TARGET;
- templ.nr_samples = state->samples;
-
- pres = ctx->base.screen->resource_create(ctx->base.screen, &templ);
- if (!pres)
- return NULL;
-
- ctx->null_buffers[idx] = pres;
+ hash_table_foreach(&fb->objects, he) {
+#if defined(_WIN64) || defined(__x86_64__)
+ VKSCR(DestroyFramebuffer)(screen->dev, he->data, NULL);
+#else
+ VkFramebuffer *ptr = he->data;
+ VKSCR(DestroyFramebuffer)(screen->dev, *ptr, NULL);
+#endif
}
- surf_templ.format = PIPE_FORMAT_R8_UINT;
- surf_templ.nr_samples = state->samples;
- return ctx->base.create_surface(&ctx->base, ctx->null_buffers[idx], &surf_templ);
+
+ ralloc_free(fb);
}
void
-zink_destroy_framebuffer(struct zink_screen *screen,
- struct zink_framebuffer *fb)
+zink_init_framebuffer_imageless(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp)
{
- hash_table_foreach(&fb->objects, he) {
+ 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__)
- vkDestroyFramebuffer(screen->dev, he->data, NULL);
+ ret = (VkFramebuffer)he->data;
#else
VkFramebuffer *ptr = he->data;
- vkDestroyFramebuffer(screen->dev, *ptr, NULL);
+ ret = *ptr;
#endif
+ goto out;
}
- zink_surface_reference(screen, (struct zink_surface**)&fb->null_surface, NULL);
+ assert(rp->state.num_cbufs + rp->state.have_zsbuf + rp->state.num_cresolves + rp->state.num_zsresolves == fb->state.num_attachments);
- ralloc_free(fb);
+ VkFramebufferCreateInfo fci;
+ fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fci.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
+ fci.renderPass = rp->render_pass;
+ fci.attachmentCount = fb->state.num_attachments;
+ fci.pAttachments = NULL;
+ fci.width = fb->state.width;
+ fci.height = fb->state.height;
+ fci.layers = fb->state.layers + 1;
+
+ VkFramebufferAttachmentsCreateInfo attachments;
+ attachments.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO;
+ attachments.pNext = NULL;
+ attachments.attachmentImageInfoCount = fb->state.num_attachments;
+ attachments.pAttachmentImageInfos = fb->infos;
+ fci.pNext = &attachments;
+
+ if (VKSCR(CreateFramebuffer)(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) {
+ VKSCR(DestroyFramebuffer)(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;
+}
+
+static void
+populate_attachment_info(VkFramebufferAttachmentImageInfo *att, struct zink_surface_info *info)
+{
+ att->sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;
+ att->pNext = NULL;
+ memcpy(&att->flags, &info->flags, offsetof(struct zink_surface_info, format));
+ att->viewFormatCount = 1;
+ att->pViewFormats = &info->format;
+}
+
+static struct zink_framebuffer *
+create_framebuffer_imageless(struct zink_context *ctx, struct zink_framebuffer_state *state)
+{
+ struct zink_screen *screen = zink_screen(ctx->base.screen);
+ struct zink_framebuffer *fb = rzalloc(ctx, struct zink_framebuffer);
+ if (!fb)
+ return NULL;
+ pipe_reference_init(&fb->reference, 1);
+
+ 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));
+ for (int i = 0; i < state->num_attachments; i++)
+ populate_attachment_info(&fb->infos[i], &fb->state.infos[i]);
+
+ return fb;
+fail:
+ zink_destroy_framebuffer(screen, fb);
+ return NULL;
+}
+
+struct zink_framebuffer *
+zink_get_framebuffer_imageless(struct zink_context *ctx)
+{
+ assert(zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer);
+
+ struct zink_framebuffer_state state;
+ const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf;
+ unsigned num_resolves = 0;
+ for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
+ struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
+ if (!psurf)
+ psurf = ctx->dummy_surface[util_logbase2_ceil(ctx->gfx_pipeline_state.rast_samples+1)];
+ struct zink_surface *surface = zink_csurface(psurf);
+ struct zink_surface *transient = zink_transient_surface(psurf);
+ if (transient) {
+ memcpy(&state.infos[i], &transient->info, sizeof(transient->info));
+ memcpy(&state.infos[cresolve_offset + i], &surface->info, sizeof(surface->info));
+ num_resolves++;
+ } else {
+ memcpy(&state.infos[i], &surface->info, sizeof(surface->info));
+ }
+ }
+
+ state.num_attachments = ctx->fb_state.nr_cbufs;
+ const unsigned zsresolve_offset = cresolve_offset + num_resolves;
+ if (ctx->fb_state.zsbuf) {
+ struct pipe_surface *psurf = ctx->fb_state.zsbuf;
+ struct zink_surface *surface = zink_csurface(psurf);
+ struct zink_surface *transient = zink_transient_surface(psurf);
+ if (transient) {
+ memcpy(&state.infos[state.num_attachments], &transient->info, sizeof(transient->info));
+ memcpy(&state.infos[zsresolve_offset], &surface->info, sizeof(surface->info));
+ num_resolves++;
+ } else {
+ memcpy(&state.infos[state.num_attachments], &surface->info, sizeof(surface->info));
+ }
+ state.num_attachments++;
+ }
+
+ /* avoid bitfield explosion */
+ assert(state.num_attachments + num_resolves < 16);
+ state.num_attachments += num_resolves;
+ state.width = MAX2(ctx->fb_state.width, 1);
+ state.height = MAX2(ctx->fb_state.height, 1);
+ state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
+ state.samples = ctx->fb_state.samples - 1;
+
+ struct zink_framebuffer *fb;
+ struct hash_entry *entry = _mesa_hash_table_search(&ctx->framebuffer_cache, &state);
+ if (entry)
+ return entry->data;
+
+ fb = create_framebuffer_imageless(ctx, &state);
+ _mesa_hash_table_insert(&ctx->framebuffer_cache, &fb->state, fb);
+
+ return fb;
}
void
@@ -98,23 +216,25 @@ zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, s
goto out;
}
- VkFramebufferCreateInfo fci = {};
+ assert(rp->state.num_cbufs + rp->state.have_zsbuf + rp->state.num_cresolves + rp->state.num_zsresolves == fb->state.num_attachments);
+
+ VkFramebufferCreateInfo fci = {0};
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;
+ fci.layers = fb->state.layers + 1;
- if (vkCreateFramebuffer(screen->dev, &fci, NULL, &ret) != VK_SUCCESS)
+ if (VKSCR(CreateFramebuffer)(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);
+ VKSCR(DestroyFramebuffer)(screen->dev, ret, NULL);
return;
}
*ptr = ret;
@@ -125,10 +245,10 @@ out:
fb->fb = ret;
}
-struct zink_framebuffer *
-zink_create_framebuffer(struct zink_context *ctx,
- struct zink_framebuffer_state *state,
- struct pipe_surface **attachments)
+static struct zink_framebuffer *
+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);
@@ -139,17 +259,15 @@ zink_create_framebuffer(struct zink_context *ctx,
for (int i = 0; i < state->num_attachments; i++) {
struct zink_surface *surf;
if (state->attachments[i]) {
- surf = zink_surface(attachments[i]);
+ surf = zink_csurface(attachments[i]);
/* no ref! */
fb->surfaces[i] = attachments[i];
num_attachments++;
+ util_dynarray_append(&surf->framebuffer_refs, struct zink_framebuffer*, fb);
} else {
- if (!fb->null_surface)
- fb->null_surface = framebuffer_null_surface_init(ctx, state);
- surf = zink_surface(fb->null_surface);
- state->attachments[i] = zink_surface(fb->null_surface)->image_view;
+ surf = zink_csurface(ctx->dummy_surface[util_logbase2_ceil(state->samples+1)]);
+ state->attachments[i] = surf->image_view;
}
- util_dynarray_append(&surf->framebuffer_refs, struct zink_framebuffer*, fb);
}
pipe_reference_init(&fb->reference, 1 + num_attachments);
@@ -168,3 +286,86 @@ debug_describe_zink_framebuffer(char* buf, const struct zink_framebuffer *ptr)
{
sprintf(buf, "zink_framebuffer");
}
+
+struct zink_framebuffer *
+zink_get_framebuffer(struct zink_context *ctx)
+{
+ struct zink_screen *screen = zink_screen(ctx->base.screen);
+
+ assert(!screen->info.have_KHR_imageless_framebuffer);
+
+ struct pipe_surface *attachments[2 * (PIPE_MAX_COLOR_BUFS + 1)] = {0};
+ const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf;
+ unsigned num_resolves = 0;
+
+ struct zink_framebuffer_state state = {0};
+ for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
+ struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
+ if (psurf) {
+ struct zink_surface *surf = zink_csurface(psurf);
+ struct zink_surface *transient = zink_transient_surface(psurf);
+ if (transient) {
+ state.attachments[i] = transient->image_view;
+ state.attachments[cresolve_offset + i] = surf->image_view;
+ attachments[cresolve_offset + i] = psurf;
+ psurf = &transient->base;
+ num_resolves++;
+ } else {
+ state.attachments[i] = surf->image_view;
+ }
+ } else {
+ state.attachments[i] = VK_NULL_HANDLE;
+ }
+ attachments[i] = psurf;
+ }
+
+ state.num_attachments = ctx->fb_state.nr_cbufs;
+ const unsigned zsresolve_offset = cresolve_offset + num_resolves;
+ if (ctx->fb_state.zsbuf) {
+ struct pipe_surface *psurf = ctx->fb_state.zsbuf;
+ if (psurf) {
+ struct zink_surface *surf = zink_csurface(psurf);
+ struct zink_surface *transient = zink_transient_surface(psurf);
+ if (transient) {
+ state.attachments[state.num_attachments] = transient->image_view;
+ state.attachments[zsresolve_offset] = surf->image_view;
+ attachments[zsresolve_offset] = psurf;
+ psurf = &transient->base;
+ num_resolves++;
+ } else {
+ state.attachments[state.num_attachments] = surf->image_view;
+ }
+ } else {
+ state.attachments[state.num_attachments] = VK_NULL_HANDLE;
+ }
+ attachments[state.num_attachments++] = psurf;
+ }
+
+ /* avoid bitfield explosion */
+ assert(state.num_attachments + num_resolves < 16);
+ state.num_attachments += num_resolves;
+ state.width = MAX2(ctx->fb_state.width, 1);
+ state.height = MAX2(ctx->fb_state.height, 1);
+ state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
+ state.samples = ctx->fb_state.samples - 1;
+
+ struct zink_framebuffer *fb;
+ simple_mtx_lock(&screen->framebuffer_mtx);
+ struct hash_entry *entry = _mesa_hash_table_search(&screen->framebuffer_cache, &state);
+ if (entry) {
+ fb = (void*)entry->data;
+ struct zink_framebuffer *fb_ref = NULL;
+ /* this gains 1 ref every time we reuse it */
+ zink_framebuffer_reference(screen, &fb_ref, fb);
+ } else {
+ /* this adds 1 extra ref on creation because all newly-created framebuffers are
+ * going to be bound; necessary to handle framebuffers which have no "real" attachments
+ * and are only using null surfaces since the only ref they get is the extra one here
+ */
+ fb = create_framebuffer(ctx, &state, attachments);
+ _mesa_hash_table_insert(&screen->framebuffer_cache, &fb->state, fb);
+ }
+ simple_mtx_unlock(&screen->framebuffer_mtx);
+
+ return fb;
+}