[PATCH v2] etnaviv: fix resource usage tracking across different pipe_context's
Marek Vasut
marex at denx.de
Wed Jan 2 14:19:46 UTC 2019
On 1/2/19 9:58 AM, Christian Gmeiner wrote:
> A pipe_resource can be shared by all the pipe_context's hanging off the
> same pipe_screen.
>
> Changes from v1 -> v2:
> - to remove the resource from the used_resources set when it is destroyed
>
> Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
Is this somehow different from the version of your patch I posted about
a month ago ?
> ---
> src/gallium/drivers/etnaviv/etnaviv_context.c | 21 ++++----
> src/gallium/drivers/etnaviv/etnaviv_context.h | 3 --
> .../drivers/etnaviv/etnaviv_resource.c | 48 ++++++++++++++-----
> .../drivers/etnaviv/etnaviv_resource.h | 7 ++-
> src/gallium/drivers/etnaviv/etnaviv_screen.c | 8 ++++
> src/gallium/drivers/etnaviv/etnaviv_screen.h | 4 ++
> 6 files changed, 61 insertions(+), 30 deletions(-)
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
> index 44b50925a4f..8d4956516f1 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
> @@ -36,6 +36,7 @@
> #include "etnaviv_query.h"
> #include "etnaviv_query_hw.h"
> #include "etnaviv_rasterizer.h"
> +#include "etnaviv_resource.h"
> #include "etnaviv_screen.h"
> #include "etnaviv_shader.h"
> #include "etnaviv_state.h"
> @@ -329,7 +330,8 @@ static void
> etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
> {
> struct etna_context *ctx = priv;
> - struct etna_resource *rsc, *rsc_tmp;
> + struct etna_screen *screen = ctx->screen;
> + struct set_entry *entry;
>
> etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL);
> etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001);
> @@ -384,16 +386,13 @@ etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
> ctx->dirty = ~0L;
> ctx->dirty_sampler_views = ~0L;
>
> - /* go through all the used resources and clear their status flag */
> - LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list)
> - {
> - debug_assert(rsc->status != 0);
> - rsc->status = 0;
> - rsc->pending_ctx = NULL;
> - list_delinit(&rsc->list);
> - }
> + /* go through all the used context resources and clear their status flag */
> + set_foreach(screen->used_resources, entry) {
> + struct etna_resource *rsc = (struct etna_resource *)entry->key;
>
> - assert(LIST_IS_EMPTY(&ctx->used_resources));
> + _mesa_set_remove_key(rsc->pending_ctx, ctx);
> + _mesa_set_remove(screen->used_resources, entry);
> + }
> }
>
> static void
> @@ -437,8 +436,6 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
> /* need some sane default in case state tracker doesn't set some state: */
> ctx->sample_mask = 0xffff;
>
> - list_inithead(&ctx->used_resources);
> -
> /* Set sensible defaults for state */
> etna_cmd_stream_reset_notify(ctx->stream, ctx);
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
> index 6ad9f3431e1..50a2cdf3d07 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
> @@ -136,9 +136,6 @@ struct etna_context {
> uint32_t prim_hwsupport;
> struct primconvert_context *primconvert;
>
> - /* list of resources used by currently-unsubmitted renders */
> - struct list_head used_resources;
> -
> struct slab_child_pool transfer_pool;
> struct blitter_context *blitter;
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index c0091288030..00b5f43bf3f 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> @@ -33,6 +33,7 @@
> #include "etnaviv_screen.h"
> #include "etnaviv_translate.h"
>
> +#include "util/hash_table.h"
> #include "util/u_inlines.h"
> #include "util/u_memory.h"
>
> @@ -282,7 +283,6 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> rsc->halign = halign;
>
> pipe_reference_init(&rsc->base.reference, 1);
> - list_inithead(&rsc->list);
>
> size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale);
>
> @@ -303,6 +303,11 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> memset(map, 0, size);
> }
>
> + rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
> + _mesa_key_pointer_equal);
> + if (!rsc->pending_ctx)
> + goto free_rsc;
> +
> return &rsc->base;
>
> free_rsc:
> @@ -462,8 +467,12 @@ etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc)
> static void
> etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
> {
> + struct etna_screen *screen = etna_screen(pscreen);
> struct etna_resource *rsc = etna_resource(prsc);
>
> + _mesa_set_destroy(rsc->pending_ctx, NULL);
> + _mesa_set_remove_key(screen->used_resources, rsc);
> +
> if (rsc->bo)
> etna_bo_del(rsc->bo);
>
> @@ -471,9 +480,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
> etna_bo_del(rsc->ts_bo);
>
> if (rsc->scanout)
> - renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro);
> -
> - list_delinit(&rsc->list);
> + renderonly_scanout_destroy(rsc->scanout, screen->ro);
>
> pipe_resource_reference(&rsc->texture, NULL);
> pipe_resource_reference(&rsc->external, NULL);
> @@ -508,7 +515,6 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
> *prsc = *tmpl;
>
> pipe_reference_init(&prsc->reference, 1);
> - list_inithead(&rsc->list);
> prsc->screen = pscreen;
>
> rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride);
> @@ -554,6 +560,11 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
> goto fail;
> }
>
> + rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
> + _mesa_key_pointer_equal);
> + if (!rsc->pending_ctx)
> + goto fail;
> +
> if (rsc->layout == ETNA_LAYOUT_LINEAR) {
> /*
> * Both sampler and pixel pipes can't handle linear, create a compatible
> @@ -628,20 +639,35 @@ void
> etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
> enum etna_resource_status status)
> {
> + struct etna_screen *screen = ctx->screen;
> + struct set_entry *entry;
> struct etna_resource *rsc;
>
> if (!prsc)
> return;
>
> rsc = etna_resource(prsc);
> +
> + set_foreach(rsc->pending_ctx, entry) {
> + struct etna_context *extctx = (struct etna_context *)entry->key;
> + struct pipe_context *pctx = &extctx->base;
> +
> + if (extctx == ctx)
> + continue;
> +
> + /* if we are pending read or write by any other context */
> + if ((status & ETNA_PENDING_WRITE) && rsc->status)
> + pctx->flush(pctx, NULL, 0);
> +
> + /* if reading a resource pending a write */
> + if ((status & ETNA_PENDING_READ) && (rsc->status & ETNA_PENDING_WRITE))
> + pctx->flush(pctx, NULL, 0);
> + }
> +
> rsc->status |= status;
>
> - /* TODO resources can actually be shared across contexts,
> - * so I'm not sure a single list-head will do the trick? */
> - debug_assert((rsc->pending_ctx == ctx) || !rsc->pending_ctx);
> - list_delinit(&rsc->list);
> - list_addtail(&rsc->list, &ctx->used_resources);
> - rsc->pending_ctx = ctx;
> + _mesa_set_add(screen->used_resources, rsc);
> + _mesa_set_add(rsc->pending_ctx, ctx);
> }
>
> bool
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> index 11ccf8f7bcb..32df349a19b 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> @@ -31,7 +31,9 @@
> #include "etnaviv_tiling.h"
> #include "pipe/p_state.h"
> #include "util/list.h"
> +#include "util/set.h"
>
> +struct etna_context;
> struct pipe_screen;
>
> struct etna_resource_level {
> @@ -83,10 +85,7 @@ struct etna_resource {
>
> enum etna_resource_status status;
>
> - /* resources accessed by queued but not flushed draws are tracked
> - * in the used_resources list. */
> - struct list_head list;
> - struct etna_context *pending_ctx;
> + struct set *pending_ctx;
> };
>
> /* returns TRUE if a is newer than b */
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> index fb51aa5f4e8..034f549e99f 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> @@ -38,6 +38,7 @@
> #include "etnaviv_resource.h"
> #include "etnaviv_translate.h"
>
> +#include "util/hash_table.h"
> #include "util/os_time.h"
> #include "util/u_math.h"
> #include "util/u_memory.h"
> @@ -82,6 +83,8 @@ etna_screen_destroy(struct pipe_screen *pscreen)
> {
> struct etna_screen *screen = etna_screen(pscreen);
>
> + _mesa_set_destroy(screen->used_resources, NULL);
> +
> if (screen->perfmon)
> etna_perfmon_del(screen->perfmon);
>
> @@ -1026,6 +1029,11 @@ etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu,
> if (screen->drm_version >= ETNA_DRM_VERSION_PERFMON)
> etna_pm_query_setup(screen);
>
> + screen->used_resources = _mesa_set_create(NULL, _mesa_hash_pointer,
> + _mesa_key_pointer_equal);
> + if (!screen->used_resources)
> + goto fail;
> +
> return pscreen;
>
> fail:
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h b/src/gallium/drivers/etnaviv/etnaviv_screen.h
> index bffd4b6ef94..3f1175fce0e 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h
> @@ -34,6 +34,7 @@
> #include "os/os_thread.h"
> #include "pipe/p_screen.h"
> #include "renderonly/renderonly.h"
> +#include "util/set.h"
> #include "util/slab.h"
> #include "util/u_dynarray.h"
>
> @@ -80,6 +81,9 @@ struct etna_screen {
> struct etna_specs specs;
>
> uint32_t drm_version;
> +
> + /* set of resources used by currently-unsubmitted renders */
> + struct set *used_resources;
> };
>
> static inline struct etna_screen *
>
--
Best regards,
Marek Vasut
More information about the etnaviv
mailing list