1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "zink_context.h" 25bf215546Sopenharmony_ci#include "zink_framebuffer.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "zink_render_pass.h" 28bf215546Sopenharmony_ci#include "zink_screen.h" 29bf215546Sopenharmony_ci#include "zink_surface.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 32bf215546Sopenharmony_ci#include "util/u_memory.h" 33bf215546Sopenharmony_ci#include "util/u_string.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_civoid 36bf215546Sopenharmony_cizink_destroy_framebuffer(struct zink_screen *screen, 37bf215546Sopenharmony_ci struct zink_framebuffer *fb) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci hash_table_foreach(&fb->objects, he) { 40bf215546Sopenharmony_ci#if VK_USE_64_BIT_PTR_DEFINES 41bf215546Sopenharmony_ci VKSCR(DestroyFramebuffer)(screen->dev, he->data, NULL); 42bf215546Sopenharmony_ci#else 43bf215546Sopenharmony_ci VkFramebuffer *ptr = he->data; 44bf215546Sopenharmony_ci VKSCR(DestroyFramebuffer)(screen->dev, *ptr, NULL); 45bf215546Sopenharmony_ci#endif 46bf215546Sopenharmony_ci } 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci ralloc_free(fb); 49bf215546Sopenharmony_ci} 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_civoid 52bf215546Sopenharmony_cizink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci VkFramebuffer ret; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci if (fb->rp == rp) 57bf215546Sopenharmony_ci return; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci uint32_t hash = _mesa_hash_pointer(rp); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&fb->objects, hash, rp); 62bf215546Sopenharmony_ci if (he) { 63bf215546Sopenharmony_ci#if VK_USE_64_BIT_PTR_DEFINES 64bf215546Sopenharmony_ci ret = (VkFramebuffer)he->data; 65bf215546Sopenharmony_ci#else 66bf215546Sopenharmony_ci VkFramebuffer *ptr = he->data; 67bf215546Sopenharmony_ci ret = *ptr; 68bf215546Sopenharmony_ci#endif 69bf215546Sopenharmony_ci goto out; 70bf215546Sopenharmony_ci } 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci assert(rp->state.num_cbufs + rp->state.have_zsbuf + rp->state.num_cresolves + rp->state.num_zsresolves == fb->state.num_attachments); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci VkFramebufferCreateInfo fci; 75bf215546Sopenharmony_ci fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 76bf215546Sopenharmony_ci fci.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT; 77bf215546Sopenharmony_ci fci.renderPass = rp->render_pass; 78bf215546Sopenharmony_ci fci.attachmentCount = fb->state.num_attachments; 79bf215546Sopenharmony_ci fci.pAttachments = NULL; 80bf215546Sopenharmony_ci fci.width = fb->state.width; 81bf215546Sopenharmony_ci fci.height = fb->state.height; 82bf215546Sopenharmony_ci fci.layers = fb->state.layers + 1; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci VkFramebufferAttachmentsCreateInfo attachments; 85bf215546Sopenharmony_ci attachments.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO; 86bf215546Sopenharmony_ci attachments.pNext = NULL; 87bf215546Sopenharmony_ci attachments.attachmentImageInfoCount = fb->state.num_attachments; 88bf215546Sopenharmony_ci attachments.pAttachmentImageInfos = fb->infos; 89bf215546Sopenharmony_ci fci.pNext = &attachments; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci if (VKSCR(CreateFramebuffer)(screen->dev, &fci, NULL, &ret) != VK_SUCCESS) 92bf215546Sopenharmony_ci return; 93bf215546Sopenharmony_ci#if VK_USE_64_BIT_PTR_DEFINES 94bf215546Sopenharmony_ci _mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ret); 95bf215546Sopenharmony_ci#else 96bf215546Sopenharmony_ci VkFramebuffer *ptr = ralloc(fb, VkFramebuffer); 97bf215546Sopenharmony_ci if (!ptr) { 98bf215546Sopenharmony_ci VKSCR(DestroyFramebuffer)(screen->dev, ret, NULL); 99bf215546Sopenharmony_ci return; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci *ptr = ret; 102bf215546Sopenharmony_ci _mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ptr); 103bf215546Sopenharmony_ci#endif 104bf215546Sopenharmony_ciout: 105bf215546Sopenharmony_ci fb->rp = rp; 106bf215546Sopenharmony_ci fb->fb = ret; 107bf215546Sopenharmony_ci} 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_cistatic void 110bf215546Sopenharmony_cipopulate_attachment_info(VkFramebufferAttachmentImageInfo *att, struct zink_surface_info *info) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci att->sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO; 113bf215546Sopenharmony_ci att->pNext = NULL; 114bf215546Sopenharmony_ci memcpy(&att->flags, &info->flags, offsetof(struct zink_surface_info, format)); 115bf215546Sopenharmony_ci att->viewFormatCount = 1 + !!info->format[1]; 116bf215546Sopenharmony_ci att->pViewFormats = info->format; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_cistatic struct zink_framebuffer * 120bf215546Sopenharmony_cicreate_framebuffer_imageless(struct zink_context *ctx, struct zink_framebuffer_state *state) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 123bf215546Sopenharmony_ci struct zink_framebuffer *fb = rzalloc(ctx, struct zink_framebuffer); 124bf215546Sopenharmony_ci if (!fb) 125bf215546Sopenharmony_ci return NULL; 126bf215546Sopenharmony_ci pipe_reference_init(&fb->reference, 1); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (!_mesa_hash_table_init(&fb->objects, fb, _mesa_hash_pointer, _mesa_key_pointer_equal)) 129bf215546Sopenharmony_ci goto fail; 130bf215546Sopenharmony_ci memcpy(&fb->state, state, sizeof(struct zink_framebuffer_state)); 131bf215546Sopenharmony_ci for (int i = 0; i < state->num_attachments; i++) 132bf215546Sopenharmony_ci populate_attachment_info(&fb->infos[i], &fb->state.infos[i]); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci return fb; 135bf215546Sopenharmony_cifail: 136bf215546Sopenharmony_ci zink_destroy_framebuffer(screen, fb); 137bf215546Sopenharmony_ci return NULL; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cibool 141bf215546Sopenharmony_cizink_use_dummy_attachments(const struct zink_context *ctx) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci return ctx->disable_color_writes && zink_screen(ctx->base.screen)->driver_workarounds.color_write_missing; 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_cistruct zink_framebuffer * 147bf215546Sopenharmony_cizink_get_framebuffer(struct zink_context *ctx) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci assert(zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci struct zink_framebuffer_state state; 152bf215546Sopenharmony_ci state.num_attachments = ctx->fb_state.nr_cbufs; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf; 155bf215546Sopenharmony_ci unsigned num_resolves = 0; 156bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 157bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb_state.cbufs[i]; 158bf215546Sopenharmony_ci if (!psurf || zink_use_dummy_attachments(ctx)) 159bf215546Sopenharmony_ci psurf = ctx->dummy_surface[util_logbase2_ceil(ctx->gfx_pipeline_state.rast_samples+1)]; 160bf215546Sopenharmony_ci struct zink_surface *surface = zink_csurface(psurf); 161bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(psurf); 162bf215546Sopenharmony_ci if (transient) { 163bf215546Sopenharmony_ci memcpy(&state.infos[i], &transient->info, sizeof(transient->info)); 164bf215546Sopenharmony_ci memcpy(&state.infos[cresolve_offset + i], &surface->info, sizeof(surface->info)); 165bf215546Sopenharmony_ci num_resolves++; 166bf215546Sopenharmony_ci } else { 167bf215546Sopenharmony_ci memcpy(&state.infos[i], &surface->info, sizeof(surface->info)); 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci const unsigned zsresolve_offset = cresolve_offset + num_resolves; 172bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf) { 173bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb_state.zsbuf; 174bf215546Sopenharmony_ci struct zink_surface *surface = zink_csurface(psurf); 175bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(psurf); 176bf215546Sopenharmony_ci if (transient) { 177bf215546Sopenharmony_ci memcpy(&state.infos[state.num_attachments], &transient->info, sizeof(transient->info)); 178bf215546Sopenharmony_ci memcpy(&state.infos[zsresolve_offset], &surface->info, sizeof(surface->info)); 179bf215546Sopenharmony_ci num_resolves++; 180bf215546Sopenharmony_ci } else { 181bf215546Sopenharmony_ci memcpy(&state.infos[state.num_attachments], &surface->info, sizeof(surface->info)); 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci state.num_attachments++; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* avoid bitfield explosion */ 187bf215546Sopenharmony_ci assert(state.num_attachments + num_resolves < 16); 188bf215546Sopenharmony_ci state.num_attachments += num_resolves; 189bf215546Sopenharmony_ci state.width = MAX2(ctx->fb_state.width, 1); 190bf215546Sopenharmony_ci state.height = MAX2(ctx->fb_state.height, 1); 191bf215546Sopenharmony_ci state.layers = MAX2(zink_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1; 192bf215546Sopenharmony_ci state.samples = ctx->fb_state.samples - 1; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci struct zink_framebuffer *fb; 195bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search(&ctx->framebuffer_cache, &state); 196bf215546Sopenharmony_ci if (entry) 197bf215546Sopenharmony_ci return entry->data; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci fb = create_framebuffer_imageless(ctx, &state); 200bf215546Sopenharmony_ci _mesa_hash_table_insert(&ctx->framebuffer_cache, &fb->state, fb); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci return fb; 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_civoid 206bf215546Sopenharmony_cidebug_describe_zink_framebuffer(char* buf, const struct zink_framebuffer *ptr) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci sprintf(buf, "zink_framebuffer"); 209bf215546Sopenharmony_ci} 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_civoid 212bf215546Sopenharmony_cizink_update_framebuffer_state(struct zink_context *ctx) 213bf215546Sopenharmony_ci{ 214bf215546Sopenharmony_ci /* get_framebuffer adds a ref if the fb is reused or created; 215bf215546Sopenharmony_ci * always do get_framebuffer first to avoid deleting the same fb 216bf215546Sopenharmony_ci * we're about to use 217bf215546Sopenharmony_ci */ 218bf215546Sopenharmony_ci struct zink_framebuffer *fb = zink_get_framebuffer(ctx); 219bf215546Sopenharmony_ci ctx->fb_changed |= ctx->framebuffer != fb; 220bf215546Sopenharmony_ci ctx->framebuffer = fb; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci/* same as u_framebuffer_get_num_layers, but clamp to lowest layer count */ 224bf215546Sopenharmony_ciunsigned 225bf215546Sopenharmony_cizink_framebuffer_get_num_layers(const struct pipe_framebuffer_state *fb) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci unsigned i, num_layers = UINT32_MAX; 228bf215546Sopenharmony_ci if (!(fb->nr_cbufs || fb->zsbuf)) 229bf215546Sopenharmony_ci return MAX2(fb->layers, 1); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci for (i = 0; i < fb->nr_cbufs; i++) { 232bf215546Sopenharmony_ci if (fb->cbufs[i]) { 233bf215546Sopenharmony_ci unsigned num = fb->cbufs[i]->u.tex.last_layer - 234bf215546Sopenharmony_ci fb->cbufs[i]->u.tex.first_layer + 1; 235bf215546Sopenharmony_ci num_layers = MIN2(num_layers, num); 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci if (fb->zsbuf) { 239bf215546Sopenharmony_ci unsigned num = fb->zsbuf->u.tex.last_layer - 240bf215546Sopenharmony_ci fb->zsbuf->u.tex.first_layer + 1; 241bf215546Sopenharmony_ci num_layers = MIN2(num_layers, num); 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci return MAX2(num_layers, 1); 244bf215546Sopenharmony_ci} 245