diff --git a/.pick_status.json b/.pick_status.json index d8dd77b893c..3bc2eca415f 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -2065,7 +2065,7 @@ "description": "panfrost: Replace resource shadowing flush", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "988d5aae74d61d1416b369172ef286b4aac933d0" }, diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index 81d69bba0ba..6ef813c2ecc 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -122,7 +122,7 @@ panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batc panfrost_bo_unreference(bo); } - set_foreach_remove(batch->resources, entry) { + set_foreach(batch->resources, entry) { struct panfrost_resource *rsrc = (void *) entry->key; if (_mesa_hash_table_search(ctx->writers, rsrc)) { @@ -364,6 +364,44 @@ panfrost_batch_write_rsrc(struct panfrost_batch *batch, panfrost_batch_update_access(batch, rsrc, true); } +void +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--; + } + + /* Swap the pointers, dropping a reference to the old BO which is no + * long referenced from the resource + */ + panfrost_bo_unreference(rsrc->image.data.bo); + rsrc->image.data.bo = newbo; +} + struct panfrost_bo * panfrost_batch_create_bo(struct panfrost_batch *batch, size_t size, uint32_t create_flags, enum pipe_shader_type stage, diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h index 6a41aeb2bde..fb62529a130 100644 --- a/src/gallium/drivers/panfrost/pan_job.h +++ b/src/gallium/drivers/panfrost/pan_job.h @@ -219,6 +219,11 @@ panfrost_batch_write_rsrc(struct panfrost_batch *batch, struct panfrost_resource *rsrc, enum pipe_shader_type stage); +void +panfrost_resource_swap_bo(struct panfrost_context *ctx, + struct panfrost_resource *rsrc, + struct panfrost_bo *newbo); + struct panfrost_bo * panfrost_batch_create_bo(struct panfrost_batch *batch, size_t size, uint32_t create_flags, uint32_t access_flags, diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 8084ba60b96..eb3859d90d4 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -1050,6 +1050,14 @@ panfrost_ptr_map(struct pipe_context *pctx, copy_resource = !panfrost_box_covers_resource(resource, box); } + /* Shadowing with separate stencil may require additional accounting. + * Bail in these exotic cases. + */ + if (rsrc->separate_stencil) { + create_new_bo = false; + copy_resource = false; + } + if (create_new_bo) { /* Make sure we re-emit any descriptors using this resource */ panfrost_dirty_state_all(ctx); @@ -1077,14 +1085,7 @@ panfrost_ptr_map(struct pipe_context *pctx, if (copy_resource) memcpy(newbo->ptr.cpu, rsrc->image.data.bo->ptr.cpu, bo->size); - panfrost_bo_unreference(bo); - rsrc->image.data.bo = newbo; - - /* Swapping out the BO will invalidate batches - * accessing this resource, flush them but do - * not wait for them. - */ - panfrost_flush_batches_accessing_rsrc(ctx, rsrc, "Resource shadowing"); + panfrost_resource_swap_bo(ctx, rsrc, newbo); if (!copy_resource && drm_is_afbc(rsrc->image.layout.modifier))