diff options
-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; }; |