diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index f5311a3ff3b..d258e7e7554 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -94,7 +94,8 @@ zink_context_destroy(struct pipe_context *pctx) pipe_resource_reference(&ctx->dummy_vertex_buffer, NULL); pipe_resource_reference(&ctx->dummy_xfb_buffer, NULL); - zink_surface_reference(screen, (struct zink_surface**)&ctx->dummy_surface, NULL); + for (unsigned i = 0; i < ARRAY_SIZE(ctx->dummy_surface); i++) + zink_surface_reference(screen, (struct zink_surface**)&ctx->dummy_surface[i], NULL); zink_buffer_view_reference(screen, &ctx->dummy_bufferview, NULL); simple_mtx_destroy(&ctx->batch_mtx); @@ -110,7 +111,10 @@ zink_context_destroy(struct pipe_context *pctx) zink_batch_state_destroy(screen, *bs); } - if (ctx->framebuffer) { + if (screen->info.have_KHR_imageless_framebuffer) { + hash_table_foreach(&ctx->framebuffer_cache, he) + zink_destroy_framebuffer(screen, he->data); + } else if (ctx->framebuffer) { simple_mtx_lock(&screen->framebuffer_mtx); struct hash_entry *entry = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state); if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL)) @@ -502,7 +506,7 @@ update_descriptor_state_sampler(struct zink_context *ctx, enum pipe_shader_type ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; ctx->di.tbos[shader][slot] = VK_NULL_HANDLE; } else { - struct zink_surface *null_surface = zink_surface(ctx->dummy_surface); + struct zink_surface *null_surface = zink_surface(ctx->dummy_surface[0]); struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview; ctx->di.textures[shader][slot].imageView = null_surface->image_view; ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -538,7 +542,7 @@ update_descriptor_state_image(struct zink_context *ctx, enum pipe_shader_type sh memset(&ctx->di.images[shader][slot], 0, sizeof(ctx->di.images[shader][slot])); ctx->di.texel_images[shader][slot] = VK_NULL_HANDLE; } else { - struct zink_surface *null_surface = zink_surface(ctx->dummy_surface); + struct zink_surface *null_surface = zink_surface(ctx->dummy_surface[0]); struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview; ctx->di.images[shader][slot].imageView = null_surface->image_view; ctx->di.images[shader][slot].imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -1479,7 +1483,7 @@ zink_update_fbfetch(struct zink_context *ctx) ctx->di.fbfetch.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; ctx->di.fbfetch.imageView = zink_screen(ctx->base.screen)->info.rb2_feats.nullDescriptor ? VK_NULL_HANDLE : - zink_surface(ctx->dummy_surface)->image_view; + zink_surface(ctx->dummy_surface[0])->image_view; zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, PIPE_SHADER_FRAGMENT, ZINK_DESCRIPTOR_TYPE_UBO, 0, 1); return; } @@ -1554,7 +1558,7 @@ get_render_pass(struct zink_context *ctx) state.rts[i].swapchain = surf->texture->bind & PIPE_BIND_SCANOUT; } else { state.rts[i].format = VK_FORMAT_R8_UINT; - state.rts[i].samples = MAX2(fb->samples, 1); + state.rts[i].samples = fb->samples; } state.num_rts++; } @@ -1612,6 +1616,20 @@ get_render_pass(struct zink_context *ctx) return rp; } +static uint32_t +hash_framebuffer_imageless(const void *key) +{ + struct zink_framebuffer_state* s = (struct zink_framebuffer_state*)key; + return _mesa_hash_data(key, offsetof(struct zink_framebuffer_state, infos) + sizeof(s->infos[0]) * s->num_attachments); +} + +static bool +equals_framebuffer_imageless(const void *a, const void *b) +{ + struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)a; + return memcmp(a, b, offsetof(struct zink_framebuffer_state, infos) + sizeof(s->infos[0]) * s->num_attachments) == 0; +} + static void setup_framebuffer(struct zink_context *ctx) { @@ -1652,11 +1670,30 @@ setup_framebuffer(struct zink_context *ctx) if (!ctx->fb_changed) return; - zink_init_framebuffer(screen, ctx->framebuffer, rp); + ctx->init_framebuffer(screen, ctx->framebuffer, rp); ctx->fb_changed = false; ctx->gfx_pipeline_state.render_pass = rp; } +static VkImageView +prep_fb_attachment(struct zink_context *ctx, struct pipe_surface *psurf, unsigned i) +{ + if (!psurf) + return zink_surface(ctx->dummy_surface[util_logbase2_ceil(ctx->fb_state.samples)])->image_view; + + struct zink_surface *surf = zink_surface(psurf); + zink_batch_resource_usage_set(&ctx->batch, zink_resource(surf->base.texture), true); + zink_batch_usage_set(&surf->batch_uses, ctx->batch.state); + + struct zink_resource *res = zink_resource(surf->base.texture); + VkAccessFlags access; + VkPipelineStageFlags pipeline; + VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass, + i, &pipeline, &access); + zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline); + return surf->image_view; +} + static unsigned begin_render_pass(struct zink_context *ctx) { @@ -1715,20 +1752,17 @@ begin_render_pass(struct zink_context *ctx) assert(ctx->gfx_pipeline_state.render_pass && ctx->framebuffer); - for (int i = 0; i < ctx->framebuffer->state.num_attachments; i++) { - if (ctx->framebuffer->surfaces[i]) { - struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[i]); - zink_batch_resource_usage_set(batch, zink_resource(surf->base.texture), true); - zink_batch_usage_set(&surf->batch_uses, batch->state); - - struct zink_resource *res = zink_resource(surf->base.texture); - VkAccessFlags access; - VkPipelineStageFlags pipeline; - VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass, - i, &pipeline, &access); - zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline); - } - } + VkRenderPassAttachmentBeginInfo infos; + VkImageView att[PIPE_MAX_COLOR_BUFS + 1]; + infos.sType = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO; + infos.pNext = NULL; + infos.attachmentCount = ctx->framebuffer->state.num_attachments; + infos.pAttachments = att; + for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) + att[i] = prep_fb_attachment(ctx, ctx->fb_state.cbufs[i], i); + att[ctx->fb_state.nr_cbufs] = prep_fb_attachment(ctx, ctx->fb_state.zsbuf, ctx->fb_state.nr_cbufs); + if (zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer) + rpbi.pNext = &infos; vkCmdBeginRenderPass(batch->state->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE); batch->in_rp = true; @@ -2021,13 +2055,15 @@ zink_set_framebuffer_state(struct pipe_context *pctx, if (ctx->fb_state.width != w || ctx->fb_state.height != h) ctx->scissor_changed = true; rebind_fb_state(ctx, NULL, true); - /* zink_get_framebuffer adds a ref if the fb is reused or created; + ctx->fb_state.samples = util_framebuffer_get_num_samples(state); + uint8_t rast_samples = ctx->fb_state.samples - 1; + /* get_framebuffer adds a ref if the fb is reused or created; * always do get_framebuffer first to avoid deleting the same fb * we're about to use */ - struct zink_framebuffer *fb = zink_get_framebuffer(ctx); - if (ctx->framebuffer) { - struct zink_screen *screen = zink_screen(pctx->screen); + struct zink_framebuffer *fb = ctx->get_framebuffer(ctx); + struct zink_screen *screen = zink_screen(ctx->base.screen); + if (ctx->framebuffer && !screen->info.have_KHR_imageless_framebuffer) { simple_mtx_lock(&screen->framebuffer_mtx); struct hash_entry *he = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state); if (ctx->framebuffer && !ctx->framebuffer->state.num_attachments) { @@ -2040,7 +2076,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx, } /* a framebuffer loses 1 ref every time we unset it; * we do NOT add refs here, as the ref has already been added in - * zink_get_framebuffer() + * get_framebuffer() */ if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL) && he) _mesa_hash_table_remove(&screen->framebuffer_cache, he); @@ -2049,7 +2085,6 @@ zink_set_framebuffer_state(struct pipe_context *pctx, ctx->fb_changed |= ctx->framebuffer != fb; ctx->framebuffer = fb; - uint8_t rast_samples = util_framebuffer_get_num_samples(state) - 1; /* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */ if ((ctx->gfx_pipeline_state.rast_samples > 0) != (rast_samples > 0)) ctx->dirty_shader_stages |= 1 << PIPE_SHADER_FRAGMENT; @@ -2685,10 +2720,8 @@ zink_texture_barrier(struct pipe_context *pctx, unsigned flags) bmb.pNext = NULL; bmb.srcAccessMask = 0; bmb.dstAccessMask = 0; - struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[ctx->framebuffer->state.num_attachments - 1]); - struct zink_resource *res = zink_resource(surf->base.texture); zink_batch_no_rp(ctx); - if (res->aspect != VK_IMAGE_ASPECT_COLOR_BIT) { + if (ctx->fb_state.zsbuf) { VkMemoryBarrier dmb; dmb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; dmb.pNext = NULL; @@ -2707,7 +2740,7 @@ zink_texture_barrier(struct pipe_context *pctx, unsigned flags) bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; } - if (ctx->framebuffer->state.num_attachments > 1) { + if (ctx->fb_state.nr_cbufs > 0) { bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; } @@ -3134,11 +3167,15 @@ zink_rebind_framebuffer(struct zink_context *ctx, struct zink_resource *res) { if (!ctx->framebuffer) return; - for (unsigned i = 0; i < ctx->framebuffer->state.num_attachments; i++) { - if (!ctx->framebuffer->surfaces[i] || - zink_resource(ctx->framebuffer->surfaces[i]->texture) != res) + for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) { + if (!ctx->fb_state.cbufs[i] || + zink_resource(ctx->fb_state.cbufs[i]->texture) != res) continue; - zink_rebind_surface(ctx, &ctx->framebuffer->surfaces[i]); + zink_rebind_surface(ctx, &ctx->fb_state.cbufs[i]); + zink_batch_no_rp(ctx); + } + if (ctx->fb_state.zsbuf && zink_resource(ctx->fb_state.zsbuf->texture) != res) { + zink_rebind_surface(ctx, &ctx->fb_state.zsbuf); zink_batch_no_rp(ctx); } if (rebind_fb_state(ctx, res, false)) @@ -3488,6 +3525,14 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->base.screen = pscreen; ctx->base.priv = priv; + if (screen->info.have_KHR_imageless_framebuffer) { + ctx->get_framebuffer = zink_get_framebuffer_imageless; + ctx->init_framebuffer = zink_init_framebuffer_imageless; + } else { + ctx->get_framebuffer = zink_get_framebuffer; + ctx->init_framebuffer = zink_init_framebuffer; + } + ctx->base.destroy = zink_context_destroy; ctx->base.get_device_reset_status = zink_get_device_reset_status; ctx->base.set_device_reset_callback = zink_set_device_reset_callback; @@ -3576,6 +3621,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) goto fail; _mesa_hash_table_init(&ctx->compute_program_cache, ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); + _mesa_hash_table_init(&ctx->framebuffer_cache, ctx, hash_framebuffer_imageless, equals_framebuffer_imageless); _mesa_set_init(&ctx->render_pass_state_cache, ctx, hash_rp_state, equals_rp_state); ctx->render_pass_cache = _mesa_hash_table_create(NULL, hash_render_pass_state, @@ -3592,9 +3638,13 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) PIPE_BIND_STREAM_OUTPUT, PIPE_USAGE_DEFAULT, sizeof(data)); if (!ctx->dummy_xfb_buffer) goto fail; - ctx->dummy_surface = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, 1, 1, 1); - if (!ctx->dummy_surface) - goto fail; + for (unsigned i = 0; i < ARRAY_SIZE(ctx->dummy_surface); i++) { + if (!(screen->info.props.limits.framebufferDepthSampleCounts & BITFIELD_BIT(i))) + continue; + ctx->dummy_surface[i] = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, 1024, 1024, BITFIELD_BIT(i)); + if (!ctx->dummy_surface[i]) + goto fail; + } ctx->dummy_bufferview = get_buffer_view(ctx, zink_resource(ctx->dummy_vertex_buffer), PIPE_FORMAT_R8_UNORM, 0, sizeof(data)); if (!ctx->dummy_bufferview) goto fail; @@ -3627,7 +3677,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) } } if (!screen->info.rb2_feats.nullDescriptor) - ctx->di.fbfetch.imageView = zink_surface(ctx->dummy_surface)->image_view; + ctx->di.fbfetch.imageView = zink_surface(ctx->dummy_surface[0])->image_view; p_atomic_inc(&screen->base.num_contexts); zink_select_draw_vbo(ctx); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 6e1d9ff701b..bdf8cd53b52 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -200,6 +200,9 @@ struct zink_context { struct zink_image_view image_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; struct pipe_framebuffer_state fb_state; + struct zink_framebuffer *(*get_framebuffer)(struct zink_context*); + void (*init_framebuffer)(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp); + struct hash_table framebuffer_cache; struct zink_vertex_elements_state *element_state; struct zink_rasterizer_state *rast_state; @@ -284,7 +287,7 @@ struct zink_context { struct pipe_resource *dummy_vertex_buffer; struct pipe_resource *dummy_xfb_buffer; - struct pipe_surface *dummy_surface; + struct pipe_surface *dummy_surface[7]; struct zink_buffer_view *dummy_bufferview; unsigned buffer_rebind_counter; diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 5494b9e103e..97838b52520 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -104,6 +104,10 @@ EXTENSIONS = [ alias="index_uint8", features=True, conditions=["$feats.indexTypeUint8"]), + Extension("VK_KHR_imageless_framebuffer", + alias="imgless", + features=True, + conditions=["$feats.imagelessFramebuffer"]), Extension("VK_EXT_robustness2", alias="rb2", properties=True, diff --git a/src/gallium/drivers/zink/zink_framebuffer.c b/src/gallium/drivers/zink/zink_framebuffer.c index a96c2e32a10..6147581383e 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.c +++ b/src/gallium/drivers/zink/zink_framebuffer.c @@ -45,13 +45,134 @@ zink_destroy_framebuffer(struct zink_screen *screen, #endif } - if (fb->null_surface) - pipe_resource_reference(&fb->null_surface->texture, NULL); - zink_surface_reference(screen, (struct zink_surface**)&fb->null_surface, NULL); - ralloc_free(fb); } +void +zink_init_framebuffer_imageless(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.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 (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; +} + +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; + 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_surface(psurf); + memcpy(&state.infos[i], &surface->info, sizeof(surface->info)); + } + + state.num_attachments = ctx->fb_state.nr_cbufs; + if (ctx->fb_state.zsbuf) { + struct pipe_surface *psurf = ctx->fb_state.zsbuf; + struct zink_surface *surface = zink_surface(psurf); + memcpy(&state.infos[state.num_attachments], &surface->info, sizeof(surface->info)); + state.num_attachments++; + } + + 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->gfx_pipeline_state.rast_samples; + + 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 zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp) { @@ -80,7 +201,7 @@ zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, s 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) return; @@ -100,10 +221,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); @@ -118,13 +239,11 @@ zink_create_framebuffer(struct zink_context *ctx, /* 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 = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, state->width, state->height, state->samples); - surf = zink_surface(fb->null_surface); - state->attachments[i] = zink_surface(fb->null_surface)->image_view; + surf = zink_surface(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); @@ -148,6 +267,9 @@ 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[PIPE_MAX_COLOR_BUFS + 1] = {0}; struct zink_framebuffer_state state = {0}; @@ -166,8 +288,8 @@ zink_get_framebuffer(struct zink_context *ctx) 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); - state.samples = ctx->fb_state.samples; + state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1; + state.samples = ctx->gfx_pipeline_state.rast_samples; struct zink_framebuffer *fb; simple_mtx_lock(&screen->framebuffer_mtx); @@ -182,7 +304,7 @@ zink_get_framebuffer(struct zink_context *ctx) * 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 = zink_create_framebuffer(ctx, &state, attachments); + fb = create_framebuffer(ctx, &state, attachments); _mesa_hash_table_insert(&screen->framebuffer_cache, &fb->state, fb); } simple_mtx_unlock(&screen->framebuffer_mtx); diff --git a/src/gallium/drivers/zink/zink_framebuffer.h b/src/gallium/drivers/zink/zink_framebuffer.h index f2a23e4b150..4fb8bf67b90 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.h +++ b/src/gallium/drivers/zink/zink_framebuffer.h @@ -36,10 +36,14 @@ struct zink_render_pass; struct zink_framebuffer_state { uint32_t width; - uint16_t height, layers; - uint8_t samples; - uint8_t num_attachments; - VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1]; + uint16_t height; + uint32_t layers:6; + uint32_t samples:6; + uint32_t num_attachments:4; + union { + VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1]; + struct zink_surface_info infos[PIPE_MAX_COLOR_BUFS + 1]; + }; }; struct zink_framebuffer { @@ -49,19 +53,18 @@ struct zink_framebuffer { 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; + union { + struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1]; + VkFramebufferAttachmentImageInfo infos[PIPE_MAX_COLOR_BUFS + 1]; + }; struct hash_table objects; }; -struct zink_framebuffer * -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_init_framebuffer_imageless(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp); void zink_destroy_framebuffer(struct zink_screen *screen, @@ -87,6 +90,9 @@ zink_framebuffer_reference(struct zink_screen *screen, return ret; } +struct zink_framebuffer * +zink_get_framebuffer_imageless(struct zink_context *ctx); + struct zink_framebuffer * zink_get_framebuffer(struct zink_context *ctx); #endif diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index c99fd83bf71..92a40de1304 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1059,14 +1059,16 @@ zink_destroy_screen(struct pipe_screen *pscreen) zink_buffer_view_reference(screen, &bv, NULL); } - hash_table_foreach(&screen->framebuffer_cache, entry) { - struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data; - zink_destroy_framebuffer(screen, fb); + if (!screen->info.have_KHR_imageless_framebuffer) { + hash_table_foreach(&screen->framebuffer_cache, entry) { + struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data; + zink_destroy_framebuffer(screen, fb); + } + simple_mtx_destroy(&screen->framebuffer_mtx); } simple_mtx_destroy(&screen->surface_mtx); simple_mtx_destroy(&screen->bufferview_mtx); - simple_mtx_destroy(&screen->framebuffer_mtx); u_transfer_helper_destroy(pscreen->transfer_helper); #ifdef ENABLE_SHADER_CACHE @@ -1919,9 +1921,11 @@ zink_internal_create_screen(const struct pipe_screen_config *config) simple_mtx_init(&screen->surface_mtx, mtx_plain); simple_mtx_init(&screen->bufferview_mtx, mtx_plain); - simple_mtx_init(&screen->framebuffer_mtx, mtx_plain); - _mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state); + if (!screen->info.have_KHR_imageless_framebuffer) { + simple_mtx_init(&screen->framebuffer_mtx, mtx_plain); + _mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state); + } _mesa_hash_table_init(&screen->surface_cache, screen, NULL, equals_ivci); _mesa_hash_table_init(&screen->bufferview_cache, screen, NULL, equals_bvci); diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c index 75b410366fe..233ec4c20ea 100644 --- a/src/gallium/drivers/zink/zink_surface.c +++ b/src/gallium/drivers/zink/zink_surface.c @@ -222,11 +222,6 @@ surface_clear_fb_refs(struct zink_screen *screen, struct pipe_surface *psurface) simple_mtx_unlock(&screen->framebuffer_mtx); break; } - /* null surface doesn't get a ref but it will double-free - * if the pointer isn't unset - */ - if (fb->null_surface == psurface) - fb->null_surface = NULL; } } util_dynarray_fini(&surface->framebuffer_refs); @@ -242,7 +237,8 @@ zink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface) assert(he->data == surface); _mesa_hash_table_remove(&screen->surface_cache, he); simple_mtx_unlock(&screen->surface_mtx); - surface_clear_fb_refs(screen, psurface); + if (!screen->info.have_KHR_imageless_framebuffer) + surface_clear_fb_refs(screen, psurface); zink_descriptor_set_refs_clear(&surface->desc_set_refs, surface); util_dynarray_fini(&surface->framebuffer_refs); pipe_resource_reference(&psurface->texture, NULL);