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)
{
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);
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))) {
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);
}
}
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
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);