mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 00:49:04 +02:00
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:
parent
955417aa3e
commit
3c56b9c7a3
4 changed files with 65 additions and 119 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue