diff options
author | Alyssa Rosenzweig <alyssa@collabora.com> | 2022-11-15 11:16:15 -0500 |
---|---|---|
committer | Dylan Baker <dylan.c.baker@intel.com> | 2022-11-18 09:47:08 -0800 |
commit | 083f3382b0eac43bef183820bda6a220509714b7 (patch) | |
tree | b8fd713077b74d10881d11a2f7c5b2ab1c9116d6 | |
parent | f9b741b1c71a17b51f7c6a1fe4f974ff2987963c (diff) | |
download | mesa-083f3382b0eac43bef183820bda6a220509714b7.tar.gz |
panfrost: Fix reference counting with batch->resources
Refactor accesses to batch->resources to happen through safe helpers
that update the appropriate bookkeeping. This makes it obvious that (in
particular) reference counts are updated when they should be.
The functional change is that we are now correctly unreferencing
resources during shadowing, fixing a leak of shadowed resources.
Closes: #7362
Fixes: 2d8f28df731 ("panfrost: Replace resource shadowing flush")
Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Reported-by: Mastodon, apparently
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19753>
(cherry picked from commit 42212a9bfdab8381beb9206b5d2551344c71d584)
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_job.c | 116 | ||||
-rw-r--r-- | src/gallium/drivers/panfrost/pan_job.h | 2 |
3 files changed, 75 insertions, 45 deletions
diff --git a/.pick_status.json b/.pick_status.json index b873cc20510..61e4b000f8e 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1057,7 +1057,7 @@ "description": "panfrost: Fix reference counting with batch->resources", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "2d8f28df731638e1270b0ae273c7bfd2b29b7993" }, diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index 6ef813c2ecc..54e294f6c48 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -99,6 +99,74 @@ panfrost_batch_init(struct panfrost_context *ctx, screen->vtbl.init_batch(batch); } +/* + * Safe helpers for manipulating batch->resources follow. In addition to + * wrapping the underlying set operations, these update the required + * bookkeeping for resource tracking and reference counting. + */ +static bool +panfrost_batch_uses_resource(struct panfrost_batch *batch, + struct panfrost_resource *rsrc) +{ + return _mesa_set_search(batch->resources, rsrc) != NULL; +} + +static void +panfrost_batch_add_resource(struct panfrost_batch *batch, + struct panfrost_resource *rsrc) +{ + bool found = false; + _mesa_set_search_or_add(batch->resources, rsrc, &found); + + if (!found) { + /* Cache number of batches accessing a resource */ + rsrc->track.nr_users++; + + /* Reference the resource on the batch */ + pipe_reference(NULL, &rsrc->base.reference); + } +} + +static void +panfrost_batch_remove_resource_internal(struct panfrost_context *ctx, + struct panfrost_resource *rsrc) +{ + struct hash_entry *writer = _mesa_hash_table_search(ctx->writers, rsrc); + if (writer) { + _mesa_hash_table_remove(ctx->writers, writer); + rsrc->track.nr_writers--; + } + + rsrc->track.nr_users--; + pipe_resource_reference((struct pipe_resource **) &rsrc, NULL); +} + +static void +panfrost_batch_remove_resource_if_present(struct panfrost_context *ctx, + struct panfrost_batch *batch, + struct panfrost_resource *rsrc) +{ + struct set_entry *ent = _mesa_set_search(batch->resources, rsrc); + + if (ent != NULL) { + panfrost_batch_remove_resource_internal(ctx, rsrc); + _mesa_set_remove(batch->resources, ent); + } +} + +static void +panfrost_batch_destroy_resources(struct panfrost_context *ctx, + struct panfrost_batch *batch) +{ + set_foreach(batch->resources, entry) { + struct panfrost_resource *rsrc = (void *) entry->key; + + panfrost_batch_remove_resource_internal(ctx, rsrc); + } + + _mesa_set_destroy(batch->resources, NULL); +} + static void panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batch) { @@ -122,20 +190,7 @@ panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batc panfrost_bo_unreference(bo); } - set_foreach(batch->resources, entry) { - struct panfrost_resource *rsrc = (void *) entry->key; - - if (_mesa_hash_table_search(ctx->writers, rsrc)) { - _mesa_hash_table_remove_key(ctx->writers, rsrc); - rsrc->track.nr_writers--; - } - - rsrc->track.nr_users--; - - pipe_resource_reference((struct pipe_resource **) &rsrc, NULL); - } - - _mesa_set_destroy(batch->resources, NULL); + panfrost_batch_destroy_resources(ctx, batch); panfrost_pool_cleanup(&batch->pool); panfrost_pool_cleanup(&batch->invisible_pool); @@ -239,17 +294,8 @@ panfrost_batch_update_access(struct panfrost_batch *batch, uint32_t batch_idx = panfrost_batch_idx(batch); struct hash_entry *entry = _mesa_hash_table_search(ctx->writers, rsrc); struct panfrost_batch *writer = entry ? entry->data : NULL; - bool found = false; - _mesa_set_search_or_add(batch->resources, rsrc, &found); - - if (!found) { - /* Cache number of batches accessing a resource */ - rsrc->track.nr_users++; - - /* Reference the resource on the batch */ - pipe_reference(NULL, &rsrc->base.reference); - } + panfrost_batch_add_resource(batch, rsrc); /* Flush users if required */ if (writes || ((writer != NULL) && (writer != batch))) { @@ -262,7 +308,7 @@ panfrost_batch_update_access(struct panfrost_batch *batch, continue; /* Submit if it's a user */ - if (_mesa_set_search(batch->resources, rsrc)) + if (panfrost_batch_uses_resource(batch, rsrc)) panfrost_batch_submit(ctx, batch); } } @@ -369,30 +415,14 @@ panfrost_resource_swap_bo(struct panfrost_context *ctx, struct panfrost_resource *rsrc, struct panfrost_bo *newbo) { - /* Any batch writing this resource is writing to the old BO, not the - * new BO. After swapping the resource's backing BO, there will be no - * writers of the updated resource. Existing writers still hold a - * reference to the old BO for reference counting. - */ - struct hash_entry *writer = _mesa_hash_table_search(ctx->writers, rsrc); - if (writer) { - _mesa_hash_table_remove(ctx->writers, writer); - rsrc->track.nr_writers--; - } - /* Likewise, any batch reading this resource is reading the old BO, and * after swapping will not be reading this resource. */ unsigned i; foreach_batch(ctx, i) { struct panfrost_batch *batch = &ctx->batches.slots[i]; - struct set_entry *ent = _mesa_set_search(batch->resources, rsrc); - - if (!ent) - continue; - _mesa_set_remove(batch->resources, ent); - rsrc->track.nr_users--; + panfrost_batch_remove_resource_if_present(ctx, batch, rsrc); } /* Swap the pointers, dropping a reference to the old BO which is no @@ -897,7 +927,7 @@ panfrost_flush_batches_accessing_rsrc(struct panfrost_context *ctx, foreach_batch(ctx, i) { struct panfrost_batch *batch = &ctx->batches.slots[i]; - if (!_mesa_set_search(batch->resources, rsrc)) + if (!panfrost_batch_uses_resource(batch, rsrc)) continue; perf_debug_ctx(ctx, "Flushing user due to: %s", reason); diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h index fb62529a130..8840ff7487b 100644 --- a/src/gallium/drivers/panfrost/pan_job.h +++ b/src/gallium/drivers/panfrost/pan_job.h @@ -192,7 +192,7 @@ struct panfrost_batch { struct pan_tristate sprite_coord_origin; struct pan_tristate first_provoking_vertex; - /* Referenced resources */ + /* Referenced resources, holds a pipe_reference. */ struct set *resources; }; |