diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-02-24 01:57:18 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-02-24 01:57:18 +0000 |
commit | b24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch) | |
tree | 658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/gallium/drivers/zink/zink_framebuffer.c | |
parent | 57768bbb154c2879d34ec20e401b19472e77aaf7 (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.c | 291 |
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; +} |