panfrost: Remove rsrc->track

Just check on the context instead. Usually the number of batches is small so
this is still fast, and avoids all the tricky atomics and the batch->resources
set which existed only for bookkeeping.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20426>
This commit is contained in:
Alyssa Rosenzweig 2022-11-30 18:45:03 -05:00 committed by Marge Bot
parent 955417aa3e
commit 3c56b9c7a3
4 changed files with 65 additions and 119 deletions

View file

@ -78,8 +78,6 @@ panfrost_batch_init(struct panfrost_context *ctx,
batch->maxx = batch->maxy = 0;
util_copy_framebuffer_state(&batch->key, key);
batch->resources =_mesa_set_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
/* Preallocate the main pool, since every batch has at least one job
* structure so it will be used */
@ -99,74 +97,6 @@ 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)
{
@ -190,7 +120,12 @@ panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batc
panfrost_bo_unreference(bo);
}
panfrost_batch_destroy_resources(ctx, batch);
/* There is no more writer for anything we wrote */
hash_table_foreach(ctx->writers, ent) {
if (ent->data == batch)
_mesa_hash_table_remove(ctx->writers, ent);
}
panfrost_pool_cleanup(&batch->pool);
panfrost_pool_cleanup(&batch->invisible_pool);
@ -286,6 +221,10 @@ panfrost_get_fresh_batch_for_fbo(struct panfrost_context *ctx, const char *reaso
return batch;
}
static bool
panfrost_batch_uses_resource(struct panfrost_batch *batch,
struct panfrost_resource *rsrc);
static void
panfrost_batch_update_access(struct panfrost_batch *batch,
struct panfrost_resource *rsrc, bool writes)
@ -295,8 +234,6 @@ panfrost_batch_update_access(struct panfrost_batch *batch,
struct hash_entry *entry = _mesa_hash_table_search(ctx->writers, rsrc);
struct panfrost_batch *writer = entry ? entry->data : NULL;
panfrost_batch_add_resource(batch, rsrc);
/* Flush users if required */
if (writes || ((writer != NULL) && (writer != batch))) {
unsigned i;
@ -315,7 +252,6 @@ panfrost_batch_update_access(struct panfrost_batch *batch,
if (writes) {
_mesa_hash_table_insert(ctx->writers, rsrc, batch);
rsrc->track.nr_writers++;
}
}
@ -334,6 +270,22 @@ panfrost_batch_get_bo_access(struct panfrost_batch *batch, unsigned handle)
return util_dynarray_element(&batch->bos, pan_bo_access, handle);
}
static bool
panfrost_batch_uses_resource(struct panfrost_batch *batch,
struct panfrost_resource *rsrc)
{
/* A resource is used iff its current BO is used */
uint32_t handle = rsrc->image.data.bo->gem_handle;
unsigned size = util_dynarray_num_elements(&batch->bos, pan_bo_access);
/* If out of bounds, certainly not used */
if (handle >= size)
return false;
/* Otherwise check if nonzero access */
return !!(*util_dynarray_element(&batch->bos, pan_bo_access, handle));
}
static void
panfrost_batch_add_bo_old(struct panfrost_batch *batch,
struct panfrost_bo *bo, uint32_t flags)
@ -404,28 +356,6 @@ 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)
{
/* 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];
panfrost_batch_remove_resource_if_present(ctx, batch, rsrc);
}
/* 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,
@ -942,6 +872,28 @@ panfrost_flush_batches_accessing_rsrc(struct panfrost_context *ctx,
}
}
bool
panfrost_any_batch_reads_rsrc(struct panfrost_context *ctx,
struct panfrost_resource *rsrc)
{
unsigned i;
foreach_batch(ctx, i) {
struct panfrost_batch *batch = &ctx->batches.slots[i];
if (panfrost_batch_uses_resource(batch, rsrc))
return true;
}
return false;
}
bool
panfrost_any_batch_writes_rsrc(struct panfrost_context *ctx,
struct panfrost_resource *rsrc)
{
return _mesa_hash_table_search(ctx->writers, rsrc) != NULL;
}
void
panfrost_batch_adjust_stack_size(struct panfrost_batch *batch)
{

View file

@ -187,9 +187,6 @@ struct panfrost_batch {
*/
struct pan_tristate sprite_coord_origin;
struct pan_tristate first_provoking_vertex;
/* Referenced resources, holds a pipe_reference. */
struct set *resources;
};
/* Functions for managing the above */
@ -215,10 +212,13 @@ 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);
bool
panfrost_any_batch_reads_rsrc(struct panfrost_context *ctx,
struct panfrost_resource *rsrc);
bool
panfrost_any_batch_writes_rsrc(struct panfrost_context *ctx,
struct panfrost_resource *rsrc);
struct panfrost_bo *
panfrost_batch_create_bo(struct panfrost_batch *batch, size_t size,

View file

@ -1013,7 +1013,8 @@ panfrost_ptr_map(struct pipe_context *pctx,
bool valid = BITSET_TEST(rsrc->valid.data, level);
if ((usage & PIPE_MAP_READ) && (valid || rsrc->track.nr_writers > 0)) {
if ((usage & PIPE_MAP_READ) &&
(valid || panfrost_any_batch_writes_rsrc(ctx, rsrc))) {
pan_blit_to_staging(pctx, transfer);
panfrost_flush_writer(ctx, staging, "AFBC read staging blit");
panfrost_bo_wait(staging->image.data.bo, INT64_MAX, false);
@ -1056,8 +1057,7 @@ panfrost_ptr_map(struct pipe_context *pctx,
!(usage & PIPE_MAP_UNSYNCHRONIZED) &&
!(resource->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) &&
(usage & PIPE_MAP_WRITE) &&
rsrc->track.nr_users > 0) {
panfrost_any_batch_reads_rsrc(ctx, rsrc)) {
/* When a resource to be modified is already being used by a
* pending batch, it is often faster to copy the whole BO than
* to flush and split the frame in two.
@ -1086,7 +1086,7 @@ panfrost_ptr_map(struct pipe_context *pctx,
* not ready yet (still accessed by one of the already flushed
* batches), we try to allocate a new one to avoid waiting.
*/
if (rsrc->track.nr_users > 0 ||
if (panfrost_any_batch_reads_rsrc(ctx, rsrc) ||
!panfrost_bo_wait(bo, 0, true)) {
/* We want the BO to be MMAPed. */
uint32_t flags = bo->flags & ~PAN_BO_DELAY_MMAP;
@ -1105,7 +1105,12 @@ panfrost_ptr_map(struct pipe_context *pctx,
if (copy_resource)
memcpy(newbo->ptr.cpu, rsrc->image.data.bo->ptr.cpu, bo->size);
panfrost_resource_swap_bo(ctx, rsrc, newbo);
/* 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;
if (!copy_resource &&
drm_is_afbc(rsrc->image.layout.modifier))

View file

@ -50,17 +50,6 @@ struct panfrost_resource {
} tile_map;
} damage;
struct {
/** Number of batches accessing this resource. Used to check if
* a resource is in use. */
_Atomic unsigned nr_users;
/** Number of batches writing this resource. Note that only one
* batch per context may write a resource, so this is the
* number of contexts that have an active writer. */
_Atomic unsigned nr_writers;
} track;
struct renderonly_scanout *scanout;
struct panfrost_resource *separate_stencil;