From d72f7cbc5a7c69634a8cdf8a3bebd96804b0b568 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 10 Sep 2024 19:31:25 -0400 Subject: [PATCH] zink: stop leaking inferred resolve surfaces this is tricky since the ownership model here works the other way around from normal: the resolve surface's lifetime is determined by the resource's lifetime, meaning that the surface should be destroyed by the resource instead of the resource being destroyed by the surface Part-of: --- src/gallium/drivers/zink/zink_context.c | 3 +++ src/gallium/drivers/zink/zink_resource.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index d7da0687cdb..37d3af5d784 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3880,6 +3880,9 @@ zink_set_framebuffer_state(struct pipe_context *pctx, zink_screen_lock_context(screen); res->surface = screen->copy_context->base.create_surface(&screen->copy_context->base, &res->base.b, &tmpl); zink_screen_unlock_context(screen); + /* delete extra ref: the resource controls the surface lifetime, not the other way around */ + struct pipe_resource *pres = ctx->fb_state.resolve; + pipe_resource_reference(&pres, NULL); } } if (depth_bias_scale_factor != ctx->depth_bias_scale_factor && diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index beaf360d347..b529ca48b64 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -234,6 +234,8 @@ zink_resource_destroy(struct pipe_screen *pscreen, { struct zink_screen *screen = zink_screen(pscreen); struct zink_resource *res = zink_resource(pres); + /* prevent double-free when unrefing internal surfaces */ + res->base.b.reference.count = 999; if (pres->target == PIPE_BUFFER) { util_range_destroy(&res->valid_buffer_range); util_idalloc_mt_free(&screen->buffer_ids, res->base.buffer_id_unique); @@ -241,10 +243,10 @@ zink_resource_destroy(struct pipe_screen *pscreen, simple_mtx_destroy(&res->bufferview_mtx); ralloc_free(res->bufferview_cache.table); } else { + pipe_surface_reference(&res->surface, NULL); assert(!_mesa_hash_table_num_entries(&res->surface_cache)); simple_mtx_destroy(&res->surface_mtx); ralloc_free(res->surface_cache.table); - pipe_surface_reference(&res->surface, NULL); } /* no need to do anything for the caches, these objects own the resource lifetimes */